What would be the math formula for this?

Dinowc

don't expect anything, prepare for everything
Reaction score
223
so I have a spell that should deal damage on each level by this order:

Level 1: 75 damage.
Level 2: 95 damage.
Level 3: 120 damage.
Level 4: 150 damage.
Level 5: 190 damage.
Level 6: 240 damage.
Level n: n damage.

as you may (or may not notice) on each level it will deal 25% more damage than on previous level (not exactly, but I rounded it :p)

so what would be the math formula for this so I can deal damage with triggers depending on spell's level?

thanks
 

Baltazhar

Active Member
Reaction score
55
A math formula for 25% rounded, is gonna be a tough nut to crack.

What I would suggest is making a Real_Array and set the damage in there.
I expect you are damaging using a trigger?

It would go something like this:
Map Ini
Set Real_Array[1]=75.00
Set Real_Array[2]=95.00
Set Real_Array[3]=120.00
...

Trigger
Unit - Have triggering unit deal Real_Array[(Level of Ability for triggering unit)] damage to targeted unit.

Would that work?
 

Dinowc

don't expect anything, prepare for everything
Reaction score
223
ye but I left that as a alternative way in case nobody finds a solution...

any other idea? :confused:
 

wraithseeker

Tired.
Reaction score
122
Code:
2.5 * N * N + 12.5 * N  + 60

Not sure if it is correct, I used a formula finder to do it by using the first 3 values.
 

Baltazhar

Active Member
Reaction score
55
It doesn't seem to add up quite.

The formula above will, at level 6, deal 225 damage, which is a bit less than the 240 wished for.
It must be possible to find a formula that increases by 25% level...

Still looking into it.

The formula above seems almost a precise +25% liniar increase.
Level 6 would be be 228.8818359375 so just out of curiosity, how much did you round up? I think you should use the formula AceHart and Wraith suggested, and change the tooltips accordingly. Having a almost liniar function with preset offsets here and there probably would be possible, but would take a month to write.

Hope that's answer enough to satisfy you.
 

Baltazhar

Active Member
Reaction score
55
That's the conclusion I reached as well, after calculation for a bit.

It's hard to find precise numbers, if the initial given values are wrong :)
 

meehael

New Member
Reaction score
6
Hi Dino,

You need to be precise in math :)
Since the growth isn't linear or simple exponential, it isn't possible to give an elementary formula.

Should the damage table look more regular, like this:
90
100
120
150
190
240

Then the formula would be really simple (in this case you see that dmg is increased by (10 * the level) from the previous level):

Code:
dmg=(5*level*level)-(5*level)+90

But, in your case I see that damage for the first three levels isn't growing regularly, while damage for levels above level 2 is growing regulary, so the precise formula in your case would be:

Code:
if level=1 then dmg=75
if level=2 then dmg=95
else if level>2 then
dmg=(5*level*level)-(5*level)+90
Regards!
 

Builder Bob

Live free or don't
Reaction score
249
Does this help? Every level 25% stronger than the last
Code:
Damage = 75 * 1.25 ^ (Level - 1)
 

No_exit

Regular User (What is Custom User Title?)
Reaction score
40
This one gives a perfect match for the first 6 levels and continues like this:
300
380
475
600
760
950
1200
1500
1900
2400
3000
3800
4800
6000
7500
9400
11800

I'd strongly advice to calculate the values at init and store them somewhere.

JASS:
set level = 1
set damage = 75
loop
    exitwhen level > 10
    set round = (R2I(damage / 100 - R2I(damage)) + R2I(damage)) * 5
    set damage = (R2I(damage / round - R2I(damage)) + R2I(damage)) * round
    call BJDebugMsg("Damage: " + R2S(damage))
    //Put here something like    set skilldamage[level] = damage
    set level = level + 1
    set damage = damage * 1.25
endloop


Edit: @ Acehart & meehael: Trying to approximate an exponential function by a second degree polynomial is not very good. If you have a lot of levels then the exponential one will go up a lot faster then the polynomial one. AceHart's level 20 number will be 1500 compared to the precise 5204 (75 * 1.25^19 as stated by Builder Bob). (My level 20 number is 6000 due to accumulated roundoffs which is what he wanted I guess.)
 

Dinowc

don't expect anything, prepare for everything
Reaction score
223
thx a bunch No_exit, your formula is just perfect

now how would I do it in GUI? :p
 

Strilanc

Veteran Scripter
Reaction score
42
The problem becomes simpler if you switch from adding 25%, rounding, adding 25%, rounding, .... to just adding 25% n times, then rounding.

JASS:

set raw_damage = 75 * Pow(1.25, level - 1)
set rounded_damage = R2I(raw_damage / 10) * 10
 

No_exit

Regular User (What is Custom User Title?)
Reaction score
40
Sorry for the late response, I didn't get the time to write a decent response to your question before.

Because I suck at GUI editing (I hate to do maths in it), I solved it with custom scripts mostly :p.

What you need to do is make a real variable which is an array called
damageSkill
(The fact that the variable doesn't have an "udg_" prefix while the one in the custom script does have one is not an error. It's just one of the differences between GUI and Jass.)

At this moment the skill is limited to 10 levels due to the loop, you can always change the index to make it work on more levels (don't forget to make the array damageSkill maximum index bigger too).

If you need to know the damage of the skill at a certain level (level = 4 for example) then just get that index (so in our example the damage will be damageSkill[4])

Trigger:
  • SomeTrigger
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: local real damage = 75.
      • Custom script: local integer round
      • For each (Integer A) from 1 to 10, do (Actions)
        • Loop - Actions
          • Custom script: set round = (R2I(damage / 100 - R2I(damage)) + R2I(damage)) * 5
          • Custom script: set damage = (R2I(damage / round - R2I(damage)) + R2I(damage)) * round
          • Custom script: set udg_damageSkill[bj_forLoopAIndex] = damage
          • Custom script: set damage = damage * 1.25
      • -------- The loop below is just for showing what the values are, you can delete it. --------
      • For each (Integer A) from 1 to 10, do (Actions)
        • Loop - Actions
          • Game - Display to (All players) the text: (Damage for level + ((String((Integer A))) + ( is + (String(damageSkill[(Integer A)])))))


@ Strilanc: I originally did it this way but the level 6 damage was just out of reach. Since he told he rounded after every step instead I tweaked it this way and managed to reconstruct a script which did what he was doing manually and managed to get his precise values. It was quite a nice challenge and I wanted to see if I could make it and it worked out perfectly :D.
 

Dinowc

don't expect anything, prepare for everything
Reaction score
223
yeah thanks I'll try it later when I get to my map again

now I think I'll go watch TV or something :p

thanks again
 

Strilanc

Veteran Scripter
Reaction score
42
@ Strilanc: I originally did it this way but the level 6 damage was just out of reach. Since he told he rounded after every step instead I tweaked it this way and managed to reconstruct a script which did what he was doing manually and managed to get his precise values. It was quite a nice challenge and I wanted to see if I could make it and it worked out perfectly :D.

I was actually talking to the OP. The values will be similar but it's easier to compute, because it doesn't require O(n) work to get the value for level n.
 

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,494
> You need to be precise in math

Indeed... :p


Original values:
75, 95, 120, 150, 190, 240

Difference from one to the next:
20, 25, 30, 40, 50

Second differences:
5, 5, 10, 10

Third differences:
0, 5, 0

Forth differences:
5, -5

Fifth differences:
-10

We finally arrived at a constant (but only because we're running out of values...).
So, a 5th degree polynomial will do (minimum! depending on how this continues it might be even worse).
Which is nice or so, but not really doable.


On the other hand, if the differences had been:
20, 25, 30, 35, 40 (With all second differences being identical: 5)
The entire thing would simplify to a second degree formula (see post #4).


Of course, one can always go with "the more complicated, the more better",
but, well, why not simply correct the initial wish?

A basic formula compared to an iterative function.


Amazing thread really... :p
 

No_exit

Regular User (What is Custom User Title?)
Reaction score
40
I was actually talking to the OP. The values will be similar but it's easier to compute, because it doesn't require O(n) work to get the value for level n.

True but you can calculate the values at map initialization and so all he needs to do now is get a value from the array which is O(1). If you would calculate the damage as 75 * Pow(1.25, level-1) then the most efficient Pow algorithm I know is O(log(level)).

JASS:
function MyPow takes real x, integer n returns real
    local real factor = 1.
    local boolean negative = (n < 0)
    if negative then
        set n = -n
    endif
    loop
        exitwhen n <= 1
        If n / 2 * 2 != n then //n is uneven
            set factor = factor * x
            // set n = n - 1 //This line is commented because it's not needed due to rounding off further down, I didn't delete it because it increases readability.
        endif
        //x^n = (x^2)^(n/2)
        set x = x * x
        set n = n / 2
    endloop
    if negative then
        return 1./(x*factor)
    else
        return x*factor
    endif
endfunction

I have no clue what a good implementation for powers with real numbers is tho :(.

So, a 5th degree polynomial will do (minimum! depending on how this continues it might be even worse).
Which is nice or so, but not really doable.

That's not very hard because through every n points there is precisely one n-1 degree polynomial that goes through it. This n-1 degree polynomial will in general be a very bad(!) function to predict future points tho (which is something I learned and tested in one of my Math courses; it managed to predict the function would drop down very fast and go to minus infinite even tho the function was slowly rising all the time).

On the other hand, if the differences had been:
20, 25, 30, 35, 40 (With all second differences being identical: 5)
The entire thing would simplify to a second degree formula (see post #4).

1.25^level <--- This is the "simple" shape he needs: 25% increase each level (exponential)
level^2 <--- This is what you are trying to give him (2nd degree polynomial)

Maybe this will convince you more about the difference between them:
The relationschip between exponentials and polynomials is given here:
0bc08045195dc823c22d1fa283cb0759.png

If you would only calculate the first 3 terms of that sum then the higher the x (or in our case level) is, the more off you'll have cutted off since higher powers of x will grow much faster then the lower ones.

Balancing wise, exponentials mean that a level 10 will lose just as bad versus a level 20 as a level 80 will lose to a level 90, since the 10 level difference will always result in a factor of (1.25)^10 stronger. This is nice for RPGs where you want to give a good reward for levelling the last hardest levels and giving the heroes new areas to fight instead of fighting the same creeps over and over with maybe maximum 1-2% more damage for each level, zzz.

A basic formula compared to an iterative function.
It's only iterative due to the accumulate rounding off else it would have been something like this (which is pretty basic except for the rounding off which just looks weird but the idea is that I just take something like 3 significant numbers and rounds up from there. But that's how humans think, they see differences between 21 and 29 but not between 84121 and 84129)
JASS:
set damage = 75. * Pow(1.25,level-1) //This is the raw damage before rounding, a very basic formula.
set round = (R2I(damage / 100 - R2I(damage)) + R2I(damage)) * 5
set damage = (R2I(damage / round - R2I(damage)) + R2I(damage)) * round

The fact that in my original formula the next value is based on the rounded version of the previous one makes sure that the minimum difference between the previous and the next is at least 25% which otherwise could not be guaranteed (unless if you take a base increase of for example 30% and then start rounding). Why would this not be a nice property to have?

but, well, why not simply correct the initial wish?
Personally if I needed the forumula myself I would do it like the one I posted in this post but since I'm here to help dinowc and not here to force him to do it my way, I just gave him what he asked and if it's not quite what he wants then he'll have learned something and be open to modifications.

Edit: w00t 50th post and it's a beauty :p.
 

Dinowc

don't expect anything, prepare for everything
Reaction score
223
LOL you guys posted all that cause of 1 damn formula I need for a simple spell that should deal damage by that order? xD

if I knew that it will be so hard I would just use normal fixed values :p (like I said in post #3)

well sorry for killing your brains and thanks all :thup:
 

Builder Bob

Live free or don't
Reaction score
249
(...)
if I knew that it will be so hard (...)

Well, it's not really a hard problem. It's just that you can approach it from different directions, and thus come to different conclusions.

Either can be right depending on what the designer were trying to accomplish to begin with. Something nobody but you know.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top