From 54912ca31c00f5e929ec5968f5326966c498fcae Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Tue, 2 Oct 2018 14:51:59 -0700 Subject: [PATCH 1/3] widgetinfo: Fix wilderness level definition --- .../src/main/java/net/runelite/api/widgets/WidgetInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 7808e06cba..bc8e6b3c36 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -446,7 +446,7 @@ public enum WidgetInfo PVP_CONTAINER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.PVP_WIDGET_CONTAINER), PVP_SKULL_CONTAINER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SKULL_CONTAINER), PVP_SKULL(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.SKULL), - PVP_WILDERNESS_LEVEL(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.ATTACK_RANGE), + PVP_WILDERNESS_LEVEL(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.WILDERNESS_LEVEL), PVP_BOUNTY_HUNTER_INFO(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.BOUNTY_HUNTER_INFO), PVP_BOUNTY_HUNTER_STATS(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.BOUNTY_HUNTER_STATS), PVP_KILLDEATH_COUNTER(WidgetID.PVP_GROUP_ID, WidgetID.Pvp.KILLDEATH_RATIO), From 7a3b5dd3a9909894e9450a626134a9984be9616f Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Mon, 28 Jan 2019 19:37:38 -0800 Subject: [PATCH 2/3] Add pvp widget builder script --- .../src/main/scripts/PvpWidgetBuilder.hash | 1 + .../src/main/scripts/PvpWidgetBuilder.rs2asm | 117 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 runelite-client/src/main/scripts/PvpWidgetBuilder.hash create mode 100644 runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm diff --git a/runelite-client/src/main/scripts/PvpWidgetBuilder.hash b/runelite-client/src/main/scripts/PvpWidgetBuilder.hash new file mode 100644 index 0000000000..144ac0aea6 --- /dev/null +++ b/runelite-client/src/main/scripts/PvpWidgetBuilder.hash @@ -0,0 +1 @@ +08461B2A942D4D792EEB9D9BCCEB9B11256AD8B217B1EAF1BDBA71314F816D6F \ No newline at end of file diff --git a/runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm b/runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm new file mode 100644 index 0000000000..c7173c0632 --- /dev/null +++ b/runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm @@ -0,0 +1,117 @@ +.id 388 +.int_stack_count 1 +.string_stack_count 0 +.int_var_count 3 +.string_var_count 0 + invoke 384 + istore 1 + invoke 1138 + istore 2 + iload 2 + iconst 1 + if_icmpeq LABEL8 + jump LABEL74 +LABEL8: + get_varp 1676 + iconst 4 + if_icmpgt LABEL12 + jump LABEL31 +LABEL12: + iload 1 + iconst 0 + if_icmpgt LABEL16 + jump LABEL27 +LABEL16: + get_varbit 5954 + iconst 1 + if_icmpeq LABEL20 + jump LABEL27 +LABEL20: + sconst "Level: " + iload 1 + tostring + join_string 2 + iload 0 + if_settext + jump LABEL30 +LABEL27: + sconst "Deadman" + iload 0 + if_settext +LABEL30: + jump LABEL73 +LABEL31: + get_varbit 4965 + iconst 0 + if_icmpgt LABEL35 + jump LABEL39 +LABEL35: + sconst "Protection" + iload 0 + if_settext + jump LABEL73 +LABEL39: + iload 1 + iconst 0 + if_icmpgt LABEL43 + jump LABEL54 +LABEL43: + get_varbit 5954 + iconst 1 + if_icmpeq LABEL47 + jump LABEL54 +LABEL47: + sconst "Level: " + iload 1 + tostring + join_string 2 + iload 0 + if_settext + jump LABEL73 +LABEL54: + get_varc_int 78 + iconst 1 + if_icmpeq LABEL58 + jump LABEL62 +LABEL58: + sconst "Guarded" + iload 0 + if_settext + jump LABEL73 +LABEL62: + get_varc_int 78 + iconst 2 + if_icmpeq LABEL66 + jump LABEL70 +LABEL66: + sconst "No PvP" + iload 0 + if_settext + jump LABEL73 +LABEL70: + sconst "Deadman" + iload 0 + if_settext +LABEL73: + jump LABEL88 +LABEL74: + iload 1 + iconst 0 + if_icmpgt LABEL78 + jump LABEL85 +LABEL78: + sconst "Level: " + iload 1 + tostring + join_string 2 + iload 0 + if_settext + jump LABEL88 +LABEL85: + sconst "" + iload 0 + if_settext +LABEL88: + iload 1 + invoke 387 + return From 2a5756202229512f2c2a4da14c24cd26f642422c Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Tue, 2 Oct 2018 21:44:30 -0700 Subject: [PATCH 3/3] combat level plugin: Add attack level range option This commit adds a PVP-world-like combat level range text to the wilderness level in non-PVP worlds, displaying the range of combats you can attack at any given wilderness level. Closes runelite/runelite#3103 Closes runelite/runelite#3318 --- .../combatlevel/CombatLevelConfig.java | 10 ++ .../combatlevel/CombatLevelPlugin.java | 133 +++++++++++++++++- .../src/main/scripts/PvpWidgetBuilder.rs2asm | 2 + 3 files changed, 143 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelConfig.java index cf910192f2..cc82bcea65 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelConfig.java @@ -40,4 +40,14 @@ public interface CombatLevelConfig extends Config { return true; } + + @ConfigItem( + keyName = "wildernessAttackLevelRange", + name = "Show level range in wilderness", + description = "Displays a PVP-world-like attack level range in the wilderness" + ) + default boolean wildernessAttackLevelRange() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java index a72e0bf2df..bbde15c2e0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/combatlevel/CombatLevelPlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, Devin French + * Copyright (c) 2019, Jordan Atwood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,14 +27,20 @@ package net.runelite.client.plugins.combatlevel; import com.google.inject.Provides; import java.text.DecimalFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.Experience; import net.runelite.api.GameState; import net.runelite.api.Skill; +import net.runelite.api.WorldType; +import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameTick; +import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; @@ -42,15 +49,31 @@ import net.runelite.client.ui.overlay.OverlayManager; @PluginDescriptor( name = "Combat Level", - description = "Show a more accurate combat level in Combat Options panel" + description = "Show a more accurate combat level in Combat Options panel and other combat level functions", + tags = {"wilderness", "attack", "range"} ) public class CombatLevelPlugin extends Plugin { - private final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.###"); + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.###"); + private static final String CONFIG_GROUP = "combatlevel"; + private static final String ATTACK_RANGE_CONFIG_KEY = "wildernessAttackLevelRange"; + private static final Pattern WILDERNESS_LEVEL_PATTERN = Pattern.compile("^Level: (\\d+)$"); + private static final int SKULL_CONTAINER_ADJUSTED_ORIGINAL_Y = 6; + private static final int WILDERNESS_LEVEL_TEXT_ADJUSTED_ORIGINAL_Y = 3; + private static final int MIN_COMBAT_LEVEL = 3; + + private int originalWildernessLevelTextPosition = -1; + private int originalSkullContainerPosition = -1; @Inject private Client client; + @Inject + private ClientThread clientThread; + + @Inject + private CombatLevelConfig config; + @Inject private CombatLevelOverlay overlay; @@ -67,6 +90,11 @@ public class CombatLevelPlugin extends Plugin protected void startUp() throws Exception { overlayManager.add(overlay); + + if (config.wildernessAttackLevelRange()) + { + appendAttackLevelRangeText(); + } } @Override @@ -84,6 +112,8 @@ public class CombatLevelPlugin extends Plugin combatLevelWidget.setText(widgetText.substring(0, widgetText.indexOf("."))); } } + + shutDownAttackLevelRange(); } @Subscribe @@ -112,4 +142,103 @@ public class CombatLevelPlugin extends Plugin combatLevelWidget.setText("Combat Lvl: " + DECIMAL_FORMAT.format(combatLevelPrecise)); } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!CONFIG_GROUP.equals(event.getGroup()) || !ATTACK_RANGE_CONFIG_KEY.equals(event.getKey())) + { + return; + } + + if (config.wildernessAttackLevelRange()) + { + appendAttackLevelRangeText(); + } + else + { + shutDownAttackLevelRange(); + } + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent event) + { + if (config.wildernessAttackLevelRange() + && "wildernessWidgetTextSet".equals(event.getEventName())) + { + appendAttackLevelRangeText(); + } + } + + private void appendAttackLevelRangeText() + { + final Widget wildernessLevelWidget = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL); + if (wildernessLevelWidget == null) + { + return; + } + + final String wildernessLevelText = wildernessLevelWidget.getText(); + final Matcher m = WILDERNESS_LEVEL_PATTERN.matcher(wildernessLevelText); + if (!m.matches() + || WorldType.isPvpWorld(client.getWorldType())) + { + return; + } + + final Widget skullContainer = client.getWidget(WidgetInfo.PVP_SKULL_CONTAINER); + if (originalWildernessLevelTextPosition == -1) + { + originalWildernessLevelTextPosition = wildernessLevelWidget.getOriginalY(); + } + if (originalSkullContainerPosition == -1) + { + originalSkullContainerPosition = skullContainer.getRelativeY(); + } + + final int wildernessLevel = Integer.parseInt(m.group(1)); + final int combatLevel = client.getLocalPlayer().getCombatLevel(); + + wildernessLevelWidget.setText(wildernessLevelText + "
" + combatAttackRange(combatLevel, wildernessLevel)); + wildernessLevelWidget.setOriginalY(WILDERNESS_LEVEL_TEXT_ADJUSTED_ORIGINAL_Y); + skullContainer.setOriginalY(SKULL_CONTAINER_ADJUSTED_ORIGINAL_Y); + + clientThread.invoke(wildernessLevelWidget::revalidate); + clientThread.invoke(skullContainer::revalidate); + } + + private void shutDownAttackLevelRange() + { + if (WorldType.isPvpWorld(client.getWorldType())) + { + return; + } + + final Widget wildernessLevelWidget = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL); + if (wildernessLevelWidget != null) + { + String wildernessLevelText = wildernessLevelWidget.getText(); + if (wildernessLevelText.contains("
")) + { + wildernessLevelWidget.setText(wildernessLevelText.substring(0, wildernessLevelText.indexOf("
"))); + } + wildernessLevelWidget.setOriginalY(originalWildernessLevelTextPosition); + clientThread.invoke(wildernessLevelWidget::revalidate); + } + originalWildernessLevelTextPosition = -1; + + final Widget skullContainer = client.getWidget(WidgetInfo.PVP_SKULL_CONTAINER); + if (skullContainer != null) + { + skullContainer.setOriginalY(originalSkullContainerPosition); + clientThread.invoke(skullContainer::revalidate); + } + originalSkullContainerPosition = -1; + } + + private static String combatAttackRange(final int combatLevel, final int wildernessLevel) + { + return Math.max(MIN_COMBAT_LEVEL, combatLevel - wildernessLevel) + "-" + Math.min(Experience.MAX_COMBAT_LEVEL, combatLevel + wildernessLevel); + } } diff --git a/runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm b/runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm index c7173c0632..ba8bf2ec2f 100644 --- a/runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm +++ b/runelite-client/src/main/scripts/PvpWidgetBuilder.rs2asm @@ -114,4 +114,6 @@ LABEL85: LABEL88: iload 1 invoke 387 + sconst "wildernessWidgetTextSet" ; set callback name + runelite_callback ; invoke callback return