Exemple #1
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;
        }
Exemple #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;
 }