Beispiel #1
0
        private static void AdjustDamage(SpellImpact damages, uint damage1, uint damage2, SpellCategory category, double chanceToHappen, int addDamage, int addDamagePercent, int reduceDamage, int reduceDamagePercent, bool negativ)
        {
            DamageType minDamage = damage1;
            DamageType maxDamage = damage1 >= damage2 ? damage1 : damage2;

            if (reduceDamagePercent >= 100)
            {
                return; // No damage
            }
            minDamage = (DamageType)(((minDamage * (1 + (addDamagePercent / 100.0)) + addDamage) - reduceDamage) * (1 - (reduceDamagePercent / 100.0)) * chanceToHappen);
            maxDamage = (DamageType)(((maxDamage * (1 + (addDamagePercent / 100.0)) + addDamage) - reduceDamage) * (1 - (reduceDamagePercent / 100.0)) * chanceToHappen);

            if (minDamage < 0)
            {
                minDamage = 0;
            }
            if (maxDamage < 0)
            {
                maxDamage = 0;
            }


            if (negativ)           // or IsFriend
            {
                minDamage *= -1.5; // High penalty for firing on friends
                maxDamage *= -1.5; // High penalty for firing on friends
            }
            switch (category)
            {
            case SpellCategory.DamagesNeutral:
                damages.MinNeutral += minDamage;
                damages.MaxNeutral += maxDamage;
                break;

            case SpellCategory.DamagesFire:
                damages.MinFire += minDamage;
                damages.MaxAir  += maxDamage;
                break;

            case SpellCategory.DamagesAir:
                damages.MinAir += minDamage;
                damages.MaxAir += maxDamage;
                break;

            case SpellCategory.DamagesWater:
                damages.MinWater += minDamage;
                damages.MaxWater += maxDamage;
                break;

            case SpellCategory.DamagesEarth:
                damages.MinEarth += minDamage;
                damages.MaxEarth += maxDamage;
                break;

            case SpellCategory.Healing:
                damages.MinHeal += minDamage;
                damages.MaxHeal += maxDamage;
                break;
            }
        }
Beispiel #2
0
        public SpellImpact GetSpellDamages(PlayedFighter caster, Fighter target /*, Spell.SpellCategory categories*/)
        {
            SpellImpact damages = null;

            foreach (var effect in LevelTemplate.effects)
            {
                CumulEffects(effect, ref damages, caster, target /*, categories*/, this);
            }
            return(damages);
        }
Beispiel #3
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 #4
0
 public void Add(SpellImpact dmg)
 {
     MinFire    += dmg.MinFire;
     MaxFire    += dmg.MaxFire;
     MinWater   += dmg.MinWater;
     MaxWater   += dmg.MaxWater;
     MinEarth   += dmg.MinEarth;
     MaxEarth   += dmg.MaxEarth;
     MinAir     += dmg.MinAir;
     MaxAir     += dmg.MaxAir;
     MinNeutral += dmg.MinNeutral;
     MaxNeutral += dmg.MaxNeutral;
     MinHeal    += dmg.MinHeal;
     MaxHeal    += dmg.MaxHeal;
     Curse      += dmg.Curse;
     Boost      += dmg.Boost;
 }
Beispiel #5
0
        // Precise compute efficiency of a spell for a given category (beware to remove pc from friend and friendcells lists before calling this !)
        // Returns -1 if it would hit friends (todo : optimize if needed)
        public int GetFullAreaEffect(PlayedFighter pc, Cell source, Cell dest, IEnumerable <Fighter> actors, Spell.SpellCategory category, ref string comment)
        {
            SpellImpact spellImpact = new SpellImpact();

            foreach (EffectInstanceDice effect in LevelTemplate.effects)
            {
                if ((Spell.GetEffectCategories((uint)effect.effectId, LevelTemplate.id) & category) > 0)
                {
                    comment += " Effect " + (EffectsEnum)(effect.effectId) + " : ";
                    EffectDice         effectCl   = new EffectDice(effect);
                    IEnumerable <Cell> cells      = effectCl.GetArea(source, dest);
                    SpellTargetType    targetType = (SpellTargetType)effect.targetId;
                    int nbAffectedTargets         = 0;
                    if (EffectBase.canAffectTarget(effectCl, this, pc, pc) && cells.Contains(source))
                    {
                        // Caster would be affected
                        DamageType efficiency = Spell.CumulEffects(effect, ref spellImpact, pc, pc /*, category*/, this);
                        if (efficiency != 0)
                        {
                            comment += string.Format("{0} on {1} => {2}, ", (decimal)efficiency, pc, (decimal)spellImpact.Damage);
                        }
                        nbAffectedTargets++;
                        if (efficiency < 0)
                        {
                            return(0);                // The caster would be affected by a bad spell => give up
                        }
                    }

                    foreach (var actor in actors.Where(act => cells.Contains(act.Cell))) // All actors within the area covered by the spell
                    {
                        if (!EffectBase.canAffectTarget(effectCl, this, pc, actor))
                        {
                            continue;                                                         // This actor is not affected by the spell
                        }
                        DamageType damage = Spell.CumulEffects(effect, ref spellImpact, pc, actor /*, category*/, this);
                        if (damage != 0)
                        {
                            comment += string.Format(" - {0} on {1} => {2}", (decimal)damage, actor, (decimal)spellImpact.Damage);
                        }

                        nbAffectedTargets++;
                        //if (damage > 0 && actor.Team == pc.Team) return 0; // Harmful on a friend => give up
                    }

                    //if (nbAffectedTargets > 1)
                    //{
                    //    pc.Character.SendWarning("Spell {0} : {1} targets affected for {2} damage - {3}", this, nbAffectedTargets, spellImpact.Damage, comment);
                    //}
                }
            }

            if (Template.id == 139) // Mot d'altruisme : only use near end of fight or if lot of spellImpact to heal
            {
                int hpLeftOnFoes = actors.Where(actor => actor.Team.Id != pc.Team.Id).Sum(actor => actor.Stats.Health);
                comment += string.Format(" - special \"Mot d'altruisme\" processing : hpLeftOnFoes = {0}, efficiency = {1}", hpLeftOnFoes, (int)spellImpact.Damage);
                if (hpLeftOnFoes > 500) // Not the end of the fight
                {
                    if (spellImpact.Damage < 300)
                    {
                        return(0);                          // Do not cast it if less than 300 hp of healing
                    }
                    else
                    {
                        return((int)spellImpact.Damage / 3); // Otherwise, far from the end of the fight, divide efficiency by 3
                    }
                }
                // if close to the end of the fight, then returns full result.
            }

            return((int)spellImpact.Damage);
        }
Beispiel #6
0
        /// <summary>
        /// Add spellImpact for a given effect, taking into account caster bonus and target resistance.
        /// </summary>
        /// <param name="effect"></param>
        /// <param name="spellImpact"></param>
        /// <param name="caster"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static DamageType CumulEffects(EffectInstanceDice effect, ref SpellImpact spellImpact, PlayedFighter caster, Fighter target /*, Spell.SpellCategory Categories*/, Spell spell)
        {
            bool        isFriend = caster.Team.Id == target.Team.Id;
            SpellImpact result   = new SpellImpact();

            SpellTargetType targetType = (SpellTargetType)effect.targetId;


            //if ((targetType & SpellTargetType.ENEMIES) == 0) return spellImpact; // No enemy can be targeted

            SpellCategory category = GetEffectCategories(effect.effectId, spell.LevelTemplate.id) /* & Categories*/;

            if (category == 0)
            {
                return(0);              // No category selected in this spell
            }
            if (spell.Template.id == 0) // Weapon => ignore non heal or damage effects
            {
                if ((category & (SpellCategory.Damages | SpellCategory.Healing)) == 0)
                {
                    return(0);
                }
            }

            double chanceToHappen = 1.0; //

            // When chances to happen is under 100%, then we reduce spellImpact accordingly, for simplicity, but after having apply damage bonus & reduction.
            // So average damage should remain exact even if Min and Max are not.
            if (effect.random > 0)
            {
                chanceToHappen = effect.random / 100.0;
            }

            if (target.Summoned && (caster.Breed.Id != (int)BreedEnum.Osamodas || target.Team.Id != caster.Team.Id))
            {
                chanceToHappen /= 2; // It's much better to hit non-summoned foes => effect on summons (except allies summon for Osa) is divided by 2.
            }
            SpellException spellException = null;

            if (spellExceptions.ContainsKey(spell.LevelTemplate.id))
            {
                spellException = spellExceptions[spell.LevelTemplate.id];
            }
            if ((category & SpellCategory.DamagesNeutral) > 0)
            {
                AdjustDamage(result, spellException != null ? spellException.MinNeutral : effect.diceNum, spellException != null ? spellException.MaxNeutral : effect.diceSide, SpellCategory.DamagesNeutral, chanceToHappen,
                             GetSafetotal(caster, Stats.PlayerField.NeutralDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.PhysicalDamage),
                             GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Strength),
                             target == null ? 0 : target.Stats.NeutralElementReduction,
                             target == null ? 0 : target.Stats.NeutralResistPercent, isFriend);
            }

            if ((category & SpellCategory.DamagesFire) > 0)
            {
                AdjustDamage(result, spellException != null ? spellException.MinFire : effect.diceNum, spellException != null ? spellException.MaxFire : effect.diceSide, SpellCategory.DamagesFire, chanceToHappen,
                             GetSafetotal(caster, Stats.PlayerField.FireDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                             GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Intelligence),
                             target == null ? 0 : target.Stats.FireElementReduction,
                             target == null ? 0 : target.Stats.FireResistPercent, isFriend);
            }

            if ((category & SpellCategory.DamagesAir) > 0)
            {
                AdjustDamage(result, spellException != null ? spellException.MinAir : effect.diceNum, spellException != null ? spellException.MaxAir : effect.diceSide, SpellCategory.DamagesAir, chanceToHappen,
                             GetSafetotal(caster, Stats.PlayerField.AirDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                             GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Agility),
                             target == null ? 0 : target.Stats.AirElementReduction,
                             target == null ? 0 : target.Stats.AirResistPercent, isFriend);
            }

            if ((category & SpellCategory.DamagesWater) > 0)
            {
                AdjustDamage(result, spellException != null ? spellException.MinWater : effect.diceNum, spellException != null ? spellException.MaxWater : effect.diceSide, SpellCategory.DamagesWater, chanceToHappen,
                             GetSafetotal(caster, Stats.PlayerField.WaterDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                             GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Chance),
                             target == null ? 0 : target.Stats.WaterElementReduction,
                             target == null ? 0 : target.Stats.WaterResistPercent, isFriend);
            }

            if ((category & SpellCategory.DamagesEarth) > 0)
            {
                AdjustDamage(result, spellException != null ? spellException.MinEarth : effect.diceNum, spellException != null ? spellException.MaxEarth : effect.diceSide, SpellCategory.DamagesEarth, chanceToHappen,
                             GetSafetotal(caster, Stats.PlayerField.EarthDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                             GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Strength),
                             target == null ? 0 : target.Stats.EarthElementReduction,
                             target == null ? 0 : target.Stats.EarthResistPercent, isFriend);
            }

            if ((category & SpellCategory.Healing) > 0)
            {
                bool steal = (category & SpellCategory.Damages) > 0;
                if (steal)
                {
                    target = caster;                                                               // Probably hp steal
                }
                uint hptoHeal = (uint)(Math.Max(0, target.Stats.MaxHealth - target.Stats.Health)); // Can't heal over max
                if (steal)
                {
                    result.MinHeal = -Math.Min(hptoHeal, Math.Abs(result.MinDamage));
                    result.MaxHeal = -Math.Min(hptoHeal, Math.Abs(result.MaxDamage));
                }
                else
                {
                    bool skip = false;
                    if (spell.Template.id == 140) // Mot de reconstruction => do only use it on purpose
                    {
                        if (hptoHeal < target.Stats.Health || hptoHeal < 400)
                        {
                            skip = true;                                                   // Only heal targets with under 50% of health and at least 400 hp to heal
                        }
                    }
                    if (!skip && hptoHeal > 0)
                    {
                        AdjustDamage(result, Math.Min(effect.diceNum, hptoHeal), Math.Min(effect.diceSide, hptoHeal), SpellCategory.Healing, chanceToHappen,
                                     GetSafetotal(caster, Stats.PlayerField.HealBonus),
                                     GetSafetotal(caster, Stats.PlayerField.Intelligence),
                                     0,
                                     0, isFriend);
                        if (result.Heal > hptoHeal)
                        {
                            if (isFriend)
                            {
                                result.MinHeal = result.MaxHeal = -hptoHeal;
                            }
                            else
                            {
                                result.MinHeal = result.MaxHeal = hptoHeal;
                            }
                        }
                    }
                }
            }
            if ((category & SpellCategory.Buff) > 0)
            {
                if (isFriend)
                {
                    result.Boost -= spell.Level * chanceToHappen;
                }
                else
                {
                    result.Boost += spell.Level * chanceToHappen;
                }
            }

            if ((category & SpellCategory.Curse) > 0)
            {
                DamageType ratio = spell.Level * chanceToHappen;

                if (effect.effectId == (int)EffectsEnum.Effect_SkipTurn) // Let say this effect counts as 2 damage per level of the target
                {
                    ratio = target.Level * 2 * chanceToHappen;
                }

                if (isFriend)
                {
                    result.Curse -= 2 * ratio;
                }
                else
                {
                    result.Curse += ratio;
                }
            }
            if (isFriend)
            {
                result.Add(result);                                                                              // amplify (double) effects on friends.
            }
            if (!isFriend && ((category & SpellCategory.Damages) > 0) && result.MinDamage > target.Stats.Health) // Enough damage to kill the target => affect an arbitrary 50% of max heal (with at least current health), so strong spells are not favored anymore.
            {
                double ratio = Math.Max(target.Stats.MaxHealth / 2, target.Stats.Health) / result.MinDamage;
                result.Multiply(ratio);
            }

            if (spell.Template.id == 114) // Rekop
            {
                if (target.Stats.Health < 1000)
                {
                    result.Multiply(0.1);
                }
                else
                if (target.Stats.Health < 2000)
                {
                    result.Multiply(0.5);
                }
            }

            // Damage reflection
            if (((category & SpellCategory.Damages) > 0) && result.Damage > 0 && !isFriend)
            {
                DamageType reflected = spell.GetDamageReflection(target);
                if (reflected > 0)
                {
                    if (reflected >= spellImpact.Damage)
                    {
                        return(0);                                 // Reflect all damages
                    }
                    result.MinHeal += reflected * 2;
                    result.MaxHeal += reflected * 2;
                }
            }

            if (spell.Template.id == 0 && (category & SpellCategory.Damages) > 0) // Weapon => consider effect of "maîtrise"
            {
                Weapon weapon = caster.Character.Inventory.GetEquippedWeapon();
                if (weapon != null)
                {
                    foreach (var boost in caster.GetBoostWeaponDamagesEffects())
                    {
                        if (boost.weaponTypeId == weapon.typeId)
                        {
                            result.Multiply(1.0 + boost.delta / 100.0);
                        }
                    }
                }
            }

            if (spellImpact != null)
            {
                spellImpact.Add(result);
            }
            else
            {
                spellImpact = result;
            }
            return(result.Damage);
        }
Beispiel #7
0
        // Precise compute efficiency of a spell for a given category (beware to remove pc from friend and friendcells lists before calling this !)
        // Returns -1 if it would hit friends (todo : optimize if needed)
        public int GetFullAreaEffect(PlayedFighter pc, Cell source, Cell dest, IEnumerable<Fighter> actors, Spell.SpellCategory category, ref string comment)
        {
            SpellImpact spellImpact = new SpellImpact();

            foreach (EffectInstanceDice effect in LevelTemplate.effects)
                if ((Spell.GetEffectCategories((uint)effect.effectId, LevelTemplate.id) & category) > 0)
                {
                    comment += " Effect " + (EffectsEnum)(effect.effectId) + " : ";
                    EffectDice effectCl = new EffectDice(effect);
                    IEnumerable<Cell> cells = effectCl.GetArea(source, dest);
                    SpellTargetType targetType = (SpellTargetType)effect.targetId;
                    int nbAffectedTargets = 0;
                    if (EffectBase.canAffectTarget(effectCl, this, pc, pc) && cells.Contains(source))
                    {
                        // Caster would be affected
                        DamageType efficiency = Spell.CumulEffects(effect, ref spellImpact, pc, pc/*, category*/, this);
                        if (efficiency != 0)
                            comment += string.Format("{0} on {1} => {2}, ", (decimal)efficiency, pc, (decimal)spellImpact.Damage);
                        nbAffectedTargets++;
                        if (efficiency < 0) return 0; // The caster would be affected by a bad spell => give up     
                    }

                    foreach (var actor in actors.Where(act => cells.Contains(act.Cell))) // All actors within the area covered by the spell
                    {
                        if (!EffectBase.canAffectTarget(effectCl, this, pc, actor)) continue; // This actor is not affected by the spell
                        DamageType damage = Spell.CumulEffects(effect, ref spellImpact, pc, actor/*, category*/, this);
                        if (damage != 0)
                            comment += string.Format(" - {0} on {1} => {2}", (decimal)damage, actor, (decimal)spellImpact.Damage);

                        nbAffectedTargets++;
                        //if (damage > 0 && actor.Team == pc.Team) return 0; // Harmful on a friend => give up                        
                    }
                                        
                    //if (nbAffectedTargets > 1)
                    //{
                    //    pc.Character.SendWarning("Spell {0} : {1} targets affected for {2} damage - {3}", this, nbAffectedTargets, spellImpact.Damage, comment);
                    //}
                }

            if (Template.id == 139) // Mot d'altruisme : only use near end of fight or if lot of spellImpact to heal
            {
                int hpLeftOnFoes = actors.Where(actor => actor.Team.Id != pc.Team.Id).Sum(actor => actor.Stats.Health);
                comment += string.Format(" - special \"Mot d'altruisme\" processing : hpLeftOnFoes = {0}, efficiency = {1}", hpLeftOnFoes, (int)spellImpact.Damage);
                if (hpLeftOnFoes > 500) // Not the end of the fight
                    if (spellImpact.Damage < 300) return 0; // Do not cast it if less than 300 hp of healing
                    else
                        return (int)spellImpact.Damage / 3; // Otherwise, far from the end of the fight, divide efficiency by 3                
                // if close to the end of the fight, then returns full result. 
            }
            
            return (int)spellImpact.Damage;
        }
Beispiel #8
0
        /// <summary>
        /// Add spellImpact for a given effect, taking into account caster bonus and target resistance. 
        /// </summary>
        /// <param name="effect"></param>
        /// <param name="spellImpact"></param>
        /// <param name="caster"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static DamageType CumulEffects(EffectInstanceDice effect, ref SpellImpact spellImpact, PlayedFighter caster, Fighter target/*, Spell.SpellCategory Categories*/, Spell spell)
        {
            bool isFriend = caster.Team.Id == target.Team.Id;
            SpellImpact result = new SpellImpact();

            SpellTargetType targetType = (SpellTargetType)effect.targetId;

                
            //if ((targetType & SpellTargetType.ENEMIES) == 0) return spellImpact; // No enemy can be targeted

            SpellCategory category = GetEffectCategories(effect.effectId, spell.LevelTemplate.id)/* & Categories*/;
            if (category == 0) return 0; // No category selected in this spell

            if (spell.Template.id == 0) // Weapon => ignore non heal or damage effects
                if ( (category & (SpellCategory.Damages | SpellCategory.Healing)) == 0) return 0;

            double chanceToHappen = 1.0; // 

            // When chances to happen is under 100%, then we reduce spellImpact accordingly, for simplicity, but after having apply damage bonus & reduction. 
            // So average damage should remain exact even if Min and Max are not. 
            if (effect.random > 0)
                chanceToHappen = effect.random / 100.0;

            if (target.Summoned && (caster.Breed.Id != (int)BreedEnum.Osamodas || target.Team.Id != caster.Team.Id))
                chanceToHappen /= 2; // It's much better to hit non-summoned foes => effect on summons (except allies summon for Osa) is divided by 2. 

            SpellException spellException = null;
            if (spellExceptions.ContainsKey(spell.LevelTemplate.id))
                spellException = spellExceptions[spell.LevelTemplate.id];
            if ((category & SpellCategory.DamagesNeutral) > 0)
                AdjustDamage(result, spellException != null ? spellException.MinNeutral : effect.diceNum, spellException != null ? spellException.MaxNeutral : effect.diceSide, SpellCategory.DamagesNeutral, chanceToHappen,
                    GetSafetotal(caster, Stats.PlayerField.NeutralDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.PhysicalDamage),
                    GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Strength),
                    target == null ? 0 : target.Stats.NeutralElementReduction,
                    target == null ? 0 : target.Stats.NeutralResistPercent, isFriend);

            if ((category & SpellCategory.DamagesFire) > 0)
                AdjustDamage(result, spellException != null ? spellException.MinFire : effect.diceNum, spellException != null ? spellException.MaxFire : effect.diceSide, SpellCategory.DamagesFire, chanceToHappen,
                    GetSafetotal(caster, Stats.PlayerField.FireDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                    GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Intelligence),
                    target == null ? 0 : target.Stats.FireElementReduction,
                    target == null ? 0 : target.Stats.FireResistPercent, isFriend);

            if ((category & SpellCategory.DamagesAir) > 0)
                AdjustDamage(result, spellException != null ? spellException.MinAir : effect.diceNum, spellException != null ? spellException.MaxAir : effect.diceSide, SpellCategory.DamagesAir, chanceToHappen,
                    GetSafetotal(caster, Stats.PlayerField.AirDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                    GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Agility),
                    target == null ? 0 : target.Stats.AirElementReduction,
                    target == null ? 0 : target.Stats.AirResistPercent, isFriend);

            if ((category & SpellCategory.DamagesWater) > 0)
                AdjustDamage(result, spellException != null ? spellException.MinWater : effect.diceNum, spellException != null ? spellException.MaxWater : effect.diceSide, SpellCategory.DamagesWater, chanceToHappen,
                    GetSafetotal(caster, Stats.PlayerField.WaterDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                    GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Chance),
                    target == null ? 0 : target.Stats.WaterElementReduction,
                    target == null ? 0 : target.Stats.WaterResistPercent, isFriend);

            if ((category & SpellCategory.DamagesEarth) > 0)
                AdjustDamage(result, spellException != null ? spellException.MinEarth : effect.diceNum, spellException != null ? spellException.MaxEarth : effect.diceSide, SpellCategory.DamagesEarth, chanceToHappen,
                    GetSafetotal(caster, Stats.PlayerField.EarthDamageBonus) + GetSafetotal(caster, Stats.PlayerField.DamageBonus) + GetSafetotal(caster, Stats.PlayerField.MagicDamage),
                    GetSafetotal(caster, Stats.PlayerField.DamageBonusPercent) + GetSafetotal(caster, Stats.PlayerField.Strength),
                    target == null ? 0 : target.Stats.EarthElementReduction,
                    target == null ? 0 : target.Stats.EarthResistPercent, isFriend);

            if ((category & SpellCategory.Healing) > 0)
            {
                bool steal = (category & SpellCategory.Damages) > 0;
                if (steal) target = caster; // Probably hp steal
                uint hptoHeal = (uint)(Math.Max(0, target.Stats.MaxHealth - target.Stats.Health)); // Can't heal over max
                if (steal)
                {
                    result.MinHeal = -Math.Min(hptoHeal, Math.Abs(result.MinDamage));
                    result.MaxHeal = -Math.Min(hptoHeal, Math.Abs(result.MaxDamage));
                }
                else
                {
                    bool skip = false;
                    if (spell.Template.id == 140) // Mot de reconstruction => do only use it on purpose
                    {
                        if (hptoHeal < target.Stats.Health || hptoHeal < 400) skip = true; // Only heal targets with under 50% of health and at least 400 hp to heal
                    }
                    if (!skip && hptoHeal > 0)
                    {
                        AdjustDamage(result, Math.Min(effect.diceNum, hptoHeal), Math.Min(effect.diceSide, hptoHeal), SpellCategory.Healing, chanceToHappen,
                             GetSafetotal(caster, Stats.PlayerField.HealBonus),
                             GetSafetotal(caster, Stats.PlayerField.Intelligence),
                             0,
                             0, isFriend);
                        if (result.Heal > hptoHeal)
                            if (isFriend)
                                result.MinHeal = result.MaxHeal = -hptoHeal;
                            else
                                result.MinHeal = result.MaxHeal = hptoHeal;
                    }
                }
            }
            if ((category & SpellCategory.Buff) > 0)
                if (isFriend)
                    result.Boost -= spell.Level * chanceToHappen;
                else
                    result.Boost += spell.Level * chanceToHappen;

            if ((category & SpellCategory.Curse) > 0)
            {
                DamageType ratio = spell.Level * chanceToHappen;

                if (effect.effectId == (int)EffectsEnum.Effect_SkipTurn) // Let say this effect counts as 2 damage per level of the target
                    ratio = target.Level * 2 * chanceToHappen;

                if (isFriend)
                    result.Curse -= 2 * ratio;
                else
                    result.Curse += ratio;
            }
            if (isFriend)
                result.Add(result); // amplify (double) effects on friends. 


            if (!isFriend && ((category & SpellCategory.Damages) > 0) && result.MinDamage > target.Stats.Health) // Enough damage to kill the target => affect an arbitrary 50% of max heal (with at least current health), so strong spells are not favored anymore. 
            {
                double ratio = Math.Max(target.Stats.MaxHealth / 2, target.Stats.Health) / result.MinDamage;
                result.Multiply(ratio);
            }

            if (spell.Template.id == 114) // Rekop
            {
                if (target.Stats.Health < 1000)
                    result.Multiply(0.1);
                else
                    if (target.Stats.Health < 2000)
                        result.Multiply(0.5);
            }

            // Damage reflection
            if (((category & SpellCategory.Damages) > 0) && result.Damage > 0 && !isFriend)
            {
                DamageType reflected = spell.GetDamageReflection(target);
                if (reflected > 0)
                {
                    if (reflected >= spellImpact.Damage) return 0; // Reflect all damages
                    result.MinHeal += reflected * 2;
                    result.MaxHeal += reflected * 2;
                }
            }

            if (spell.Template.id == 0 && (category & SpellCategory.Damages) > 0) // Weapon => consider effect of "maîtrise"
            {
                Weapon weapon = caster.Character.Inventory.GetEquippedWeapon();
                if (weapon != null)
                    foreach(var boost in caster.GetBoostWeaponDamagesEffects())
                        if (boost.weaponTypeId == weapon.typeId)
                            result.Multiply(1.0+boost.delta/100.0);
            }

            if (spellImpact != null)
                spellImpact.Add(result);
            else
                spellImpact = result;
            return result.Damage;
        }        
Beispiel #9
0
     private static void AdjustDamage(SpellImpact damages, uint damage1, uint damage2, SpellCategory category, double chanceToHappen, int addDamage, int addDamagePercent, int reduceDamage, int reduceDamagePercent, bool negativ)
     {
         DamageType minDamage = damage1;
         DamageType maxDamage = damage1 >= damage2 ? damage1 : damage2;
         if (reduceDamagePercent >= 100)
             return; // No damage
         minDamage = (DamageType)(((minDamage * (1 + (addDamagePercent / 100.0)) + addDamage) - reduceDamage) * (1 - (reduceDamagePercent / 100.0)) * chanceToHappen);
         maxDamage = (DamageType)(((maxDamage * (1 + (addDamagePercent / 100.0)) + addDamage) - reduceDamage) * (1 - (reduceDamagePercent / 100.0)) * chanceToHappen);
         
         if (minDamage < 0) minDamage = 0;
         if (maxDamage < 0) maxDamage = 0;
     
 
         if (negativ) // or IsFriend
         {
             minDamage *= -1.5; // High penalty for firing on friends
             maxDamage *= -1.5; // High penalty for firing on friends
         }
         switch (category)
         {
             case SpellCategory.DamagesNeutral:
                 damages.MinNeutral += minDamage;
                 damages.MaxNeutral += maxDamage;
                 break;
             case SpellCategory.DamagesFire:
                 damages.MinFire += minDamage;
                 damages.MaxAir += maxDamage;
                 break;
             case SpellCategory.DamagesAir:
                 damages.MinAir += minDamage;
                 damages.MaxAir += maxDamage;
                 break;
             case SpellCategory.DamagesWater:
                 damages.MinWater += minDamage;
                 damages.MaxWater += maxDamage;
                 break;
             case SpellCategory.DamagesEarth:
                 damages.MinEarth += minDamage;
                 damages.MaxEarth += maxDamage;
                 break;
             case SpellCategory.Healing:
                 damages.MinHeal += minDamage;
                 damages.MaxHeal += maxDamage;
                 break;
         }
     }
Beispiel #10
0
 public void Add(SpellImpact dmg)
 {
     MinFire += dmg.MinFire;
     MaxFire += dmg.MaxFire;
     MinWater += dmg.MinWater;
     MaxWater += dmg.MaxWater;
     MinEarth += dmg.MinEarth;
     MaxEarth += dmg.MaxEarth;
     MinAir += dmg.MinAir;
     MaxAir += dmg.MaxAir;
     MinNeutral += dmg.MinNeutral;
     MaxNeutral += dmg.MaxNeutral;
     MinHeal += dmg.MinHeal;
     MaxHeal += dmg.MaxHeal;
     Curse += dmg.Curse;
     Boost += dmg.Boost;
 }