From 2b27e2163c6ea4cc93fc40e42927f75e6eeafdb9 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 19 Sep 2018 18:25:35 -0400 Subject: [PATCH 1/2] runelite-api: add queueChangedSkill for queueing a skill change event --- .../src/main/java/net/runelite/api/Client.java | 9 +-------- .../client/plugins/devtools/DevToolsPlugin.java | 5 +---- .../main/java/net/runelite/mixins/RSClientMixin.java | 10 ++++++++++ .../src/main/java/net/runelite/rs/api/RSClient.java | 3 --- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 6c7c8f6c10..b90dd40ed8 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1391,14 +1391,7 @@ public interface Client extends GameEngine @VisibleForDevtools int[] getSkillExperiences(); - @VisibleForDevtools - int[] getChangedSkills(); - - @VisibleForDevtools - int getChangedSkillsCount(); - - @VisibleForDevtools - void setChangedSkillsCount(int i); + void queueChangedSkill(Skill skill); /** * Sets a mapping of sprites to override. diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java index 4b50dd7181..6c0d471020 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java @@ -225,10 +225,7 @@ public class DevToolsPlugin extends Plugin client.getRealSkillLevels()[skill.ordinal()] = level; client.getSkillExperiences()[skill.ordinal()] = totalXp; - int[] skills = client.getChangedSkills(); - int count = client.getChangedSkillsCount(); - skills[++count - 1 & 31] = skill.ordinal(); - client.setChangedSkillsCount(count); + client.queueChangedSkill(skill); ExperienceChanged experienceChanged = new ExperienceChanged(); experienceChanged.setSkill(skill); diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java index 4ea887eb0b..15f270a276 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSClientMixin.java @@ -1243,4 +1243,14 @@ public abstract class RSClientMixin implements RSClient { RSClientMixin.lastItemDespawn = lastItemDespawn; } + + @Inject + @Override + public void queueChangedSkill(Skill skill) + { + int[] skills = client.getChangedSkills(); + int count = client.getChangedSkillsCount(); + skills[++count - 1 & 31] = skill.ordinal(); + client.setChangedSkillsCount(count); + } } \ No newline at end of file diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java index d3518c5c99..6e37fe19f7 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java @@ -135,15 +135,12 @@ public interface RSClient extends RSGameEngine, Client int[] getSkillExperiences(); @Import("changedSkills") - @Override int[] getChangedSkills(); @Import("changedSkillsCount") - @Override int getChangedSkillsCount(); @Import("changedSkillsCount") - @Override void setChangedSkillsCount(int i); @Import("gameState") From b81954cd60b2252db0a7b84d23f0eaac03d50bf9 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Mon, 17 Sep 2018 19:33:29 -0700 Subject: [PATCH 2/2] Add Virtual Levels plugin This plugin displays the virtual level in the denominator of given skills, and the virtual total level on the skills tab. Fixes runelite/runelite#375 Co-authored-by: Joshua Filby --- .../virtuallevels/VirtualLevelsPlugin.java | 124 ++++++ .../src/main/scripts/SkillTabBuilder.hash | 1 + .../src/main/scripts/SkillTabBuilder.rs2asm | 367 ++++++++++++++++++ .../src/main/scripts/SkillTabTotalLevel.hash | 1 + .../main/scripts/SkillTabTotalLevel.rs2asm | 83 ++++ 5 files changed, 576 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsPlugin.java create mode 100644 runelite-client/src/main/scripts/SkillTabBuilder.hash create mode 100644 runelite-client/src/main/scripts/SkillTabBuilder.rs2asm create mode 100644 runelite-client/src/main/scripts/SkillTabTotalLevel.hash create mode 100644 runelite-client/src/main/scripts/SkillTabTotalLevel.rs2asm diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsPlugin.java new file mode 100644 index 0000000000..743ad7ccf9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsPlugin.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2018, Joshua Filby + * Copyright (c) 2018, Jordan Atwood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.plugins.virtuallevels; + +import com.google.common.eventbus.Subscribe; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Experience; +import net.runelite.api.Skill; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.events.PluginChanged; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; + +@PluginDescriptor( + name = "Virtual Levels", + description = "Configuration for the virtual levels plugin.", + tags = {"skill", "total", "max"}, + enabledByDefault = false +) +public class VirtualLevelsPlugin extends Plugin +{ + private static final String TOTAL_LEVEL_TEXT_PREFIX = "Total level:
"; + + @Inject + private Client client; + + @Inject + private ClientThread clientThread; + + @Override + protected void shutDown() + { + clientThread.invoke(this::simulateSkillChange); + } + + @Subscribe + public void a(PluginChanged pluginChanged) + { + // this is guaranteed to be called after the plugin has been registered by the eventbus. startUp is not. + if (pluginChanged.getPlugin() == this) + { + clientThread.invoke(this::simulateSkillChange); + } + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent e) + { + final String eventName = e.getEventName(); + + final int[] intStack = client.getIntStack(); + final int intStackSize = client.getIntStackSize(); + final String[] stringStack = client.getStringStack(); + final int stringStackSize = client.getStringStackSize(); + + switch (eventName) + { + case "skillTabBaseLevel": + final int skillId = intStack[intStackSize - 2]; + final Skill skill = Skill.values()[skillId]; + final int exp = client.getSkillExperience(skill); + + // alter the local variable containing the level to show + intStack[intStackSize - 1] = Experience.getLevelForXp(exp); + break; + case "skillTabMaxLevel": + // alter max level constant + intStack[intStackSize - 1] = Experience.MAX_VIRT_LEVEL; + break; + case "skillTabTotalLevel": + int level = 0; + + for (Skill s : Skill.values()) + { + if (s == Skill.OVERALL) + { + continue; + } + + level += Experience.getLevelForXp(client.getSkillExperience(s)); + } + + stringStack[stringStackSize - 1] = TOTAL_LEVEL_TEXT_PREFIX + level; + break; + } + } + + private void simulateSkillChange() + { + // this fires widgets listening for all skill changes + for (Skill skill : Skill.values()) + { + if (skill != Skill.OVERALL) + { + client.queueChangedSkill(skill); + } + } + } +} diff --git a/runelite-client/src/main/scripts/SkillTabBuilder.hash b/runelite-client/src/main/scripts/SkillTabBuilder.hash new file mode 100644 index 0000000000..d679edf9ad --- /dev/null +++ b/runelite-client/src/main/scripts/SkillTabBuilder.hash @@ -0,0 +1 @@ +BE6DF54FF18E3B1D03EC67240FA1F88846AB50B8F3FC88709D0E7E69C7688107 \ No newline at end of file diff --git a/runelite-client/src/main/scripts/SkillTabBuilder.rs2asm b/runelite-client/src/main/scripts/SkillTabBuilder.rs2asm new file mode 100644 index 0000000000..a3605f9b43 --- /dev/null +++ b/runelite-client/src/main/scripts/SkillTabBuilder.rs2asm @@ -0,0 +1,367 @@ +.id 395 +.int_stack_count 3 +.string_stack_count 1 +.int_var_count 10 +.string_var_count 4 + iload 0 + get_boostedskilllevels + int_to_string + widget_put_text + iload 0 + get_realskilllevels + istore 3 + iload 0 ; load the skill id from arguments + iload 3 ; load the current real skill level + load_string "skillTabBaseLevel" ; push event name + runelite_callback ; invoke callback + istore 3 ; store the (possibly) edited real skill level + iload 3 + int_to_string + widget_put_text 1 + iload 0 + get_skillexperiences + istore 4 + load_string "," + sstore 1 + sload 0 + load_string " XP:" + string_append 2 + sstore 2 + iload 4 + sload 1 + invoke 46 + sstore 3 + load_int 0 + istore 5 + get_varbit 4181 + load_int 0 + if_icmpeq LABEL29 + jump LABEL60 +LABEL29: + iload 3 + load_int 99 + load_string "skillTabMaxLevel" ; push event name + runelite_callback ; invoke callback + if_icmplt LABEL33 + jump LABEL59 +LABEL33: + load_int 105 + load_int 105 + load_int 256 + iload 3 + load_int 1 + iadd + get_enum_value + istore 5 + sload 2 + load_string "|Next level at:|Remaining XP:" + concat_string + sstore 2 + sload 3 + load_string "|" + iload 5 + sload 1 + invoke 46 + load_string "|" + iload 5 + iload 4 + isub + sload 1 + invoke 46 + string_append 4 + concat_string + sstore 3 +LABEL59: + jump LABEL78 +LABEL60: + sload 2 + load_string "|Next level at:" + concat_string + sstore 2 + sload 3 + load_string "|" + load_int 105 + load_int 105 + load_int 256 + iload 3 + load_int 1 + iadd + get_enum_value + sload 1 + invoke 46 + string_append 2 + concat_string + sstore 3 +LABEL78: + load_int 0 + istore 6 + load_int 0 + istore 7 + load_int 0 + istore 8 + load_int 0 + istore 9 + invoke 1138 + load_int 1 + if_icmpeq LABEL90 + jump LABEL227 +LABEL90: + iload 0 + invoke 1936 + istore 6 + iload 6 + load_int -1 + if_icmpne LABEL97 + jump LABEL127 +LABEL97: + iload 6 + load_int 10 + idiv + istore 6 + iload 6 + iload 4 + if_icmpgt LABEL105 + jump LABEL127 +LABEL105: + sload 2 + load_string "|" + load_string "" + load_string "XP to regain:" + load_string "" + string_append 4 + concat_string + sstore 2 + sload 3 + load_string "|" + load_string "" + iload 6 + iload 4 + isub + sload 1 + invoke 46 + load_string "" + string_append 4 + concat_string + sstore 3 + load_int 1 + istore 7 +LABEL127: + iload 7 + load_int 0 + if_icmpeq LABEL131 + jump LABEL227 +LABEL131: + get_varp 1588 + load_int 0 + if_icmpgt LABEL135 + jump LABEL227 +LABEL135: + iload 0 + switch + 0: LABEL138 + 1: LABEL183 + 2: LABEL138 + 4: LABEL183 + 6: LABEL138 + jump LABEL227 +LABEL138: + load_int 20 + invoke 2031 + istore 9 + iload 9 + load_int 0 + if_icmpgt LABEL145 + jump LABEL164 +LABEL145: + sload 2 + load_string "|" + load_string "" + load_string "XP permitted:" + load_string "" + string_append 4 + concat_string + sstore 2 + sload 3 + load_string "|" + load_string "" + iload 9 + sload 1 + invoke 46 + load_string "" + string_append 4 + concat_string + sstore 3 + jump LABEL182 +LABEL164: + load_int 1 + istore 8 + sload 2 + load_string "|" + load_string "" + load_string "XP permitted:" + load_string "" + string_append 4 + concat_string + sstore 2 + sload 3 + load_string "|" + load_string "" + load_string "NONE" + load_string "" + string_append 4 + concat_string + sstore 3 +LABEL182: + jump LABEL227 +LABEL183: + load_int 30 + invoke 2031 + istore 9 + iload 9 + load_int 0 + if_icmpgt LABEL190 + jump LABEL209 +LABEL190: + sload 2 + load_string "|" + load_string "" + load_string "XP permitted:" + load_string "" + string_append 4 + concat_string + sstore 2 + sload 3 + load_string "|" + load_string "" + iload 9 + sload 1 + invoke 46 + load_string "" + string_append 4 + concat_string + sstore 3 + jump LABEL227 +LABEL209: + load_int 1 + istore 8 + sload 2 + load_string "|" + load_string "" + load_string "XP permitted:" + load_string "" + string_append 4 + concat_string + sstore 2 + sload 3 + load_string "|" + load_string "" + load_string "NONE" + load_string "" + string_append 4 + concat_string + sstore 3 +LABEL227: + iload 1 + load_int 5 + widget_load_child 1 + load_int 1 + if_icmpeq LABEL233 + jump LABEL243 +LABEL233: + iload 8 + load_int 1 + if_icmpeq LABEL237 + jump LABEL240 +LABEL237: + load_int 0 + widget_put_hidden 1 + jump LABEL242 +LABEL240: + load_int 1 + widget_put_hidden 1 +LABEL242: + jump LABEL270 +LABEL243: + iload 1 + load_int 5 + load_int 5 + widget_create_child 1 + load_int 6 + load_int 0 + load_int 0 + load_int 1 + widget_put_position 1 + load_int 19 + load_int 19 + load_int 0 + load_int 0 + widget_put_size 1 + load_int 940 + widget_put_spriteid 1 + load_int 65793 + widget_put_sprite2 1 + iload 8 + load_int 1 + if_icmpeq LABEL265 + jump LABEL268 +LABEL265: + load_int 0 + widget_put_hidden 1 + jump LABEL270 +LABEL268: + load_int 1 + widget_put_hidden 1 +LABEL270: + invoke 1972 + load_int 1 + if_icmpeq LABEL274 + jump LABEL301 +LABEL274: + load_int 2367 + load_int -2147483644 + load_int -2147483645 + load_int -1 + iload 2 + sload 2 + sload 3 + load_int 495 + load_string "iIiIssf" + iload 1 + widget_put_option_click_listener_widget + get_varc 218 + iload 1 + if_icmpeq LABEL289 + jump LABEL300 +LABEL289: + get_varc 217 + load_int -1 + if_icmpeq LABEL293 + jump LABEL300 +LABEL293: + iload 1 + load_int -1 + iload 2 + sload 2 + sload 3 + load_int 495 + invoke 2344 +LABEL300: + jump LABEL316 +LABEL301: + load_int 992 + load_int -2147483645 + load_int -1 + iload 2 + sload 2 + sload 3 + load_int 495 + load_int 25 + load_int 5 + idiv + load_string "IiIssfi" + iload 1 + widget_put_mouse_hover_listener_widget + load_int 0 + put_varc 2 +LABEL316: + return diff --git a/runelite-client/src/main/scripts/SkillTabTotalLevel.hash b/runelite-client/src/main/scripts/SkillTabTotalLevel.hash new file mode 100644 index 0000000000..c624387804 --- /dev/null +++ b/runelite-client/src/main/scripts/SkillTabTotalLevel.hash @@ -0,0 +1 @@ +97557341CEF7AB7480D59D0841E480DD0FD7370D12588A2C02D4A814CAA462CE \ No newline at end of file diff --git a/runelite-client/src/main/scripts/SkillTabTotalLevel.rs2asm b/runelite-client/src/main/scripts/SkillTabTotalLevel.rs2asm new file mode 100644 index 0000000000..959b0ae244 --- /dev/null +++ b/runelite-client/src/main/scripts/SkillTabTotalLevel.rs2asm @@ -0,0 +1,83 @@ +.id 396 +.int_stack_count 2 +.string_stack_count 0 +.int_var_count 2 +.string_var_count 2 + load_string "Total level:" + load_string "
" + invoke 1007 + int_to_string + string_append 3 + iload 0 + load_string "skillTabTotalLevel" ; push event name + runelite_callback ; invoke callback + widget_put_text_widget + iload 0 + widget_put_actions_null_widget + load_string "Total XP:" + sstore 0 + invoke 1008 + invoke 1009 + sstore 1 + invoke 1972 + load_int 1 + if_icmpeq LABEL18 + jump LABEL49 +LABEL18: + load_int 1 + load_string "Toggle Total XP" + iload 0 + widget_put_action_widget + load_int 2367 + load_int -2147483644 + load_int -2147483645 + load_int -1 + iload 1 + sload 0 + sload 1 + load_int 495 + load_string "iIiIssf" + iload 0 + widget_put_option_click_listener_widget + get_varc 218 + iload 0 + if_icmpeq LABEL37 + jump LABEL48 +LABEL37: + get_varc 217 + load_int -1 + if_icmpeq LABEL41 + jump LABEL48 +LABEL41: + iload 0 + load_int -1 + iload 1 + sload 0 + sload 1 + load_int 495 + invoke 2344 +LABEL48: + jump LABEL69 +LABEL49: + load_int 992 + load_int -2147483645 + load_int -1 + iload 1 + sload 0 + sload 1 + load_int 495 + load_int 25 + load_int 5 + idiv + load_string "IiIssfi" + iload 0 + widget_put_mouse_hover_listener_widget + load_int 40 + iload 1 + load_string "I" + iload 0 + widget_put_mouse_exit_listener_widget + load_int 0 + put_varc 2 +LABEL69: + return