Silkroad Damage Formula

10/05/2026 09:40 mgunbatti#1
Formula is here!
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']
        )
    ];
}
10/06/2026 03:01 JellyBitz#2
I tried long ago to make the maths on how damage is calculated to know what's the best output, the break point on damage between bow hybrid builds, but I wasn't able to do it.

Here is my maths, I was able to calculate exactly hp/mp/phy and mag balance. But the most important, the damage didn't matched at all in game, I give up.

calcs.py
PHP Code:
### Define your server settings
StatsPointsPerLevel = 3
BaseSTR 
= 20
BaseINT 
= 20
### Define your character
## (Bow lv.135 | 3:0 | FullBlue | Devil 15% | Fire/Cold)
Level = 100
BalancePointsSTR 
= 1 # Ex. 9:10 => 9 STR : 10 INT
BalancePointsINT = 1
SetTotalSTR 
= 0#12*3 # 11 items * 8 STR
SetTotalINT = 0#12*3 # 11 items * 8 INT
ExtraSTR = 5
ExtraINT 
= 0
ExtraHP 
= 0#30*3
ExtraMP = 0#30*3
ExtraHPPercent = 0 # 15% Devil
ExtraMPPercent = 0 #
ExtraPhyDamagePercent = 5 # 5% avatar
ExtraMagDamagePercent = 5
### Define your weapon (Bow | Legendary D15 +15)
PhyAtkPwrMin = 6750
PhyAtkPwrMax 
= 7798
PhyReinforceMin 
= 496.7
PhyReinforceMax 
= 608.7
MagAtkPwrMin 
= 10814
MagAtkPwrMax 
= 12491
MagReinforceMin 
= 794.8
MagReinforceMax 
= 974.0

### WARNING !!!
### Math alert, read by your own risk ...
BalancePointsTotal = BalancePointsSTR+BalancePointsINT
StatsPointsTotal 
= (Level-1)*StatsPointsPerLevel
BalanceTotalSTR 
= StatsPointsTotal*(BalancePointsSTR*1.0/BalancePointsTotal)
BalanceTotalINT = StatsPointsTotal*(BalancePointsINT*1.0/BalancePointsTotal)
STR = BaseSTR + (Level-1) + BalanceTotalSTR + SetTotalSTR + ExtraSTR
INT 
= BaseINT + (Level-1) + BalanceTotalINT + SetTotalINT + ExtraINT
HP 
= round(pow(1.02,(Level-1)) * STR * 10) + ExtraHP
MP 
= round(pow(1.02,(Level-1)) * INT * 10) + ExtraMP
HP 
= HP + (ExtraHPPercent * HP / 100)
MP = MP + (ExtraMPPercent * MP / 100)

M = 28 +Level*4
PhysicalBalance 
= 100-100*2/3*(M - STR)/M  #round(100-(100*2/3*(StatsPointsTotal-STR)/StatsPointsTotal))
MagicalBalance = 100*INT/M
if PhysicalBalance > 120:
    
PhysicalBalance = 120
if MagicalBalance > 120:
    
MagicalBalance = 120

PhyAtkMin 
= (PhyAtkPwrMin+(STR*PhyReinforceMin/100))*(1+ExtraPhyDamagePercent/100)
PhyAtkMax = (PhyAtkPwrMax+(STR*PhyReinforceMax/100))*(1+ExtraPhyDamagePercent/100)
MagAtkMin = (MagAtkPwrMin+(INT*MagReinforceMin/100))*(1+ExtraMagDamagePercent/100)
MagAtkMax = (MagAtkPwrMax+(INT*MagReinforceMax/100))*(1+ExtraMagDamagePercent/100)
### Your Results are on screen! ->
print("SRO Hybrid Solutions v0.0.1")
print()
print(
"HP: "+str(HP))
print(
"MP: "+str(MP))
print()
print(
"STR: "+str(STR))
print(
"INT: "+str(INT))
print(
"Stat points distribuited: "+str(StatsPointsTotal))
print()
print(
"Physical balance: "+str(int(PhysicalBalance))+"(%) "+str(PhysicalBalance))
print(
"Magical balance: "+str(int(MagicalBalance))+"(%) "+str(MagicalBalance))
print()
print(
"Phy. Atk. Pwr: "+str(int(PhyAtkMin))+" to "+str(int(PhyAtkMax)))
print(
"Mag. Atk. Pwr: "+str(int(MagAtkMin))+" to "+str(int(MagAtkMax)))
print(
"Total Atk. Pwr: "+str(int(PhyAtkMin + MagAtkMin))+" to "+str(int(PhyAtkMax + MagAtkMax)))
print(
"Total Atk. Pwr. (Critical): "+str(int(PhyAtkMin*(1+PhysicalBalance/100) + MagAtkMin))+" to "+str(int(PhyAtkMax*(1+PhysicalBalance/100) + MagAtkMax))) 
Let me know if you can :p

Edit: Oh, and to answer your question, yeah, skill should be flat added to the damage of the weapon based on the percentage it says at the end between parenthesis for each hit.
1 hit (+%100) = x1
3 hit (+%80) = x0.8 + x0.8 + x0.8 so each hit is calculated separately with different dice/roll.
10/06/2026 03:17 alangomez2#3
i recently did it to my UE project, and it was a nightmare, but if i manage to, i bet you can also, just put effort
10/06/2026 09:15 Devsome#4
Quote:
Originally Posted by alangomez2 View Post
i recently did it to my UE project, and it was a nightmare, but if i manage to, i bet you can also, just put effort
Messages like that don't help at all, so you might as well not reply.
10/06/2026 10:07 mgunbatti#5
Quote:
Originally Posted by JellyBitz View Post
I tried long ago to make the maths on how damage is calculated to know what's the best output, the break point on damage between bow hybrid builds, but I wasn't able to do it.

Here is my maths, I was able to calculate exactly hp/mp/phy and mag balance. But the most important, the damage didn't matched at all in game, I give up.

calcs.py
PHP Code:
### Define your server settings
StatsPointsPerLevel = 3
BaseSTR 
= 20
BaseINT 
= 20
### Define your character
## (Bow lv.135 | 3:0 | FullBlue | Devil 15% | Fire/Cold)
Level = 100
BalancePointsSTR 
= 1 # Ex. 9:10 => 9 STR : 10 INT
BalancePointsINT = 1
SetTotalSTR 
= 0#12*3 # 11 items * 8 STR
SetTotalINT = 0#12*3 # 11 items * 8 INT
ExtraSTR = 5
ExtraINT 
= 0
ExtraHP 
= 0#30*3
ExtraMP = 0#30*3
ExtraHPPercent = 0 # 15% Devil
ExtraMPPercent = 0 #
ExtraPhyDamagePercent = 5 # 5% avatar
ExtraMagDamagePercent = 5
### Define your weapon (Bow | Legendary D15 +15)
PhyAtkPwrMin = 6750
PhyAtkPwrMax 
= 7798
PhyReinforceMin 
= 496.7
PhyReinforceMax 
= 608.7
MagAtkPwrMin 
= 10814
MagAtkPwrMax 
= 12491
MagReinforceMin 
= 794.8
MagReinforceMax 
= 974.0

### WARNING !!!
### Math alert, read by your own risk ...
BalancePointsTotal = BalancePointsSTR+BalancePointsINT
StatsPointsTotal 
= (Level-1)*StatsPointsPerLevel
BalanceTotalSTR 
= StatsPointsTotal*(BalancePointsSTR*1.0/BalancePointsTotal)
BalanceTotalINT = StatsPointsTotal*(BalancePointsINT*1.0/BalancePointsTotal)
STR = BaseSTR + (Level-1) + BalanceTotalSTR + SetTotalSTR + ExtraSTR
INT 
= BaseINT + (Level-1) + BalanceTotalINT + SetTotalINT + ExtraINT
HP 
= round(pow(1.02,(Level-1)) * STR * 10) + ExtraHP
MP 
= round(pow(1.02,(Level-1)) * INT * 10) + ExtraMP
HP 
= HP + (ExtraHPPercent * HP / 100)
MP = MP + (ExtraMPPercent * MP / 100)

M = 28 +Level*4
PhysicalBalance 
= 100-100*2/3*(M - STR)/M  #round(100-(100*2/3*(StatsPointsTotal-STR)/StatsPointsTotal))
MagicalBalance = 100*INT/M
if PhysicalBalance > 120:
    
PhysicalBalance = 120
if MagicalBalance > 120:
    
MagicalBalance = 120

PhyAtkMin 
= (PhyAtkPwrMin+(STR*PhyReinforceMin/100))*(1+ExtraPhyDamagePercent/100)
PhyAtkMax = (PhyAtkPwrMax+(STR*PhyReinforceMax/100))*(1+ExtraPhyDamagePercent/100)
MagAtkMin = (MagAtkPwrMin+(INT*MagReinforceMin/100))*(1+ExtraMagDamagePercent/100)
MagAtkMax = (MagAtkPwrMax+(INT*MagReinforceMax/100))*(1+ExtraMagDamagePercent/100)
### Your Results are on screen! ->
print("SRO Hybrid Solutions v0.0.1")
print()
print(
"HP: "+str(HP))
print(
"MP: "+str(MP))
print()
print(
"STR: "+str(STR))
print(
"INT: "+str(INT))
print(
"Stat points distribuited: "+str(StatsPointsTotal))
print()
print(
"Physical balance: "+str(int(PhysicalBalance))+"(%) "+str(PhysicalBalance))
print(
"Magical balance: "+str(int(MagicalBalance))+"(%) "+str(MagicalBalance))
print()
print(
"Phy. Atk. Pwr: "+str(int(PhyAtkMin))+" to "+str(int(PhyAtkMax)))
print(
"Mag. Atk. Pwr: "+str(int(MagAtkMin))+" to "+str(int(MagAtkMax)))
print(
"Total Atk. Pwr: "+str(int(PhyAtkMin + MagAtkMin))+" to "+str(int(PhyAtkMax + MagAtkMax)))
print(
"Total Atk. Pwr. (Critical): "+str(int(PhyAtkMin*(1+PhysicalBalance/100) + MagAtkMin))+" to "+str(int(PhyAtkMax*(1+PhysicalBalance/100) + MagAtkMax))) 
Let me know if you can :p

Edit: Oh, and to answer your question, yeah, skill should be flat added to the damage of the weapon based on the percentage it says at the end between parenthesis for each hit.
1 hit (+%100) = x1
3 hit (+%80) = x0.8 + x0.8 + x0.8 so each hit is calculated separately with different dice/roll.
thanks bro you save me a lot of time on hp mp phy mag balance,ı cooked some damage formulas but didnt tested yet when its finished i share the code here :bandit: