Merge pull request #3917 from deathbeam/preserve-change-indicator
Add debuff/buff change indicators
This commit is contained in:
@@ -29,21 +29,22 @@ import java.awt.image.BufferedImage;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.Skill;
|
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.InfoBox;
|
||||||
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
|
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
|
||||||
|
|
||||||
public class BoostIndicator extends InfoBox
|
public class BoostIndicator extends InfoBox
|
||||||
{
|
{
|
||||||
|
private final BoostsPlugin plugin;
|
||||||
private final BoostsConfig config;
|
private final BoostsConfig config;
|
||||||
private final Client client;
|
private final Client client;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Skill skill;
|
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);
|
super(image, plugin);
|
||||||
|
this.plugin = plugin;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.skill = skill;
|
this.skill = skill;
|
||||||
@@ -82,4 +83,15 @@ public class BoostIndicator extends InfoBox
|
|||||||
|
|
||||||
return new Color(238, 51, 51);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ import net.runelite.client.config.ConfigItem;
|
|||||||
@ConfigGroup("boosts")
|
@ConfigGroup("boosts")
|
||||||
public interface BoostsConfig extends Config
|
public interface BoostsConfig extends Config
|
||||||
{
|
{
|
||||||
|
enum DisplayChangeMode
|
||||||
|
{
|
||||||
|
ALWAYS,
|
||||||
|
BOOSTED,
|
||||||
|
NEVER
|
||||||
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
keyName = "enableSkill",
|
keyName = "enableSkill",
|
||||||
name = "Enable Skill Boosts",
|
name = "Enable Skill Boosts",
|
||||||
@@ -65,21 +72,32 @@ public interface BoostsConfig extends Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConfigItem(
|
@ConfigItem(
|
||||||
keyName = "displayNextChange",
|
keyName = "displayNextBuffChange",
|
||||||
name = "Display next change",
|
name = "Display next buff change",
|
||||||
description = "Configures whether or not to display when the next stat change will be",
|
description = "Configures whether or not to display when the next buffed stat change will be",
|
||||||
position = 4
|
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(
|
@ConfigItem(
|
||||||
keyName = "boostThreshold",
|
keyName = "boostThreshold",
|
||||||
name = "Boost Amount Threshold",
|
name = "Boost Amount Threshold",
|
||||||
description = "The amount of levels boosted to send a notification at. A value of 0 will disable notification.",
|
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()
|
default int boostThreshold()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,117 +27,79 @@ package net.runelite.client.plugins.boosts;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.time.Instant;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import lombok.Getter;
|
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.Skill;
|
import net.runelite.api.Skill;
|
||||||
import net.runelite.client.game.SkillIconManager;
|
|
||||||
import net.runelite.client.ui.overlay.Overlay;
|
import net.runelite.client.ui.overlay.Overlay;
|
||||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
|
||||||
|
|
||||||
class BoostsOverlay extends Overlay
|
class BoostsOverlay extends Overlay
|
||||||
{
|
{
|
||||||
@Getter
|
|
||||||
private final BoostIndicator[] indicators = new BoostIndicator[Skill.values().length - 1];
|
|
||||||
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private final BoostsConfig config;
|
private final BoostsConfig config;
|
||||||
private final InfoBoxManager infoBoxManager;
|
|
||||||
private final PanelComponent panelComponent = new PanelComponent();
|
private final PanelComponent panelComponent = new PanelComponent();
|
||||||
|
private final BoostsPlugin plugin;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BoostsPlugin plugin;
|
private BoostsOverlay(Client client, BoostsConfig config, BoostsPlugin plugin)
|
||||||
|
|
||||||
@Inject
|
|
||||||
private SkillIconManager iconManager;
|
|
||||||
|
|
||||||
private boolean overlayActive;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
BoostsOverlay(Client client, BoostsConfig config, InfoBoxManager infoBoxManager)
|
|
||||||
{
|
{
|
||||||
setPosition(OverlayPosition.TOP_LEFT);
|
this.plugin = plugin;
|
||||||
setPriority(OverlayPriority.MED);
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.infoBoxManager = infoBoxManager;
|
setPosition(OverlayPosition.TOP_LEFT);
|
||||||
|
setPriority(OverlayPriority.MED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension render(Graphics2D graphics)
|
public Dimension render(Graphics2D graphics)
|
||||||
{
|
{
|
||||||
Instant lastChange = plugin.getLastChange();
|
if (config.displayIndicators())
|
||||||
panelComponent.getChildren().clear();
|
|
||||||
|
|
||||||
if (!config.displayIndicators()
|
|
||||||
&& config.displayNextChange()
|
|
||||||
&& lastChange != null
|
|
||||||
&& overlayActive)
|
|
||||||
{
|
{
|
||||||
int nextChange = plugin.getChangeTime();
|
return null;
|
||||||
if (nextChange > 0)
|
|
||||||
{
|
|
||||||
panelComponent.getChildren().add(LineComponent.builder()
|
|
||||||
.left("Next change in")
|
|
||||||
.right(String.valueOf(nextChange))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
overlayActive = false;
|
panelComponent.getChildren().clear();
|
||||||
|
|
||||||
for (Skill skill : plugin.getShownSkills())
|
int nextChange = plugin.getChangeDownTicks();
|
||||||
|
|
||||||
|
if (nextChange != -1)
|
||||||
{
|
{
|
||||||
int boosted = client.getBoostedSkillLevel(skill),
|
panelComponent.getChildren().add(LineComponent.builder()
|
||||||
base = client.getRealSkillLevel(skill);
|
.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;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int boost = boosted - base;
|
||||||
|
final Color strColor = getTextColor(boost);
|
||||||
String str;
|
String str;
|
||||||
int boost = boosted - base;
|
|
||||||
Color strColor = getTextColor(boost);
|
if (config.useRelativeBoost())
|
||||||
if (!config.useRelativeBoost())
|
|
||||||
{
|
|
||||||
str = "<col=" + Integer.toHexString(strColor.getRGB() & 0xFFFFFF) + ">" + boosted + "<col=ffffff>/" + base;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
str = String.valueOf(boost);
|
str = String.valueOf(boost);
|
||||||
if (boost > 0)
|
if (boost > 0)
|
||||||
@@ -145,6 +107,10 @@ class BoostsOverlay extends Overlay
|
|||||||
str = "+" + str;
|
str = "+" + str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str = "<col=" + Integer.toHexString(strColor.getRGB() & 0xFFFFFF) + ">" + boosted + "<col=ffffff>/" + base;
|
||||||
|
}
|
||||||
|
|
||||||
panelComponent.getChildren().add(LineComponent.builder()
|
panelComponent.getChildren().add(LineComponent.builder()
|
||||||
.left(skill.getName())
|
.left(skill.getName())
|
||||||
|
|||||||
@@ -24,15 +24,15 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.boosts;
|
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.common.eventbus.Subscribe;
|
||||||
import com.google.inject.Provides;
|
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.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
@@ -40,6 +40,8 @@ import net.runelite.api.Prayer;
|
|||||||
import net.runelite.api.Skill;
|
import net.runelite.api.Skill;
|
||||||
import net.runelite.api.events.BoostedLevelChanged;
|
import net.runelite.api.events.BoostedLevelChanged;
|
||||||
import net.runelite.api.events.ConfigChanged;
|
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.Notifier;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.game.SkillIconManager;
|
import net.runelite.client.game.SkillIconManager;
|
||||||
@@ -54,23 +56,20 @@ import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
|||||||
tags = {"combat", "notifications", "skilling", "overlay"}
|
tags = {"combat", "notifications", "skilling", "overlay"}
|
||||||
)
|
)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Singleton
|
||||||
public class BoostsPlugin extends Plugin
|
public class BoostsPlugin extends Plugin
|
||||||
{
|
{
|
||||||
private static final Skill[] COMBAT = new Skill[]
|
private static final Set<Skill> BOOSTABLE_COMBAT_SKILLS = ImmutableSet.of(
|
||||||
{
|
Skill.ATTACK,
|
||||||
Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE, Skill.RANGED, Skill.MAGIC
|
Skill.STRENGTH,
|
||||||
};
|
Skill.DEFENCE,
|
||||||
private static final Skill[] SKILLING = new Skill[]
|
Skill.RANGED,
|
||||||
{
|
Skill.MAGIC);
|
||||||
|
|
||||||
|
private static final Set<Skill> BOOSTABLE_NON_COMBAT_SKILLS = ImmutableSet.of(
|
||||||
Skill.MINING, Skill.AGILITY, Skill.SMITHING, Skill.HERBLORE, Skill.FISHING, Skill.THIEVING,
|
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.COOKING, Skill.CRAFTING, Skill.FIREMAKING, Skill.FLETCHING, Skill.WOODCUTTING, Skill.RUNECRAFT,
|
||||||
Skill.SLAYER, Skill.FARMING, Skill.CONSTRUCTION, Skill.HUNTER
|
Skill.SLAYER, Skill.FARMING, Skill.CONSTRUCTION, Skill.HUNTER);
|
||||||
};
|
|
||||||
|
|
||||||
private final int[] lastSkillLevels = new int[Skill.values().length - 1];
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private Instant lastChange;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Notifier notifier;
|
private Notifier notifier;
|
||||||
@@ -94,13 +93,15 @@ public class BoostsPlugin extends Plugin
|
|||||||
private SkillIconManager skillIconManager;
|
private SkillIconManager skillIconManager;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private Skill[] shownSkills;
|
private final Set<Skill> shownSkills = new HashSet<>();
|
||||||
|
|
||||||
private StatChangeIndicator statChangeIndicator;
|
|
||||||
|
|
||||||
private BufferedImage overallIcon;
|
|
||||||
|
|
||||||
|
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 boolean preserveBeenActive = false;
|
||||||
|
private long lastTickMillis;
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
BoostsConfig provideConfig(ConfigManager configManager)
|
BoostsConfig provideConfig(ConfigManager configManager)
|
||||||
@@ -109,12 +110,27 @@ public class BoostsPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startUp()
|
protected void startUp() throws Exception
|
||||||
{
|
{
|
||||||
overlayManager.add(boostsOverlay);
|
overlayManager.add(boostsOverlay);
|
||||||
updateShownSkills(config.enableSkill());
|
updateShownSkills();
|
||||||
|
updateBoostedStats();
|
||||||
Arrays.fill(lastSkillLevels, -1);
|
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
|
@Override
|
||||||
@@ -122,6 +138,24 @@ public class BoostsPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
overlayManager.remove(boostsOverlay);
|
overlayManager.remove(boostsOverlay);
|
||||||
infoBoxManager.removeIf(t -> t instanceof BoostIndicator || t instanceof StatChangeIndicator);
|
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
|
@Subscribe
|
||||||
@@ -132,29 +166,25 @@ public class BoostsPlugin extends Plugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.getKey().equals("displayIndicators") || event.getKey().equals("displayNextChange"))
|
updateShownSkills();
|
||||||
|
|
||||||
|
if (config.displayNextBuffChange() == BoostsConfig.DisplayChangeMode.NEVER)
|
||||||
{
|
{
|
||||||
addStatChangeIndicator();
|
lastChangeDown = -1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Skill[] old = shownSkills;
|
if (config.displayNextDebuffChange() == BoostsConfig.DisplayChangeMode.NEVER)
|
||||||
updateShownSkills(config.enableSkill());
|
|
||||||
|
|
||||||
if (!Arrays.equals(old, shownSkills))
|
|
||||||
{
|
{
|
||||||
infoBoxManager.removeIf(t -> t instanceof BoostIndicator
|
lastChangeUp = -1;
|
||||||
&& !Arrays.asList(shownSkills).contains(((BoostIndicator) t).getSkill()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
void onBoostedLevelChange(BoostedLevelChanged boostedLevelChanged)
|
public void onBoostedLevelChange(BoostedLevelChanged boostedLevelChanged)
|
||||||
{
|
{
|
||||||
Skill skill = boostedLevelChanged.getSkill();
|
Skill skill = boostedLevelChanged.getSkill();
|
||||||
|
|
||||||
// Ignore changes to hitpoints or prayer
|
if (!BOOSTABLE_COMBAT_SKILLS.contains(skill) && !BOOSTABLE_NON_COMBAT_SKILLS.contains(skill))
|
||||||
if (skill == Skill.HITPOINTS || skill == Skill.PRAYER)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -163,16 +193,23 @@ public class BoostsPlugin extends Plugin
|
|||||||
int last = lastSkillLevels[skillIdx];
|
int last = lastSkillLevels[skillIdx];
|
||||||
int cur = client.getBoostedSkillLevel(skill);
|
int cur = client.getBoostedSkillLevel(skill);
|
||||||
|
|
||||||
// Check if stat goes +1 or -1
|
if (cur == last - 1)
|
||||||
if (cur == last + 1 || cur == last - 1)
|
|
||||||
{
|
{
|
||||||
log.debug("Skill {} healed", skill);
|
// Stat was restored down (from buff)
|
||||||
lastChange = Instant.now();
|
lastChangeDown = client.getTickCount();
|
||||||
addStatChangeIndicator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cur == last + 1)
|
||||||
|
{
|
||||||
|
// Stat was restored up (from debuff)
|
||||||
|
lastChangeUp = client.getTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
lastSkillLevels[skillIdx] = cur;
|
lastSkillLevels[skillIdx] = cur;
|
||||||
|
updateBoostedStats();
|
||||||
|
|
||||||
int boostThreshold = config.boostThreshold();
|
int boostThreshold = config.boostThreshold();
|
||||||
|
|
||||||
if (boostThreshold != 0)
|
if (boostThreshold != 0)
|
||||||
{
|
{
|
||||||
int real = client.getRealSkillLevel(skill);
|
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);
|
if (config.enableSkill())
|
||||||
statChangeIndicator = null;
|
|
||||||
|
|
||||||
if (lastChange != null
|
|
||||||
&& config.displayIndicators()
|
|
||||||
&& config.displayNextChange())
|
|
||||||
{
|
{
|
||||||
statChangeIndicator = new StatChangeIndicator(getChangeTime(), ChronoUnit.SECONDS, overallIcon, this);
|
shownSkills.addAll(BOOSTABLE_NON_COMBAT_SKILLS);
|
||||||
infoBoxManager.addInfoBox(statChangeIndicator);
|
|
||||||
}
|
}
|
||||||
|
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
|
* Preserve is only required to be on for the 4th and 5th sections of the boost timer
|
||||||
* to gain full effect (seconds 45-75).
|
* 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);
|
boolean isPreserveActive = client.isPrayerActive(Prayer.PRESERVE);
|
||||||
|
|
||||||
if ((isPreserveActive && (timeSinceChange < 45 || preserveBeenActive)) || timeSinceChange > 75)
|
if ((isPreserveActive && (ticksSinceChange < 75 || preserveBeenActive)) || ticksSinceChange > 125)
|
||||||
{
|
{
|
||||||
preserveBeenActive = true;
|
preserveBeenActive = true;
|
||||||
return 90 - timeSinceChange;
|
return 150 - ticksSinceChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
preserveBeenActive = false;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,18 +24,43 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.boosts;
|
package net.runelite.client.plugins.boosts;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.time.temporal.ChronoUnit;
|
import net.runelite.client.ui.overlay.infobox.InfoBox;
|
||||||
import net.runelite.client.plugins.Plugin;
|
|
||||||
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
|
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);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,15 +89,20 @@ public class InfoBoxOverlay extends Overlay
|
|||||||
: PanelComponent.Orientation.HORIZONTAL);
|
: PanelComponent.Orientation.HORIZONTAL);
|
||||||
panelComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
|
panelComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
|
||||||
|
|
||||||
infoBoxes.forEach(box ->
|
for (InfoBox box : infoBoxes)
|
||||||
{
|
{
|
||||||
|
if (!box.render())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
final InfoBoxComponent infoBoxComponent = new InfoBoxComponent();
|
final InfoBoxComponent infoBoxComponent = new InfoBoxComponent();
|
||||||
infoBoxComponent.setColor(box.getTextColor());
|
infoBoxComponent.setColor(box.getTextColor());
|
||||||
infoBoxComponent.setImage(box.getScaledImage());
|
infoBoxComponent.setImage(box.getScaledImage());
|
||||||
infoBoxComponent.setText(box.getText());
|
infoBoxComponent.setText(box.getText());
|
||||||
infoBoxComponent.setTooltip(box.getTooltip());
|
infoBoxComponent.setTooltip(box.getTooltip());
|
||||||
panelComponent.getChildren().add(infoBoxComponent);
|
panelComponent.getChildren().add(infoBoxComponent);
|
||||||
});
|
}
|
||||||
|
|
||||||
final Dimension dimension = panelComponent.render(graphics);
|
final Dimension dimension = panelComponent.render(graphics);
|
||||||
final Client client = clientProvider.get();
|
final Client client = clientProvider.get();
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 429 B |
Binary file not shown.
|
After Width: | Height: | Size: 443 B |
Reference in New Issue
Block a user