/// <summary>
        ///
        /// </summary>
        /// <param name="type"></param>
        /// <param name="activeType"></param>
        /// <param name="fight"></param>
        /// <param name="caster"></param>
        /// <param name="castInfos"></param>
        /// <param name="cell"></param>
        /// <param name="duration"></param>
        /// <param name="actionId"></param>
        /// <param name="canGoThrough"></param>
        /// <param name="canStack"></param>
        /// <param name="hide"></param>
        protected AbstractActivableObject(FightObstacleTypeEnum type, ActiveType activeType, AbstractFight fight, AbstractFighter caster, CastInfos castInfos, int cell, int duration, int actionId, bool canGoThrough, bool canStack, bool hide = false)
        {
            m_fight        = fight;
            m_caster       = caster;
            m_spellId      = castInfos.SpellId;
            m_actionSpell  = SpellManager.Instance.GetTemplate(castInfos.Value1);
            m_actionEffect = m_actionSpell.GetLevel(castInfos.Value2);

            Cell           = fight.GetCell(cell);
            ObstacleType   = type;
            ActivationType = activeType;
            CanGoThrough   = canGoThrough;
            CanStack       = canStack;
            Color          = castInfos.Value3;
            Targets        = new List <AbstractFighter>();
            Length         = Pathfinding.GetDirection(castInfos.RangeType[1]);
            AffectedCells  = new List <FightCell>();
            Duration       = duration;
            ActionId       = actionId;
            Hide           = hide;

            foreach (var effect in m_actionEffect.Effects)
            {
                if (CastInfos.IsDamageEffect(effect.TypeEnum))
                {
                    Priority--;
                }
            }

            // On ajout l'objet a toutes les cells qu'il affecte
            foreach (var cellId in CellZone.GetCircleCells(fight.Map, cell, Length))
            {
                var fightCell = m_fight.GetCell(cellId);
                if (fightCell != null)
                {
                    fightCell.AddObject(this);
                    AffectedCells.Add(fightCell);
                }
            }

            if (Hide)
            {
                Appear(caster.Team);
            }
            else
            {
                AppearForAll();
            }
        }
Example #2
0
        public override AIActionResult Execute()
        {
            switch (AttackState)
            {
            case AttackStateEnum.STATE_CALCULATE_CELLS:
                CastCellList    = new Dictionary <int, List <SpellLevel> >();
                WeakestEnnemies = Fighter.Team.OpponentTeam.AliveFighters.OrderBy(fighter => Pathfinding.GoalDistance(Map, Fighter.Cell.Id, fighter.Cell.Id));

                foreach (var spellLevel in Fighter.SpellBook.GetSpells())
                {
                    foreach (var castCell in CellZone.GetCircleCells(Map, Fighter.Cell.Id, spellLevel.MaxPO))
                    {
                        if (Fight.CanLaunchSpell(Fighter, spellLevel, spellLevel.SpellId, Fighter.Cell.Id, castCell) == FightSpellLaunchResultEnum.RESULT_OK)
                        {
                            if (!CastCellList.ContainsKey(castCell))
                            {
                                CastCellList.Add(castCell, new List <SpellLevel>());
                            }
                            CastCellList[castCell].Add(spellLevel);
                        }
                    }
                }

                if (CastCellList.Count == 0)
                {
                    return(AIActionResult.FAILURE);
                }

                AttackState = AttackStateEnum.STATE_CALCULATE_EFFECT_TARGETS;
                return(AIActionResult.RUNNING);

            case AttackStateEnum.STATE_CALCULATE_EFFECT_TARGETS:
                TargetList = new Dictionary <int, Dictionary <int, Dictionary <SpellEffect, List <AbstractFighter> > > >();
                foreach (var castInfos in CastCellList)
                {
                    var castCell = castInfos.Key;
                    TargetList.Add(castCell, new Dictionary <int, Dictionary <SpellEffect, List <AbstractFighter> > >());
                    foreach (var spellLevel in castInfos.Value)
                    {
                        if (spellLevel == null || spellLevel.Effects == null)
                        {
                            continue;
                        }

                        TargetList[castCell].Add(spellLevel.SpellId, new Dictionary <SpellEffect, List <AbstractFighter> >());

                        int effectIndex = 0;
                        foreach (var effect in spellLevel.Effects)
                        {
                            TargetList[castCell][spellLevel.SpellId].Add(effect, new List <AbstractFighter>());

                            var targetType = spellLevel.Template.Targets != null ? spellLevel.Template.Targets.Count > effectIndex ? spellLevel.Template.Targets[effectIndex] : -1 : -1;

                            if (effect.TypeEnum != EffectEnum.UseGlyph && effect.TypeEnum != EffectEnum.UseTrap)
                            {
                                foreach (var currentCellId in CellZone.GetCells(Map, castCell, Fighter.Cell.Id, spellLevel.RangeType))
                                {
                                    var fightCell = Fight.GetCell(currentCellId);
                                    if (fightCell != null)
                                    {
                                        foreach (var fighterObject in fightCell.FightObjects.OfType <AbstractFighter>())
                                        {
                                            if (targetType != -1)
                                            {
                                                if (((((targetType >> 5) & 1) == 1) && (Fighter.Id != fighterObject.Id)))
                                                {
                                                    if (!TargetList[castCell][spellLevel.SpellId][effect].Contains(Fighter))
                                                    {
                                                        TargetList[castCell][spellLevel.SpellId][effect].Add(Fighter);
                                                    }
                                                    continue;
                                                }
                                                if (((targetType & 1) == 1) && Fighter.Team == fighterObject.Team)
                                                {
                                                    continue;
                                                }
                                                if ((((targetType >> 1) & 1) == 1) && Fighter == fighterObject)
                                                {
                                                    continue;
                                                }
                                                if ((((targetType >> 2) & 1) == 1) && Fighter.Team != fighterObject.Team)
                                                {
                                                    continue;
                                                }
                                                if (((((targetType >> 3) & 1) == 1) && (fighterObject.Invocator == null)))
                                                {
                                                    continue;
                                                }
                                                if (((((targetType >> 4) & 1) == 1) && (fighterObject.Invocator != null)))
                                                {
                                                    continue;
                                                }
                                            }

                                            if (!TargetList[castCell][spellLevel.SpellId][effect].Contains(fighterObject))
                                            {
                                                TargetList[castCell][spellLevel.SpellId][effect].Add(fighterObject);
                                            }
                                        }
                                    }
                                }
                            }
                            effectIndex++;
                        }
                    }
                }

                AttackState = AttackStateEnum.STATE_CALCULATE_BEST_SPELL;

                return(AIActionResult.RUNNING);

            case AttackStateEnum.STATE_CALCULATE_BEST_SPELL:
                int bestScore = 0;
                foreach (var target in TargetList)
                {
                    var castCell = target.Key;

                    foreach (var spell in target.Value)
                    {
                        var spellId      = spell.Key;
                        var currentScore = -1;
                        foreach (var levelInfos in spell.Value)
                        {
                            var effect = levelInfos.Key;
                            foreach (var fighter in levelInfos.Value)
                            {
                                if (CastInfos.IsDamageEffect(effect.TypeEnum))
                                {
                                    if (fighter.Team.Id != Fighter.Team.Id)
                                    {
                                        currentScore += 200 + effect.Value1 + effect.Value2 + effect.Value3;
                                    }
                                    else
                                    {
                                        currentScore -= 200 + effect.Value1 + effect.Value2 + effect.Value3;
                                    }
                                }
                                else if (CastInfos.IsMalusEffect(effect.TypeEnum))
                                {
                                    if (fighter.Team.Id != Fighter.Team.Id)
                                    {
                                        currentScore += 45;
                                    }
                                    else
                                    {
                                        currentScore -= 45 + effect.Value1 + effect.Value2 + effect.Value3;
                                    }
                                }
                                else if (CastInfos.IsBonusEffect(effect.TypeEnum) || CastInfos.IsFriendlyEffect(effect.TypeEnum))
                                {
                                    if (fighter.Team.Id != Fighter.Team.Id)
                                    {
                                        currentScore -= 50 + effect.Value1 + effect.Value2 + effect.Value3;
                                    }
                                    else
                                    if (effect.TypeEnum == EffectEnum.Heal)
                                    {
                                        currentScore += 50 + (effect.Value1 + effect.Value2 + effect.Value3) * (100 - (int)((double)fighter.Life / fighter.MaxLife));
                                    }
                                    else
                                    {
                                        currentScore += 50 + effect.Value1 + effect.Value2 + effect.Value3;
                                    }
                                }
                            }

                            if (levelInfos.Value.Count == 0)
                            {
                                switch (effect.TypeEnum)
                                {
                                case EffectEnum.UseTrap:
                                case EffectEnum.UseGlyph:
                                case EffectEnum.Teleport:
                                    foreach (var ennemy in WeakestEnnemies)
                                    {
                                        currentScore += 50;
                                        currentScore -= Pathfinding.GoalDistance(Map, castCell, ennemy.Cell.Id);
                                    }
                                    break;

                                case EffectEnum.Invocation:
                                case EffectEnum.InvocationStatic:
                                case EffectEnum.InvocDouble:
                                    currentScore += 50;
                                    break;
                                }
                            }
                        }

                        if (currentScore > bestScore)
                        {
                            bestScore  = currentScore;
                            SpellId    = spellId;
                            TargetCell = castCell;
                        }
                    }
                }

                if (SpellId == 0)
                {
                    return(AIActionResult.FAILURE);
                }

                AttackState = AttackStateEnum.STATE_LAUNCH_ATTACK;

                return(AIActionResult.RUNNING);

            case AttackStateEnum.STATE_LAUNCH_ATTACK:

                Fight.TryLaunchSpell(Fighter, SpellId, TargetCell, 1000);
                Timeout = 1000;

                AttackState = AttackStateEnum.STATE_ATTACKING;

                return(AIActionResult.RUNNING);

            case AttackStateEnum.STATE_ATTACKING:
                if (!Timedout)
                {
                    return(AIActionResult.RUNNING);
                }

                return(Initialize());

            default:
                throw new Exception("AI Attack action invalid state.");
            }
        }