From b52025ae72464ea944063110f99d05db2df3df97 Mon Sep 17 00:00:00 2001 From: Levi Schuck Date: Wed, 2 May 2018 17:42:46 -0500 Subject: [PATCH] Fix negative total XP calculation when skill starts Closes #1734 Summary: If you start a skill like fishing lobster after logging in, you will have the xpGained value as `90`. But, since you just started the skill, it will divide by `0`. This results in the max integer value of `2147483647`. If you did fletching before fishing, and had a XP per hour of `40000`. Then when you add the fishing XP per hour of `2147483647`, the result overflows and you get a negative number as the total XP per hour. Solution: Don't divide by zero, instead suppose that the skill has been active for **at least** 60 seconds. This will result in a fair estimate that improves as the skill continues to be used, rather than the ridiculous estimate of 2 Billion one second and 200K the next second. 60 seconds is chosen over 1 or 5 or 10 seconds as the result is more conservative and closer matches my hourly XP experiences. --- .../runelite/client/plugins/xptracker/XpStateSingle.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java index 20fb3a4e2d..2b263406ab 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpStateSingle.java @@ -71,7 +71,11 @@ class XpStateSingle return 0; } - long timeElapsedInSeconds = Duration.between(skillTimeStart, Instant.now()).getSeconds(); + // If the skill started just now, we can divide by near zero, this results in odd behavior. + // To prevent that, pretend the skill has been active for a minute (60 seconds) + // This will create a lower estimate for the first minute, + // but it isn't ridiculous like saying 2 billion XP per hour. + long timeElapsedInSeconds = Math.max(60, Duration.between(skillTimeStart, Instant.now()).getSeconds()); return (int) ((1.0 / (timeElapsedInSeconds / 3600.0)) * value); }