I bring with me a question on loot generation from ARPGs. In Diablo 3, items are generated for each level range, with damage range being defined manually.

I need help with an equation that generates weapons with damage scaling up based on level.

Level 1 - LowD - Lowest Damage

Level 80 - CapD - Cap Damage

I would like to generate weapons that scale linearly in damage based on item level. So item level is an important variable.

There are two additional factors: min damage and max damage.

Damage Range Example Level X Sword: MinDmg - MaxDmg

MinDmg is a random number rolled by dice based on the linear scale with level. MaxDmg likewise, is a random number rolled by dice based on the linear scale with level.

Level 1 Sword: 1-3

Level 10 Sword: 10-15

Level 10 Sword: 9-14

Level 80 Sword: 250-300

CapD is there to set the ceiling that the maximum range can reach up to. Example is the max damage a level 80 sword can deal.


4 Answers 4


I would not define minDamage and maxDamage when generating the item at all. Your goal is to find minD and maxD, but it is important to realize that there is single damage number(in your case, as you said its linear scaling with level).
You know the damage is linear: damage = scaling_factor * item_level. For example scaling factor of sword might be 2, for dagger 1.5 and for two-handed axe it is 3. Also note I used item_level, if you want to have different quality items it might be a good idea to separate required level and item level(but you probably do that already).
The level 50 sword now has 100 damage, to introduce minD and maxD you should also define "randomness", lets call it random_factor and set it for all swords to 0.15 (=15%). Now you can get minD and maxD very easily:

minD = (1 - random_factor) * damage
maxD = (1 + random_factor) * damage

Every level 50 sword now has 85 to 115 damage. To improve randomness we will say random factor not same for all swords, but rather within some specific range, lets say from min_rndF = 0.07 to max_rnd_f = 0.24.

rnd_f = rand(min_rndF, max_rnd_f)
var sword = new Sword(level, rnd_f)

At this point you are at the solution you wanted, level 50 sword can be anywhere between 93-107 and 76-124 swords, all of these having exactly same DPS.
If you want to play with the randomness even further, you might say you dont want to have all the possibilities from above equally likely and for example want the more unbalanced versions(93-107 and 76-124) less likely so that the player would find "average" 85-115 swords more often. In that case you should also choose the distribution.
As I mentioned above, you can also separate the required(displayed) level and the actual level so player can find slightly worse or slightly better swords of same level, that can be achieved in similar manner:

rnd_f = rand(min_rndF, max_rnd_f)
rnd_l = rand(-quality_rnd/*0.1*/, quality_rnd)
var actual_level = (1 + rnd_l) * level 
var sword = new Sword(level, actual_level , rnd_f)

This way, level 50 swords can be anywhere between 84-96(low quality, low randomness), 68-111(lq, hr), 84-138(hq, hr) or 103-119(hq, lr), all equally likely. Or even all not equally likely(if you chose to use non-default distribution).

  • \$\begingroup\$ You basically summarized my current plans quite well, and reinforced my current concepts. After looking at World of Warcraft items via Wowhead, I'm pretty certain that Swords, Axes, Maces, Dagger, etc all have their own coefficients. Swords do less damage than axes, etc. And two handed weapons are almost always far stronger than their one-handed counterparts. Item quality (greens, blues, purples) also seem to provide an even further compounding coefficient. I can't glean an actual formula from the results though, because later level items in wow are just out of control. (iLvl 800+) \$\endgroup\$
    – Krythic
    Commented Jul 18, 2018 at 9:19
  • \$\begingroup\$ ... Is just absurd, and quite frankly Blizzard should have maintained the formula from the way the first 60 levels are organized, where an item level is always 5 above the required level to wield it. It seems like everything past lvl 60 is entirely exponential in terms of both iLvl and damage. It's a bad system if you ask me. In short though, the damage should depend on the weapon type, and it's quality, with a slight weapon-type-specific variance between min and Max damage. \$\endgroup\$
    – Krythic
    Commented Jul 18, 2018 at 9:25

One way to achieve it is to find a formula for the maximum damage, and one for the minimum damage, both based on the level, then find random values in-between these.

Start by devising 2 formulas: enter image description here

maxLv       = 80
maxAtLvOne  = 3
maxAtLvMax  = 300
minAtLvOne  = 1
minAtLvMax  = 250

maxAtLv( inLv )
  return inLv * ((maxAtLvMax - maxAtLvOne) / maxLv) + maxAtLvOne

minAtLv( inLv )
  return inLv * ((minAtLvMax - minAtLvOne) / minLv) + minAtLvOne

This will give you the minimums and maximums at each level.

Then you can generate your values for your weapon:

genMinMaxAtLv( inLv, outMin, outMax )
  min = minAtLv( x )
  max = maxAtLv( x )

  diff = max - min
  halfDiff = diff / 2

  outMin = min + rnd( 0, halfDiff )
  outMax = max - rnd( 0, halfDiff )

This offers the possibility to set the maximum and the minimum, and allows for generating random numbers in between.

In addition, you could also devise a 3rd and a 4th formula to replace the use of the halfDiff value used above: one for the variation of the maximum, and one for the variation of the minimum (you could also use only one for the two purposes, if it suits your needs). This furthers the control you can have on the data produced. (You could also transform this to a "minimal higher value" and a "maximal lower value".)

The graph has been made with this tool and this Load & Save string:


I recommend you to put a random valve between 1-4 depending on the type of the weapon.

That valve will mark the breach between the low and max attack valve. For example, if the valve is 1, make a rand between 5 and 10; 2 between 8 and 15...

That way depending on the type of the weapon and the valve that you have assign to them, the weapon will have a variable range of damage (for example a dagger) or less (an battle axe).

To set the base damage depending on the item lvl, you can multiply the item lvl by a base damage using the valve said before (different type of weapons can be more or less powerful in that case). For example, a dagger (wepon type 1) can have a base valve of damage 8, so you multiply the lvl by the base damage, and then using the rand function over the base damage that I have said before, to set the minimum and maximum number.


if(weaponType == 1){
   diference = rand(5, 10)
   damage = itemLvl * 8     //Being 8 the base damage for the weapon Type 1

minDamage = damage - diference/2
maxDamage = damage - diference/2

I've had a crack at something that might satisfy your needs (pseudo code below)

rand = new rand(level/2) -- 0 to level/2
min = level + rand
max = min + (level/2)

For example this will give you the following for some example levels:

Level 2: (rand = 1) min = 3 max = 4

Level 10: (rand = 4) min = 14 max = 18

Level 10: (rand = 1) min = 11 max = 12

Level 80: (rand = 35) min = 115 max = 150

If this doesn't meet your needs i can work up another solution

  • \$\begingroup\$ I just realized i haven't included cap damage in there. But it will technically be a fixed at a max with a random role of 40 (max) to 160. \$\endgroup\$
    – Lex Webb
    Commented Oct 20, 2015 at 16:27
  • \$\begingroup\$ You can edit your answer to reflect this :) \$\endgroup\$
    – Vaillancourt
    Commented Oct 20, 2015 at 16:28
  • \$\begingroup\$ I will once I'm home! \$\endgroup\$
    – Lex Webb
    Commented Oct 20, 2015 at 16:31
  • \$\begingroup\$ I've also just noticed I made a mistake in my calculations of the examples. I'm on form today! I will also fix that when I'm home. What's there now is max = min + rand \$\endgroup\$
    – Lex Webb
    Commented Oct 20, 2015 at 16:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .