Incorrect Effective Durability Calculations
madsmith opened this issue ยท 3 comments
I took a glance at the code and realized that Reinforced 10 basically equals Infinite durability...
This made me think about how you do the "Effective Durability" calculations and I realized that it's completely incorrect.
in ToolHelper.java under getEffectiveDurability
return (int) (toolTag.getInteger("TotalDurability") * (1f + getReinforcedLevel(toolTag) * .1f));
This says that each level of reinforcement is a 10% increase in effective durability. If this were true, then Reinforced 10 would be 2 * "Total Durability".
The correct formula is
effectiveDurability = totalDurability * ( 1 / (reinforcedLevel / 10)
At Reinforced 5, 50% (half) of the time you do not use durability, so you have effectively twice the durability. So our multiplier to total durability would be 1 / ( 1 - 5/10) = 1 / (1 - .5) = 1 / .5 = 2
If there was a Reinforced 7.5, that would be 3/4 of the time, you do not use durability, and the remaining 1/4 you do. Our total durability is used in the 1/4 of the time, the other 3/4 is effectively free so your effective durability would be 4x.
`1 / (1 - 7.5/10) = 1 / (1 - .75 ) = 1 / .25 = 4`
If we go conceptually halfway closer to Reinforced 10 and compute reinforced 8.75, we would see an 8x improvement. The closer you get to reinforced 10, the larger the improvement.
For a tool with 100 durability here is how effective durabilty would change as we make it accurate.
- Reinforced 1 - OLD 110 NEW 111
- Reinforced 2 - OLD 120 NEW 125
- Reinforced 3 - OLD 130 NEW 142
- Reinforced 4 - OLD 140 NEW 166
- Reinforced 5 - OLD 150 NEW 200
- Reinforced 6 - OLD 160 NEW 250
- Reinforced 7 - OLD 170 NEW 333
- Reinforced 8 - OLD 180 NEW 500
- Reinforced 9 - OLD 190 NEW 1000
- Reinforced 10 - OLD 200 with special case to show infinity NEW Infinity
The correct code should be
int r = getReinforcedLevel(toolTag);
return r == 10 ?
-1 :
(int) (toolTag.getInteger("TotalDurability") * ( 1f / (1f - r/10f)));
Note, we use the ternary conditional to circumvent the divide by zero. I've chosen to use -1 here as you use that elsewhere in TooltipHandler.java instead of something like Double.POSITIVE_INFINITY or Integer.MAX_VALUE.
I'd send a patch but I don't have a modding environment setup and I'm hesitant to send a patch for code that I haven't compiled myself.
That code could be simplified slightly by moving total durability into the numerator of the second term
int r = getReinforcedLevel(toolTag);
return r == 10 ?
-1 :
(int) (toolTag.getInteger("TotalDurability") / (1f - r/10f));
Thank you very much for the detailed correction. I clearly didn't think that through at all. I'll make those changes ASAP.