From 51f2d0ed430922de2b8f783b3851a0bca552de33 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 16 May 2019 09:06:30 -0400 Subject: [PATCH 01/11] emoji plugin: add modprivatechat too --- .../java/net/runelite/client/plugins/emojis/EmojiPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java index bfca89c184..988e73a625 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/emojis/EmojiPlugin.java @@ -122,6 +122,7 @@ public class EmojiPlugin extends Plugin case FRIENDSCHAT: case PRIVATECHAT: case PRIVATECHATOUT: + case MODPRIVATECHAT: break; default: return; From 07680c5aa101848cd86c46f8461ecddec4aedceb Mon Sep 17 00:00:00 2001 From: Timer180 <36247639+Timer180@users.noreply.github.com> Date: Thu, 16 May 2019 10:17:22 -0700 Subject: [PATCH 02/11] Add item mapping for Tormented Bracelent (or) --- .../src/main/java/net/runelite/client/game/ItemMapping.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java index 22eed36031..782a77dc7f 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java @@ -103,6 +103,8 @@ public enum ItemMapping ITEM_OCCULT_ORNAMENT_KIT(OCCULT_ORNAMENT_KIT, OCCULT_NECKLACE_OR), ITE_AMULET_OF_FURY(AMULET_OF_FURY, AMULET_OF_FURY_OR), ITE_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR), + ITEM_TORMENTED_BRACELET(TORMENTED_BRACELET, TORMENTED_BRACELET_OR), + ITEM_TORMENTED_ORNAMENT_KIT(TORMENTED_ORNAMENT_KIT, TORMENTED_BRACELET_OR), // Ensouled heads ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD), From 6071592e578c975b9d9c37629a697dea576a1400 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 17 May 2019 00:40:52 +0200 Subject: [PATCH 03/11] Change RuneLiteAPI#apiRoot to #sessionBase - Rename apiRoot method to sessionBase method - Move /session context path to sessionBase method Signed-off-by: Tomas Slusny --- .../src/main/java/net/runelite/http/api/RuneLiteAPI.java | 4 ++-- .../src/main/java/net/runelite/client/SessionClient.java | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java index 3dee9272d9..65aeab39f1 100644 --- a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java +++ b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java @@ -95,9 +95,9 @@ public class RuneLiteAPI .build(); } - public static HttpUrl getApiRoot() + public static HttpUrl getSessionBase() { - return HttpUrl.parse(BASE); + return HttpUrl.parse(BASE + "/session"); } public static HttpUrl getApiBase() diff --git a/runelite-client/src/main/java/net/runelite/client/SessionClient.java b/runelite-client/src/main/java/net/runelite/client/SessionClient.java index 9d02ee1961..e3166dfc98 100644 --- a/runelite-client/src/main/java/net/runelite/client/SessionClient.java +++ b/runelite-client/src/main/java/net/runelite/client/SessionClient.java @@ -39,8 +39,7 @@ class SessionClient { UUID open() throws IOException { - HttpUrl url = RuneLiteAPI.getApiRoot().newBuilder() - .addPathSegment("session") + HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder() .build(); Request request = new Request.Builder() @@ -62,8 +61,7 @@ class SessionClient void ping(UUID uuid) throws IOException { - HttpUrl url = RuneLiteAPI.getApiRoot().newBuilder() - .addPathSegment("session") + HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder() .addPathSegment("ping") .addQueryParameter("session", uuid.toString()) .build(); @@ -83,8 +81,7 @@ class SessionClient void delete(UUID uuid) throws IOException { - HttpUrl url = RuneLiteAPI.getApiRoot().newBuilder() - .addPathSegment("session") + HttpUrl url = RuneLiteAPI.getSessionBase().newBuilder() .addQueryParameter("session", uuid.toString()) .build(); From e4cd2bb0b9f7375a6d803e8b324f0726ddc609bb Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 5 Mar 2019 08:30:01 +0100 Subject: [PATCH 04/11] Support specifying API endpoins via java props - Add support fo specifying runelite.session.url java prop to be used instead of RuneLite session base - Add support fo specifying runelite.http-service.url java prop to be used instead of RuneLite api base url - Add support fo specifying runelite.ws.url java prop to be used instead of RuneLite websocket url - Add support for specifying runelite.static.url java prop to be used instead of RuneLite s.r.n url Signed-off-by: Tomas Slusny --- .../net/runelite/http/api/RuneLiteAPI.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java index 65aeab39f1..472c241f72 100644 --- a/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java +++ b/http-api/src/main/java/net/runelite/http/api/RuneLiteAPI.java @@ -97,21 +97,49 @@ public class RuneLiteAPI public static HttpUrl getSessionBase() { + final String prop = System.getProperty("runelite.session.url"); + + if (prop != null && !prop.isEmpty()) + { + return HttpUrl.parse(prop); + } + return HttpUrl.parse(BASE + "/session"); } public static HttpUrl getApiBase() { + final String prop = System.getProperty("runelite.http-service.url"); + + if (prop != null && !prop.isEmpty()) + { + return HttpUrl.parse(prop); + } + return HttpUrl.parse(BASE + "/runelite-" + getVersion()); } public static HttpUrl getStaticBase() { + final String prop = System.getProperty("runelite.static.url"); + + if (prop != null && !prop.isEmpty()) + { + return HttpUrl.parse(prop); + } + return HttpUrl.parse(STATICBASE); } public static HttpUrl getWsEndpoint() { + final String prop = System.getProperty("runelite.ws.url"); + + if (prop != null && !prop.isEmpty()) + { + return HttpUrl.parse(prop); + } + return HttpUrl.parse(WSBASE); } From f21a86af41afd1b39df5c38c439fed34cc21e152 Mon Sep 17 00:00:00 2001 From: xDemoN Date: Fri, 17 May 2019 14:28:30 -0400 Subject: [PATCH 05/11] cannon: remove counter on decay --- .../java/net/runelite/client/plugins/cannon/CannonPlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java index de44d67c59..f95f21dc72 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cannon/CannonPlugin.java @@ -295,7 +295,8 @@ public class CannonPlugin extends Plugin cballsLeft = 0; } - if (event.getMessage().contains("You pick up the cannon")) + if (event.getMessage().contains("You pick up the cannon") + || event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!")) { cannonPlaced = false; cballsLeft = 0; From 61724ed0ad65a614cb300516914fb36e216e29de Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sat, 18 May 2019 14:23:03 +0200 Subject: [PATCH 06/11] Add MODPRIVATECHAT to chat command manager This allows ChatCommandManager to handle also priv messages from pmods. Signed-off-by: Tomas Slusny --- .../main/java/net/runelite/client/chat/ChatCommandManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java index d4a3964e08..b1aa9b3ac2 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatCommandManager.java @@ -98,6 +98,7 @@ public class ChatCommandManager implements ChatboxInputListener case MODCHAT: case FRIENDSCHAT: case PRIVATECHAT: + case MODPRIVATECHAT: case PRIVATECHATOUT: break; default: From 6444b1cb64313e044ee7b2579c73aa53877fd3d2 Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Fri, 17 May 2019 15:53:03 +0200 Subject: [PATCH 07/11] Add configurable bottom line contents for XP tracker Add option to switch between xp/hour and actions/hour for bottom line of XP tracker. Signed-off-by: Tomas Slusny --- .../plugins/xptracker/XpInfoBoxOverlay.java | 24 +++++++++++++++---- .../plugins/xptracker/XpTrackerConfig.java | 20 +++++++++++++++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java index 5ff11871e5..e64f398d07 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBoxOverlay.java @@ -125,14 +125,30 @@ class XpInfoBoxOverlay extends Overlay .right(StackFormatter.quantityToRSDecimalStack(rightNum, true)) .build(); - final LineComponent xpHour = LineComponent.builder() - .left("XP/Hour:") - .right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour(), true)) + final String bottemLeftStr; + final int bottomRightNum; + + switch (config.onScreenDisplayModeBottom()) + { + case ACTIONS_HOUR: + bottemLeftStr = snapshot.getActionType().getLabel() + "/Hour"; + bottomRightNum = snapshot.getActionsPerHour(); + break; + case XP_HOUR: + default: + bottemLeftStr = "XP/Hour"; + bottomRightNum = snapshot.getXpPerHour(); + break; + } + + final LineComponent xpLineBottom = LineComponent.builder() + .left(bottemLeftStr + ":") + .right(StackFormatter.quantityToRSDecimalStack(bottomRightNum, true)) .build(); final SplitComponent xpSplit = SplitComponent.builder() .first(xpLine) - .second(xpHour) + .second(xpLineBottom) .orientation(ComponentOrientation.VERTICAL) .build(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java index d3ded4f54c..b757bc1f22 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java @@ -41,6 +41,13 @@ public interface XpTrackerConfig extends Config ACTIONS_LEFT } + @AllArgsConstructor + enum OnScreenDisplayModeBottom + { + XP_HOUR, + ACTIONS_HOUR, + } + @ConfigItem( position = 0, keyName = "hideMaxed", @@ -88,11 +95,22 @@ public interface XpTrackerConfig extends Config @ConfigItem( position = 4, keyName = "onScreenDisplayMode", - name = "On-screen tracker display mode", + name = "On-screen tracker display mode (top)", description = "Configures the information displayed in the first line of on-screen XP overlays" ) default OnScreenDisplayMode onScreenDisplayMode() { return OnScreenDisplayMode.XP_GAINED; } + + @ConfigItem( + position = 4, + keyName = "onScreenDisplayMode", + name = "On-screen tracker display mode (bottom)", + description = "Configures the information displayed in the second line of on-screen XP overlays" + ) + default OnScreenDisplayModeBottom onScreenDisplayModeBottom() + { + return OnScreenDisplayModeBottom.XP_HOUR; + } } From 8026785f16c817ece70e4323dd5289baa678d4aa Mon Sep 17 00:00:00 2001 From: emerald000 Date: Mon, 20 May 2019 10:31:16 -0400 Subject: [PATCH 08/11] Refactor combat level calculations to use closed-form formulas. (#8874) * Refactor combat level calculations to use closed-form formulas. Also move most calculations to the Experience utility class. Fixes #7411. * Add new test for magic levels that barely reach the next combat level. * Add another test that breaks on master. --- .../java/net/runelite/api/Experience.java | 117 ++++- .../combatlevel/CombatLevelOverlay.java | 103 +--- .../combatlevel/CombatLevelPluginTest.java | 462 ++++++++++-------- 3 files changed, 396 insertions(+), 286 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Experience.java b/runelite-api/src/main/java/net/runelite/api/Experience.java index 088a88d544..d83a61c97b 100644 --- a/runelite-api/src/main/java/net/runelite/api/Experience.java +++ b/runelite-api/src/main/java/net/runelite/api/Experience.java @@ -24,9 +24,6 @@ */ package net.runelite.api; -import static java.lang.Math.floor; -import static java.lang.Math.max; - /** * A utility class used for calculating experience related values. *

@@ -127,6 +124,15 @@ public class Experience return high + 1; } + private static double getMeleeRangeOrMagicCombatLevelContribution(int attackLevel, int strengthLevel, int magicLevel, int rangeLevel) + { + double melee = 0.325 * (attackLevel + strengthLevel); + double range = 0.325 * (Math.floor(rangeLevel / 2) + rangeLevel); + double magic = 0.325 * (Math.floor(magicLevel / 2) + magicLevel); + + return Math.max(melee, Math.max(range, magic)); + } + /** * Calculates a non-virtual high-precision combat level without integer * rounding. @@ -146,13 +152,11 @@ public class Experience int defenceLevel, int hitpointsLevel, int magicLevel, int rangeLevel, int prayerLevel) { - double base = 0.25 * (defenceLevel + hitpointsLevel + floor(prayerLevel / 2)); + double base = 0.25 * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2)); - double melee = 0.325 * (attackLevel + strengthLevel); - double range = 0.325 * (floor(rangeLevel / 2) + rangeLevel); - double magic = 0.325 * (floor(magicLevel / 2) + magicLevel); + double typeContribution = getMeleeRangeOrMagicCombatLevelContribution(attackLevel, strengthLevel, magicLevel, rangeLevel); - return base + max(melee, max(range, magic)); + return base + typeContribution; } /** @@ -173,4 +177,101 @@ public class Experience { return (int) getCombatLevelPrecise(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, magicLevel, rangeLevel, prayerLevel); } + + /** + * Calculate number of attack/strength levels required to increase combat level. + * + * @param attackLevel the attack level + * @param strengthLevel the strength level + * @param defenceLevel the defence level + * @param hitpointsLevel the hitpoints level + * @param magicLevel the magic level + * @param rangeLevel the range level + * @param prayerLevel the prayer level + * @return the number of levels required + */ + public static int getNextCombatLevelMelee(int attackLevel, int strengthLevel, int defenceLevel, int hitpointsLevel, + int magicLevel, int rangeLevel, int prayerLevel) + { + int nextCombatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, magicLevel, rangeLevel, prayerLevel) + 1; + return (int) Math.ceil(-10. / 13 * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2) - 4 * nextCombatLevel)) - strengthLevel - attackLevel; + } + + /** + * Calculate number of hitpoints/defence levels required to increase combat level. + * + * @param attackLevel the attack level + * @param strengthLevel the strength level + * @param defenceLevel the defence level + * @param hitpointsLevel the hitpoints level + * @param magicLevel the magic level + * @param rangeLevel the range level + * @param prayerLevel the prayer level + * @return the number of levels required + */ + public static int getNextCombatLevelHpDef(int attackLevel, int strengthLevel, int defenceLevel, int hitpointsLevel, + int magicLevel, int rangeLevel, int prayerLevel) + { + int nextCombatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, magicLevel, rangeLevel, prayerLevel) + 1; + double typeContribution = Experience.getMeleeRangeOrMagicCombatLevelContribution(attackLevel, strengthLevel, magicLevel, rangeLevel); + return (int) Math.ceil(4 * nextCombatLevel - Math.floor(prayerLevel / 2) - 4 * typeContribution) - hitpointsLevel - defenceLevel; + } + + /** + * Calculate number of magic levels required to increase combat level. + * + * @param attackLevel the attack level + * @param strengthLevel the strength level + * @param defenceLevel the defence level + * @param hitpointsLevel the hitpoints level + * @param magicLevel the magic level + * @param rangeLevel the range level + * @param prayerLevel the prayer level + * @return the number of levels required + */ + public static int getNextCombatLevelMagic(int attackLevel, int strengthLevel, int defenceLevel, int hitpointsLevel, + int magicLevel, int rangeLevel, int prayerLevel) + { + int nextCombatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, magicLevel, rangeLevel, prayerLevel) + 1; + return (int) Math.ceil(2. / 3 * Math.ceil(-10. / 13 * (hitpointsLevel + defenceLevel - 4 * nextCombatLevel + Math.floor(prayerLevel / 2)))) - magicLevel; + } + + /** + * Calculate number of ranged levels required to increase combat level. + * + * @param attackLevel the attack level + * @param strengthLevel the strength level + * @param defenceLevel the defence level + * @param hitpointsLevel the hitpoints level + * @param magicLevel the magic level + * @param rangeLevel the range level + * @param prayerLevel the prayer level + * @return the number of levels required + */ + public static int getNextCombatLevelRange(int attackLevel, int strengthLevel, int defenceLevel, int hitpointsLevel, + int magicLevel, int rangeLevel, int prayerLevel) + { + int nextCombatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, magicLevel, rangeLevel, prayerLevel) + 1; + return (int) Math.ceil(2. / 3 * Math.ceil(-10. / 13 * (hitpointsLevel + defenceLevel - 4 * nextCombatLevel + Math.floor(prayerLevel / 2)))) - rangeLevel; + } + + /** + * Calculate number of prayer levels required to increase combat level. + * + * @param attackLevel the attack level + * @param strengthLevel the strength level + * @param defenceLevel the defence level + * @param hitpointsLevel the hitpoints level + * @param magicLevel the magic level + * @param rangeLevel the range level + * @param prayerLevel the prayer level + * @return the number of levels required + */ + public static int getNextCombatLevelPrayer(int attackLevel, int strengthLevel, int defenceLevel, int hitpointsLevel, + int magicLevel, int rangeLevel, int prayerLevel) + { + int nextCombatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, magicLevel, rangeLevel, prayerLevel) + 1; + double typeContribution = Experience.getMeleeRangeOrMagicCombatLevelContribution(attackLevel, strengthLevel, magicLevel, rangeLevel); + return 2 * (int) Math.ceil(-hitpointsLevel - defenceLevel + 4 * nextCombatLevel - 4 * typeContribution) - prayerLevel; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java index 6e81a7a983..01586b9e2e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelOverlay.java @@ -24,7 +24,6 @@ */ package net.runelite.client.plugins.combatlevel; -import com.google.common.annotations.VisibleForTesting; import net.runelite.api.Client; import net.runelite.api.Experience; import net.runelite.api.Skill; @@ -43,11 +42,6 @@ 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 RANGE_MAGIC_LEVEL_MULT = 1.5; - static final double RANGE_MAGIC_MULT = 0.325; private final Client client; private final CombatLevelConfig config; @@ -95,23 +89,20 @@ class CombatLevelOverlay extends Overlay int defenceLevel = client.getRealSkillLevel(Skill.DEFENCE); int hitpointsLevel = client.getRealSkillLevel(Skill.HITPOINTS); int magicLevel = client.getRealSkillLevel(Skill.MAGIC); - int rangedLevel = client.getRealSkillLevel(Skill.RANGED); + int rangeLevel = client.getRealSkillLevel(Skill.RANGED); int prayerLevel = client.getRealSkillLevel(Skill.PRAYER); - // calculate initial required numbers - double base = DEF_HP_MULT * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2)); - double melee = ATT_STR_MULT * (attackLevel + strengthLevel); - double range = RANGE_MAGIC_MULT * Math.floor(rangedLevel * RANGE_MAGIC_LEVEL_MULT); - double mage = RANGE_MAGIC_MULT * Math.floor(magicLevel * RANGE_MAGIC_LEVEL_MULT); - double max = Math.max(melee, Math.max(range, mage)); - // find the needed levels until level up - 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 = calcLevelsPray(base + max, next, prayerLevel); - int rangeNeed = calcLevelsRM(rangedLevel, next, base); - int magicNeed = calcLevelsRM(magicLevel, next, base); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int rangeNeed = Experience.getNextCombatLevelRange(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int magicNeed = Experience.getNextCombatLevelMagic(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); // create tooltip string StringBuilder sb = new StringBuilder(); @@ -121,11 +112,11 @@ class CombatLevelOverlay extends Overlay { sb.append(meleeNeed).append(" Attack/Strength
"); } - if ((hitpointsLevel + defenceLevel + hpdefNeed) <= Experience.MAX_REAL_LEVEL * 2) + if ((hitpointsLevel + defenceLevel + hpDefNeed) <= Experience.MAX_REAL_LEVEL * 2) { - sb.append(hpdefNeed).append(" Defence/Hitpoints
"); + sb.append(hpDefNeed).append(" Defence/Hitpoints
"); } - if ((rangedLevel + rangeNeed) <= Experience.MAX_REAL_LEVEL) + if ((rangeLevel + rangeNeed) <= Experience.MAX_REAL_LEVEL) { sb.append(rangeNeed).append(" Ranged
"); } @@ -133,73 +124,11 @@ class CombatLevelOverlay extends Overlay { sb.append(magicNeed).append(" Magic
"); } - if ((prayerLevel + prayNeed) <= Experience.MAX_REAL_LEVEL) + if ((prayerLevel + prayerNeed) <= Experience.MAX_REAL_LEVEL) { - sb.append(prayNeed).append(" Prayer"); + sb.append(prayerNeed).append(" Prayer"); } return sb.toString(); } - /** - * Calculate skill levels required for increasing combat level, meant - * 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 - * @return levels required for a specific skill to level up combat - */ - @VisibleForTesting - static int calcLevels(double start, int end, double multiple) - { - return (int) Math.ceil(calcMultipliedLevels(start, end, multiple)); - } - - /** - * Calculate skill levels for increasing combat level, meant ONLY for the Prayer skill. - *

- * Note: Prayer is a special case, only leveling up upon even level numbers. This is accounted - * for in this function. - *

- * @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) - { - int neededLevels = (int) Math.ceil(calcMultipliedLevels(start, end, PRAY_MULT)); - - if (prayerLevel % 2 != 0) - { - neededLevels--; - } - - if ((prayerLevel + neededLevels) % 2 != 0) - { - return neededLevels + 1; - } - - return neededLevels; - } - - private static double calcMultipliedLevels(double start, int end, double multiple) - { - return (end - start) / multiple; - } - - /** - * Calculate skill levels required for increasing combat level, meant - * ONLY for Ranged and Magic skills. - * @param start either the current ranged or magic level - * @param end ending value (combat level + 1) - * @param dhp defence, hitpoints, and prayer; this is the initial calculated "base" value - * @return levels required for a specific skill to level up combat - */ - @VisibleForTesting - static int calcLevelsRM(double start, int end, double dhp) - { - 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)); - } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java index 361fa04aea..e372ef763f 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/combatlevel/CombatLevelPluginTest.java @@ -24,209 +24,184 @@ */ package net.runelite.client.plugins.combatlevel; -import com.google.inject.Guice; -import com.google.inject.testing.fieldbinder.Bind; -import com.google.inject.testing.fieldbinder.BoundFieldModule; -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.ATT_STR_MULT; -import static net.runelite.client.plugins.combatlevel.CombatLevelOverlay.DEF_HP_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 net.runelite.api.Experience; import static org.junit.Assert.assertEquals; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import static org.mockito.Mockito.when; -import org.mockito.runners.MockitoJUnitRunner; -import java.util.HashMap; -@RunWith(MockitoJUnitRunner.class) public class CombatLevelPluginTest { - @Mock - @Bind - private Client client; - - @Mock - private Player player; - - @Before - public void setUp() - { - Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); - - when(client.getLocalPlayer()).thenReturn(player); - } - - private HashMap getBaseValues() - { - int attackLevel = client.getRealSkillLevel(Skill.ATTACK); - int strengthLevel = client.getRealSkillLevel(Skill.STRENGTH); - int defenceLevel = client.getRealSkillLevel(Skill.DEFENCE); - int hitpointsLevel = client.getRealSkillLevel(Skill.HITPOINTS); - int magicLevel = client.getRealSkillLevel(Skill.MAGIC); - int rangedLevel = client.getRealSkillLevel(Skill.RANGED); - int prayerLevel = client.getRealSkillLevel(Skill.PRAYER); - - double base = DEF_HP_MULT * (defenceLevel + hitpointsLevel + Math.floor(prayerLevel / 2)); - double melee = ATT_STR_MULT * (attackLevel + strengthLevel); - double range = RANGE_MAGIC_MULT * Math.floor(rangedLevel * RANGE_MAGIC_LEVEL_MULT); - double mage = RANGE_MAGIC_MULT * Math.floor(magicLevel * RANGE_MAGIC_LEVEL_MULT); - double max = Math.max(melee, Math.max(range, mage)); - - HashMap result = new HashMap<>(); - result.put("base", base); - result.put("melee", melee); - result.put("max", max); - return result; - } - @Test public void testNewPlayer() { - when(player.getCombatLevel()).thenReturn(3); - when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(1); - when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(1); - when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(1); - when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(1); - when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(1); - when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(1); - when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(10); + int attackLevel = 1; + int strengthLevel = 1; + int defenceLevel = 1; + int hitpointsLevel = 10; + int magicLevel = 1; + int rangeLevel = 1; + int prayerLevel = 1; - HashMap baseValues = getBaseValues(); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int rangeNeed = Experience.getNextCombatLevelRange(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int magicNeed = Experience.getNextCombatLevelMagic(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(3, combatLevel); // test attack/strength - assertEquals(2, calcLevels(baseValues.get("base") + baseValues.get("melee"), - player.getCombatLevel() + 1, ATT_STR_MULT)); + assertEquals(2, meleeNeed); // test defence/hitpoints - assertEquals(3, calcLevels(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, DEF_HP_MULT)); - - // test prayer - assertEquals(5, calcLevelsPray(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER))); + assertEquals(3, hpDefNeed); // test ranged - assertEquals(2, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(2, rangeNeed); // test magic - assertEquals(2, calcLevelsRM(client.getRealSkillLevel(Skill.MAGIC), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(2, magicNeed); + + // test prayer + assertEquals(5, prayerNeed); } @Test public void testAll10() { - when(player.getCombatLevel()).thenReturn(12); - when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(10); - when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(10); - when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(10); - when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(10); - when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(10); - when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(10); - when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(10); + int attackLevel = 10; + int strengthLevel = 10; + int defenceLevel = 10; + int hitpointsLevel = 10; + int magicLevel = 10; + int rangeLevel = 10; + int prayerLevel = 10; - HashMap baseValues = getBaseValues(); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int rangeNeed = Experience.getNextCombatLevelRange(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int magicNeed = Experience.getNextCombatLevelMagic(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(12, combatLevel); // test attack/strength - assertEquals(1, calcLevels(baseValues.get("base") + baseValues.get("melee"), - player.getCombatLevel() + 1, ATT_STR_MULT)); + assertEquals(1, meleeNeed); // test defence/hitpoints - assertEquals(1, calcLevels(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, DEF_HP_MULT)); - - // test prayer - assertEquals(2, calcLevelsPray(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER))); + assertEquals(1, hpDefNeed); // test ranged - assertEquals(4, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(4, rangeNeed); // test magic - assertEquals(4, calcLevelsRM(client.getRealSkillLevel(Skill.MAGIC), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(4, magicNeed); + + // test prayer + assertEquals(2, prayerNeed); } @Test public void testPlayerBmid() { // snapshot of current stats 2018-10-2 - when(player.getCombatLevel()).thenReturn(83); - when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(65); - when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(70); - when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(60); - when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(56); - when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(75); - when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(73); - when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(71); + int attackLevel = 65; + int strengthLevel = 70; + int defenceLevel = 60; + int hitpointsLevel = 71; + int magicLevel = 73; + int rangeLevel = 75; + int prayerLevel = 56; - HashMap baseValues = getBaseValues(); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int rangeNeed = Experience.getNextCombatLevelRange(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int magicNeed = Experience.getNextCombatLevelMagic(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(83, combatLevel); // test attack/strength - assertEquals(2, calcLevels(baseValues.get("base") + baseValues.get("melee"), - player.getCombatLevel() + 1, ATT_STR_MULT)); + assertEquals(2, meleeNeed); // test defence/hitpoints - assertEquals(2, calcLevels(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, DEF_HP_MULT)); - - // test prayer - assertEquals(4, calcLevelsPray(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER))); + assertEquals(2, hpDefNeed); // test ranged - assertEquals(17, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(17, rangeNeed); // test magic - assertEquals(19, calcLevelsRM(client.getRealSkillLevel(Skill.MAGIC), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(19, magicNeed); + + // test prayer + assertEquals(4, prayerNeed); } @Test public void testPlayerRunelite() { // snapshot of current stats 2018-10-2 - when(player.getCombatLevel()).thenReturn(43); - when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(43); - when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(36); - when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(1); - when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(15); - when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(51); - when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(64); - when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(42); + int attackLevel = 43; + int strengthLevel = 36; + int defenceLevel = 1; + int hitpointsLevel = 42; + int magicLevel = 64; + int rangeLevel = 51; + int prayerLevel = 15; - HashMap baseValues = getBaseValues(); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int rangeNeed = Experience.getNextCombatLevelRange(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int magicNeed = Experience.getNextCombatLevelMagic(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(43, combatLevel); // test attack/strength - assertEquals(18, calcLevels(baseValues.get("base") + baseValues.get("melee"), - player.getCombatLevel() + 1, ATT_STR_MULT)); + assertEquals(18, meleeNeed); // test defence/hitpoints - assertEquals(2, calcLevels(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, DEF_HP_MULT)); - - // test prayer - assertEquals(3, calcLevelsPray(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER))); + assertEquals(2, hpDefNeed); // test ranged - assertEquals(14, calcLevelsRM(client.getRealSkillLevel(Skill.RANGED), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(14, rangeNeed); // test magic - assertEquals(1, calcLevelsRM(client.getRealSkillLevel(Skill.MAGIC), - player.getCombatLevel() + 1, baseValues.get("base"))); + assertEquals(1, magicNeed); + + // test prayer + assertEquals(3, prayerNeed); } @Test @@ -234,83 +209,188 @@ public class CombatLevelPluginTest { // snapshot of current stats 2018-10-3 // Zezima cannot earn a combat level from ranged/magic anymore, so it won't show as the result is too high - when(player.getCombatLevel()).thenReturn(90); - when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(74); - when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(74); - when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(72); - when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(52); - when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(44); - when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(60); - when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(72); + int attackLevel = 74; + int strengthLevel = 74; + int defenceLevel = 72; + int hitpointsLevel = 72; + int magicLevel = 60; + int rangeLevel = 44; + int prayerLevel = 52; - HashMap baseValues = getBaseValues(); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(90, combatLevel); // test attack/strength - assertEquals(2, calcLevels(baseValues.get("base") + baseValues.get("melee"), - player.getCombatLevel() + 1, ATT_STR_MULT)); + assertEquals(2, meleeNeed); // test defence/hitpoints - assertEquals(2, calcLevels(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, DEF_HP_MULT)); + assertEquals(2, hpDefNeed); // test prayer - assertEquals(4, calcLevelsPray(baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, client.getRealSkillLevel(Skill.PRAYER))); + assertEquals(4, prayerNeed); } @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); + int attackLevel = 99; + int strengthLevel = 99; + int defenceLevel = 99; + int hitpointsLevel = 99; + int magicLevel = 99; + int rangeLevel = 99; + int prayerLevel = 89; - assertEquals(1, neededPrayerLevels()); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(124, combatLevel); + + // test prayer + assertEquals(1, prayerNeed); } @Test public void testEvenPrayerLevelsNeededWhenNearNextCombatLevel() { - when(player.getCombatLevel()).thenReturn(90); - when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(74); - when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(75); - when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(72); - when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(52); - when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(44); - when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(60); - when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(72); + int attackLevel = 74; + int strengthLevel = 75; + int defenceLevel = 72; + int hitpointsLevel = 72; + int magicLevel = 60; + int rangeLevel = 44; + int prayerLevel = 52; - assertEquals(2, neededPrayerLevels()); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(90, combatLevel); + + // test prayer + assertEquals(2, prayerNeed); } @Test public void testOddPrayerLevelsNeededWhenNearNextCombatLevel() { - when(player.getCombatLevel()).thenReturn(90); - when(client.getRealSkillLevel(Skill.ATTACK)).thenReturn(74); - when(client.getRealSkillLevel(Skill.STRENGTH)).thenReturn(75); - when(client.getRealSkillLevel(Skill.DEFENCE)).thenReturn(72); - when(client.getRealSkillLevel(Skill.PRAYER)).thenReturn(53); - when(client.getRealSkillLevel(Skill.RANGED)).thenReturn(44); - when(client.getRealSkillLevel(Skill.MAGIC)).thenReturn(60); - when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(72); + int attackLevel = 74; + int strengthLevel = 75; + int defenceLevel = 72; + int hitpointsLevel = 72; + int magicLevel = 60; + int rangeLevel = 44; + int prayerLevel = 53; - assertEquals(1, neededPrayerLevels()); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(90, combatLevel); + + // test prayer + assertEquals(1, prayerNeed); } - private int neededPrayerLevels() + @Test + public void testNextMagicLevelBarelyReachesNextCombatLevel() { - HashMap baseValues = getBaseValues(); + int attackLevel = 40; + int strengthLevel = 44; + int defenceLevel = 46; + int hitpointsLevel = 39; + int magicLevel = 57; + int rangeLevel = 40; + int prayerLevel = 29; - return calcLevelsPray( - baseValues.get("base") + baseValues.get("max"), - player.getCombatLevel() + 1, - client.getRealSkillLevel(Skill.PRAYER) - ); + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int rangeNeed = Experience.getNextCombatLevelRange(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int magicNeed = Experience.getNextCombatLevelMagic(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(52, combatLevel); + + // test attack/strength + assertEquals(3, meleeNeed); + + // test defence/hitpoints + assertEquals(3, hpDefNeed); + + // test ranged + assertEquals(18, rangeNeed); + + // test magic + assertEquals(1, magicNeed); + + // test prayer + assertEquals(5, prayerNeed); + } + + @Test + public void testRangeMagicLevelsNeeded() + { + int attackLevel = 60; + int strengthLevel = 69; + int defenceLevel = 1; + int hitpointsLevel = 78; + int magicLevel = 85; + int rangeLevel = 85; + int prayerLevel = 52; + + int combatLevel = Experience.getCombatLevel(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int meleeNeed = Experience.getNextCombatLevelMelee(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int hpDefNeed = Experience.getNextCombatLevelHpDef(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int rangeNeed = Experience.getNextCombatLevelRange(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int magicNeed = Experience.getNextCombatLevelMagic(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + int prayerNeed = Experience.getNextCombatLevelPrayer(attackLevel, strengthLevel, defenceLevel, hitpointsLevel, + magicLevel, rangeLevel, prayerLevel); + + // test combat level + assertEquals(68, combatLevel); + + // test attack/strength + assertEquals(3, meleeNeed); + + // test defence/hitpoints + assertEquals(4, hpDefNeed); + + // test ranged + assertEquals(3, rangeNeed); + + // test magic + assertEquals(3, magicNeed); + + // test prayer + assertEquals(8, prayerNeed); } } From b89d535fcbef725326e1fd864a56727941cd950c Mon Sep 17 00:00:00 2001 From: aleios Date: Wed, 22 May 2019 04:30:41 +1000 Subject: [PATCH 09/11] itemcharges: Add explorer's ring alchemy charge overlay. (#8867) --- .../main/java/net/runelite/api/Varbits.java | 10 +++- .../plugins/itemcharges/ItemChargeConfig.java | 32 ++++++++++++- .../itemcharges/ItemChargeOverlay.java | 12 ++++- .../plugins/itemcharges/ItemChargePlugin.java | 48 +++++++++++++++++++ .../plugins/itemcharges/ItemChargeType.java | 3 +- .../plugins/itemcharges/ItemWithSlot.java | 2 + 6 files changed, 103 insertions(+), 4 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index f1768c2aaf..58cdc80380 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -487,7 +487,15 @@ public enum Varbits /** * The active tab within the quest interface */ - QUEST_TAB(8168); + QUEST_TAB(8168), + + /** + * Explorer ring + */ + EXPLORER_RING_ALCHTYPE(5398), + EXPLORER_RING_TELEPORTS(4552), + EXPLORER_RING_ALCHS(4554), + EXPLORER_RING_RUNENERGY(4553); /** * The raw varbit ID. diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java index 275aa31d24..84667abcf3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeConfig.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, Devin French + * Copyright (c) 2019, Aleios * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -244,11 +245,40 @@ public interface ItemChargeConfig extends Config return true; } + @ConfigItem( + keyName = "showExplorerRingCharges", + name = "Show Explorer's Ring Alch Charges", + description = "Configures if explorer's ring alchemy charges are shown", + position = 17 + ) + default boolean showExplorerRingCharges() + { + return true; + } + + @ConfigItem( + keyName = "explorerRing", + name = "", + description = "", + hidden = true + ) + default int explorerRing() + { + return -1; + } + + @ConfigItem( + keyName = "explorerRing", + name = "", + description = "" + ) + void explorerRing(int explorerRing); + @ConfigItem( keyName = "showInfoboxes", name = "Show Infoboxes", description = "Configures whether to show an infobox equipped charge items", - position = 17 + position = 18 ) default boolean showInfoboxes() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java index 5082ab2ccd..2c8220e1a6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeOverlay.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, Seth + * Copyright (c) 2019, Aleios * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -84,6 +85,15 @@ class ItemChargeOverlay extends WidgetItemOverlay charges = config.bindingNecklace(); } + else if (itemId >= ItemID.EXPLORERS_RING_1 && itemId <= ItemID.EXPLORERS_RING_4) + { + if (!config.showExplorerRingCharges()) + { + return; + } + + charges = config.explorerRing(); + } else { ItemWithCharge chargeItem = ItemWithCharge.findItem(itemId); @@ -119,6 +129,6 @@ class ItemChargeOverlay extends WidgetItemOverlay { return config.showTeleportCharges() || config.showDodgyCount() || config.showFungicideCharges() || config.showImpCharges() || config.showWateringCanCharges() || config.showWaterskinCharges() - || config.showBellowCharges() || config.showAbyssalBraceletCharges(); + || config.showBellowCharges() || config.showAbyssalBraceletCharges() || config.showExplorerRingCharges(); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java index 3a6c44a0fb..d6b4417c55 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargePlugin.java @@ -1,6 +1,7 @@ /* * Copyright (c) 2017, Seth * Copyright (c) 2018, Hydrox6 + * Copyright (c) 2019, Aleios * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,10 +39,12 @@ import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; +import net.runelite.api.Varbits; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.events.VarbitChanged; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.Notifier; @@ -75,6 +78,9 @@ public class ItemChargePlugin extends Plugin private static final int MAX_DODGY_CHARGES = 10; private static final int MAX_BINDING_CHARGES = 16; + private static final int MAX_EXPLORER_RING_CHARGES = 30; + + private int lastExplorerRingCharge = -1; @Inject private Client client; @@ -153,6 +159,11 @@ public class ItemChargePlugin extends Plugin { removeInfobox(ItemWithSlot.BINDING_NECKLACE); } + + if (!config.showExplorerRingCharges()) + { + removeInfobox(ItemWithSlot.EXPLORER_RING); + } } @Subscribe @@ -246,6 +257,11 @@ public class ItemChargePlugin extends Plugin { updateJewelleryInfobox(ItemWithSlot.BINDING_NECKLACE, items); } + + if (config.showExplorerRingCharges()) + { + updateJewelleryInfobox(ItemWithSlot.EXPLORER_RING, items); + } } @Subscribe @@ -263,6 +279,16 @@ public class ItemChargePlugin extends Plugin } } + @Subscribe + private void onVarbitChanged(VarbitChanged event) + { + int explorerRingCharge = client.getVar(Varbits.EXPLORER_RING_ALCHS); + if (lastExplorerRingCharge != explorerRingCharge) + { + updateExplorerRingCharges(explorerRingCharge); + } + } + private void updateDodgyNecklaceCharges(final int value) { config.dodgyNecklace(value); @@ -297,6 +323,24 @@ public class ItemChargePlugin extends Plugin } } + private void updateExplorerRingCharges(final int value) + { + // Note: Varbit counts upwards. We count down from the maximum charges. + config.explorerRing(MAX_EXPLORER_RING_CHARGES - value); + + if (config.showInfoboxes() && config.showExplorerRingCharges()) + { + final ItemContainer itemContainer = client.getItemContainer(InventoryID.EQUIPMENT); + + if (itemContainer == null) + { + return; + } + + updateJewelleryInfobox(ItemWithSlot.EXPLORER_RING, itemContainer.getItems()); + } + } + private void checkDestroyWidget() { final int currentTick = client.getTickCount(); @@ -359,6 +403,10 @@ public class ItemChargePlugin extends Plugin { charges = config.bindingNecklace(); } + else if ((id >= ItemID.EXPLORERS_RING_1 && id <= ItemID.EXPLORERS_RING_4) && type == ItemWithSlot.EXPLORER_RING) + { + charges = config.explorerRing(); + } } else if (itemWithCharge.getType() == type.getType()) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java index d941bf0962..827858d4d4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemChargeType.java @@ -34,5 +34,6 @@ enum ItemChargeType WATERCAN, WATERSKIN, DODGY_NECKLACE, - BINDING_NECKLACE + BINDING_NECKLACE, + EXPLORER_RING } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java index 4ec4aa36be..16c2b0fd1b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithSlot.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2019, Tomas Slusny + * Copyright (c) 2019, Aleios * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,6 +36,7 @@ enum ItemWithSlot ABYSSAL_BRACELET(ItemChargeType.ABYSSAL_BRACELET, EquipmentInventorySlot.GLOVES), DODGY_NECKLACE(ItemChargeType.DODGY_NECKLACE, EquipmentInventorySlot.AMULET), BINDING_NECKLACE(ItemChargeType.BINDING_NECKLACE, EquipmentInventorySlot.AMULET), + EXPLORER_RING(ItemChargeType.EXPLORER_RING, EquipmentInventorySlot.RING), TELEPORT(ItemChargeType.TELEPORT, EquipmentInventorySlot.WEAPON, EquipmentInventorySlot.AMULET, EquipmentInventorySlot.GLOVES, EquipmentInventorySlot.RING); private final ItemChargeType type; From 1a375cb3f599e9bdfe78b897e92506bbfb35c407 Mon Sep 17 00:00:00 2001 From: Jouni Pikkarainen Date: Wed, 22 May 2019 20:57:28 +0300 Subject: [PATCH 10/11] Fixed incorrect bones to peaches xp value --- .../runelite/client/plugins/skillcalculator/skill_magic.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json index 15905e0a0c..0c53391ba7 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/skillcalculator/skill_magic.json @@ -460,7 +460,7 @@ "level": 60, "sprite": 354, "name": "Bones To Peaches", - "xp": 65 + "xp": 35.5 }, { "level": 61, From fac3d0cb4c4549ddb845a3060638bfbf89548055 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 22 May 2019 22:02:54 -0400 Subject: [PATCH 11/11] xptracker: fix onscreendisplaymodebottom config key --- .../net/runelite/client/plugins/xptracker/XpTrackerConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java index b757bc1f22..616844739b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpTrackerConfig.java @@ -105,7 +105,7 @@ public interface XpTrackerConfig extends Config @ConfigItem( position = 4, - keyName = "onScreenDisplayMode", + keyName = "onScreenDisplayModeBottom", name = "On-screen tracker display mode (bottom)", description = "Configures the information displayed in the second line of on-screen XP overlays" )