diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostIndicator.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostIndicator.java new file mode 100644 index 0000000000..d461917b02 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostIndicator.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018 Kamiel + * 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.boosts; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import net.runelite.api.Client; +import net.runelite.api.Skill; +import net.runelite.client.ui.overlay.infobox.InfoBox; + +public class BoostIndicator extends InfoBox +{ + private final BoostsConfig config; + private final Client client; + private final Skill skill; + + public BoostIndicator(Skill skill, BufferedImage image, Client client, BoostsConfig config) + { + super(image); + this.config = config; + this.client = client; + this.skill = skill; + setTooltip(skill.getName() + " boost"); + } + + @Override + public String getText() + { + if (!config.useRelativeBoost()) + { + return String.valueOf(client.getBoostedSkillLevel(skill)); + } + + int boost = client.getBoostedSkillLevel(skill) - client.getRealSkillLevel(skill); + String text = String.valueOf(boost); + if (boost > 0) + { + text = "+" + text; + } + + return text; + } + + @Override + public Color getTextColor() + { + int boosted = client.getBoostedSkillLevel(skill), + base = client.getRealSkillLevel(skill); + + if (boosted > base) + { + return Color.GREEN; + } + + return new Color(238, 51, 51); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java index 2ab3bf34ce..a04ddf692a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java @@ -64,4 +64,14 @@ public interface BoostsConfig extends Config { return false; } + + @ConfigItem( + keyName = "displayIndicators", + name = "Display as indicators", + description = "Configures whether or not to display the boost as indicators" + ) + default boolean displayIndicators() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java index 05736b3da2..671450b53c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsOverlay.java @@ -24,44 +24,48 @@ */ package net.runelite.client.plugins.boosts; -import com.google.common.collect.ObjectArrays; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; +import java.awt.image.BufferedImage; +import java.io.IOException; import javax.annotation.Nullable; +import javax.imageio.ImageIO; import javax.inject.Inject; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.Skill; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPriority; import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; +@Slf4j class BoostsOverlay extends Overlay { - private static final Skill[] COMBAT = new Skill[] - { - Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE, Skill.RANGED, Skill.MAGIC - }; - private static final Skill[] SKILLING = new Skill[] - { - Skill.MINING, Skill.AGILITY, Skill.SMITHING, Skill.HERBLORE, Skill.FISHING, Skill.THIEVING, - Skill.COOKING, Skill.CRAFTING, Skill.FIREMAKING, Skill.FLETCHING, Skill.WOODCUTTING, Skill.RUNECRAFT, - Skill.SLAYER, Skill.FARMING, Skill.CONSTRUCTION, Skill.HUNTER - }; + private final BufferedImage[] imgCache = new BufferedImage[Skill.values().length - 1]; + @Getter + private final BoostIndicator[] indicators = new BoostIndicator[Skill.values().length - 1]; private final Client client; private final BoostsConfig config; + private final InfoBoxManager infoBoxManager; + + @Inject + private BoostsPlugin plugin; private PanelComponent panelComponent; @Inject - BoostsOverlay(@Nullable Client client, BoostsConfig config) + BoostsOverlay(@Nullable Client client, BoostsConfig config, InfoBoxManager infoBoxManager) { setPosition(OverlayPosition.TOP_LEFT); setPriority(OverlayPriority.MED); this.client = client; this.config = config; + this.infoBoxManager = infoBoxManager; } @Override @@ -72,59 +76,97 @@ class BoostsOverlay extends Overlay return null; } - Skill[] show; - if (config.enableSkill()) - { - show = ObjectArrays.concat(COMBAT, SKILLING, Skill.class); - } - else - { - show = COMBAT; - } - panelComponent = new PanelComponent(); - for (Skill skill : show) + for (Skill skill : plugin.getShownSkills()) { int boosted = client.getBoostedSkillLevel(skill), base = client.getRealSkillLevel(skill); if (boosted == base) { + if (indicators[skill.ordinal()] != null) + { + infoBoxManager.removeInfoBox(indicators[skill.ordinal()]); + indicators[skill.ordinal()] = null; + } + continue; } - - String str; - Color strColor = Color.WHITE; - if (!config.useRelativeBoost()) + if (config.displayIndicators()) { - str = boosted + "/" + base; + if (indicators[skill.ordinal()] == null) + { + BoostIndicator indicator = new BoostIndicator(skill, getSkillImage(skill), client, config); + indicators[skill.ordinal()] = indicator; + infoBoxManager.addInfoBox(indicator); + } } else { - int boost = boosted - base; - str = String.valueOf(boost); - if (boost > 0) + String str; + Color strColor = Color.WHITE; + if (!config.useRelativeBoost()) { - str = "+" + str; - strColor = Color.GREEN.darker(); + str = boosted + "/" + base; } else { - strColor = Color.RED.darker(); + int boost = boosted - base; + str = String.valueOf(boost); + strColor = getTextColor(boost); + if (boost > 0) + { + str = "+" + str; + } } - } - panelComponent.getLines().add(new PanelComponent.Line( - skill.getName(), - Color.WHITE, - str, - strColor - )); + panelComponent.getLines().add(new PanelComponent.Line( + skill.getName(), + Color.WHITE, + str, + strColor + )); + } } - return panelComponent.render(graphics, parent); + return config.displayIndicators() ? null : panelComponent.render(graphics, parent); } + private Color getTextColor(int boost) + { + if (boost > 0) + { + return Color.GREEN; + } + + return new Color(238, 51, 51); + + } + + private BufferedImage getSkillImage(Skill skill) + { + int skillIdx = skill.ordinal(); + BufferedImage skillImage = null; + + if (imgCache[skillIdx] != null) + { + return imgCache[skillIdx]; + } + + try + { + String skillIconPath = "/skill_icons/" + skill.getName().toLowerCase() + ".png"; + log.debug("Loading skill icon from {}", skillIconPath); + skillImage = ImageIO.read(BoostsOverlay.class.getResourceAsStream(skillIconPath)); + imgCache[skillIdx] = skillImage; + } + catch (IOException e) + { + log.debug("Error Loading skill icons {}", e); + } + + return skillImage; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java index 8aaff06234..bc32c3e037 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java @@ -24,22 +24,48 @@ */ package net.runelite.client.plugins.boosts; +import com.google.common.collect.ObjectArrays; +import com.google.common.eventbus.Subscribe; import com.google.inject.Binder; import com.google.inject.Provides; import javax.inject.Inject; +import lombok.Getter; +import net.runelite.api.Skill; +import net.runelite.api.events.ConfigChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; @PluginDescriptor( name = "Boosts plugin" ) public class BoostsPlugin extends Plugin { + private static final Skill[] COMBAT = new Skill[] + { + Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE, Skill.RANGED, Skill.MAGIC + }; + private static final Skill[] SKILLING = new Skill[] + { + Skill.MINING, Skill.AGILITY, Skill.SMITHING, Skill.HERBLORE, Skill.FISHING, Skill.THIEVING, + Skill.COOKING, Skill.CRAFTING, Skill.FIREMAKING, Skill.FLETCHING, Skill.WOODCUTTING, Skill.RUNECRAFT, + Skill.SLAYER, Skill.FARMING, Skill.CONSTRUCTION, Skill.HUNTER + }; + + @Inject + InfoBoxManager infoBoxManager; + @Inject BoostsOverlay boostsOverlay; + @Inject + BoostsConfig config; + + @Getter + private Skill[] shownSkills; + @Override public void configure(Binder binder) { @@ -57,4 +83,42 @@ public class BoostsPlugin extends Plugin { return boostsOverlay; } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (!config.enabled()) + { + return; + } + + if (config.enableSkill()) + { + shownSkills = ObjectArrays.concat(COMBAT, SKILLING, Skill.class); + } + else + { + shownSkills = COMBAT; + } + + if (event.getKey().equals("displayIndicators")) + { + for (BoostIndicator indicator : boostsOverlay.getIndicators()) + { + if (indicator == null) + { + continue; + } + + if (config.displayIndicators()) + { + infoBoxManager.addInfoBox(indicator); + } + else + { + infoBoxManager.removeInfoBox(indicator); + } + } + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java index 36621e57d3..51befb8c7a 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java @@ -71,7 +71,7 @@ public class InfoBoxComponent implements RenderableEntity { graphics.drawImage(image, position.x + (BOX_SIZE - image.getWidth()) / 2, - SEPARATOR, null); + (BOX_SIZE - image.getHeight()) / 2, null); } final TextComponent textComponent = new TextComponent();