combatlevel: Fix prayer level needed to next combat

This adds a test which exposes an edge case where the needed prayer
levels to next combat level had been calculated to be 3 instead of 1,
and fixes that calculation.

Fixes runelite/runelite#7103
This commit is contained in:
Jordan Atwood
2018-12-31 10:39:48 -08:00
parent 541ad1e26d
commit 5edeeb6633
2 changed files with 62 additions and 44 deletions

View File

@@ -43,9 +43,9 @@ import java.awt.Rectangle;
class CombatLevelOverlay extends Overlay
{
private static final Color COMBAT_LEVEL_COLOUR = new Color(0xff981f);
private static final double PRAY_MULT = 0.125;
static final double ATT_STR_MULT = 0.325;
static final double DEF_HP_MULT = 0.25;
static final double PRAY_MULT = 0.125;
static final double RANGE_MAGIC_LEVEL_MULT = 1.5;
static final double RANGE_MAGIC_MULT = 0.325;
@@ -109,13 +109,10 @@ class CombatLevelOverlay extends Overlay
int next = client.getLocalPlayer().getCombatLevel() + 1;
int meleeNeed = calcLevels(base + melee, next, ATT_STR_MULT);
int hpdefNeed = calcLevels(base + max, next, DEF_HP_MULT);
int prayNeed = calcLevels(base + max, next, PRAY_MULT);
int prayNeed = calcLevelsPray(base + max, next, prayerLevel);
int rangeNeed = calcLevelsRM(rangedLevel, next, base);
int magicNeed = calcLevelsRM(magicLevel, next, base);
// prayer is a special case, increasing combat every even level. need to correct its value
prayNeed = correctPrayer(prayerLevel, prayNeed);
// create tooltip string
StringBuilder sb = new StringBuilder();
sb.append(ColorUtil.wrapWithColorTag("Next combat level:</br>", COMBAT_LEVEL_COLOUR));
@@ -145,7 +142,7 @@ class CombatLevelOverlay extends Overlay
/**
* Calculate skill levels required for increasing combat level, meant
* for all combat skills besides ranged and magic.
* for all combat skills besides prayer, ranged, and magic.
* @param start initial value
* @param end ending value (combat level + 1)
* @param multiple how much adding one skill level will change combat
@@ -154,7 +151,35 @@ class CombatLevelOverlay extends Overlay
@VisibleForTesting
static int calcLevels(double start, int end, double multiple)
{
return (int) Math.ceil((end - start) / multiple);
return (int) Math.ceil(calcMultipliedLevels(start, end, multiple));
}
/**
* Calculate skill levels for increasing combat level, meant ONLY for the Prayer skill.
* <p>
* Note: Prayer is a special case, only leveling up upon even level numbers. This is accounted
* for in this function.
* </p>
* @param start current combat level
* @param end ending value (combat level + 1)
* @param prayerLevel the player's current prayer level
* @return Prayer levels required to level up combat
*/
@VisibleForTesting
static int calcLevelsPray(double start, int end, int prayerLevel)
{
final int neededLevels = (int) Math.floor(calcMultipliedLevels(start, end, PRAY_MULT));
if ((prayerLevel + neededLevels) % 2 != 0)
{
return neededLevels + 1;
}
return neededLevels;
}
private static double calcMultipliedLevels(double start, int end, double multiple)
{
return (end - start) / multiple;
}
/**
@@ -171,20 +196,4 @@ class CombatLevelOverlay extends Overlay
start = Math.floor(start * RANGE_MAGIC_LEVEL_MULT) * RANGE_MAGIC_MULT;
return (int) Math.ceil((end - dhp - start) / (RANGE_MAGIC_MULT * RANGE_MAGIC_LEVEL_MULT));
}
/**
* Corrects how many levels you need to level up combat through prayer.
* @param level current prayer level
* @param need needed prayer level calculated by calcLevels(...)
* @return a corrected number to increase combat through prayer only
*/
@VisibleForTesting
static int correctPrayer(int level, int need)
{
if ((level + need) % 2 != 0)
{
need++;
}
return need;
}
}

View File

@@ -31,11 +31,10 @@ import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.Skill;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.calcLevels;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.calcLevelsPray;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.calcLevelsRM;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.correctPrayer;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.ATT_STR_MULT;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.DEF_HP_MULT;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.PRAY_MULT;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.RANGE_MAGIC_LEVEL_MULT;
import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.RANGE_MAGIC_MULT;
import static org.junit.Assert.assertEquals;
@@ -50,10 +49,6 @@ import java.util.HashMap;
@RunWith(MockitoJUnitRunner.class)
public class CombatLevelPluginTest
{
private static final double ATT_STR_MULT = 0.325;
private static final double DEF_HP_MULT = 0.25;
private static final double PRAY_MULT = 0.125;
@Mock
@Bind
private Client client;
@@ -114,9 +109,8 @@ public class CombatLevelPluginTest
player.getCombatLevel() + 1, DEF_HP_MULT));
// test prayer
int prayNeed = calcLevels(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, PRAY_MULT);
assertEquals(5, correctPrayer(client.getRealSkillLevel(Skill.PRAYER), prayNeed));
assertEquals(5, calcLevelsPray(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER)));
// test ranged
assertEquals(2, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED),
@@ -150,9 +144,8 @@ public class CombatLevelPluginTest
player.getCombatLevel() + 1, DEF_HP_MULT));
// test prayer
int prayNeed = calcLevels(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, PRAY_MULT);
assertEquals(2, correctPrayer(client.getRealSkillLevel(Skill.PRAYER), prayNeed));
assertEquals(2, calcLevelsPray(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER)));
// test ranged
assertEquals(4, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED),
@@ -187,9 +180,8 @@ public class CombatLevelPluginTest
player.getCombatLevel() + 1, DEF_HP_MULT));
// test prayer
int prayNeed = calcLevels(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, PRAY_MULT);
assertEquals(4, correctPrayer(client.getRealSkillLevel(Skill.PRAYER), prayNeed));
assertEquals(4, calcLevelsPray(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER)));
// test ranged
assertEquals(17, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED),
@@ -224,9 +216,8 @@ public class CombatLevelPluginTest
player.getCombatLevel() + 1, DEF_HP_MULT));
// test prayer
int prayNeed = calcLevels(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, PRAY_MULT);
assertEquals(3, correctPrayer(client.getRealSkillLevel(Skill.PRAYER), prayNeed));
assertEquals(3, calcLevelsPray(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER)));
// test ranged
assertEquals(14, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED),
@@ -262,8 +253,26 @@ public class CombatLevelPluginTest
player.getCombatLevel() + 1, DEF_HP_MULT));
// test prayer
int prayNeed = calcLevels(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, PRAY_MULT);
assertEquals(4, correctPrayer(client.getRealSkillLevel(Skill.PRAYER), prayNeed));
assertEquals(4, calcLevelsPray(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER)));
}
@Test
public void testPrayerLevelsNeeded()
{
when(player.getCombatLevel()).thenReturn(124);
when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(99);
when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(99);
when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(99);
when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(89);
when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(99);
when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(99);
when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(99);
HashMap<String, Double> baseValues = getBaseValues();
// test prayer
assertEquals(1, calcLevelsPray(baseValues.get("base") + baseValues.get("max"),
player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER)));
}
}