1879 lines
No EOL
104 KiB
C#
1879 lines
No EOL
104 KiB
C#
using System;
|
|
using WingsAPI.Data.Families;
|
|
using WingsAPI.Packets.Enums.Shells;
|
|
using WingsEmu.Game._enum;
|
|
using WingsEmu.Game.Battle;
|
|
using WingsEmu.Game.Buffs;
|
|
using WingsEmu.Game.Entities;
|
|
using WingsEmu.Game.Helpers.Damages;
|
|
using WingsEmu.Game.Helpers.Damages.Calculation;
|
|
using WingsEmu.Game.Maps;
|
|
using WingsEmu.Game.Monster;
|
|
using WingsEmu.Packets.Enums;
|
|
using WingsEmu.Packets.Enums.Battle;
|
|
|
|
namespace WingsEmu.Game.Extensions;
|
|
|
|
public static class DamageExtension
|
|
{
|
|
private static readonly double[] _plus = { 0, 0.1, 0.15, 0.22, 0.32, 0.43, 0.54, 0.65, 0.9, 1.2, 2 };
|
|
private static IRandomGenerator _randomGenerator => StaticRandomGenerator.Instance;
|
|
|
|
public static bool IsMiss(this IBattleEntityDump attacker, IBattleEntityDump defender, CalculationBasicStatistics basicStatistics)
|
|
{
|
|
bool isPvP = attacker.IsPlayer() && defender.IsPlayer();
|
|
|
|
int morale = basicStatistics.AttackerMorale;
|
|
int attackerHitRate = basicStatistics.AttackerHitRate;
|
|
int targetMorale = basicStatistics.DefenderMorale;
|
|
int targetDodge = basicStatistics.DefenderDodge;
|
|
|
|
if (defender.HasBCard(BCardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.NoDefence))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (isPvP && attacker.GetShellWeaponEffectValue(ShellEffectType.NeverMissInPVP) > 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (attacker.IsMonster())
|
|
{
|
|
IBattleEntity monster = attacker.MapInstance.GetBattleEntity(attacker.Type, attacker.Id);
|
|
if (monster != null && monster is IMonsterEntity mapMonster && mapMonster.MonsterRaceType == MonsterRaceType.Fixed && mapMonster.MonsterRaceSubType == 1)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (isPvP)
|
|
{
|
|
int shellChance = attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetShellArmorEffectValue(ShellEffectType.CloseDefenceDodgeInPVP),
|
|
AttackType.Ranged => defender.GetShellArmorEffectValue(ShellEffectType.DistanceDefenceDodgeInPVP),
|
|
AttackType.Magical => defender.GetShellArmorEffectValue(ShellEffectType.IgnoreMagicDamage),
|
|
_ => 0
|
|
};
|
|
|
|
if (shellChance != 0 && _randomGenerator.RandomNumber() <= shellChance)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (attacker.AttackType == AttackType.Magical)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
shellChance = defender.GetShellArmorEffectValue(ShellEffectType.DodgeAllDamage);
|
|
if (shellChance != 0 && _randomGenerator.RandomNumber() <= shellChance)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (attacker.AttackType == AttackType.Magical)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int attackerHitRateFinal = attackerHitRate + morale * 4;
|
|
double targetDodgeFinal = targetDodge + targetMorale * 4;
|
|
double difference = attackerHitRateFinal - targetDodgeFinal;
|
|
|
|
// formula by friends111
|
|
double chance = 100 / Math.PI * Math.Atan(0.015 * difference + 2) + 50;
|
|
if (chance <= 40)
|
|
{
|
|
chance = 40;
|
|
}
|
|
|
|
double randomChance = _randomGenerator.RandomNumber() * 1.0;
|
|
if (attacker.GetBCardInformation(BCardType.GuarantedDodgeRangedAttack, (byte)AdditionalTypes.GuarantedDodgeRangedAttack.AttackHitChance).count == 0)
|
|
{
|
|
if (chance <= randomChance)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
chance = attacker.GetBCardInformation(BCardType.GuarantedDodgeRangedAttack, (byte)AdditionalTypes.GuarantedDodgeRangedAttack.AttackHitChance).firstData;
|
|
if (chance <= randomChance)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static CalculationBasicStatistics CalculateBasicStatistics(this IBattleEntityDump attacker, IBattleEntityDump defender, SkillInfo skill)
|
|
{
|
|
bool isPvP = attacker.IsPlayer() && defender.IsPlayer();
|
|
|
|
#region Attacker
|
|
|
|
int attackerMorale = attacker.Morale;
|
|
int attackerAttackUpgrade = attacker.AttackUpgrade;
|
|
int attackerHitRate = attacker.HitRate;
|
|
int attackerCriticalChance = attacker.CriticalChance;
|
|
int attackerCriticalDamage = attacker.CriticalDamage;
|
|
|
|
int attackerElementRate = attacker.ElementRate;
|
|
|
|
#endregion
|
|
|
|
#region Defender
|
|
|
|
int defenderMorale = defender.Morale;
|
|
int defenderDefenseUpgrade = defender.DefenseUpgrade;
|
|
|
|
int defenderDefense = attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.MeleeDefense,
|
|
AttackType.Ranged => defender.RangeDefense,
|
|
AttackType.Magical => defender.MagicalDefense
|
|
};
|
|
|
|
int defenderDodge = attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.MeleeDodge,
|
|
AttackType.Ranged => defender.RangeDodge,
|
|
AttackType.Magical => 0
|
|
};
|
|
|
|
int defenderResistance = attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => defender.FireResistance,
|
|
ElementType.Water => defender.WaterResistance,
|
|
ElementType.Light => defender.LightResistance,
|
|
ElementType.Shadow => defender.ShadowResistance
|
|
};
|
|
|
|
#endregion
|
|
|
|
/* MORALE */
|
|
|
|
if (!defender.HasBCard(BCardType.Morale, (byte)AdditionalTypes.Morale.LockMorale)) // 17 | 2
|
|
{
|
|
attackerMorale += attacker.GetBCardInformation(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased).firstData;
|
|
attackerMorale -= attacker.GetBCardInformation(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased).firstData;
|
|
}
|
|
|
|
if (!attacker.HasBCard(BCardType.Morale, (byte)AdditionalTypes.Morale.IgnoreEnemyMorale)) // 17 | 4
|
|
{
|
|
defenderMorale += defender.GetBCardInformation(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleIncreased).firstData;
|
|
defenderMorale -= defender.GetBCardInformation(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleDecreased).firstData;
|
|
}
|
|
|
|
if (attacker.HasBCard(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleHalved))
|
|
{
|
|
attackerMorale /= 2;
|
|
}
|
|
|
|
if (attacker.HasBCard(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleDoubled))
|
|
{
|
|
attackerMorale *= 2;
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleHalved))
|
|
{
|
|
defenderMorale /= 2;
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.Morale, (byte)AdditionalTypes.Morale.MoraleDoubled))
|
|
{
|
|
defenderMorale *= 2;
|
|
}
|
|
|
|
/* ATTACK UPGRADE */
|
|
|
|
attackerAttackUpgrade += attacker.GetBCardInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.AttackLevelIncreased).firstData;
|
|
attackerAttackUpgrade -= attacker.GetBCardInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.AttackLevelDecreased).firstData;
|
|
|
|
if (attacker.HasBCard(BCardType.CalculatingLevel, (byte)AdditionalTypes.CalculatingLevel.CalculatedAttackLevel) && attackerAttackUpgrade > 0)
|
|
{
|
|
attackerAttackUpgrade = 0;
|
|
}
|
|
|
|
/* DEFENSE UPGRADE */
|
|
|
|
defenderDefenseUpgrade += defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelIncreased).firstData;
|
|
defenderDefenseUpgrade -= defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.DefenceLevelDecreased).firstData;
|
|
|
|
if (defender.HasBCard(BCardType.CalculatingLevel, (byte)AdditionalTypes.CalculatingLevel.CalculatedDefenceLevel) && defenderDefenseUpgrade > 0)
|
|
{
|
|
defenderDefenseUpgrade = 0;
|
|
}
|
|
|
|
/* HITRATE */
|
|
|
|
attackerHitRate += attacker.GetBCardInformation(BCardType.Target, (byte)AdditionalTypes.Target.AllHitRateIncreased).firstData;
|
|
attackerHitRate -= attacker.GetBCardInformation(BCardType.Target, (byte)AdditionalTypes.Target.AllHitRateDecreased).firstData;
|
|
attackerHitRate += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.GetBCardInformation(BCardType.Target, (byte)AdditionalTypes.Target.MeleeHitRateIncreased).firstData,
|
|
AttackType.Ranged => attacker.GetBCardInformation(BCardType.Target, (byte)AdditionalTypes.Target.RangedHitRateIncreased).firstData,
|
|
_ => 0
|
|
};
|
|
|
|
attackerHitRate -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.GetBCardInformation(BCardType.Target, (byte)AdditionalTypes.Target.MeleeHitRateDecreased).firstData,
|
|
AttackType.Ranged => attacker.GetBCardInformation(BCardType.Target, (byte)AdditionalTypes.Target.RangedHitRateDecreased).firstData,
|
|
_ => 0
|
|
};
|
|
|
|
attackerHitRate += (int)(attackerHitRate * attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseSpPoints, (byte)AdditionalTypes.IncreaseSpPoints.AccuracyIncrease).firstData));
|
|
attackerHitRate -= (int)(attackerHitRate * attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseSpPoints, (byte)AdditionalTypes.IncreaseSpPoints.AccuracyDecrease).firstData));
|
|
attackerHitRate += (int)(attackerHitRate * attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.MagicShield, (byte)AdditionalTypes.MagicShield.AccuracyIncrease).firstData));
|
|
|
|
/* CRITICAL CHANCE */
|
|
|
|
attackerCriticalChance += attacker.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.InflictingIncreased).firstData;
|
|
attackerCriticalChance -= attacker.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.InflictingReduced).firstData;
|
|
|
|
attackerCriticalChance -= defender.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.DamageIncreasedInflictingReduced).firstData;
|
|
|
|
attackerCriticalChance += attacker.GetShellWeaponEffectValue(ShellEffectType.CriticalChance);
|
|
attackerCriticalChance -= defender.GetShellArmorEffectValue(ShellEffectType.ReducedCritChanceRecive);
|
|
|
|
attackerCriticalChance += defender.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.ReceivingIncreased).firstData;
|
|
attackerCriticalChance -= defender.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.ReceivingDecreased).firstData;
|
|
|
|
if (defender.IsMonster())
|
|
{
|
|
MonsterRaceType monsterRaceType = defender.MonsterRaceType;
|
|
Enum monsterRaceSubType = defender.MonsterRaceSubType;
|
|
|
|
if (attacker.HasBCard(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.IncreaseCriticalAgainst))
|
|
{
|
|
(int firstData, int secondData, int count) raceBCard =
|
|
attacker.GetBCardInformation(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.IncreaseCriticalAgainst);
|
|
|
|
int monsterRace = raceBCard.firstData;
|
|
var bCardRaceType = (MonsterRaceType)Math.Floor(monsterRace / 10.0);
|
|
Enum bCardRaceSubType = attacker.GetRaceSubType(bCardRaceType, (byte)(monsterRace % 10));
|
|
|
|
if (monsterRaceType == bCardRaceType && bCardRaceSubType != null && Equals(monsterRaceSubType, bCardRaceSubType))
|
|
{
|
|
attackerCriticalChance += raceBCard.secondData;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.SniperAttack, (byte)AdditionalTypes.SniperAttack.ReceiveCriticalFromSniper) && skill != null && skill.Vnum == (short)SkillsVnums.SNIPER)
|
|
{
|
|
attackerCriticalChance = defender.GetBCardInformation(BCardType.SniperAttack, (byte)AdditionalTypes.SniperAttack.ReceiveCriticalFromSniper).firstData;
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.InflictingChancePercent))
|
|
{
|
|
attackerCriticalChance = defender.GetBCardInformation(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.InflictingChancePercent).firstData;
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.ReceivingChancePercent))
|
|
{
|
|
attackerCriticalChance = defender.GetBCardInformation(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.ReceivingChancePercent).firstData;
|
|
}
|
|
|
|
if (attacker.HasBCard(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.AlwaysInflict))
|
|
{
|
|
attackerCriticalChance = 100;
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.AlwaysReceives))
|
|
{
|
|
attackerCriticalChance = 100;
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.NeverReceives))
|
|
{
|
|
attackerCriticalChance = 0;
|
|
}
|
|
|
|
if (attacker.HasBCard(BCardType.SpecialCritical, (byte)AdditionalTypes.SpecialCritical.NeverInflict))
|
|
{
|
|
attackerCriticalChance = 0;
|
|
}
|
|
|
|
/* CRITICAL DAMAGE */
|
|
|
|
int damageCriticalIncrease = attacker.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.DamageIncreased).firstData;
|
|
|
|
if (damageCriticalIncrease != 0)
|
|
{
|
|
damageCriticalIncrease -= defender.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.DamageIncreasedInflictingReduced).firstData;
|
|
}
|
|
|
|
attackerCriticalDamage += attacker.GetShellWeaponEffectValue(ShellEffectType.CriticalDamage);
|
|
attackerCriticalDamage += damageCriticalIncrease;
|
|
attackerCriticalDamage -= defender.GetJewelsEffectValue(CellonType.CriticalDamageDecrease);
|
|
attackerCriticalDamage += defender.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.DamageFromCriticalIncreased).firstData;
|
|
attackerCriticalDamage -= defender.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.DamageFromCriticalDecreased).firstData;
|
|
|
|
if (defender.HasBCard(BCardType.StealBuff, (byte)AdditionalTypes.StealBuff.ReduceCriticalReceivedChance))
|
|
{
|
|
(int firstData, int secondData, _) = defender.GetBCardInformation(BCardType.StealBuff, (byte)AdditionalTypes.StealBuff.ReduceCriticalReceivedChance);
|
|
if (defender.IsSucceededChance(firstData))
|
|
{
|
|
attackerCriticalDamage -= secondData;
|
|
}
|
|
}
|
|
|
|
/* ELEMENT RATE */
|
|
|
|
if (attacker.HasBCard(BCardType.IncreaseElementFairy, (byte)AdditionalTypes.IncreaseElementFairy.FairyElementIncreaseWhileAttackingChance) && attacker.Element != ElementType.Neutral)
|
|
{
|
|
(int firstData, int secondData, _) = attacker.GetBCardInformation(BCardType.IncreaseElementFairy, (byte)AdditionalTypes.IncreaseElementFairy.FairyElementIncreaseWhileAttackingChance);
|
|
if (attacker.IsSucceededChance(firstData))
|
|
{
|
|
attackerElementRate += secondData;
|
|
}
|
|
}
|
|
|
|
/* DEFENSE */
|
|
|
|
defenderDefense += defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.AllIncreased).firstData;
|
|
defenderDefense -= defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.AllDecreased).firstData;
|
|
|
|
defenderDefense += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.MeleeIncreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.RangedIncreased).firstData,
|
|
AttackType.Magical => defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.MagicalIncreased).firstData
|
|
};
|
|
|
|
defenderDefense += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetShellArmorEffectValue(ShellEffectType.CloseDefence),
|
|
AttackType.Ranged => defender.GetShellArmorEffectValue(ShellEffectType.DistanceDefence),
|
|
AttackType.Magical => defender.GetShellArmorEffectValue(ShellEffectType.MagicDefence)
|
|
};
|
|
|
|
defenderDefense -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.MeleeDecreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.RangedDecreased).firstData,
|
|
AttackType.Magical => defender.GetBCardInformation(BCardType.Defence, (byte)AdditionalTypes.Defence.MagicalDecreased).firstData
|
|
};
|
|
|
|
defenderDefense += (int)(defenderDefense * defender.GetMultiplier(defender.GetShellArmorEffectValue(ShellEffectType.PercentageTotalDefence)));
|
|
defenderDefense += (int)(defenderDefense *
|
|
defender.GetMultiplier(defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DefenceIncreased).firstData));
|
|
defenderDefense -= (int)(defenderDefense *
|
|
defender.GetMultiplier(defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DefenceReduced).firstData));
|
|
|
|
bool nullifiedDefense = attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.HasBCard(BCardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.MeleeDefenceNullified),
|
|
AttackType.Ranged => defender.HasBCard(BCardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.RangedDefenceNullified),
|
|
AttackType.Magical => defender.HasBCard(BCardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.MagicDefenceNullified)
|
|
};
|
|
|
|
if (nullifiedDefense)
|
|
{
|
|
defenderDefense = 0;
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.SpecialDefence, (byte)AdditionalTypes.SpecialDefence.AllDefenceNullified))
|
|
{
|
|
defenderDefense = 0;
|
|
}
|
|
|
|
/* DODGE */
|
|
|
|
defenderDodge += defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgeIncreased).firstData;
|
|
defenderDodge -= defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgeDecreased).firstData;
|
|
|
|
defenderDodge += (int)(defenderDodge * defender.GetMultiplier(defender.GetBCardInformation(BCardType.MagicShield, (byte)AdditionalTypes.MagicShield.DodgeIncrease).firstData));
|
|
|
|
defenderDodge += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgingMeleeIncreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgingRangedIncreased).firstData,
|
|
AttackType.Magical => 0
|
|
};
|
|
|
|
defenderDodge -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgingMeleeDecreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.DodgeAndDefencePercent, (byte)AdditionalTypes.DodgeAndDefencePercent.DodgingRangedDecreased).firstData,
|
|
AttackType.Magical => 0
|
|
};
|
|
|
|
/* RESISTANCE */
|
|
|
|
defenderResistance -= attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllDecreased).firstData;
|
|
defenderResistance -= attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.FireDecreased).firstData,
|
|
ElementType.Water => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.WaterDecreased).firstData,
|
|
ElementType.Light => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.LightDecreased).firstData,
|
|
ElementType.Shadow => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.DarkDecreased).firstData
|
|
};
|
|
|
|
defenderResistance += attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.AllIncreased).firstData;
|
|
defenderResistance += attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.FireIncreased).firstData,
|
|
ElementType.Water => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.WaterIncreased).firstData,
|
|
ElementType.Light => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.LightIncreased).firstData,
|
|
ElementType.Shadow => attacker.GetBCardInformation(BCardType.EnemyElementResistance, (byte)AdditionalTypes.EnemyElementResistance.DarkIncreased).firstData
|
|
};
|
|
|
|
defenderResistance -= defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllDecreased).firstData;
|
|
defenderResistance -= attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireDecreased).firstData,
|
|
ElementType.Water => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterDecreased).firstData,
|
|
ElementType.Light => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightDecreased).firstData,
|
|
ElementType.Shadow => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkDecreased).firstData
|
|
};
|
|
|
|
defenderResistance += defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.AllIncreased).firstData;
|
|
defenderResistance += attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.FireIncreased).firstData,
|
|
ElementType.Water => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.WaterIncreased).firstData,
|
|
ElementType.Light => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.LightIncreased).firstData,
|
|
ElementType.Shadow => defender.GetBCardInformation(BCardType.ElementResistance, (byte)AdditionalTypes.ElementResistance.DarkIncreased).firstData
|
|
};
|
|
|
|
defenderResistance += defender.GetShellArmorEffectValue(ShellEffectType.IncreasedAllResistance);
|
|
defenderResistance += attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => defender.GetShellArmorEffectValue(ShellEffectType.IncreasedFireResistance),
|
|
ElementType.Water => defender.GetShellArmorEffectValue(ShellEffectType.IncreasedWaterResistance),
|
|
ElementType.Light => defender.GetShellArmorEffectValue(ShellEffectType.IncreasedLightResistance),
|
|
ElementType.Shadow => defender.GetShellArmorEffectValue(ShellEffectType.IncreasedDarkResistance)
|
|
};
|
|
|
|
defenderResistance += attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => defender.GetFamilyUpgradeValue(FamilyUpgradeType.FIRE_RESISTANCE),
|
|
ElementType.Water => defender.GetFamilyUpgradeValue(FamilyUpgradeType.WATER_RESISTANCE),
|
|
ElementType.Light => defender.GetFamilyUpgradeValue(FamilyUpgradeType.LIGHT_RESISTANCE),
|
|
ElementType.Shadow => defender.GetFamilyUpgradeValue(FamilyUpgradeType.DARK_RESISTANCE)
|
|
};
|
|
|
|
defenderResistance += (int)(defenderResistance *
|
|
defender.GetMultiplier(defender.GetBCardInformation(BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.AllElementResisIncrease).firstData));
|
|
defenderResistance -= (int)(defenderResistance *
|
|
defender.GetMultiplier(defender.GetBCardInformation(BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.AllElementResisDecrease).firstData));
|
|
|
|
defenderResistance += attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.FireElementResisIncrease).firstData)),
|
|
ElementType.Water => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.WaterElementResisIncrease).firstData)),
|
|
ElementType.Light => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.LightElementResisIncrease).firstData)),
|
|
ElementType.Shadow => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.ShadowElementResisIncrease).firstData))
|
|
};
|
|
|
|
defenderResistance -= attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.FireElementResisDecrease).firstData)),
|
|
ElementType.Water => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.WaterElementResisDecrease).firstData)),
|
|
ElementType.Light => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.LightElementResisDecrease).firstData)),
|
|
ElementType.Shadow => (int)(defenderResistance * defender.GetMultiplier(defender.GetBCardInformation(
|
|
BCardType.IncreaseElementByResis, (byte)AdditionalTypes.IncreaseElementByResis.ShadowElementResisDecrease).firstData))
|
|
};
|
|
|
|
if (isPvP)
|
|
{
|
|
defenderResistance -= (int)(defenderResistance * attacker.GetShellWeaponEffectValue(ShellEffectType.ReducesEnemyAllResistancesInPVP) * 0.01);
|
|
defenderResistance -= attacker.Element switch
|
|
{
|
|
ElementType.Neutral => 0,
|
|
ElementType.Fire => (int)(defenderResistance * attacker.GetShellWeaponEffectValue(ShellEffectType.ReducesEnemyFireResistanceInPVP) * 0.01),
|
|
ElementType.Water => (int)(defenderResistance * attacker.GetShellWeaponEffectValue(ShellEffectType.ReducesEnemyWaterResistanceInPVP) * 0.01),
|
|
ElementType.Light => (int)(defenderResistance * attacker.GetShellWeaponEffectValue(ShellEffectType.ReducesEnemyLightResistanceInPVP) * 0.01),
|
|
ElementType.Shadow => (int)(defenderResistance * attacker.GetShellWeaponEffectValue(ShellEffectType.ReducesEnemyDarkResistanceInPVP) * 0.01)
|
|
};
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.AllResistancesNullified))
|
|
{
|
|
defenderResistance = 0;
|
|
}
|
|
|
|
bool removeResistance = attacker.Element switch
|
|
{
|
|
ElementType.Neutral => false,
|
|
ElementType.Fire => defender.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.FireResistanceNullified),
|
|
ElementType.Water => defender.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.WaterResistanceNullified),
|
|
ElementType.Light => defender.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.LightResistanceNullified),
|
|
ElementType.Shadow => defender.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.DarkResistanceNullified)
|
|
};
|
|
|
|
if (removeResistance)
|
|
{
|
|
defenderResistance = 0;
|
|
}
|
|
|
|
return new CalculationBasicStatistics
|
|
{
|
|
AttackerMorale = attackerMorale,
|
|
AttackerAttackUpgrade = attackerAttackUpgrade,
|
|
AttackerHitRate = attackerHitRate,
|
|
AttackerCriticalChance = attackerCriticalChance,
|
|
AttackerCriticalDamage = attackerCriticalDamage,
|
|
AttackerElementRate = attackerElementRate,
|
|
DefenderMorale = defenderMorale,
|
|
DefenderDefenseUpgrade = defenderDefenseUpgrade,
|
|
DefenderDefense = defenderDefense,
|
|
DefenderDodge = defenderDodge,
|
|
DefenderResistance = defenderResistance
|
|
};
|
|
}
|
|
|
|
public static CalculationPhysicalDamage CalculatePhysicalDamage(this IBattleEntityDump attacker, IBattleEntityDump defender, SkillInfo skill)
|
|
{
|
|
bool isPvP = attacker.IsPlayer() && defender.IsPlayer();
|
|
|
|
double damagePercentage = 1;
|
|
double damagePercentageSecond = 0;
|
|
double ignoreEnemyDefense = 1;
|
|
double vesselLodDamage = 1;
|
|
double vesselGlacernonDamage = 1;
|
|
double increaseAllDamage = 1;
|
|
double increaseAllDamageAttackType = 1;
|
|
double increaseDamageMagicDefense = 0;
|
|
int increaseDamageRace = 0;
|
|
double increaseDamageRacePercentage = 1;
|
|
double increaseLoDDamage = 1;
|
|
double increaseVesselDamage = 1;
|
|
double increaseDamageFaction = 1;
|
|
double increaseDamageInPvP = 1;
|
|
double increaseDamageVersusMonstersMapType = 1;
|
|
double increaseAllDamageVersusMonsters = 1;
|
|
|
|
/* DAMAGE */
|
|
int damage = attacker.TryFindPartnerSkillInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksIncreased, skill).firstData;
|
|
damage -= attacker.GetBCardInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.AllAttacksDecreased).firstData;
|
|
|
|
damage += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.TryFindPartnerSkillInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksIncreased, skill).firstData,
|
|
AttackType.Ranged => attacker.TryFindPartnerSkillInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.RangedAttacksIncreased, skill).firstData,
|
|
AttackType.Magical => attacker.TryFindPartnerSkillInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.MagicalAttacksIncreased, skill).firstData
|
|
};
|
|
|
|
damage -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.GetBCardInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.MeleeAttacksDecreased).firstData,
|
|
AttackType.Ranged => attacker.GetBCardInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.RangedAttacksDecreased).firstData,
|
|
AttackType.Magical => attacker.GetBCardInformation(BCardType.AttackPower, (byte)AdditionalTypes.AttackPower.MagicalAttacksDecreased).firstData
|
|
};
|
|
|
|
if (isPvP)
|
|
{
|
|
damage += attacker.GetBCardInformation(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.IncreaseDamageInPVP).firstData;
|
|
damage -= attacker.GetBCardInformation(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.DecreaseDamageInPVP).firstData;
|
|
}
|
|
|
|
/* DAMAGE PERCENTAGE */
|
|
if (attacker.HasBCard(BCardType.Critical, (byte)AdditionalTypes.Critical.DamageIncreasingChance))
|
|
{
|
|
(int firstData, int secondData, _) = attacker.GetBCardInformation(BCardType.Critical, (byte)AdditionalTypes.Critical.DamageIncreasingChance);
|
|
if (attacker.IsSucceededChance(firstData))
|
|
{
|
|
damagePercentage *= 1 + secondData * 0.01;
|
|
}
|
|
}
|
|
|
|
/* DAMAGE PERCENTAGE - SOFT DAMAGE */
|
|
if (attacker.HasBCard(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.IncreasingProbability))
|
|
{
|
|
(int firstData, int secondData, _) = attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.IncreasingProbability);
|
|
if (attacker.IsSucceededChance(firstData))
|
|
{
|
|
damagePercentageSecond = secondData * 0.01;
|
|
}
|
|
}
|
|
|
|
if (damagePercentageSecond != 0)
|
|
{
|
|
if (attacker.HasBCard(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.DecreasingProbability))
|
|
{
|
|
(int firstData, int secondData, _) = attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.DecreasingProbability);
|
|
if (attacker.IsSucceededChance(firstData))
|
|
{
|
|
damagePercentageSecond = secondData * 0.01 <= 0 ? 0 : damagePercentageSecond - secondData * 0.01;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* MULTIPLY DAMAGE */
|
|
double multiplyDamage = 1;
|
|
int multiplyDamageInt = attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.AllAttackIncreased).firstData;
|
|
multiplyDamageInt += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.MeleeAttackIncreased).firstData,
|
|
AttackType.Ranged => attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.RangedAttackIncreased).firstData,
|
|
AttackType.Magical => attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.MagicalAttackIncreased).firstData
|
|
};
|
|
|
|
multiplyDamageInt -= attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.AllAttackDecreased).firstData;
|
|
multiplyDamageInt -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.MeleeAttackDecreased).firstData,
|
|
AttackType.Ranged => attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.RangedAttackDecreased).firstData,
|
|
AttackType.Magical => attacker.GetBCardInformation(BCardType.MultAttack, (byte)AdditionalTypes.MultAttack.MagicalAttackDecreased).firstData
|
|
};
|
|
|
|
multiplyDamage = multiplyDamageInt == 0 ? 1 : multiplyDamageInt;
|
|
|
|
/* INVISIBLE DAMAGE */
|
|
int invisibleDamage = attacker.IsInvisible() ? attacker.GetBCardInformation(BCardType.LightAndShadow, (byte)AdditionalTypes.LightAndShadow.AdditionalDamageWhenHidden).firstData : 0;
|
|
|
|
/* END CRITICAL DAMAGE */
|
|
double endCriticalDamage = 1;
|
|
endCriticalDamage += attacker.GetBCardInformation(BCardType.Count, (byte)AdditionalTypes.Count.IncreaseCritAttackOnEnd).firstData;
|
|
|
|
/* INCREASE DAMAGE BY RACE */
|
|
if (defender.IsMonster())
|
|
{
|
|
MonsterRaceType monsterRaceType = defender.MonsterRaceType;
|
|
Enum monsterRaceSubType = defender.MonsterRaceSubType;
|
|
|
|
int monsterRace;
|
|
|
|
MonsterRaceType bCardRaceType;
|
|
Enum bCardRaceSubType;
|
|
if (attacker.HasBCard(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.IncreaseDamageAgainst))
|
|
{
|
|
(int firstData, int secondData, int count) raceBCard =
|
|
attacker.GetBCardInformation(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.IncreaseDamageAgainst);
|
|
|
|
monsterRace = raceBCard.firstData;
|
|
bCardRaceType = (MonsterRaceType)Math.Floor(monsterRace / 10.0);
|
|
bCardRaceSubType = attacker.GetRaceSubType(bCardRaceType, (byte)(monsterRace % 10));
|
|
|
|
if (monsterRaceType == bCardRaceType && bCardRaceSubType != null && Equals(monsterRaceSubType, bCardRaceSubType))
|
|
{
|
|
increaseDamageRace += raceBCard.secondData;
|
|
}
|
|
}
|
|
|
|
if (attacker.HasBCard(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.IncreaseDamageAgainst))
|
|
{
|
|
(int firstData, int secondData, int count) raceBCard =
|
|
attacker.GetBCardInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.IncreaseDamageAgainst);
|
|
|
|
monsterRace = raceBCard.firstData;
|
|
bCardRaceType = (MonsterRaceType)Math.Floor(monsterRace / 10.0);
|
|
bCardRaceSubType = attacker.GetRaceSubType(bCardRaceType, (byte)(monsterRace % 10));
|
|
|
|
if (monsterRaceType == bCardRaceType && bCardRaceSubType != null && Equals(monsterRaceSubType, bCardRaceSubType))
|
|
{
|
|
increaseDamageRacePercentage += raceBCard.secondData * 0.01;
|
|
}
|
|
}
|
|
|
|
switch (monsterRaceSubType)
|
|
{
|
|
case MonsterSubRace.LowLevel.Animal:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedSmallMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedAnimal) * 0.01;
|
|
break;
|
|
case MonsterSubRace.HighLevel.Animal:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedBigMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedAnimal) * 0.01;
|
|
break;
|
|
case MonsterSubRace.LowLevel.Plant:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedSmallMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedPlant) * 0.01;
|
|
break;
|
|
case MonsterSubRace.HighLevel.Plant:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedBigMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedPlant) * 0.01;
|
|
break;
|
|
case MonsterSubRace.LowLevel.Monster:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedSmallMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedEnemy) * 0.01;
|
|
break;
|
|
case MonsterSubRace.HighLevel.Monster:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedBigMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedEnemy) * 0.01;
|
|
break;
|
|
case MonsterSubRace.Undead.LowLevelUndead:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedSmallMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedUnDead) * 0.01;
|
|
break;
|
|
case MonsterSubRace.Undead.HighLevelUndead:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedBigMonster) * 0.01;
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedUnDead) * 0.01;
|
|
break;
|
|
case MonsterSubRace.Undead.Vampire:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedUnDead) * 0.01;
|
|
break;
|
|
case MonsterSubRace.Spirits.LowLevelGhost:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedSmallMonster) * 0.01;
|
|
break;
|
|
case MonsterSubRace.Spirits.HighLevelGhost:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedBigMonster) * 0.01;
|
|
break;
|
|
case MonsterSubRace.Spirits.LowLevelSpirit:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedSmallMonster) * 0.01;
|
|
break;
|
|
case MonsterSubRace.Spirits.HighLevelSpirit:
|
|
increaseDamageRacePercentage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageIncreasedBigMonster) * 0.01;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* DECREASE DAMAGE BY RACE */
|
|
if (defender.IsPlayer() && defender.HasBCard(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.ReduceDamageAgainst))
|
|
{
|
|
(int firstData, int secondData, int count) raceBCard =
|
|
defender.GetBCardInformation(BCardType.SpecialisationBuffResistance, (byte)AdditionalTypes.SpecialisationBuffResistance.ReduceDamageAgainst);
|
|
|
|
int monsterRace = raceBCard.firstData;
|
|
var bCardRaceType = (MonsterRaceType)Math.Floor(monsterRace / 10.0);
|
|
Enum bCardRaceSubType = attacker.GetRaceSubType(bCardRaceType, (byte)(monsterRace % 10));
|
|
|
|
if (attacker.MonsterRaceType == bCardRaceType && bCardRaceSubType != null && Equals(attacker.MonsterRaceSubType, bCardRaceSubType))
|
|
{
|
|
increaseDamageRace -= raceBCard.secondData;
|
|
}
|
|
}
|
|
|
|
/* IGNORE DEFENDER DEFENSE */
|
|
if (attacker.HasBCard(BCardType.StealBuff, (byte)AdditionalTypes.StealBuff.IgnoreDefenceChance))
|
|
{
|
|
(int firstData, int secondData, _) = attacker.GetBCardInformation(BCardType.StealBuff, (byte)AdditionalTypes.StealBuff.IgnoreDefenceChance);
|
|
if (attacker.IsSucceededChance(firstData))
|
|
{
|
|
ignoreEnemyDefense -= secondData * 0.01;
|
|
attacker.BroadcastEffect(EffectType.IgnoreDefence);
|
|
}
|
|
}
|
|
|
|
/* INCREASE DAMAGE BY FACTION */
|
|
if (isPvP)
|
|
{
|
|
(int firstData, int secondData, int count) factionBCard;
|
|
|
|
switch (attacker.Faction)
|
|
{
|
|
case FactionType.Angel:
|
|
factionBCard = attacker.GetBCardInformation(BCardType.ChangingPlace, (byte)AdditionalTypes.ChangingPlace.IncreaseDamageVersusDemons);
|
|
increaseDamageFaction += factionBCard.firstData * 0.01;
|
|
break;
|
|
case FactionType.Demon:
|
|
factionBCard = attacker.GetBCardInformation(BCardType.ChangingPlace, (byte)AdditionalTypes.ChangingPlace.IncreaseDamageVersusAngels);
|
|
increaseDamageFaction += factionBCard.firstData * 0.01;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* INCREASE DAMAGE VS VESSEL MONSTERS */
|
|
if (defender.IsMonster())
|
|
{
|
|
bool isVesselMonster = defender is NpcMonsterEntityDump { IsVesselMonster: true };
|
|
if (isVesselMonster)
|
|
{
|
|
(int firstData, int secondData, int count) vesselBCard =
|
|
attacker.GetBCardInformation(BCardType.IncreaseDamageVersus, (byte)AdditionalTypes.IncreaseDamageVersus.VesselAndLodMobDamageIncrease);
|
|
vesselLodDamage += vesselBCard.firstData * 0.01;
|
|
|
|
vesselBCard = attacker.GetBCardInformation(BCardType.IncreaseDamageVersus, (byte)AdditionalTypes.IncreaseDamageVersus.VesselAndFrozenCrownMobDamageIncrease);
|
|
vesselGlacernonDamage += vesselBCard.firstData * 0.01;
|
|
|
|
vesselBCard = attacker.GetBCardInformation(BCardType.IncreaseDamageInLoD, (byte)AdditionalTypes.IncreaseDamageInLoD.VesselMonstersAttackIncrease);
|
|
increaseVesselDamage += vesselBCard.firstData * 0.01;
|
|
}
|
|
}
|
|
|
|
/* INCREASE DAMAGE VS LOD MONSTERS */
|
|
if (attacker.MapInstance.MapId == (short)MapIds.LAND_OF_DEATH)
|
|
{
|
|
(int firstData, int secondData, int count)
|
|
lodBCard = attacker.GetBCardInformation(BCardType.IncreaseDamageVersus, (byte)AdditionalTypes.IncreaseDamageVersus.VesselAndLodMobDamageIncrease);
|
|
|
|
vesselLodDamage += lodBCard.secondData * 0.01;
|
|
|
|
lodBCard = attacker.GetBCardInformation(BCardType.IncreaseDamageInLoD, (byte)AdditionalTypes.IncreaseDamageInLoD.LodMonstersAttackIncrease);
|
|
increaseLoDDamage += lodBCard.firstData * 0.01;
|
|
}
|
|
|
|
/* INCREASE ALL DAMAGE */
|
|
increaseAllDamage += attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.AllAttackIncrease).firstData);
|
|
increaseAllDamage -= attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.AllAttackDecrease).firstData);
|
|
|
|
/* INCREASE ALL DAMAGE BY ATTACK TYPE */
|
|
increaseAllDamageAttackType += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.MeleeAttackIncrease).firstData),
|
|
AttackType.Ranged => attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.RangeAttackIncrease).firstData),
|
|
AttackType.Magical => attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.MagicAttackIncrease).firstData)
|
|
};
|
|
|
|
increaseAllDamageAttackType -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.MeleeAttackDecrease).firstData),
|
|
AttackType.Ranged => attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.RangeAttackDecrease).firstData),
|
|
AttackType.Magical => attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseAllDamage, (byte)AdditionalTypes.IncreaseAllDamage.MagicAttackDecrease).firstData)
|
|
};
|
|
|
|
/* INCREASE ALL DAMAGE BY MAGIC DEFENSE */
|
|
increaseDamageMagicDefense += attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.ReflectDamage, (byte)AdditionalTypes.ReflectDamage.AllAttackIncreasePerMagicDefense).firstData);
|
|
|
|
/* INCREASE/DECREASE PVP DAMAGE */
|
|
(int firstData, int secondData, int count) pvpBCard = attacker.GetBCardInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.AttackIncreasedInPVP);
|
|
if (isPvP)
|
|
{
|
|
increaseDamageInPvP += pvpBCard.firstData * 0.01;
|
|
increaseDamageInPvP += attacker.GetShellWeaponEffectValue(ShellEffectType.PercentageDamageInPVP) * 0.01;
|
|
if (attacker.MapInstance.MapInstanceType == MapInstanceType.RainbowBattle)
|
|
{
|
|
increaseDamageInPvP += attacker.GetBCardInformation(BCardType.IncreaseDamageVersus, (byte)AdditionalTypes.IncreaseDamageVersus.PvpDamageAndSpeedRainbowBattleIncrease).firstData * 0.01;
|
|
}
|
|
|
|
pvpBCard = attacker.GetBCardInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.AttackDecreasedInPVP);
|
|
increaseDamageInPvP -= pvpBCard.firstData * 0.01;
|
|
increaseDamageInPvP -= defender.GetShellWeaponEffectValue(ShellEffectType.PercentageAllPVPDefence) * 0.01;
|
|
}
|
|
else
|
|
{
|
|
if (pvpBCard.secondData == 1)
|
|
{
|
|
increaseDamageInPvP -= pvpBCard.firstData * 0.01;
|
|
}
|
|
}
|
|
|
|
/* INCREASE/DECRASE ATTACK */
|
|
double increaseAttack = 1;
|
|
(int firstData, int secondData, int count) attackBCard = defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.DamageIncreased);
|
|
increaseAttack += defender.GetMultiplier(attackBCard.firstData);
|
|
|
|
attackBCard = defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.DamageDecreased);
|
|
increaseAttack -= defender.GetMultiplier(attackBCard.firstData);
|
|
|
|
/* INCREASE/DECREASE ATTACK BY ATTACK TYPE*/
|
|
double increaseAttackAttackType = 1;
|
|
increaseAttackAttackType += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.MeleeIncreased).firstData),
|
|
AttackType.Ranged => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.RangedIncreased).firstData),
|
|
AttackType.Magical => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.MagicalIncreased).firstData)
|
|
};
|
|
|
|
increaseAttackAttackType -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.MeleeDecreased).firstData),
|
|
AttackType.Ranged => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.RangedDecreased).firstData),
|
|
AttackType.Magical => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Damage, (byte)AdditionalTypes.Damage.MagicalDecreased).firstData)
|
|
};
|
|
|
|
/* INCREASE SHADOW ATTACK */
|
|
double increaseDamageShadowFairy = 1;
|
|
if (attacker.Element == ElementType.Shadow)
|
|
{
|
|
(int firstData, int secondData, int count) shadowBCard =
|
|
attacker.GetBCardInformation(BCardType.DarkCloneSummon, (byte)AdditionalTypes.DarkCloneSummon.DarkElementDamageIncreaseChance);
|
|
|
|
if (attacker.IsSucceededChance(shadowBCard.firstData))
|
|
{
|
|
increaseDamageShadowFairy += shadowBCard.secondData * 0.01;
|
|
}
|
|
}
|
|
|
|
/* INCREASE ALL ATTACKS */
|
|
double increaseAllAttacks = 1 + attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.Item, (byte)AdditionalTypes.Item.AttackIncreased).firstData);
|
|
|
|
double markOfDeath = 1;
|
|
double knockdown = 1;
|
|
double loserSigh = 1;
|
|
double comboSkill = 1;
|
|
|
|
if (skill != null)
|
|
{
|
|
if (defender.HasBuff((int)BuffVnums.MARK_OF_DEATH) && skill.Vnum == (int)SkillsVnums.SPIRIT_SPLITTER)
|
|
{
|
|
markOfDeath = 3;
|
|
}
|
|
|
|
if (defender.HasBuff((int)BuffVnums.KNOCKDOWN) && skill.Vnum == (int)SkillsVnums.EXECUTION)
|
|
{
|
|
knockdown = 1.2;
|
|
}
|
|
|
|
if (defender.HasBuff((int)BuffVnums.LOSER_SIGH) && skill.Vnum == (int)SkillsVnums.EXECUTION)
|
|
{
|
|
loserSigh = 1.4;
|
|
}
|
|
|
|
if (skill.IsComboSkill && defender.HasBCard(BCardType.DamageConvertingSkill, (byte)AdditionalTypes.DamageConvertingSkill.AdditionalDamageCombo))
|
|
{
|
|
comboSkill += defender.GetMultiplier(defender.GetBCardInformation(BCardType.DamageConvertingSkill, (byte)AdditionalTypes.DamageConvertingSkill.AdditionalDamageCombo).firstData);
|
|
}
|
|
}
|
|
|
|
double damageFromDebuff = markOfDeath * knockdown * loserSigh * comboSkill;
|
|
|
|
/* INCREASE DAMAGE VS HIGH MONSTERS*/
|
|
double increaseDamageHighMonsters = 0;
|
|
if (defender.IsMonster() && defender.Level > attacker.Level && attacker.HasBCard(BCardType.EffectSummon, (byte)AdditionalTypes.EffectSummon.IfMobHigherLevelDamageIncrease))
|
|
{
|
|
(int firstData, int secondData, int count) increaseDamageMonsterBCard =
|
|
attacker.GetBCardInformation(BCardType.EffectSummon, (byte)AdditionalTypes.EffectSummon.IfMobHigherLevelDamageIncrease);
|
|
if (attacker.IsSucceededChance(increaseDamageMonsterBCard.firstData))
|
|
{
|
|
increaseDamageHighMonsters += attacker.GetMultiplier(increaseDamageMonsterBCard.secondData);
|
|
}
|
|
}
|
|
|
|
/* INCREASE ALL ATTACKS VERSUS MONSTERS */
|
|
if (!isPvP)
|
|
{
|
|
increaseAllDamageVersusMonsters += attacker.GetBCardInformation(BCardType.IncreaseElementFairy, (byte)AdditionalTypes.IncreaseElementFairy.DamageToMonstersIncrease).firstData * 0.01;
|
|
increaseAllDamageVersusMonsters -= attacker.GetBCardInformation(BCardType.IncreaseElementFairy, (byte)AdditionalTypes.IncreaseElementFairy.DamageToMonstersDecrease).firstData * 0.01;
|
|
}
|
|
|
|
return new CalculationPhysicalDamage
|
|
{
|
|
CleanDamage = damage,
|
|
DamagePercentage = damagePercentage,
|
|
DamagePercentageSecond = damagePercentageSecond,
|
|
MultiplyDamage = multiplyDamage,
|
|
EndCriticalDamage = endCriticalDamage,
|
|
IgnoreEnemyDefense = ignoreEnemyDefense,
|
|
VesselLoDDamage = vesselLodDamage,
|
|
VesselGlacernonDamage = vesselGlacernonDamage,
|
|
IncreaseAllDamage = increaseAllDamage,
|
|
IncreaseAllDamageAttackType = increaseAllDamageAttackType,
|
|
IncreaseDamageMagicDefense = increaseDamageMagicDefense,
|
|
IncreaseDamageRace = increaseDamageRace,
|
|
IncreaseDamageRacePercentage = increaseDamageRacePercentage,
|
|
IncreaseLoDDamage = increaseLoDDamage,
|
|
IncreaseVesselDamage = increaseVesselDamage,
|
|
IncreaseDamageFaction = increaseDamageFaction,
|
|
InvisibleDamage = invisibleDamage,
|
|
IncreaseDamageInPvP = increaseDamageInPvP,
|
|
IncreaseAttack = increaseAttack,
|
|
IncreaseAttackAttackType = increaseAttackAttackType,
|
|
IncreaseDamageShadowFairy = increaseDamageShadowFairy,
|
|
IncreaseAllAttacks = increaseAllAttacks,
|
|
IncreaseDamageByDebuffs = damageFromDebuff,
|
|
IncreaseDamageHighMonsters = increaseDamageHighMonsters,
|
|
IncreaseDamageVersusMonsters = increaseDamageVersusMonstersMapType,
|
|
IncreaseAllAttacksVersusMonsters = increaseAllDamageVersusMonsters
|
|
};
|
|
}
|
|
|
|
public static CalculationElementDamage CalculateElementDamage(this IBattleEntityDump attacker, IBattleEntityDump defender, SkillInfo skill)
|
|
{
|
|
int element = 0;
|
|
double elementMultiply = 0;
|
|
|
|
if (attacker.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.AllPowersNullified))
|
|
{
|
|
return new CalculationElementDamage();
|
|
}
|
|
|
|
if (skill != null && skill.Element != (byte)attacker.Element)
|
|
{
|
|
return new CalculationElementDamage();
|
|
}
|
|
|
|
bool turnOffElement = attacker.Element switch
|
|
{
|
|
ElementType.Neutral => true,
|
|
ElementType.Fire => attacker.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.FireElementNullified),
|
|
ElementType.Water => attacker.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.WaterElementNullified),
|
|
ElementType.Light => attacker.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.LightElementNullified),
|
|
ElementType.Shadow => attacker.HasBCard(BCardType.NoCharacteristicValue, (byte)AdditionalTypes.NoCharacteristicValue.DarkElementNullified)
|
|
};
|
|
|
|
if (turnOffElement)
|
|
{
|
|
return new CalculationElementDamage();
|
|
}
|
|
|
|
switch (attacker.Element)
|
|
{
|
|
case ElementType.Fire:
|
|
element += attacker.TryFindPartnerSkillInformation(BCardType.Element, (byte)AdditionalTypes.Element.FireIncreased, skill).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.Element, (byte)AdditionalTypes.Element.FireDecreased).firstData;
|
|
element += attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.FireIncreased).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.FireDecreased).firstData;
|
|
element += attacker.GetShellWeaponEffectValue(ShellEffectType.IncreasedFireProperties);
|
|
element += (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.FireElementIncrease).firstData));
|
|
element -= (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.FireElementDecrease).firstData));
|
|
break;
|
|
case ElementType.Water:
|
|
element += attacker.TryFindPartnerSkillInformation(BCardType.Element, (byte)AdditionalTypes.Element.WaterIncreased, skill).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.Element, (byte)AdditionalTypes.Element.WaterDecreased).firstData;
|
|
element += attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.WaterIncreased).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.WaterDecreased).firstData;
|
|
element += attacker.GetShellWeaponEffectValue(ShellEffectType.IncreasedWaterProperties);
|
|
element += (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.WaterElementIncrease).firstData));
|
|
element -= (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.WaterElementDecrease).firstData));
|
|
break;
|
|
case ElementType.Light:
|
|
element += attacker.TryFindPartnerSkillInformation(BCardType.Element, (byte)AdditionalTypes.Element.LightIncreased, skill).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.Element, (byte)AdditionalTypes.Element.LightDecreased).firstData;
|
|
element += attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.LightIncreased).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.LightDecreased).firstData;
|
|
element += attacker.GetShellWeaponEffectValue(ShellEffectType.IncreasedLightProperties);
|
|
element += (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.LightElementIncrease).firstData));
|
|
element -= (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.LightElementDecrease).firstData));
|
|
|
|
break;
|
|
case ElementType.Shadow:
|
|
element += attacker.TryFindPartnerSkillInformation(BCardType.Element, (byte)AdditionalTypes.Element.DarkIncreased, skill).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.Element, (byte)AdditionalTypes.Element.DarkDecreased).firstData;
|
|
element += attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.DarkIncreased).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.IncreaseDamage, (byte)AdditionalTypes.IncreaseDamage.DarkDecreased).firstData;
|
|
element += attacker.GetShellWeaponEffectValue(ShellEffectType.IncreasedDarkProperties);
|
|
element += (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.ShadowElementIncrease).firstData));
|
|
element -= (int)(element *
|
|
attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.ShadowElementDecrease).firstData));
|
|
break;
|
|
case ElementType.Neutral:
|
|
return new CalculationElementDamage();
|
|
}
|
|
|
|
element += attacker.GetBCardInformation(BCardType.Element, (byte)AdditionalTypes.Element.AllIncreased).firstData;
|
|
element -= attacker.GetBCardInformation(BCardType.Element, (byte)AdditionalTypes.Element.AllDecreased).firstData;
|
|
element += attacker.GetShellWeaponEffectValue(ShellEffectType.IncreasedElementalProperties);
|
|
element += (int)(element * attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.AllElementIncrease).firstData));
|
|
element -= (int)(element * attacker.GetMultiplier(attacker.GetBCardInformation(BCardType.IncreaseElementProcent, (byte)AdditionalTypes.IncreaseElementProcent.AllElementDecrease).firstData));
|
|
|
|
elementMultiply = attacker.Element switch
|
|
{
|
|
ElementType.Fire => defender.Element switch
|
|
{
|
|
ElementType.Neutral => 1.3,
|
|
ElementType.Fire => 1,
|
|
ElementType.Water => 3,
|
|
ElementType.Light => 1,
|
|
ElementType.Shadow => 1.5
|
|
},
|
|
ElementType.Water => defender.Element switch
|
|
{
|
|
ElementType.Neutral => 1.3,
|
|
ElementType.Fire => 3,
|
|
ElementType.Water => 1,
|
|
ElementType.Light => 1.5,
|
|
ElementType.Shadow => 1
|
|
},
|
|
ElementType.Light => defender.Element switch
|
|
{
|
|
ElementType.Neutral => 1.3,
|
|
ElementType.Fire => 1.5,
|
|
ElementType.Water => 1,
|
|
ElementType.Light => 1,
|
|
ElementType.Shadow => 3
|
|
},
|
|
ElementType.Shadow => defender.Element switch
|
|
{
|
|
ElementType.Neutral => 1.3,
|
|
ElementType.Fire => 1,
|
|
ElementType.Water => 1.5,
|
|
ElementType.Light => 3,
|
|
ElementType.Shadow => 1
|
|
},
|
|
_ => elementMultiply
|
|
};
|
|
|
|
return new CalculationElementDamage
|
|
{
|
|
Element = element,
|
|
ElementMultiply = elementMultiply
|
|
};
|
|
}
|
|
|
|
public static CalculationDefense CalculationDefense(this IBattleEntityDump attacker, IBattleEntityDump defender)
|
|
{
|
|
double increaseDefense = 1;
|
|
double increaseDefenseAttackType = 1;
|
|
(int, double) increaseDefenseByLevel = (0, 1);
|
|
(int, double) increaseDefenseByLevelAttackType = (0, 1);
|
|
double increaseAllDefense = 1;
|
|
double increaseDefenseInPve = 1;
|
|
|
|
if (defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceAllIncreased))
|
|
{
|
|
(int firstData, int secondData, _) = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceAllIncreased);
|
|
if (defender.IsSucceededChance(firstData))
|
|
{
|
|
increaseDefense += secondData * 0.01;
|
|
}
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceAllDecreased))
|
|
{
|
|
(int firstData, int secondData, _) = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceAllDecreased);
|
|
if (defender.IsSucceededChance(firstData))
|
|
{
|
|
increaseDefense -= secondData * 0.01;
|
|
}
|
|
}
|
|
|
|
(int firstData, int secondData, int count) increaseDefenseAttackTypeBCard = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMeleeIncreased);
|
|
switch (attacker.AttackType)
|
|
{
|
|
case AttackType.Melee when defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMeleeIncreased):
|
|
if (defender.IsSucceededChance(increaseDefenseAttackTypeBCard.firstData))
|
|
{
|
|
increaseDefenseAttackType += increaseDefenseAttackTypeBCard.secondData * 0.01;
|
|
defender.BroadcastEffect(EffectType.MeleeDefense);
|
|
}
|
|
|
|
break;
|
|
case AttackType.Ranged when defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceRangedIncreased):
|
|
increaseDefenseAttackTypeBCard = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceRangedIncreased);
|
|
if (defender.IsSucceededChance(increaseDefenseAttackTypeBCard.firstData))
|
|
{
|
|
increaseDefenseAttackType += increaseDefenseAttackTypeBCard.secondData * 0.01;
|
|
defender.BroadcastEffect(EffectType.RangeDefense);
|
|
}
|
|
|
|
break;
|
|
case AttackType.Magical when defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMagicalIncreased):
|
|
increaseDefenseAttackTypeBCard = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMagicalIncreased);
|
|
if (defender.IsSucceededChance(increaseDefenseAttackTypeBCard.firstData))
|
|
{
|
|
increaseDefenseAttackType += increaseDefenseAttackTypeBCard.secondData * 0.01;
|
|
defender.BroadcastEffect(EffectType.MagicDefense);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
increaseDefenseAttackTypeBCard = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMeleeDecreased);
|
|
switch (attacker.AttackType)
|
|
{
|
|
case AttackType.Melee when defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMeleeDecreased):
|
|
if (defender.IsSucceededChance(increaseDefenseAttackTypeBCard.firstData))
|
|
{
|
|
increaseDefenseAttackType -= increaseDefenseAttackTypeBCard.secondData * 0.01;
|
|
defender.BroadcastEffect(EffectType.MeleeDefense);
|
|
}
|
|
|
|
break;
|
|
case AttackType.Ranged when defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceRangedDecreased):
|
|
increaseDefenseAttackTypeBCard = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceRangedDecreased);
|
|
if (defender.IsSucceededChance(increaseDefenseAttackTypeBCard.firstData))
|
|
{
|
|
increaseDefenseAttackType -= increaseDefenseAttackTypeBCard.secondData * 0.01;
|
|
defender.BroadcastEffect(EffectType.RangeDefense);
|
|
}
|
|
|
|
break;
|
|
case AttackType.Magical when defender.HasBCard(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMagicalDecreased):
|
|
increaseDefenseAttackTypeBCard = defender.GetBCardInformation(BCardType.Block, (byte)AdditionalTypes.Block.ChanceMagicalDecreased);
|
|
if (defender.IsSucceededChance(increaseDefenseAttackTypeBCard.firstData))
|
|
{
|
|
increaseDefenseAttackType -= increaseDefenseAttackTypeBCard.secondData * 0.01;
|
|
defender.BroadcastEffect(EffectType.MagicDefense);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
increaseDefenseByLevel.Item1 += defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.AllAttackDecreased).firstData;
|
|
increaseDefenseByLevel.Item1 -= defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.AllAttackIncreased).firstData;
|
|
|
|
increaseDefenseByLevel.Item2 -= defender.GetMultiplier(attacker.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.AllAttackDecreased).secondData);
|
|
increaseDefenseByLevel.Item2 += defender.GetMultiplier(attacker.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.AllAttackIncreased).secondData);
|
|
|
|
increaseDefenseByLevelAttackType.Item1 += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MeleeAttackDecreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.RangedAttackDecreased).firstData,
|
|
AttackType.Magical => defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MagicalAttacksDecreased).firstData
|
|
};
|
|
|
|
increaseDefenseByLevelAttackType.Item1 -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MeleeAttackIncreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.RangedAttackIncreased).firstData,
|
|
AttackType.Magical => defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MagicalAttackIncreased).firstData
|
|
};
|
|
|
|
increaseDefenseByLevelAttackType.Item2 -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MeleeAttackDecreased).secondData),
|
|
AttackType.Ranged => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.RangedAttackDecreased).secondData),
|
|
AttackType.Magical => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MagicalAttacksDecreased).secondData)
|
|
};
|
|
|
|
increaseDefenseByLevelAttackType.Item2 += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MeleeAttackIncreased).secondData),
|
|
AttackType.Ranged => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.RangedAttackIncreased).secondData),
|
|
AttackType.Magical => defender.GetMultiplier(defender.GetBCardInformation(BCardType.Absorption, (byte)AdditionalTypes.Absorption.MagicalAttackIncreased).secondData)
|
|
};
|
|
|
|
increaseAllDefense = 1 + defender.GetMultiplier(defender.GetBCardInformation(BCardType.Item, (byte)AdditionalTypes.Item.DefenceIncreased).firstData);
|
|
|
|
int maximumCriticalDamage = defender.GetBCardInformation(BCardType.VulcanoElementBuff, (byte)AdditionalTypes.VulcanoElementBuff.CriticalDefence).firstData;
|
|
|
|
bool isPvP = attacker.IsPlayer() && defender.IsPlayer();
|
|
double defenseInPvP = 1;
|
|
(int firstData, int secondData, int count) pvpBCard = defender.GetBCardInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DefenceIncreasedInPVP);
|
|
if (isPvP)
|
|
{
|
|
defenseInPvP -= pvpBCard.firstData * 0.01;
|
|
|
|
pvpBCard = attacker.GetBCardInformation(BCardType.LeonaPassiveSkill, (byte)AdditionalTypes.LeonaPassiveSkill.DefenceDecreasedInPVP);
|
|
defenseInPvP += pvpBCard.firstData * 0.01;
|
|
defenseInPvP += attacker.GetShellWeaponEffectValue(ShellEffectType.ReducesPercentageEnemyDefenceInPVP) * 0.01;
|
|
}
|
|
else
|
|
{
|
|
if (pvpBCard.secondData == 1)
|
|
{
|
|
defenseInPvP += pvpBCard.firstData * 0.01;
|
|
}
|
|
}
|
|
|
|
int multiplyDefenseInt = defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.AllDefenceIncreased).firstData;
|
|
multiplyDefenseInt += attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.MeleeDefenceIncreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.RangedDefenceIncreased).firstData,
|
|
AttackType.Magical => defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.MagicalDefenceIncreased).firstData
|
|
};
|
|
|
|
multiplyDefenseInt -= defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.AllDefenceDecreased).firstData;
|
|
multiplyDefenseInt -= attacker.AttackType switch
|
|
{
|
|
AttackType.Melee => defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.MeleeDefenceDecreased).firstData,
|
|
AttackType.Ranged => defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.RangedDefenceDecreased).firstData,
|
|
AttackType.Magical => defender.GetBCardInformation(BCardType.MultDefence, (byte)AdditionalTypes.MultDefence.MagicalDefenceDecreased).firstData
|
|
};
|
|
|
|
int multiplyDefense = multiplyDefenseInt == 0 ? 1 : multiplyDefenseInt;
|
|
|
|
return new CalculationDefense
|
|
{
|
|
IncreaseDefense = increaseDefense,
|
|
IncreaseDefenseAttackType = increaseDefenseAttackType,
|
|
IncreaseDefenseByLevel = increaseDefenseByLevel,
|
|
IncreaseDefenseByLevelAttackType = increaseDefenseByLevelAttackType,
|
|
IncreaseAllDefense = increaseAllDefense,
|
|
MaximumCriticalDamage = maximumCriticalDamage,
|
|
DefenseInPvP = defenseInPvP,
|
|
IncreaseDefenseInPve = increaseDefenseInPve,
|
|
MultiplyDefense = multiplyDefense
|
|
};
|
|
}
|
|
|
|
public static CalculationResult DamageResult(
|
|
this IBattleEntityDump attacker,
|
|
IBattleEntityDump defender,
|
|
CalculationBasicStatistics baseStatistics,
|
|
CalculationDefense defense,
|
|
CalculationPhysicalDamage physicalDamage,
|
|
CalculationElementDamage elementDamage,
|
|
SkillInfo skill)
|
|
{
|
|
bool isCritical = false;
|
|
|
|
bool isSoftDamage = false;
|
|
bool isHighMonsterDamage = false;
|
|
double softDamageMultiplier = 0;
|
|
|
|
int distance = attacker.Position.GetDistance(defender.Position);
|
|
|
|
#region Attacker Values
|
|
|
|
int attackerMorale = baseStatistics.AttackerMorale;
|
|
int attackerAttackUpgrade = baseStatistics.AttackerAttackUpgrade;
|
|
int attackerCriticalChance = baseStatistics.AttackerCriticalChance;
|
|
double attackerCriticalDamage = baseStatistics.AttackerCriticalDamage * 0.01;
|
|
double attackerElementRate = baseStatistics.AttackerElementRate * 0.01;
|
|
|
|
ElementType attackerElement = attacker.Element;
|
|
AttackType attackType = attacker.AttackType;
|
|
|
|
int basicDamage = _randomGenerator.RandomNumber(attacker.DamageMinimum + attacker.WeaponDamageMinimum, attacker.DamageMaximum + attacker.WeaponDamageMaximum);
|
|
|
|
int weaponMin = attacker.WeaponDamageMinimum;
|
|
int weaponMax = attacker.WeaponDamageMaximum;
|
|
|
|
double shellDamagePercentage = attacker.GetShellWeaponEffectValue(ShellEffectType.PercentageTotalDamage) * 0.01;
|
|
|
|
#endregion
|
|
|
|
#region Defender Values
|
|
|
|
int defenderMorale = baseStatistics.DefenderMorale;
|
|
int defenderDefenseUpgrade = baseStatistics.DefenderDefenseUpgrade;
|
|
int defenderDefense = baseStatistics.DefenderDefense;
|
|
int defenderResistance = baseStatistics.DefenderResistance;
|
|
|
|
#endregion
|
|
|
|
#region Defense Values
|
|
|
|
double increaseDefense = defense.IncreaseDefense; // 11, 1
|
|
double increaseDefenseAttackType = defense.IncreaseDefenseAttackType; // 11, 3-5-7
|
|
(int, double) increaseDefenseByLevel = defense.IncreaseDefenseByLevel; // 12, 1
|
|
(int, double) increaseDefenseByLevelAttackType = defense.IncreaseDefenseByLevelAttackType; // 12, 3-5-7
|
|
double increaseAllDefense = defense.IncreaseAllDefense; // 44, 4
|
|
int maximumCriticalDamage = defense.MaximumCriticalDamage; // 66, 7
|
|
double defenseInPvP = defense.DefenseInPvP; // 71, 7
|
|
double increaseDefenseInPve = defense.IncreaseDefenseInPve;
|
|
double multiplyDefense = defense.MultiplyDefense;
|
|
|
|
#endregion
|
|
|
|
#region Psychical Damage
|
|
|
|
int cleanDamage = physicalDamage.CleanDamage;
|
|
double damagePercentage = physicalDamage.DamagePercentage; // 5, 5
|
|
double damagePercentageSecond = physicalDamage.DamagePercentageSecond; // 8, 5
|
|
double multiplierDamage = physicalDamage.MultiplyDamage; // 34, 1
|
|
double endCriticalDamage = physicalDamage.EndCriticalDamage; // 38, 5
|
|
double ignoreEnemyDefense = physicalDamage.IgnoreEnemyDefense; // 84, 1
|
|
double vesselLodDamage = physicalDamage.VesselLoDDamage; // 90, 3
|
|
double vesselGlacernonDamage = physicalDamage.VesselGlacernonDamage; // 90, 7
|
|
double increaseAllDamage = physicalDamage.IncreaseAllDamage; // 103, 1
|
|
double increaseAllDamageAttackType = physicalDamage.IncreaseAllDamageAttackType; // 103, 3-5-7
|
|
double increaseDamageMagicDefense = physicalDamage.IncreaseDamageMagicDefense; // 108, 9
|
|
int increaseDamageRace = physicalDamage.IncreaseDamageRace; // 24, 1
|
|
double increaseDamageRacePercentage = physicalDamage.IncreaseDamageRacePercentage; // 71, 1
|
|
double increaseLodDamage = physicalDamage.IncreaseLoDDamage; // 101, 1
|
|
double increaseVesselDamage = physicalDamage.IncreaseVesselDamage; // 101, 3
|
|
double increaseDamageFaction = physicalDamage.IncreaseDamageFaction; // 85, 7-9
|
|
int invisibleDamage = physicalDamage.InvisibleDamage; // 43, 7
|
|
double increaseDamageInPvP = physicalDamage.IncreaseDamageInPvP; // 71, 9
|
|
double increaseAttack = physicalDamage.IncreaseAttack; // 15, 1
|
|
double increaseAttackAttackType = physicalDamage.IncreaseAttackAttackType; // 15, 3-5-7
|
|
double increaseDamageShadowFairy = physicalDamage.IncreaseDamageShadowFairy; // 80, 9
|
|
double increaseAllAttacks = physicalDamage.IncreaseAllAttacks; // 44, 3
|
|
double increaseDamageByDebuffs = physicalDamage.IncreaseDamageByDebuffs;
|
|
double increaseDamageHighMonsters = physicalDamage.IncreaseDamageHighMonsters; // 86, 5
|
|
double increaseDamageVersusMonsters = physicalDamage.IncreaseDamageVersusMonsters;
|
|
double increaseAllAttacksVersusMonsters = physicalDamage.IncreaseAllAttacksVersusMonsters;
|
|
|
|
#endregion
|
|
|
|
#region Element Damage
|
|
|
|
int element = elementDamage.Element;
|
|
double elementMultiply = elementDamage.ElementMultiply;
|
|
|
|
#endregion
|
|
|
|
if (skill != null && skill.Element != (byte)attackerElement)
|
|
{
|
|
attackerElementRate = 0;
|
|
}
|
|
|
|
if (attacker.HasBCard(BCardType.Mode, (byte)AdditionalTypes.Mode.EffectNoDamage))
|
|
{
|
|
return new CalculationResult(0, false, false);
|
|
}
|
|
|
|
basicDamage += cleanDamage;
|
|
basicDamage += invisibleDamage;
|
|
basicDamage += increaseDamageRace;
|
|
|
|
basicDamage += attacker.GetShellWeaponEffectValue(ShellEffectType.DamageImproved);
|
|
|
|
if (increaseDamageRacePercentage > 0)
|
|
{
|
|
basicDamage = (int)(basicDamage * increaseDamageRacePercentage);
|
|
}
|
|
|
|
double damageFromMap = vesselLodDamage * vesselGlacernonDamage;
|
|
|
|
if (increaseDamageMagicDefense > 0 && attackType == AttackType.Magical)
|
|
{
|
|
basicDamage += (int)Math.Floor(attacker.MagicalDefense * increaseDamageMagicDefense);
|
|
}
|
|
|
|
if (increaseDamageHighMonsters > 0)
|
|
{
|
|
isHighMonsterDamage = true;
|
|
}
|
|
|
|
int plusDifference = attackerAttackUpgrade - defenderDefenseUpgrade;
|
|
|
|
bool countWeaponPlus = false;
|
|
int additionalDefense = 0;
|
|
|
|
if (Math.Abs(plusDifference) > Math.Abs(increaseDefenseByLevel.Item1))
|
|
{
|
|
increaseDefenseByLevel.Item2 = 1;
|
|
}
|
|
|
|
if (Math.Abs(plusDifference) > Math.Abs(increaseDefenseByLevelAttackType.Item1))
|
|
{
|
|
increaseDefenseByLevelAttackType.Item2 = 1;
|
|
}
|
|
|
|
if (plusDifference > 0)
|
|
{
|
|
plusDifference = Math.Abs(plusDifference);
|
|
if (plusDifference > 10)
|
|
{
|
|
plusDifference = 10;
|
|
}
|
|
|
|
weaponMin = (int)(weaponMin * _plus[plusDifference]);
|
|
weaponMax = (int)(weaponMax * _plus[plusDifference]);
|
|
countWeaponPlus = true;
|
|
}
|
|
else if (plusDifference < 0)
|
|
{
|
|
plusDifference = Math.Abs(plusDifference);
|
|
if (plusDifference > 10)
|
|
{
|
|
plusDifference = 10;
|
|
}
|
|
|
|
additionalDefense += (int)Math.Floor(defenderDefense * _plus[plusDifference]);
|
|
}
|
|
|
|
if (attackType != AttackType.Magical && attackerCriticalChance != 0 && attacker.IsSucceededChance(attackerCriticalChance))
|
|
{
|
|
isCritical = true;
|
|
}
|
|
|
|
if (damagePercentageSecond > 0 && isHighMonsterDamage)
|
|
{
|
|
softDamageMultiplier = increaseDamageHighMonsters + damagePercentageSecond + increaseDamageHighMonsters * damagePercentageSecond;
|
|
isSoftDamage = true;
|
|
}
|
|
else if (damagePercentageSecond > 0)
|
|
{
|
|
softDamageMultiplier = damagePercentageSecond;
|
|
isSoftDamage = true;
|
|
}
|
|
else if (isHighMonsterDamage)
|
|
{
|
|
softDamageMultiplier = increaseDamageHighMonsters;
|
|
isSoftDamage = true;
|
|
}
|
|
|
|
double defenderResistanceMultiplier = defenderResistance >= 100 ? 0 : 1.0 - defenderResistance * 0.01;
|
|
|
|
int minDamage = basicDamage + (countWeaponPlus ? weaponMin : 0);
|
|
int maxDamage = basicDamage + (countWeaponPlus ? weaponMax : 0);
|
|
|
|
int calculatedDamage = _randomGenerator.RandomNumber(minDamage, maxDamage);
|
|
|
|
#region Normal Damage
|
|
|
|
int normalDmg = (int)((attacker.PhysicalDamageShell(calculatedDamage, shellDamagePercentage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalDamageIncreaseDefenseByLevel(calculatedDamage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalDamageIncreaseDefenseByLevelAttackType(calculatedDamage, increaseDefenseByLevelAttackType.Item2, increaseDefenseByLevel.Item2) +
|
|
attacker.PhysicalDamageIncreaseAttack(calculatedDamage, defenderDefense, additionalDefense, increaseAttack, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalDamageIncreaseDefense(calculatedDamage, defenderDefense, additionalDefense, increaseDefenseAttackType, increaseDefenseByLevel.Item2,
|
|
increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalDamageMultiplier(calculatedDamage, multiplierDamage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2)) * increaseDefense);
|
|
|
|
normalDmg = attacker.Penalties(defender, normalDmg, distance);
|
|
|
|
normalDmg = (int)(normalDmg * damagePercentage);
|
|
normalDmg = (int)(normalDmg * increaseAttack);
|
|
normalDmg = (int)(normalDmg * increaseDefenseAttackType);
|
|
|
|
#endregion
|
|
|
|
#region Basic Damage
|
|
|
|
int basicDmg = (int)(calculatedDamage * increaseAttack * increaseDefense);
|
|
basicDmg = attacker.Penalties(defender, basicDmg, distance);
|
|
|
|
#endregion
|
|
|
|
#region Critical Damage
|
|
|
|
int criticalDmg = 0;
|
|
if (isCritical)
|
|
{
|
|
criticalDmg = (int)((attacker.PhysicalCriticalDamage(calculatedDamage, defenderDefense, attackerCriticalDamage, multiplierDamage) +
|
|
attacker.PhysicalCriticalDamageShell(calculatedDamage, defenderDefense, shellDamagePercentage, increaseDefenseByLevel.Item2,
|
|
increaseDefenseByLevelAttackType.Item2, attackerCriticalDamage, multiplierDamage) +
|
|
attacker.PhysicalCriticalDamageIncreaseDefenseByLevel(calculatedDamage, attackerCriticalDamage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalCriticalDamageIncreaseDefenseByLevelAttackType(calculatedDamage, attackerCriticalDamage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalCriticalIncreaseAttack(calculatedDamage, increaseAttack, attackerCriticalDamage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2,
|
|
multiplierDamage)) * increaseDefense);
|
|
|
|
criticalDmg = attacker.Penalties(defender, criticalDmg, distance);
|
|
|
|
criticalDmg = (int)(criticalDmg * damagePercentage);
|
|
criticalDmg = (int)(criticalDmg * increaseAttack);
|
|
criticalDmg = (int)(criticalDmg * increaseDefenseAttackType);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Element Damage
|
|
|
|
int elementDmg = 0;
|
|
if (attackerElement != ElementType.Neutral)
|
|
{
|
|
elementDmg =
|
|
attacker.ElementFairyDamage(calculatedDamage, attackerElementRate) +
|
|
attacker.ElementFairyDamageShell(calculatedDamage, shellDamagePercentage, attackerElementRate) +
|
|
attacker.ElementFairyDamageMultiplier(calculatedDamage, multiplierDamage, attackerElementRate);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Physical Soft Damage
|
|
|
|
int physicalSoft = 0;
|
|
if (isSoftDamage)
|
|
{
|
|
physicalSoft = (int)((attacker.SoftDamageMultiplier(calculatedDamage, softDamageMultiplier, multiplierDamage) +
|
|
attacker.SoftDamageShell(calculatedDamage, softDamageMultiplier, shellDamagePercentage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.SoftDamageIncreaseDefenseByLevel(calculatedDamage, softDamageMultiplier, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.SoftDamageIncreaseDefenseByLevelAttackType(calculatedDamage, softDamageMultiplier, increaseDefenseByLevelAttackType.Item2, increaseDefenseByLevel.Item2) +
|
|
attacker.SoftDamageIncreaseAttack(calculatedDamage, increaseAttack, softDamageMultiplier, increaseDefense, increaseDefenseAttackType)) * increaseDefense);
|
|
|
|
physicalSoft = attacker.Penalties(defender, physicalSoft, distance);
|
|
|
|
physicalSoft = (int)(physicalSoft * damagePercentage);
|
|
physicalSoft = (int)(physicalSoft * increaseAttack);
|
|
physicalSoft = (int)(physicalSoft * increaseDefenseAttackType);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Critical Soft Damage
|
|
|
|
int criticalSoft = 0;
|
|
if (isCritical && isSoftDamage)
|
|
{
|
|
criticalSoft = (int)((attacker.PhysicalSoftCriticalDamage(calculatedDamage, softDamageMultiplier, attackerCriticalDamage, multiplierDamage) +
|
|
attacker.PhysicalSoftCriticalDamageShell(calculatedDamage, softDamageMultiplier, attackerCriticalDamage,
|
|
shellDamagePercentage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalSoftCriticalIncreaseDefenseByLevel(calculatedDamage, softDamageMultiplier,
|
|
attackerCriticalDamage, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2) +
|
|
attacker.PhysicalSoftCriticalIncreaseDefenseByLevelAttackType(calculatedDamage, softDamageMultiplier,
|
|
attackerCriticalDamage, increaseDefenseByLevelAttackType.Item2, increaseDefenseByLevel.Item2) +
|
|
attacker.PhysicalSoftCriticalIncreaseAttack(calculatedDamage, softDamageMultiplier, attackerCriticalDamage,
|
|
increaseAttack, increaseDefenseByLevel.Item2, increaseDefenseByLevelAttackType.Item2)) * increaseDefense);
|
|
|
|
criticalSoft = attacker.Penalties(defender, criticalSoft, distance);
|
|
|
|
criticalSoft = (int)(criticalSoft * damagePercentage);
|
|
criticalSoft = (int)(criticalSoft * increaseAttack);
|
|
criticalSoft = (int)(criticalSoft * increaseDefenseAttackType);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Element Soft Damage
|
|
|
|
int elementSoft = 0;
|
|
if (attackerElement != ElementType.Neutral && isSoftDamage)
|
|
{
|
|
elementSoft =
|
|
attacker.SoftElementDamage(calculatedDamage, softDamageMultiplier, attackerElementRate, multiplierDamage) +
|
|
attacker.SoftElementDamageShell(calculatedDamage, shellDamagePercentage, softDamageMultiplier, attackerElementRate);
|
|
}
|
|
|
|
#endregion
|
|
|
|
/* FINAL PHYSICAL DAMAGE */
|
|
|
|
int physicalDmg = (int)(attackerMorale + (basicDmg + normalDmg + criticalDmg + physicalSoft + criticalSoft) * endCriticalDamage * increaseAllDamageAttackType * increaseAllDamage *
|
|
increaseAllAttacksVersusMonsters);
|
|
double magicialDamageReduction = defender is PlayerBattleEntityDump playerBattleEntityDump && attackType == AttackType.Magical ? playerBattleEntityDump.DecreaseMagicDamage : 1;
|
|
physicalDmg = (int)Math.Floor(physicalDmg * magicialDamageReduction);
|
|
|
|
int defenceByLevel;
|
|
if (defender.IsPlayer())
|
|
{
|
|
defenceByLevel = -15;
|
|
}
|
|
else
|
|
{
|
|
defenceByLevel = attacker.GetMonsterDamageBonus(defender.Level);
|
|
}
|
|
|
|
int defenderDefenseDamage = (int)(defenderMorale + defenceByLevel + (defenderDefense + additionalDefense) * ignoreEnemyDefense * increaseAllDefense * increaseDefenseInPve * multiplyDefense);
|
|
|
|
physicalDmg -= defenderDefenseDamage <= 0 ? 0 : defenderDefenseDamage;
|
|
|
|
|
|
/* FINAL ELEMENT DAMAGE */
|
|
|
|
int elementalDamage = (int)(element + (elementDmg + elementSoft) * increaseAllDamageAttackType * increaseAllDamage);
|
|
|
|
if (elementalDamage != 0)
|
|
{
|
|
elementalDamage = (int)Math.Floor(elementalDamage * increaseDefense);
|
|
|
|
elementalDamage = (int)Math.Floor(elementalDamage * increaseDamageShadowFairy);
|
|
|
|
elementalDamage = (int)Math.Floor(elementalDamage * elementMultiply);
|
|
|
|
elementalDamage = (int)Math.Floor(elementalDamage * defenderResistanceMultiplier);
|
|
}
|
|
|
|
/* FINAL DAMAGE */
|
|
|
|
int finalDamage = physicalDmg + elementalDamage;
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * increaseAllAttacks);
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * increaseDamageByDebuffs);
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * damageFromMap);
|
|
finalDamage = (int)Math.Floor(finalDamage * (1 + attacker.GetFamilyUpgradeValue(FamilyUpgradeType.INCREASE_ATTACK_DEFENSE) * 0.01));
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * increaseDamageInPvP);
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * increaseLodDamage);
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * increaseVesselDamage);
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * increaseDamageFaction);
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * increaseDamageVersusMonsters);
|
|
if (attacker is PlayerBattleEntityDump { IncreaseJajamaruDamage: true })
|
|
{
|
|
finalDamage = (int)Math.Floor(finalDamage * 1.5);
|
|
}
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * defenseInPvP);
|
|
|
|
finalDamage = (int)Math.Floor(finalDamage * (1 - defender.GetFamilyUpgradeValue(FamilyUpgradeType.INCREASE_ATTACK_DEFENSE) * 0.01));
|
|
|
|
if (isCritical && maximumCriticalDamage != 0)
|
|
{
|
|
finalDamage = maximumCriticalDamage;
|
|
}
|
|
|
|
if (attacker.HasBCard(BCardType.RecoveryAndDamagePercent, (byte)AdditionalTypes.RecoveryAndDamagePercent.DecreaseEnemyHP))
|
|
{
|
|
double maxHpPercentage = attacker.GetBCardInformation(BCardType.RecoveryAndDamagePercent, (byte)AdditionalTypes.RecoveryAndDamagePercent.DecreaseEnemyHP).firstData * 0.01;
|
|
finalDamage = (int)(defender.MaxHp * maxHpPercentage);
|
|
}
|
|
|
|
if (defender.HasBCard(BCardType.RecoveryAndDamagePercent, (byte)AdditionalTypes.RecoveryAndDamagePercent.DecreaseSelfHP))
|
|
{
|
|
double maxHpPercentage = defender.GetBCardInformation(BCardType.RecoveryAndDamagePercent, (byte)AdditionalTypes.RecoveryAndDamagePercent.DecreaseSelfHP).firstData * 0.01;
|
|
finalDamage = (int)(defender.MaxHp * maxHpPercentage);
|
|
}
|
|
|
|
if (finalDamage <= 0)
|
|
{
|
|
finalDamage = 1;
|
|
}
|
|
|
|
finalDamage += (int)(GetMonsterBaseDamage(attacker, defender) * increaseAttack * increaseDefense);
|
|
|
|
return new CalculationResult(finalDamage, isCritical, isSoftDamage);
|
|
}
|
|
|
|
private static int GetMonsterBaseDamage(IBattleEntityDump attacker, IBattleEntityDump defender)
|
|
{
|
|
if (!attacker.IsMonster())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int monsterLevel = attacker.Level;
|
|
int multiplier = monsterLevel switch
|
|
{
|
|
< 30 => 0,
|
|
<= 50 => 1,
|
|
< 60 => 2,
|
|
< 65 => 3,
|
|
< 70 => 4,
|
|
_ => 5
|
|
};
|
|
|
|
double damageReduction = defender is PlayerBattleEntityDump playerBattleEntityDump ? playerBattleEntityDump.MinimalDamageReduction : 1;
|
|
|
|
return (int)(monsterLevel * multiplier * damageReduction);
|
|
}
|
|
|
|
private static int Penalties(this IBattleEntityDump attacker, IBattleEntityDump defender, int damage, int distance)
|
|
{
|
|
if (attacker.AttackType != AttackType.Ranged)
|
|
{
|
|
return damage;
|
|
}
|
|
|
|
bool hasRangePenalty = !attacker.HasBCard(BCardType.GuarantedDodgeRangedAttack, (byte)AdditionalTypes.GuarantedDodgeRangedAttack.NoPenalty);
|
|
bool increaseDamageRangeDistance = attacker.HasBCard(BCardType.GuarantedDodgeRangedAttack, (byte)AdditionalTypes.GuarantedDodgeRangedAttack.DistanceDamageIncreasing);
|
|
|
|
int returnDamage = damage;
|
|
returnDamage = distance switch
|
|
{
|
|
<= 2 when hasRangePenalty => (int)(returnDamage * 0.7),
|
|
> 2 when increaseDamageRangeDistance => (int)(returnDamage * (0.95 + 0.05 * distance)),
|
|
_ => returnDamage
|
|
};
|
|
|
|
return returnDamage;
|
|
}
|
|
|
|
/*
|
|
* Calculation:
|
|
* 1. Clean damage
|
|
* 2. Element damage
|
|
* 3. Critical damage
|
|
* 4. Soft Damage
|
|
*/
|
|
|
|
// Calculate all bonuses for physical damage
|
|
|
|
private static int PhysicalDamageShell(this IBattleEntityDump attacker, int cleanDamage, double shellPercentage, double increaseDefenseByLevel, double increaseDefenseByLevelAttackType)
|
|
=> (int)Math.Floor((cleanDamage + 15) * shellPercentage * increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalDamageIncreaseAttack(this IBattleEntityDump attacker, int cleanDamage, int defense, int additionalDefense, double increaseAttack, double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType)
|
|
=> (int)Math.Floor((cleanDamage - defense - additionalDefense) / (1 / (increaseAttack - 1 < 0 ? 0 : increaseAttack - 1) + 1) * increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalDamageIncreaseDefense(this IBattleEntityDump attacker, int cleanDamage, int defense, int additionalDefense, double increaseDefenseAttackType,
|
|
double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType)
|
|
=> (int)Math.Floor((cleanDamage + 15 - defense - additionalDefense) / (1 / (increaseDefenseAttackType - 1 < 0 ? 0 : increaseDefenseAttackType - 1) + 1) * increaseDefenseByLevel *
|
|
increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalDamageIncreaseDefenseByLevel(this IBattleEntityDump attacker, int cleanDamage, double increaseDefenseByLevel, double increaseDefenseByLevelAttackType)
|
|
=> increaseDefenseByLevel == 1.0
|
|
? 0
|
|
: (int)Math.Floor((cleanDamage + 15) / (1 / (increaseDefenseByLevel - 1 < 0 ? 0 : increaseDefenseByLevel - 1) + 1) * increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalDamageIncreaseDefenseByLevelAttackType(this IBattleEntityDump attacker, int cleanDamage, double increaseDefenseByLevelAttackType, double increaseDefenseByLevel)
|
|
=> increaseDefenseByLevelAttackType == 1.0
|
|
? 0
|
|
: (int)Math.Floor((cleanDamage + 15) / (1 / (increaseDefenseByLevelAttackType - 1 < 0 ? 0 : increaseDefenseByLevelAttackType - 1) + 1) * increaseDefenseByLevel *
|
|
increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalDamageMultiplier(this IBattleEntityDump attacker, int cleanDamage, double multiplyDamage, double increaseDefenseByLevel, double increaseDefenseByLevelAttackType)
|
|
=> (int)Math.Floor((cleanDamage + 15) * (multiplyDamage - 1) * increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
// Calculate all bonuses for element damage
|
|
|
|
private static int ElementFairyDamage(this IBattleEntityDump attacker, int cleanDamage, double fairyMultiplier) => (int)Math.Floor((cleanDamage + 115) * fairyMultiplier);
|
|
|
|
private static int ElementFairyDamageShell(this IBattleEntityDump attacker, int cleanDamage, double shellPercentage, double fairyMultiplier) =>
|
|
(int)Math.Floor((cleanDamage + 75) * shellPercentage * fairyMultiplier);
|
|
|
|
private static int ElementFairyDamageMultiplier(this IBattleEntityDump attacker, int cleanDamage, double multiplierDamage, double fairyMultiplier) =>
|
|
(int)Math.Floor((cleanDamage + 15) * fairyMultiplier * (multiplierDamage - 1));
|
|
|
|
// Calculate all bonuses for critical damage
|
|
|
|
private static int PhysicalCriticalDamage(this IBattleEntityDump attacker, int cleanDamage, int defense, double criticalMultiplier, double multiplierDamage)
|
|
=> (int)Math.Floor((cleanDamage + 15 - defense) * criticalMultiplier * multiplierDamage);
|
|
|
|
private static int PhysicalCriticalDamageShell(this IBattleEntityDump attacker, int cleanDamage, int defense, double shellPercentage, double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType, double criticalMultiplier, double multiplierDamage)
|
|
=> (int)Math.Floor((cleanDamage + 15 - defense) * criticalMultiplier * shellPercentage * increaseDefenseByLevel * increaseDefenseByLevelAttackType * multiplierDamage);
|
|
|
|
// Calculate all bonuses for critical soft damage
|
|
|
|
private static int PhysicalCriticalIncreaseAttack(this IBattleEntityDump attacker, int cleanDamage, double increaseAttack, double criticalMultiplier, double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType,
|
|
double multiplierDamage) => (int)Math.Floor(cleanDamage / (1 / (increaseAttack - 1 < 0 ? 0 : increaseAttack - 1) + 1) * criticalMultiplier * increaseDefenseByLevel *
|
|
increaseDefenseByLevelAttackType * multiplierDamage);
|
|
|
|
private static int PhysicalCriticalDamageIncreaseDefenseByLevel(this IBattleEntityDump attacker, int cleanDamage, double criticalMultiplier, double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType)
|
|
=> increaseDefenseByLevel == 1.0
|
|
? 0
|
|
: (int)Math.Floor((cleanDamage + 15) / (1 / (increaseDefenseByLevel - 1 < 0 ? 0 : increaseDefenseByLevel - 1) + 1) * criticalMultiplier * increaseDefenseByLevel *
|
|
increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalCriticalDamageIncreaseDefenseByLevelAttackType(this IBattleEntityDump attacker, int cleanDamage, double criticalMultiplier, double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType)
|
|
=> increaseDefenseByLevelAttackType == 1.0
|
|
? 0
|
|
: (int)Math.Floor((cleanDamage + 15) / (1 / (increaseDefenseByLevelAttackType - 1 < 0 ? 0 : increaseDefenseByLevelAttackType - 1) + 1) * criticalMultiplier * increaseDefenseByLevel *
|
|
increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalSoftCriticalDamage(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double criticalMultiplier, double damageMultiplier)
|
|
=> (int)Math.Floor((cleanDamage + 15) * softDamageMultiplier * criticalMultiplier * damageMultiplier);
|
|
|
|
private static int PhysicalSoftCriticalDamageShell(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double criticalMultiplier, double shellPercentage,
|
|
double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType) =>
|
|
(int)Math.Floor((cleanDamage + 15) * softDamageMultiplier * criticalMultiplier * shellPercentage * increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalSoftCriticalIncreaseAttack(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double criticalMultiplier, double increaseAttack,
|
|
double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType) => (int)Math.Floor(cleanDamage / (1 / (increaseAttack - 1 < 0 ? 0 : increaseAttack - 1) + 1) * softDamageMultiplier * criticalMultiplier *
|
|
increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalSoftCriticalIncreaseDefenseByLevel(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double criticalMultiplier,
|
|
double increaseDefenseByLevel, double increaseDefenseByLevelAttackType)
|
|
=> increaseDefenseByLevel == 1.0
|
|
? 0
|
|
: (int)Math.Floor(cleanDamage / (1 / (increaseDefenseByLevel - 1) + 1) * softDamageMultiplier * criticalMultiplier * increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
private static int PhysicalSoftCriticalIncreaseDefenseByLevelAttackType(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double criticalMultiplier,
|
|
double increaseDefenseByLevelAttackType, double increaseDefenseByLevel)
|
|
=> increaseDefenseByLevelAttackType == 1.0
|
|
? 0
|
|
: (int)Math.Floor(cleanDamage * increaseDefenseByLevelAttackType * softDamageMultiplier * criticalMultiplier * increaseDefenseByLevelAttackType * increaseDefenseByLevel);
|
|
|
|
// Calculate all bonuses for physical soft damage
|
|
|
|
private static int SoftDamageMultiplier(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double multiplierDamage)
|
|
=> (int)Math.Floor((cleanDamage + 15) * softDamageMultiplier * multiplierDamage);
|
|
|
|
private static int SoftDamageShell(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double shellPercentage, double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType)
|
|
=> (int)Math.Floor((cleanDamage + 15) * softDamageMultiplier * shellPercentage * increaseDefenseByLevel * increaseDefenseByLevelAttackType);
|
|
|
|
private static int SoftDamageIncreaseAttack(this IBattleEntityDump attacker, int cleanDamage, double increaseAttack, double softDamageMultiplier, double increaseDefense,
|
|
double increaseDefenseAttackType)
|
|
=> (int)Math.Floor(cleanDamage * increaseAttack * softDamageMultiplier * increaseDefense * increaseDefenseAttackType);
|
|
|
|
private static int SoftDamageIncreaseDefenseByLevel(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double increaseDefenseByLevel,
|
|
double increaseDefenseByLevelAttackType)
|
|
=> increaseDefenseByLevel == 1.0
|
|
? 0
|
|
: (int)Math.Floor((cleanDamage + 15) / (1 / (increaseDefenseByLevel - 1 < 0 ? 0 : increaseDefenseByLevel - 1) + 1) * softDamageMultiplier * increaseDefenseByLevel *
|
|
increaseDefenseByLevelAttackType);
|
|
|
|
private static int SoftDamageIncreaseDefenseByLevelAttackType(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double increaseDefenseByLevelAttackType,
|
|
double increaseDefenseByLevel)
|
|
=> increaseDefenseByLevelAttackType == 1.0
|
|
? 0
|
|
: (int)Math.Floor((cleanDamage + 15) / (1 / (increaseDefenseByLevelAttackType - 1 < 0 ? 0 : increaseDefenseByLevelAttackType - 1) + 1) * softDamageMultiplier * increaseDefenseByLevel *
|
|
increaseDefenseByLevelAttackType);
|
|
|
|
// Calculate all bonuses for element soft damage
|
|
|
|
private static int SoftElementDamage(this IBattleEntityDump attacker, int cleanDamage, double softDamageMultiplier, double elementMultiplier, double multiplierDamage)
|
|
=> (int)Math.Floor((cleanDamage + 15) * softDamageMultiplier * elementMultiplier * multiplierDamage);
|
|
|
|
private static int SoftElementDamageShell(this IBattleEntityDump attacker, int cleanDamage, double shellPercentage, double softDamageMultiplier, double elementMultiplier)
|
|
=> (int)Math.Floor((cleanDamage + 15) * softDamageMultiplier * shellPercentage * elementMultiplier);
|
|
} |