5

I'm getting mad with this problem. Well, let's begin. I want to add some modifiers to different minecraft events (such as how much damage is dealed in the EntityDamageByEntityEvent) according to a level that is stored in a MySQL database.

This level system would have 99 levels (1 to 100), beeing 50 the default level; for example, in the case of the EntityDamageByEntityEvent I'd like to change the damage so:

a) If the player had a 50 level, the damage wouldn't be modified (just would would be multiplied by 1).

b) If the player had a 1 level, the damage dealed would be multiplied by 1/3.

c) If the player had level 100, the damage would be miltiplied by 3.

So far, so good, but how could I do it in the case of a player with level 17 or 89? What I want to know is how to convert, let's say, a 1 to 100 scale in a 1/3 to 3, beeing 50 = 1... A little bit mind blowing... Thanks in advance, hope you understood me!

pitazzo
  • 1,125
  • 1
  • 13
  • 28
  • I can't believe how long I've spent trying to figure this out haha – user184994 May 18 '14 at 15:53
  • Can't you just change your design a bit, so that level 1 will be multiplied by 1, and level 50 be multiplied by 3, and level 100 multiplied by 9? That's in fact meaning the same thing but implementation is going to be much easier – Adrian Shum May 19 '14 at 03:24
  • It turns out that 1-100 is a bit strange... from 1-50 there are 49 in range, and 50-100 there are 50 in range. Will you reconsider your calculation method? – Adrian Shum May 19 '14 at 03:36

2 Answers2

3

If you plot the points (1, 1/3), (50, 1), and (100, 3) on a graph, you'll see that they don't form a line. So it's not clear how your damage-modifier function should behave between those points.

You could do it in piecewise-linear fashion, with linear interpolation from 1 to 50 and (separately) from 50 to 100:

final float scalingFactor;
if (level < 50) {
    // Convert (1..50) range into (0..1) range.
    final float interp = (level - 1) / 49.0;

    // Convert (0..1) range into (1/3..3/3) range.
    scalingFactor = ((interp * 2.0) + 1.0) / 3.0;
}
else {
    // Convert (50..100) range into (0..1) range.
    final float interp = (level - 50) / 50.0;

    // Convert (0..1) range into (1..3) range.
    scalingFactor = (interp * 2.0) + 1.0;
}

return damage * scalingFactor;

Or, if you're willing to have the 1/3 damage be at level 0 instead of 1, you could use an exponential function:

// Convert (0..100) range into (-1..+1) range.
final float interp = (level - 50) / 50.0;

// 3^(-1) == 1/3
// 3^0    == 1
// 3^(+1) == 3
final float scalingFactor = Math.pow(3.0, interp);

return damage * scalingFactor;

With the piecewise-linear approach, the difference in damage from one level to the next is the same for levels between 1 and 50, and the same for levels between 50 and 100, but the difference in damage from level 50 to 51 is significantly greater than from level 49 to 50.

The exponential function gives you a smooth curve, where the difference in damage per level increases gradually over the full range.

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • Yeah, it is. Finally I decided to separate the function in two different ecuaction, one for the line between (1, 1/3) and (50, 1) and the other for (50, 1) and (100,3) – pitazzo May 19 '14 at 22:23
0

You could do something like this:

@EventHandler
public void damage(EntityDamageEvent e){
  int i = e.getDamage();
  if(e.getDamager() instanceof Player){
    int level = //get players level here
    float multiplier = (level >= 50 ? (1 + ((1/25) * (level - 50)) : ((1/3) + (1/75) * (level - 1)));
    e.setDamage(i * multiplier);
  }
}

This will multiply the damage by 1/3 if the players level is 1, by 1 if the level is 50, and by 3 if the level is 100. This will also work for all numbers in-between.

Here's how it works:

  • There are 50 numbers between 50 (inclusive) and 100 (exclusive), and if you want to add 2 gradually in that range, you can use the fraction 2/50, or 1/25 every time the number goes up.

  • You can do the same thing, just removing 2/3 gradually within 50 values, you could remove 2/150, or 1/75 every time the number goes down.

So, for example, a level of 5 would give you 1/3 + (1/75 * (5 - 1)) = 0.386666... = 29/75 of the original damage

Jojodmo
  • 23,357
  • 13
  • 65
  • 107