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
index 382a17b3e1..012c168534 100644
--- 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
@@ -29,21 +29,22 @@ import java.awt.image.BufferedImage;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.Skill;
-import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.InfoBox;
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
public class BoostIndicator extends InfoBox
{
+ private final BoostsPlugin plugin;
private final BoostsConfig config;
private final Client client;
@Getter
private final Skill skill;
- public BoostIndicator(Skill skill, BufferedImage image, Plugin plugin, Client client, BoostsConfig config)
+ BoostIndicator(Skill skill, BufferedImage image, BoostsPlugin plugin, Client client, BoostsConfig config)
{
super(image, plugin);
+ this.plugin = plugin;
this.config = config;
this.client = client;
this.skill = skill;
@@ -82,4 +83,15 @@ public class BoostIndicator extends InfoBox
return new Color(238, 51, 51);
}
+
+ @Override
+ public boolean render()
+ {
+ if (config.displayIndicators() && plugin.canShowBoosts() && plugin.getShownSkills().contains(getSkill()))
+ {
+ return client.getBoostedSkillLevel(skill) != client.getRealSkillLevel(skill);
+ }
+
+ return false;
+ }
}
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 3e2a04edc9..14cc80b003 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
@@ -31,6 +31,13 @@ import net.runelite.client.config.ConfigItem;
@ConfigGroup("boosts")
public interface BoostsConfig extends Config
{
+ enum DisplayChangeMode
+ {
+ ALWAYS,
+ BOOSTED,
+ NEVER
+ }
+
@ConfigItem(
keyName = "enableSkill",
name = "Enable Skill Boosts",
@@ -65,21 +72,32 @@ public interface BoostsConfig extends Config
}
@ConfigItem(
- keyName = "displayNextChange",
- name = "Display next change",
- description = "Configures whether or not to display when the next stat change will be",
+ keyName = "displayNextBuffChange",
+ name = "Display next buff change",
+ description = "Configures whether or not to display when the next buffed stat change will be",
position = 4
)
- default boolean displayNextChange()
+ default DisplayChangeMode displayNextBuffChange()
{
- return true;
+ return DisplayChangeMode.BOOSTED;
+ }
+
+ @ConfigItem(
+ keyName = "displayNextDebuffChange",
+ name = "Display next debuff change",
+ description = "Configures whether or not to display when the next debuffed stat change will be",
+ position = 5
+ )
+ default DisplayChangeMode displayNextDebuffChange()
+ {
+ return DisplayChangeMode.NEVER;
}
@ConfigItem(
keyName = "boostThreshold",
name = "Boost Amount Threshold",
description = "The amount of levels boosted to send a notification at. A value of 0 will disable notification.",
- position = 5
+ position = 6
)
default int boostThreshold()
{
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 364d2e97b3..44f6d2cd31 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
@@ -27,117 +27,79 @@ package net.runelite.client.plugins.boosts;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
-import java.time.Instant;
import javax.inject.Inject;
-import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.Skill;
-import net.runelite.client.game.SkillIconManager;
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.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
-import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
class BoostsOverlay extends Overlay
{
- @Getter
- private final BoostIndicator[] indicators = new BoostIndicator[Skill.values().length - 1];
-
private final Client client;
private final BoostsConfig config;
- private final InfoBoxManager infoBoxManager;
private final PanelComponent panelComponent = new PanelComponent();
+ private final BoostsPlugin plugin;
@Inject
- private BoostsPlugin plugin;
-
- @Inject
- private SkillIconManager iconManager;
-
- private boolean overlayActive;
-
- @Inject
- BoostsOverlay(Client client, BoostsConfig config, InfoBoxManager infoBoxManager)
+ private BoostsOverlay(Client client, BoostsConfig config, BoostsPlugin plugin)
{
- setPosition(OverlayPosition.TOP_LEFT);
- setPriority(OverlayPriority.MED);
+ this.plugin = plugin;
this.client = client;
this.config = config;
- this.infoBoxManager = infoBoxManager;
+ setPosition(OverlayPosition.TOP_LEFT);
+ setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
- Instant lastChange = plugin.getLastChange();
- panelComponent.getChildren().clear();
-
- if (!config.displayIndicators()
- && config.displayNextChange()
- && lastChange != null
- && overlayActive)
+ if (config.displayIndicators())
{
- int nextChange = plugin.getChangeTime();
- if (nextChange > 0)
- {
- panelComponent.getChildren().add(LineComponent.builder()
- .left("Next change in")
- .right(String.valueOf(nextChange))
- .build());
- }
+ return null;
}
- overlayActive = false;
+ panelComponent.getChildren().clear();
- for (Skill skill : plugin.getShownSkills())
+ int nextChange = plugin.getChangeDownTicks();
+
+ if (nextChange != -1)
{
- int boosted = client.getBoostedSkillLevel(skill),
- base = client.getRealSkillLevel(skill);
+ panelComponent.getChildren().add(LineComponent.builder()
+ .left("Next + restore in")
+ .right(String.valueOf(plugin.getChangeTime(nextChange)))
+ .build());
+ }
- BoostIndicator indicator = indicators[skill.ordinal()];
+ nextChange = plugin.getChangeUpTicks();
- if (boosted == base)
+ if (nextChange != -1)
+ {
+ panelComponent.getChildren().add(LineComponent.builder()
+ .left("Next - restore in")
+ .right(String.valueOf(plugin.getChangeTime(nextChange)))
+ .build());
+ }
+
+ if (plugin.canShowBoosts())
+ {
+ for (Skill skill : plugin.getShownSkills())
{
- if (indicator != null && infoBoxManager.getInfoBoxes().contains(indicator))
+ final int boosted = client.getBoostedSkillLevel(skill);
+ final int base = client.getRealSkillLevel(skill);
+
+ if (boosted == base)
{
- infoBoxManager.removeInfoBox(indicator);
- }
-
- continue;
- }
-
- overlayActive = true;
-
- if (config.displayIndicators())
- {
- if (indicator == null)
- {
- indicator = new BoostIndicator(skill, iconManager.getSkillImage(skill), plugin, client, config);
- indicators[skill.ordinal()] = indicator;
- }
-
- if (!infoBoxManager.getInfoBoxes().contains(indicator))
- {
- infoBoxManager.addInfoBox(indicator);
- }
- }
- else
- {
- if (indicator != null && infoBoxManager.getInfoBoxes().contains(indicator))
- {
- infoBoxManager.removeInfoBox(indicator);
+ continue;
}
+ final int boost = boosted - base;
+ final Color strColor = getTextColor(boost);
String str;
- int boost = boosted - base;
- Color strColor = getTextColor(boost);
- if (!config.useRelativeBoost())
- {
- str = "
" + boosted + "/" + base;
- }
- else
+
+ if (config.useRelativeBoost())
{
str = String.valueOf(boost);
if (boost > 0)
@@ -145,6 +107,10 @@ class BoostsOverlay extends Overlay
str = "+" + str;
}
}
+ else
+ {
+ str = "" + boosted + "/" + base;
+ }
panelComponent.getChildren().add(LineComponent.builder()
.left(skill.getName())
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 0efb989ac0..623d40a3da 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,15 +24,15 @@
*/
package net.runelite.client.plugins.boosts;
-import com.google.common.collect.ObjectArrays;
+import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Provides;
-import java.awt.image.BufferedImage;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import javax.imageio.ImageIO;
import javax.inject.Inject;
+import javax.inject.Singleton;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
@@ -40,6 +40,8 @@ import net.runelite.api.Prayer;
import net.runelite.api.Skill;
import net.runelite.api.events.BoostedLevelChanged;
import net.runelite.api.events.ConfigChanged;
+import net.runelite.api.events.GameStateChanged;
+import net.runelite.api.events.GameTick;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.SkillIconManager;
@@ -54,23 +56,20 @@ import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
tags = {"combat", "notifications", "skilling", "overlay"}
)
@Slf4j
+@Singleton
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[]
- {
+ private static final Set BOOSTABLE_COMBAT_SKILLS = ImmutableSet.of(
+ Skill.ATTACK,
+ Skill.STRENGTH,
+ Skill.DEFENCE,
+ Skill.RANGED,
+ Skill.MAGIC);
+
+ private static final Set BOOSTABLE_NON_COMBAT_SKILLS = ImmutableSet.of(
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 int[] lastSkillLevels = new int[Skill.values().length - 1];
-
- @Getter
- private Instant lastChange;
+ Skill.SLAYER, Skill.FARMING, Skill.CONSTRUCTION, Skill.HUNTER);
@Inject
private Notifier notifier;
@@ -94,13 +93,15 @@ public class BoostsPlugin extends Plugin
private SkillIconManager skillIconManager;
@Getter
- private Skill[] shownSkills;
-
- private StatChangeIndicator statChangeIndicator;
-
- private BufferedImage overallIcon;
+ private final Set shownSkills = new HashSet<>();
+ private boolean isChangedDown = false;
+ private boolean isChangedUp = false;
+ private final int[] lastSkillLevels = new int[Skill.values().length - 1];
+ private int lastChangeDown = -1;
+ private int lastChangeUp = -1;
private boolean preserveBeenActive = false;
+ private long lastTickMillis;
@Provides
BoostsConfig provideConfig(ConfigManager configManager)
@@ -109,12 +110,27 @@ public class BoostsPlugin extends Plugin
}
@Override
- protected void startUp()
+ protected void startUp() throws Exception
{
overlayManager.add(boostsOverlay);
- updateShownSkills(config.enableSkill());
+ updateShownSkills();
+ updateBoostedStats();
Arrays.fill(lastSkillLevels, -1);
- overallIcon = skillIconManager.getSkillImage(Skill.OVERALL);
+
+ // Add infoboxes for everything at startup and then determine inside if it will be rendered
+ synchronized (ImageIO.class)
+ {
+ infoBoxManager.addInfoBox(new StatChangeIndicator(true, ImageIO.read(getClass().getResourceAsStream("debuffed.png")), this, config));
+ infoBoxManager.addInfoBox(new StatChangeIndicator(false, ImageIO.read(getClass().getResourceAsStream("buffed.png")), this, config));
+ }
+
+ for (final Skill skill : Skill.values())
+ {
+ if (skill != Skill.OVERALL)
+ {
+ infoBoxManager.addInfoBox(new BoostIndicator(skill, skillIconManager.getSkillImage(skill), this, client, config));
+ }
+ }
}
@Override
@@ -122,6 +138,24 @@ public class BoostsPlugin extends Plugin
{
overlayManager.remove(boostsOverlay);
infoBoxManager.removeIf(t -> t instanceof BoostIndicator || t instanceof StatChangeIndicator);
+ preserveBeenActive = false;
+ lastChangeDown = -1;
+ lastChangeUp = -1;
+ isChangedUp = false;
+ isChangedDown = false;
+ }
+
+ @Subscribe
+ public void onGameStateChanged(GameStateChanged event)
+ {
+ switch (event.getGameState())
+ {
+ case LOGIN_SCREEN:
+ case HOPPING:
+ // After world hop and log out timers are in undefined state so just reset
+ lastChangeDown = -1;
+ lastChangeUp = -1;
+ }
}
@Subscribe
@@ -132,29 +166,25 @@ public class BoostsPlugin extends Plugin
return;
}
- if (event.getKey().equals("displayIndicators") || event.getKey().equals("displayNextChange"))
+ updateShownSkills();
+
+ if (config.displayNextBuffChange() == BoostsConfig.DisplayChangeMode.NEVER)
{
- addStatChangeIndicator();
- return;
+ lastChangeDown = -1;
}
- Skill[] old = shownSkills;
- updateShownSkills(config.enableSkill());
-
- if (!Arrays.equals(old, shownSkills))
+ if (config.displayNextDebuffChange() == BoostsConfig.DisplayChangeMode.NEVER)
{
- infoBoxManager.removeIf(t -> t instanceof BoostIndicator
- && !Arrays.asList(shownSkills).contains(((BoostIndicator) t).getSkill()));
+ lastChangeUp = -1;
}
}
@Subscribe
- void onBoostedLevelChange(BoostedLevelChanged boostedLevelChanged)
+ public void onBoostedLevelChange(BoostedLevelChanged boostedLevelChanged)
{
Skill skill = boostedLevelChanged.getSkill();
- // Ignore changes to hitpoints or prayer
- if (skill == Skill.HITPOINTS || skill == Skill.PRAYER)
+ if (!BOOSTABLE_COMBAT_SKILLS.contains(skill) && !BOOSTABLE_NON_COMBAT_SKILLS.contains(skill))
{
return;
}
@@ -163,16 +193,23 @@ public class BoostsPlugin extends Plugin
int last = lastSkillLevels[skillIdx];
int cur = client.getBoostedSkillLevel(skill);
- // Check if stat goes +1 or -1
- if (cur == last + 1 || cur == last - 1)
+ if (cur == last - 1)
{
- log.debug("Skill {} healed", skill);
- lastChange = Instant.now();
- addStatChangeIndicator();
+ // Stat was restored down (from buff)
+ lastChangeDown = client.getTickCount();
}
+
+ if (cur == last + 1)
+ {
+ // Stat was restored up (from debuff)
+ lastChangeUp = client.getTickCount();
+ }
+
lastSkillLevels[skillIdx] = cur;
+ updateBoostedStats();
int boostThreshold = config.boostThreshold();
+
if (boostThreshold != 0)
{
int real = client.getRealSkillLevel(skill);
@@ -185,30 +222,93 @@ public class BoostsPlugin extends Plugin
}
}
- private void updateShownSkills(boolean showSkillingSkills)
+ @Subscribe
+ public void onGameTick(GameTick event)
{
- if (showSkillingSkills)
+ lastTickMillis = System.currentTimeMillis();
+
+ if (getChangeUpTicks() <= 0)
{
- shownSkills = ObjectArrays.concat(COMBAT, SKILLING, Skill.class);
+ switch (config.displayNextDebuffChange())
+ {
+ case ALWAYS:
+ if (lastChangeUp != -1)
+ {
+ lastChangeUp = client.getTickCount();
+ }
+
+ break;
+ case BOOSTED:
+ case NEVER:
+ lastChangeUp = -1;
+ break;
+ }
}
- else
+
+ if (getChangeDownTicks() <= 0)
{
- shownSkills = COMBAT;
+ switch (config.displayNextBuffChange())
+ {
+ case ALWAYS:
+ if (lastChangeDown != -1)
+ {
+ lastChangeDown = client.getTickCount();
+ }
+
+ break;
+ case BOOSTED:
+ case NEVER:
+ lastChangeDown = -1;
+ break;
+ }
}
}
- public void addStatChangeIndicator()
+ private void updateShownSkills()
{
- infoBoxManager.removeInfoBox(statChangeIndicator);
- statChangeIndicator = null;
-
- if (lastChange != null
- && config.displayIndicators()
- && config.displayNextChange())
+ if (config.enableSkill())
{
- statChangeIndicator = new StatChangeIndicator(getChangeTime(), ChronoUnit.SECONDS, overallIcon, this);
- infoBoxManager.addInfoBox(statChangeIndicator);
+ shownSkills.addAll(BOOSTABLE_NON_COMBAT_SKILLS);
}
+ else
+ {
+ shownSkills.removeAll(BOOSTABLE_NON_COMBAT_SKILLS);
+ }
+
+ shownSkills.addAll(BOOSTABLE_COMBAT_SKILLS);
+ }
+
+ private void updateBoostedStats()
+ {
+ // Reset is boosted
+ isChangedDown = false;
+ isChangedUp = false;
+
+ // Check if we are still boosted
+ for (final Skill skill : Skill.values())
+ {
+ if (!BOOSTABLE_COMBAT_SKILLS.contains(skill) && !BOOSTABLE_NON_COMBAT_SKILLS.contains(skill))
+ {
+ continue;
+ }
+
+ final int boosted = client.getBoostedSkillLevel(skill);
+ final int base = client.getRealSkillLevel(skill);
+
+ if (boosted > base)
+ {
+ isChangedUp = true;
+ }
+ else if (boosted < base)
+ {
+ isChangedDown = true;
+ }
+ }
+ }
+
+ boolean canShowBoosts()
+ {
+ return isChangedDown || isChangedUp;
}
/**
@@ -224,26 +324,54 @@ public class BoostsPlugin extends Plugin
* Preserve is only required to be on for the 4th and 5th sections of the boost timer
* to gain full effect (seconds 45-75).
*
- * @return integer value in seconds until next boost change
+ * @return integer value in ticks until next boost change
*/
- public int getChangeTime()
+ int getChangeDownTicks()
{
- int timeSinceChange = timeSinceLastChange();
+ if (lastChangeDown == -1 || (config.displayNextBuffChange() == BoostsConfig.DisplayChangeMode.BOOSTED && !isChangedUp))
+ {
+ return -1;
+ }
+
+ int ticksSinceChange = client.getTickCount() - lastChangeDown;
boolean isPreserveActive = client.isPrayerActive(Prayer.PRESERVE);
- if ((isPreserveActive && (timeSinceChange < 45 || preserveBeenActive)) || timeSinceChange > 75)
+ if ((isPreserveActive && (ticksSinceChange < 75 || preserveBeenActive)) || ticksSinceChange > 125)
{
preserveBeenActive = true;
- return 90 - timeSinceChange;
+ return 150 - ticksSinceChange;
}
preserveBeenActive = false;
- return (timeSinceChange > 60) ? 75 - timeSinceChange : 60 - timeSinceChange;
+ return (ticksSinceChange > 100) ? 125 - ticksSinceChange : 100 - ticksSinceChange;
}
- private int timeSinceLastChange()
+ /**
+ * Restoration from debuff is separate timer as restoration from buff because of preserve messing up the buff timer.
+ * Restoration timer is always in 100 tick cycles.
+ *
+ * @return integer value in ticks until next stat restoration up
+ */
+ int getChangeUpTicks()
{
- return (int) Duration.between(lastChange, Instant.now()).getSeconds();
+ if (lastChangeUp == -1 || (config.displayNextDebuffChange() == BoostsConfig.DisplayChangeMode.BOOSTED && !isChangedDown))
+ {
+ return -1;
+ }
+
+ int ticksSinceChange = client.getTickCount() - lastChangeUp;
+ return 100 - ticksSinceChange;
}
-}
+
+ /**
+ * Converts tick-based time to accurate second time
+ * @param time tick-based time
+ * @return second-based time
+ */
+ int getChangeTime(final int time)
+ {
+ final long diff = System.currentTimeMillis() - lastTickMillis;
+ return time != -1 ? (int)(time * 0.6 - (diff / 1000d)) : time;
+ }
+}
\ No newline at end of file
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/StatChangeIndicator.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/StatChangeIndicator.java
index 78275e4027..4d6d1952ab 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/StatChangeIndicator.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/StatChangeIndicator.java
@@ -24,18 +24,43 @@
*/
package net.runelite.client.plugins.boosts;
+import java.awt.Color;
import java.awt.image.BufferedImage;
-import java.time.temporal.ChronoUnit;
-import net.runelite.client.plugins.Plugin;
+import net.runelite.client.ui.overlay.infobox.InfoBox;
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
-import net.runelite.client.ui.overlay.infobox.Timer;
-public class StatChangeIndicator extends Timer
+public class StatChangeIndicator extends InfoBox
{
- public StatChangeIndicator(long period, ChronoUnit unit, BufferedImage image, Plugin plugin)
+ private final boolean up;
+ private final BoostsPlugin plugin;
+ private final BoostsConfig config;
+
+ StatChangeIndicator(boolean up, BufferedImage image, BoostsPlugin plugin, BoostsConfig config)
{
- super(period, unit, image, plugin);
+ super(image, plugin);
+ this.up = up;
+ this.plugin = plugin;
+ this.config = config;
setPriority(InfoBoxPriority.MED);
- setTooltip("Next stat change");
+ setTooltip(up ? "Next debuff change" : "Next buff change");
+ }
+
+ @Override
+ public String getText()
+ {
+ return String.format("%02d", plugin.getChangeTime(up ? plugin.getChangeUpTicks() : plugin.getChangeDownTicks()));
+ }
+
+ @Override
+ public Color getTextColor()
+ {
+ return (up ? plugin.getChangeUpTicks() : plugin.getChangeDownTicks()) < 10 ? Color.RED.brighter() : Color.WHITE;
+ }
+
+ @Override
+ public boolean render()
+ {
+ final int time = up ? plugin.getChangeUpTicks() : plugin.getChangeDownTicks();
+ return config.displayIndicators() && time != -1;
}
}
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java
index 25e42b03fa..d3aa9923e7 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxOverlay.java
@@ -89,15 +89,20 @@ public class InfoBoxOverlay extends Overlay
: PanelComponent.Orientation.HORIZONTAL);
panelComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
- infoBoxes.forEach(box ->
+ for (InfoBox box : infoBoxes)
{
+ if (!box.render())
+ {
+ continue;
+ }
+
final InfoBoxComponent infoBoxComponent = new InfoBoxComponent();
infoBoxComponent.setColor(box.getTextColor());
infoBoxComponent.setImage(box.getScaledImage());
infoBoxComponent.setText(box.getText());
infoBoxComponent.setTooltip(box.getTooltip());
panelComponent.getChildren().add(infoBoxComponent);
- });
+ }
final Dimension dimension = panelComponent.render(graphics);
final Client client = clientProvider.get();
diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/boosts/buffed.png b/runelite-client/src/main/resources/net/runelite/client/plugins/boosts/buffed.png
new file mode 100644
index 0000000000..c8ab82e845
Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/boosts/buffed.png differ
diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/boosts/debuffed.png b/runelite-client/src/main/resources/net/runelite/client/plugins/boosts/debuffed.png
new file mode 100644
index 0000000000..fb334fd743
Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/plugins/boosts/debuffed.png differ