Formula is here!
All tests done ingame by me no ai used gathering data.
All tests done ingame by me no ai used gathering data.
- The deviation is below 1%
- Basically, the formula builds the character’s physical and magical attack from the weapon values, STR/INT, reinforce values and mastery contribution. Then skill power is added, absorption is applied before defense, and the remaining damage is multiplied by the character’s balance, skill rate and the physical/magical damage constant.
- Critical damage only doubles the physical part, while magical/imbue damage stays unchanged. Final damage bonuses like avatar, premium or devil are added together and applied at the very end.
- Attack Rate and Parry Rate don’t seem to directly increase or reduce damage. They affect the roll inside the min-max attack range: higher Attack Rate pushes results toward the maximum, while higher Parry pushes them toward the minimum.
Code:
<?php
function physicalBalance(int $level, int $str): float
{
$m = 28 + ($level * 4);
return min(
1.20,
1 - ((2 / 3) * (($m - $str) / $m))
);
}
function magicalBalance(int $level, int $int): float
{
$m = 28 + ($level * 4);
return min(
1.20,
$int / $m
);
}
function physicalDamage(
float $basicPhysicalAP,
float $skillPhysicalAP,
float $masteryContribution,
float $physicalAbsorption,
float $enemyPhysicalDefense,
float $physicalBalance,
float $skillRate
): float {
$damage =
(
(
$basicPhysicalAP +
($skillPhysicalAP * $masteryContribution)
)
/ (1 + $physicalAbsorption)
- $enemyPhysicalDefense
)
* $physicalBalance
* $skillRate
* 1.276772606;
return max(0, $damage);
}
function magicalDamage(
float $basicMagicalAP,
float $skillMagicalAP,
float $masteryContribution,
float $magicalAbsorption,
float $enemyMagicalDefense,
float $magicalBalance,
float $skillRate
): float {
$damage =
(
(
($basicMagicalAP + $skillMagicalAP)
* $masteryContribution
)
/ (1 + $magicalAbsorption)
- $enemyMagicalDefense
)
* $magicalBalance
* $skillRate
* 1.287004542;
return max(0, $damage);
}
function normalDamage(
float $physicalDamage,
float $magicalDamage,
float $damageIncrease = 0
): int {
return (int) round(
($physicalDamage + $magicalDamage)
* (1 + $damageIncrease)
);
}
function criticalDamage(
float $physicalDamage,
float $magicalDamage,
float $damageIncrease = 0
): int {
return (int) round(
(($physicalDamage * 2) + $magicalDamage)
* (1 + $damageIncrease)
);
}
function calculateDamage(array $data): array
{
$phyBalance = physicalBalance(
$data['level'],
$data['str']
);
$magBalance = magicalBalance(
$data['level'],
$data['int']
);
$physical = physicalDamage(
$data['basic_physical_ap'],
$data['skill_physical_ap'],
$data['physical_mastery'],
$data['physical_absorption'],
$data['enemy_physical_defense'],
$phyBalance,
$data['skill_rate']
);
$magical = magicalDamage(
$data['basic_magical_ap'],
$data['skill_magical_ap'],
$data['magical_mastery'],
$data['magical_absorption'],
$data['enemy_magical_defense'],
$magBalance,
$data['skill_rate']
);
return [
'physical_balance' => $phyBalance,
'magical_balance' => $magBalance,
'physical_damage' => $physical,
'magical_damage' => $magical,
'normal_damage' => normalDamage(
$physical,
$magical,
$data['damage_increase']
),
'critical_damage' => criticalDamage(
$physical,
$magical,
$data['damage_increase']
)
];
}