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; } }
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); }
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); }
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; }
// 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); }
/// <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); }
// 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; }
/// <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; }
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; } }