diff --git a/runelite-api/src/main/java/net/runelite/api/ModelID.java b/runelite-api/src/main/java/net/runelite/api/ModelID.java new file mode 100644 index 0000000000..0a2ea46816 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/ModelID.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Magic fTail + * 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.api; + +public final class ModelID +{ + public static final int ANVIL = 1251; + public static final int WILLOW_TREE = 1570; + public static final int SLAYER_SKILL_MODEL = 1733; + public static final int FIREMAKING_SKILL_MODEL = 2260; + public static final int STEEL_KITESHIELD = 2339; + public static final int PURE_ESSENCE = 2349; + public static final int RAW_TUNA = 2355; + public static final int CLEAN_HERB = 2364; + public static final int HAMMER = 2376; + public static final int BLUE_WIZARD_HAT = 2483; + public static final int CHISEL = 2489; + public static final int HIGHWAYMAN_MASK = 2500; + public static final int STEEL_PICKAXE = 2529; + public static final int SHORTBOW = 2562; + public static final int STEEL_LONGSWORD = 2602; + public static final int STEEL_SWORD = 2604; + public static final int STEEL_ARROW = 2711; + public static final int PRAYER_SKILL_MODEL = 3325; + public static final int STRENGTH_SKILL_MODEL = 3327; + public static final int AGILITY_SKILL_MODEL = 3328; + public static final int HEARTH = 3326; + public static final int WATERING_CAN = 7331; + public static final int SAW = 12309; + public static final int FOOTPRINT = 19980; + public static final int COOKING_SKILL_MODEL = 27611; +} \ No newline at end of file diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index 55a51700a7..b8cb626ae6 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -242,13 +242,6 @@ public interface Widget */ void setName(String name); - /** - * Gets the model ID displayed in the widget. - * - * @return the model ID - */ - int getModelId(); - /** * Gets the sprite ID displayed in the widget. * @@ -294,6 +287,76 @@ public interface Widget */ int getIndex(); + /** + * Gets the model ID displayed in the widget. + * + * @return the model ID + */ + int getModelId(); + + /** + * Sets the model ID displayed in the widget + * + * @param modelId the new model ID + */ + void setModelId(int modelId); + + /** + * Gets the x rotation of the model displayed in the widget + * + * @return the x rotation + */ + int getRotationX(); + + /** + * Sets the x rotation of the model displayed in the widget + * + * @param rotationX 0 = no rotation, 2047 = full rotation, outside range = crash + */ + void setRotationX(int rotationX); + + /** + * Gets the y rotation of the model displayed in the widget + * + * @return the y rotation + */ + int getRotationY(); + + /** + * Sets the y rotation of the model displayed in the widget + * + * @param rotationY 0 = no rotation, 2047 = full rotation, outside range = crash + */ + void setRotationY(int rotationY); + + /** + * Gets the z rotation of the model displayed in the widget + * + * @return the z rotation + */ + int getRotationZ(); + + /** + * Sets the z rotation of the model displayed in the widget + * + * @param rotationZ 0 = no rotation, 2047 = full rotation, outside range = crash + */ + void setRotationZ(int rotationZ); + + /** + * Gets the amount zoomed in on the model displayed in the widget + * + * @return the amount zoomed in + */ + int getModelZoom(); + + /** + * Sets the amount zoomed in on the model displayed in the widget + * + * @param modelZoom the new zoom amount + */ + void setModelZoom(int modelZoom); + /** * Gets the location the widget is being drawn on the canvas. *

diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java index a4a82072fe..c8a41586f4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java @@ -76,6 +76,7 @@ import net.runelite.api.util.Text; import net.runelite.api.widgets.Widget; import static net.runelite.api.widgets.WidgetID.BARROWS_REWARD_GROUP_ID; import static net.runelite.api.widgets.WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID; +import static net.runelite.api.widgets.WidgetID.CHATBOX_GROUP_ID; import static net.runelite.api.widgets.WidgetID.CLUE_SCROLL_REWARD_GROUP_ID; import static net.runelite.api.widgets.WidgetID.DIALOG_SPRITE_GROUP_ID; import static net.runelite.api.widgets.WidgetID.KINGDOM_GROUP_ID; @@ -303,11 +304,11 @@ public class ScreenshotPlugin extends Plugin String fileName = null; if (client.getWidget(WidgetInfo.LEVEL_UP_LEVEL) != null) { - fileName = parseLevelUpWidget(WidgetInfo.LEVEL_UP_LEVEL); + fileName = parseLevelUpWidget(client.getWidget(WidgetInfo.LEVEL_UP_LEVEL)); } else if (client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT) != null) { - fileName = parseLevelUpWidget(WidgetInfo.DIALOG_SPRITE_TEXT); + fileName = parseLevelUpWidget(client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT)); } else if (client.getWidget(WidgetInfo.QUEST_COMPLETED_NAME_TEXT) != null) { @@ -315,6 +316,10 @@ public class ScreenshotPlugin extends Plugin String text = client.getWidget(WidgetInfo.QUEST_COMPLETED_NAME_TEXT).getText(); fileName = "Quest(" + text.substring(19, text.length() - 1) + ")"; } + else if (client.getWidget(WidgetInfo.CHATBOX_CONTAINER).getChild(1) != null) + { + fileName = parseLevelUpWidget(client.getWidget(WidgetInfo.CHATBOX_CONTAINER).getChild(1)); + } if (fileName != null) { @@ -485,6 +490,7 @@ public class ScreenshotPlugin extends Plugin break; case LEVEL_UP_GROUP_ID: case DIALOG_SPRITE_GROUP_ID: + case CHATBOX_GROUP_ID: if (!this.screenshotLevels) { return; @@ -549,6 +555,7 @@ public class ScreenshotPlugin extends Plugin case LEVEL_UP_GROUP_ID: case DIALOG_SPRITE_GROUP_ID: case QUEST_COMPLETED_GROUP_ID: + case CHATBOX_GROUP_ID: { // level up widget gets loaded prior to the text being set, so wait until the next tick shouldTakeScreenshot = true; @@ -574,22 +581,21 @@ public class ScreenshotPlugin extends Plugin } /** - * Receives a WidgetInfo pointing to the middle widget of the level-up dialog, + * Receives a Widget containing the level-up dialog, * and parses it into a shortened string for filename usage. * - * @param levelUpLevel WidgetInfo pointing to the required text widget, - * with the format "Your Skill (level is/are) now 99." + * @param levelUpWidget Widget containing the level-up text, + * with the format "Your Skill (level is/are) now 99." * @return Shortened string in the format "Skill(99)" */ - String parseLevelUpWidget(WidgetInfo levelUpLevel) + String parseLevelUpWidget(Widget levelUpWidget) { - Widget levelChild = client.getWidget(levelUpLevel); - if (levelChild == null) + if (levelUpWidget == null) { return null; } - Matcher m = LEVEL_UP_PATTERN.matcher(levelChild.getText()); + Matcher m = LEVEL_UP_PATTERN.matcher(levelUpWidget.getText()); if (!m.matches()) { return null; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/SkillModel.java b/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/SkillModel.java new file mode 100644 index 0000000000..dceeccde42 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/SkillModel.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, Magic fTail + * 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.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import java.util.List; +import lombok.Getter; +import net.runelite.api.ModelID; +import net.runelite.api.Skill; + +@Getter +public enum SkillModel +{ + CONSTRUCTION1(Skill.CONSTRUCTION, ModelID.HAMMER, 10, 14, 669, 15, 0, 329), + CONSTRUCTION2(Skill.CONSTRUCTION, ModelID.SAW, 11, 14, 615, 111, 0, 451), + COOKING(Skill.COOKING, ModelID.COOKING_SKILL_MODEL, 31, 59, 169, 1593, 0, 963), + CRAFTING1(Skill.CRAFTING, ModelID.HAMMER, 30, 24, 418, 14, 0, 496), + CRAFTING2(Skill.CRAFTING, ModelID.CHISEL, 39, 45, 353, 18, 0, 400), + DEFENCE(Skill.DEFENCE, ModelID.STEEL_KITESHIELD, 34, 37, 337, 1074, 0, 598), + FARMING(Skill.FARMING, ModelID.WATERING_CAN, 31, 52, 118, 1278, 0, 451), + FIREMAKING(Skill.FIREMAKING, ModelID.FIREMAKING_SKILL_MODEL, 29, 55, 115, 1689, 0, 771), + FISHING(Skill.FISHING, ModelID.RAW_TUNA, 33, 30, 351, 1865, 0, 517), + FLETCHING1(Skill.FLETCHING, ModelID.STEEL_ARROW, 43, 19, 254, 1257, 0, 408), + FLETCHING2(Skill.FLETCHING, ModelID.STEEL_ARROW, 46, 44, 223, 177, 0, 444), + HERBLORE(Skill.HERBLORE, ModelID.CLEAN_HERB, 20, 35, 550, 2024, 0, 344), + HITPOINTS(Skill.HITPOINTS, ModelID.HEARTH, 35, 58, 538, 0, 0, 250), + MAGIC(Skill.MAGIC, ModelID.BLUE_WIZARD_HAT, 29, 50, 131, 1913, 0, 344), + MINING(Skill.MINING, ModelID.STEEL_PICKAXE, 38, 33, 292, 1166, 0, 413), + PRAYER(Skill.PRAYER, ModelID.PRAYER_SKILL_MODEL, 29, 27, 582, 504, 0, 505), + RANGED1(Skill.RANGED, ModelID.STEEL_ARROW, 28, 34, 206, 195, 0, 405), + RANGED2(Skill.RANGED, ModelID.SHORTBOW, 42, 17, 422, 1618, 0, 397), + RUNECRAFT(Skill.RUNECRAFT, ModelID.PURE_ESSENCE, 35, 38, 242, 1979, 0, 328), + SLAYER(Skill.SLAYER, ModelID.SLAYER_SKILL_MODEL, 34, 60, 221, 1944, 0, 649), + SMITHING(Skill.SMITHING, ModelID.ANVIL, 34, 53, 97, 1868, 0, 716), + STRENGTH(Skill.STRENGTH, ModelID.STRENGTH_SKILL_MODEL, 35, 23, 512, 14, 0, 631), + AGILITY(Skill.AGILITY, ModelID.AGILITY_SKILL_MODEL, 29, 29, 533, 2040, 0, 685), + THIEVING(Skill.THIEVING, ModelID.HIGHWAYMAN_MASK, 42, 31, 366, 55, 0, 155), + WOODCUTTING(Skill.WOODCUTTING, ModelID.WILLOW_TREE, 20, 69, 116, 1978, 0, 1800), + ATTACK1(Skill.ATTACK, ModelID.STEEL_SWORD, 65, 38, 234, 148, 0, 444), + ATTACK2(Skill.ATTACK, ModelID.STEEL_LONGSWORD, 27, 29, 198, 1419, 0, 330), + HUNTER(Skill.HUNTER, ModelID.FOOTPRINT, 45, 48, 512, 0, 0, 1000); + + private static final ListMultimap skillModels = ArrayListMultimap.create(); + + private final Skill skill; + private final int modelID; + private final int originalX; + private final int originalY; + private final int rotationX; + private final int rotationY; + private final int rotationZ; + private final int modelZoom; + + SkillModel(Skill skill, int modelID, int originalX, int originalY, int rotationX, int rotationY, int rotationZ, int modelZoom) + { + this.skill = skill; + this.modelID = modelID; + this.originalX = originalX; + this.originalY = originalY; + this.rotationX = rotationX; + this.rotationY = rotationY; + this.rotationZ = rotationZ; + this.modelZoom = modelZoom; + } + + static + { + for (SkillModel skillModel : values()) + { + skillModels.put(skillModel.skill, skillModel); + } + } + + public static List getSkillModels(Skill skill) + { + return skillModels.get(skill); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsConfig.java index 83bacd8b8f..9028bc6fe7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/virtuallevels/VirtualLevelsConfig.java @@ -31,11 +31,22 @@ import net.runelite.client.config.ConfigItem; @ConfigGroup("virtuallevels") public interface VirtualLevelsConfig extends Config { + @ConfigItem( + keyName = "virtualMessage", + name = "Enable level up message for virtual levels", + description = "Configures whether or not to show level up messages for virtual levels", + position = 0 + ) + default boolean virtualMessage() + { + return true; + } + @ConfigItem( keyName = "virtualTotalLevel", name = "Virtual Total Level", description = "Count virtual levels towards total level", - position = 0 + position = 1 ) default boolean virtualTotalLevel() { 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 index 3e9d3d0f54..8e5188c844 100644 --- 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 @@ -1,6 +1,7 @@ /* * Copyright (c) 2018, Joshua Filby * Copyright (c) 2018, Jordan Atwood + * Copyright (c) 2018, Magic fTail * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,17 +27,40 @@ package net.runelite.client.plugins.virtuallevels; import com.google.inject.Provides; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; import javax.inject.Inject; import javax.inject.Singleton; import net.runelite.api.Client; import net.runelite.api.Experience; +import net.runelite.api.FontID; +import net.runelite.api.GameState; +import net.runelite.api.ScriptID; import net.runelite.api.Skill; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.events.StatChanged; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.api.widgets.WidgetType; import net.runelite.client.callback.ClientThread; import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.PluginChanged; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -47,9 +71,14 @@ import net.runelite.client.plugins.PluginDescriptor; enabledByDefault = false ) @Singleton -public class VirtualLevelsPlugin extends Plugin +public class VirtualLevelsPlugin extends Plugin implements KeyListener { private static final String TOTAL_LEVEL_TEXT_PREFIX = "Total level:
"; + private static final int X_OFFSET = 13; + private static final int Y_OFFSET = 16; + + private final Map previousXpMap = new EnumMap<>(Skill.class); + private final List skillsLeveledUp = new ArrayList<>(); @Inject private VirtualLevelsConfig config; @@ -60,6 +89,16 @@ public class VirtualLevelsPlugin extends Plugin @Inject private ClientThread clientThread; + @Inject + private EventBus eventBus; + + @Inject + private KeyManager keyManager; + + private boolean loginTick = false; + private boolean closeMessage; + private boolean messageOpen; + @Provides VirtualLevelsConfig provideConfig(ConfigManager configManager) { @@ -71,6 +110,7 @@ public class VirtualLevelsPlugin extends Plugin protected void shutDown() { clientThread.invoke(this::simulateSkillChange); + keyManager.unregisterKeyListener(this); } @Subscribe @@ -79,6 +119,7 @@ public class VirtualLevelsPlugin extends Plugin // this is guaranteed to be called after the plugin has been registered by the eventbus. startUp is not. if (pluginChanged.getPlugin() == this) { + keyManager.registerKeyListener(this); clientThread.invoke(this::simulateSkillChange); } } @@ -151,4 +192,228 @@ public class VirtualLevelsPlugin extends Plugin } } } + + private void buildVirtualLevelUp(Skill skill) + { + Widget chatboxContainer = client.getWidget(WidgetInfo.CHATBOX_CONTAINER); + + if (chatboxContainer == null) + { + return; + } + + String skillName = skill.getName(); + int skillLevel = Experience.getLevelForXp(client.getSkillExperience(skill)); + List skillModels = SkillModel.getSkillModels(skill); + String prefix = (skill == Skill.AGILITY || skill == Skill.ATTACK) ? "an " : "a "; + + Widget levelUpLevel = chatboxContainer.createChild(-1, WidgetType.TEXT); + Widget levelUpText = chatboxContainer.createChild(-1, WidgetType.TEXT); + Widget levelUpContinue = chatboxContainer.createChild(-1, WidgetType.TEXT); + + levelUpLevel.setText("Congratulations, you just advanced " + prefix + skillName + " level."); + levelUpLevel.setTextColor(0x000080); + levelUpLevel.setFontId(FontID.QUILL_8); + levelUpLevel.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpLevel.setOriginalX(73 + X_OFFSET); + levelUpLevel.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpLevel.setOriginalY(15 + Y_OFFSET); + levelUpLevel.setOriginalWidth(390); + levelUpLevel.setOriginalHeight(30); + levelUpLevel.setXTextAlignment(WidgetTextAlignment.CENTER); + levelUpLevel.setYTextAlignment(WidgetTextAlignment.LEFT); + levelUpLevel.setWidthMode(WidgetSizeMode.ABSOLUTE); + levelUpLevel.revalidate(); + + levelUpText.setText((skill == Skill.HITPOINTS ? "Your Hitpoints are now " + skillLevel : + "Your " + skillName + " level is now " + skillLevel) + "."); + levelUpText.setFontId(FontID.QUILL_8); + levelUpText.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpText.setOriginalX(73 + X_OFFSET); + levelUpText.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpText.setOriginalY(44 + Y_OFFSET); + levelUpText.setOriginalWidth(390); + levelUpText.setOriginalHeight(30); + levelUpText.setXTextAlignment(WidgetTextAlignment.CENTER); + levelUpText.setYTextAlignment(WidgetTextAlignment.LEFT); + levelUpText.setWidthMode(WidgetSizeMode.ABSOLUTE); + levelUpText.revalidate(); + + levelUpContinue.setText("Click here to continue"); + levelUpContinue.setTextColor(0x0000ff); + levelUpContinue.setFontId(FontID.QUILL_8); + levelUpContinue.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpContinue.setOriginalX(73 + X_OFFSET); + levelUpContinue.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpContinue.setOriginalY(74 + Y_OFFSET); + levelUpContinue.setOriginalWidth(390); + levelUpContinue.setOriginalHeight(17); + levelUpContinue.setXTextAlignment(WidgetTextAlignment.CENTER); + levelUpContinue.setYTextAlignment(WidgetTextAlignment.LEFT); + levelUpContinue.setWidthMode(WidgetSizeMode.ABSOLUTE); + levelUpContinue.setAction(0, "Continue"); + levelUpContinue.setOnOpListener((JavaScriptCallback) ev -> closeNextTick()); + levelUpContinue.setOnMouseOverListener((JavaScriptCallback) ev -> levelUpContinue.setTextColor(0xFFFFFF)); + levelUpContinue.setOnMouseLeaveListener((JavaScriptCallback) ev -> levelUpContinue.setTextColor(0x0000ff)); + levelUpContinue.setHasListener(true); + levelUpContinue.revalidate(); + + for (SkillModel skillModel : skillModels) + { + buildWidgetModel(chatboxContainer, skillModel); + } + + messageOpen = true; + } + + private void buildWidgetModel(Widget chatboxContainer, SkillModel model) + { + int iconWidth = 32; + int iconHeight = 32; + + if (model.getSkill() == Skill.CONSTRUCTION) + { + iconWidth = 49; + iconHeight = 61; + } + + Widget levelUpModel = chatboxContainer.createChild(-1, WidgetType.MODEL); + + levelUpModel.setModelId(model.getModelID()); + levelUpModel.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpModel.setOriginalX(model.getOriginalX() + X_OFFSET); + levelUpModel.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + levelUpModel.setOriginalY(model.getOriginalY() + Y_OFFSET); + levelUpModel.setOriginalWidth(iconWidth); + levelUpModel.setOriginalHeight(iconHeight); + levelUpModel.setRotationX(model.getRotationX()); + levelUpModel.setRotationY(model.getRotationY()); + levelUpModel.setRotationZ(model.getRotationZ()); + levelUpModel.setModelZoom(model.getModelZoom()); + levelUpModel.revalidate(); + } + + private void closeNextTick() + { + if (!messageOpen) + { + return; + } + + Widget levelUpContinue = client.getWidget(WidgetInfo.CHATBOX_CONTAINER).getChild(2); + + levelUpContinue.setText("Please wait..."); + + messageOpen = false; + closeMessage = true; + } + + @Subscribe + public void onGameStateChanged(GameStateChanged event) + { + if (event.getGameState() == GameState.LOGIN_SCREEN) + { + loginTick = true; + return; + } + + if (event.getGameState() != GameState.LOGGED_IN) + { + return; + } + + for (Skill skill : Skill.values()) + { + previousXpMap.put(skill, client.getSkillExperience(skill)); + } + } + + @Subscribe + public void onStatChanged(StatChanged event) + { + if (loginTick) + { + return; + } + + Skill skill = event.getSkill(); + + int xpAfter = client.getSkillExperience(skill); + int levelAfter = Experience.getLevelForXp(xpAfter); + + int xpBefore = previousXpMap.get(skill); + int levelBefore = Experience.getLevelForXp(xpBefore); + + previousXpMap.put(skill, xpAfter); + + if (!config.virtualMessage() || levelAfter < 100 || levelBefore >= levelAfter) + { + return; + } + + skillsLeveledUp.add(skill); + } + + @Subscribe + public void onGameTick(GameTick event) + { + loginTick = false; + + if (closeMessage) + { + clientThread.invoke(() -> client.runScript( + ScriptID.MESSAGE_LAYER_CLOSE, + 1, + 1 + )); + + closeMessage = false; + } + + if (skillsLeveledUp.isEmpty()) + { + return; + } + + Widget chatboxContainer = client.getWidget(WidgetInfo.CHATBOX_CONTAINER); + + if (chatboxContainer != null && !chatboxContainer.isHidden()) + { + return; + } + + Skill skill = skillsLeveledUp.get(0); + + skillsLeveledUp.remove(skill); + + clientThread.invoke(() -> client.runScript(ScriptID.MESSAGE_LAYER_OPEN)); + clientThread.invoke(() -> buildVirtualLevelUp(skill)); + WidgetLoaded widgetLoaded = new WidgetLoaded(); + widgetLoaded.setGroupId(WidgetID.CHATBOX_GROUP_ID); + eventBus.post(WidgetLoaded.class, widgetLoaded); + } + + @Override + public void keyTyped(KeyEvent e) + { + if (e.getKeyChar() != ' ') + { + return; + } + + if (messageOpen) + { + closeNextTick(); + } + } + + @Override + public void keyPressed(KeyEvent e) + { + } + + @Override + public void keyReleased(KeyEvent e) + { + } } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java index df840c4e34..5c199b2b09 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java @@ -178,7 +178,7 @@ public class ScreenshotPluginTest when(levelChild.getText()).thenReturn("Your Hitpoints are now 99."); - assertEquals("Hitpoints(99)", screenshotPlugin.parseLevelUpWidget(LEVEL_UP_LEVEL)); + assertEquals("Hitpoints(99)", screenshotPlugin.parseLevelUpWidget(client.getWidget(LEVEL_UP_LEVEL))); WidgetLoaded event = new WidgetLoaded(); event.setGroupId(LEVEL_UP_GROUP_ID); @@ -199,7 +199,7 @@ public class ScreenshotPluginTest when(levelChild.getText()).thenReturn("Your Firemaking level is now 9."); - assertEquals("Firemaking(9)", screenshotPlugin.parseLevelUpWidget(LEVEL_UP_LEVEL)); + assertEquals("Firemaking(9)", screenshotPlugin.parseLevelUpWidget(client.getWidget(LEVEL_UP_LEVEL))); WidgetLoaded event = new WidgetLoaded(); event.setGroupId(LEVEL_UP_GROUP_ID); @@ -220,7 +220,7 @@ public class ScreenshotPluginTest when(levelChild.getText()).thenReturn("Your Attack level is now 70."); - assertEquals("Attack(70)", screenshotPlugin.parseLevelUpWidget(LEVEL_UP_LEVEL)); + assertEquals("Attack(70)", screenshotPlugin.parseLevelUpWidget(client.getWidget(LEVEL_UP_LEVEL))); WidgetLoaded event = new WidgetLoaded(); event.setGroupId(LEVEL_UP_GROUP_ID); @@ -241,7 +241,7 @@ public class ScreenshotPluginTest when(levelChild.getText()).thenReturn("Congratulations, you've just advanced a Hunter level.

Your Hunter level is now 2."); - assertEquals("Hunter(2)", screenshotPlugin.parseLevelUpWidget(DIALOG_SPRITE_TEXT)); + assertEquals("Hunter(2)", screenshotPlugin.parseLevelUpWidget(client.getWidget(DIALOG_SPRITE_TEXT))); WidgetLoaded event = new WidgetLoaded(); event.setGroupId(DIALOG_SPRITE_GROUP_ID); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index 78ec802de9..589074b78b 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -73,6 +73,10 @@ public interface RSWidget extends Widget @Override int getModelId(); + @Import("modelId") + @Override + void setModelId(int modelId); + @Import("itemIds") int[] getItemIds(); @@ -160,14 +164,37 @@ public interface RSWidget extends Widget @Import("childIndex") void setIndex(int index); - //@Import("rotationX") - //int getRotationX(); + @Import("modelAngleX") + @Override + int getRotationX(); - //@Import("rotationY") --- All unused - //int getRotationY(); + @Import("modelAngleX") + @Override + void setRotationX(int rotationX); - //@Import("rotationZ") - //int getRotationZ(); + @Import("modelAngleY") + @Override + int getRotationY(); + + @Import("modelAngleY") + @Override + void setRotationY(int rotationY); + + @Import("modelAngleZ") + @Override + int getRotationZ(); + + @Import("modelAngleZ") + @Override + void setRotationZ(int rotationZ); + + @Import("modelZoom") + @Override + int getModelZoom(); + + @Import("modelZoom") + @Override + void setModelZoom(int modelZoom); @Import("contentType") @Override