diff --git a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java index 81abe76827..7f940e8060 100644 --- a/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java +++ b/http-api/src/main/java/net/runelite/http/api/ws/messages/party/UserJoin.java @@ -34,5 +34,6 @@ import net.runelite.http.api.ws.WebsocketMessage; public class UserJoin extends WebsocketMessage { private final UUID memberId; + private final UUID partyId; private final String name; } diff --git a/runelite-api/src/main/java/net/runelite/api/Constants.java b/runelite-api/src/main/java/net/runelite/api/Constants.java index b1cfde8dde..ffb2c1ba66 100644 --- a/runelite-api/src/main/java/net/runelite/api/Constants.java +++ b/runelite-api/src/main/java/net/runelite/api/Constants.java @@ -89,4 +89,12 @@ public class Constants * the maximum framerate of 50 fps. */ public static final int CLIENT_TICK_LENGTH = 20; + + /** + * The number of milliseconds in a server game tick. + *

+ * This is the length of a single game cycle under ideal conditions. + * All game-play actions operate within multiples of this duration. + */ + public static final int GAME_TICK_LENGTH = 600; } diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index 8d33776269..dccdc89331 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -217,6 +217,7 @@ public enum Varbits * Barbarian Assault */ IN_GAME_BA(3923), + BA_GC(4768), /** * 0 = Outside wilderness diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index 01cd1ac88f..dc461ef773 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -573,36 +573,47 @@ public class WidgetID static final int VENT_C_STATUS = 25; } - public static class BarbarianAssault + static class BarbarianAssault { static class ATK { - static final int CALL_TEXT = 8; + static final int LISTEN = 8; static final int TO_CALL_WIDGET = 9; static final int TO_CALL = 10; static final int ROLE_SPRITE = 11; static final int ROLE = 12; } - static class HLR { + static class HLR + { static final int TEAMMATE1 = 18; static final int TEAMMATE2 = 22; static final int TEAMMATE3 = 26; static final int TEAMMATE4 = 30; } - public static class REWARD_VALUES + static class REWARD_VALUES { - public static final int RUNNERS_PASSED = 14; + static final int RUNNERS_PASSED = 14; static final int HITPOINTS_REPLENISHED = 19; static final int WRONG_POISON_PACKS_USED = 20; static final int EGGS_COLLECTED = 21; static final int FAILED_ATTACKER_ATTACKS = 22; + static final int RUNNERS_PASSED_POINTS = 24; + static final int RANGERS_KILLED = 25; + static final int FIGHTERS_KILLED = 26; + static final int HEALERS_KILLED = 27; + static final int RUNNERS_KILLED = 28; + static final int HITPOINTS_REPLENISHED_POINTS = 29; + static final int WRONG_POISON_PACKS_USED_POINTS = 30; + static final int EGGS_COLLECTED_POINTS = 31; + static final int FAILED_ATTACKER_ATTACKS_POINTS = 32; + static final int BASE_POINTS = 33; static final int HONOUR_POINTS_REWARD = 49; } - static final int CORRECT_STYLE = 3; + static final int GAME_WIDGET = 3; static final int CURRENT_WAVE_WIDGET = 4; static final int CURRENT_WAVE = 5; - static final int CALL_WIDGET = 6; - static final int HEARD_CALL = 7; + static final int LISTEN_WIDGET = 6; + static final int LISTEN = 7; static final int TO_CALL_WIDGET = 8; static final int TO_CALL = 9; static final int ROLE_SPRITE = 10; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 1bd7cfa25a..dfc8b7bf50 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -362,7 +362,7 @@ public enum WidgetInfo BA_HEAL_WAVE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_HEAL_CALL_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), - BA_HEAL_LISTEN_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), + BA_HEAL_LISTEN_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN), BA_HEAL_ROLE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_HEAL_ROLE_SPRITE(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), @@ -373,20 +373,19 @@ public enum WidgetInfo BA_COLL_WAVE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_COLL_CALL_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), - BA_COLL_LISTEN_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), - BA_COLL_HEARD_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.HEARD_CALL), + BA_COLL_LISTEN_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.LISTEN), BA_COLL_ROLE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_COLL_ROLE_SPRITE(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), BA_ATK_WAVE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_ATK_CALL_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.TO_CALL), - BA_ATK_LISTEN_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), + BA_ATK_LISTEN_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.LISTEN), BA_ATK_ROLE_TEXT(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE), BA_ATK_ROLE_SPRITE(WidgetID.BA_ATTACKER_GROUP_ID, WidgetID.BarbarianAssault.ATK.ROLE_SPRITE), BA_DEF_WAVE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_DEF_CALL_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), - BA_DEF_LISTEN_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.CORRECT_STYLE), + BA_DEF_LISTEN_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.LISTEN), BA_DEF_ROLE_TEXT(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_DEF_ROLE_SPRITE(WidgetID.BA_DEFENDER_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), @@ -396,7 +395,17 @@ public enum WidgetInfo BA_WRONG_POISON_PACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED), BA_EGGS_COLLECTED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED), BA_FAILED_ATTACKER_ATTACKS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS), + BA_RUNNERS_PASSED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_PASSED_POINTS), + BA_RANGERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RANGERS_KILLED), + BA_FIGHTERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FIGHTERS_KILLED), + BA_HEALERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HEALERS_KILLED), + BA_RUNNERS_KILLED(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.RUNNERS_KILLED), + BA_HITPOINTS_REPLENISHED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HITPOINTS_REPLENISHED_POINTS), + BA_WRONG_POISON_PACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.WRONG_POISON_PACKS_USED_POINTS), + BA_EGGS_COLLECTED_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.EGGS_COLLECTED_POINTS), + BA_FAILED_ATTACKER_ATTACKS_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.FAILED_ATTACKER_ATTACKS_POINTS), BA_HONOUR_POINTS_REWARD(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.HONOUR_POINTS_REWARD), + BA_BASE_POINTS(WidgetID.BA_REWARD_GROUP_ID, WidgetID.BarbarianAssault.REWARD_VALUES.BASE_POINTS), LEVEL_UP(WidgetID.LEVEL_UP_GROUP_ID, 0), LEVEL_UP_SKILL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.SKILL), diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index fea751ffcf..12de2c567b 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -42,6 +42,7 @@ import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.BufferProvider; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.MainBufferProvider; import net.runelite.api.NullItemID; import net.runelite.api.RenderOverview; @@ -79,7 +80,7 @@ import net.runelite.client.util.DeferredEventBus; @Slf4j public class Hooks implements Callbacks { - private static final long CHECK = 600; // ms - how often to run checks + private static final long CHECK = Constants.GAME_TICK_LENGTH; // ms - how often to run checks private static final Injector injector = RuneLite.getInjector(); private static final Client client = injector.getInstance(Client.class); diff --git a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java index bc0d3bc58a..da4c222fd6 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/ChatMessageManager.java @@ -548,8 +548,14 @@ public class ChatMessageManager { if (!queuedMessages.isEmpty()) { - queuedMessages.forEach(this::add); - queuedMessages.clear(); + try + { + queuedMessages.forEach(this::add); + } + finally + { + queuedMessages.clear(); + } } } diff --git a/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java b/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java index 9c88826af7..f89ce84b43 100644 --- a/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java +++ b/runelite-client/src/main/java/net/runelite/client/chat/QueuedMessage.java @@ -26,12 +26,14 @@ package net.runelite.client.chat; import lombok.Builder; import lombok.Data; +import lombok.NonNull; import net.runelite.api.ChatMessageType; @Data @Builder public class QueuedMessage { + @NonNull private final ChatMessageType type; private final String value; private String name; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java index 3de1d5430d..d93e5b43c9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/antidrag/AntiDragConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.antidrag; import java.awt.Color; import java.awt.event.KeyEvent; import net.runelite.client.config.Alpha; +import net.runelite.api.Constants; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; @@ -44,7 +45,7 @@ public interface AntiDragConfig extends Config ) default int dragDelay() { - return 600 / 20; // one game tick + return Constants.GAME_TICK_LENGTH / Constants.CLIENT_TICK_LENGTH; // one game tick } @ConfigItem( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultConfig.java index b271addd34..41700d7fd3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultConfig.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2018, Cameron - * Copyright (c) 2018, Jacob M + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,33 +24,35 @@ */ package net.runelite.client.plugins.barbarianassault; +import java.awt.Color; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -import java.awt.*; - @ConfigGroup("barbarianAssault") public interface BarbarianAssaultConfig extends Config { @ConfigItem( keyName = "showTimer", name = "Show call change timer", - description = "Show time to next call change" + description = "Show time to next call change", + position = 0 ) default boolean showTimer() { return true; } @ConfigItem( keyName = "waveTimes", name = "Show wave and game duration", - description = "Displays wave and game duration" + description = "Displays wave and game duration", + position = 1 ) default boolean waveTimes() { return true; } + @ConfigItem( keyName = "showEggCountMessage", name = "Show count of eggs collected as collector.", description = "Display egg count as collector after each wave", - position = 0 + position = 2 ) default boolean showEggCount() { return false; } @@ -59,7 +60,7 @@ public interface BarbarianAssaultConfig extends Config keyName = "showEggCountOverlay", name = "Overlay of eggs counted", description = "Display current egg count as collector", - position = 1 + position = 3 ) default boolean showEggCountOverlay() { return false; } @@ -67,34 +68,31 @@ public interface BarbarianAssaultConfig extends Config keyName = "showHpCountMessage", name = "Show count of Hp healed as healer.", description = "Display healed count as healer after each wave", - position = 2 + position = 4 ) default boolean showHpCount() { return false; } - @ConfigItem( - keyName = "showHpCountOverlay", - name = "Overlay of Hp counted", - description = "Display current healed count as healer", - position = 3 - ) - default boolean showHpCountOverlay() { return false; } + @ConfigItem( + keyName = "showHpCountOverlay", + name = "Overlay of Hp counted", + description = "Display current healed count as healer", + position = 5 + ) + default boolean showHpCountOverlay() { return false; } @ConfigItem( keyName = "highlightCollectorEggs", name = "Highlight collector eggs", description = "Highlight called egg colors", - position = 4 + position = 6 ) - default boolean highlightCollectorEggs() - { - return false; - } + default boolean highlightCollectorEggs() { return false; } @ConfigItem( keyName = "showTotalRewards", name = "Summarize total reward points", description = "Displays total eggs/healed hp and missed attacks/lost runners", - position = 5 + position = 7 ) default boolean showTotalRewards(){ return false; }; @@ -102,14 +100,37 @@ public interface BarbarianAssaultConfig extends Config keyName = "showSummaryOfPoints", name = "Display summary of advanced points", description = "Gives summary of advanced points breakdown in chat log", - position = 7 - ) + position = 8 + ) default boolean showSummaryOfPoints() { return false; }; + @ConfigItem( keyName = "wrongPoisonFoodTextColor", name = "Change healer wrong poison pack color", description = "Change healer wrong poison pack color", - position = 8 + position = 9 ) default Color wrongPoisonFoodTextColor() { return Color.BLACK;} + + @ConfigItem( + keyName = "highlightItems", + name = "Highlight called poison/bait", + description = "Highlights the poison or bait that was called by your teammate", + position = 10 + ) + default boolean highlightItems() + { + return false; + } + + @ConfigItem( + keyName = "highlightColor", + name = "Highlight color", + description = "Configures the color to highlight the called poison/bait", + position = 11 + ) + default Color highlightColor() + { + return Color.GREEN; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultOverlay.java index 446db596ac..84a4d424ef 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultOverlay.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Cameron + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ import java.awt.Polygon; import java.awt.Rectangle; import java.awt.Stroke; import java.util.Map; +import java.awt.image.BufferedImage; import javax.inject.Inject; import lombok.Getter; import lombok.Setter; @@ -44,22 +45,28 @@ import net.runelite.api.Point; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.game.ItemManager; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayLayer; import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE; import net.runelite.client.ui.overlay.OverlayMenuEntry; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.util.ImageUtil; + class BarbarianAssaultOverlay extends Overlay { private static final int MAX_EGG_DISTANCE = 2500; - private final int HEALTH_BAR_HEIGHT = 20; - private final Color HEALTH_BAR_COLOR = new Color(225, 35, 0, 125); - private static final Color BACKGROUND = new Color(0, 0, 0, 150); + private final int HEALTH_BAR_HEIGHT = 20; + private final Color HEALTH_BAR_COLOR = new Color(225, 35, 0, 125); + private static final Color BACKGROUND = new Color(0, 0, 0, 150); private static final int OFFSET_Z = 20; private final Client client; + private final ItemManager itemManager; private final BarbarianAssaultPlugin plugin; private final BarbarianAssaultConfig config; @@ -67,13 +74,15 @@ class BarbarianAssaultOverlay extends Overlay @Setter private Round currentRound; + @Inject - private BarbarianAssaultOverlay(Client client, BarbarianAssaultPlugin plugin, BarbarianAssaultConfig config) + private BarbarianAssaultOverlay(Client client, ItemManager itemManager, BarbarianAssaultPlugin plugin, BarbarianAssaultConfig config) { super(plugin); setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ABOVE_WIDGETS); this.client = client; + this.itemManager = itemManager; this.plugin = plugin; this.config = config; getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "B.A. overlay")); @@ -115,50 +124,80 @@ class BarbarianAssaultOverlay extends Overlay graphics.drawImage(plugin.getClockImage(), spriteBounds.x, spriteBounds.y, null); } - if (role == Role.COLLECTOR && config.highlightCollectorEggs()) - { + if (role == Role.COLLECTOR && config.highlightCollectorEggs()) { String heardCall = plugin.getCollectorHeardCall(); Color highlightColor = BarbarianAssaultPlugin.getEggColor(heardCall); Map calledEggMap = plugin.getCalledEggMap(); Map yellowEggMap = plugin.getYellowEggs(); - if (calledEggMap != null) - { + if (calledEggMap != null) { renderEggLocations(graphics, calledEggMap, highlightColor); } // Always show yellow eggs renderEggLocations(graphics, yellowEggMap, Color.YELLOW); } - if (role == Role.HEALER) - { - for (HealerTeam teammate : HealerTeam.values()) - { - Widget widget = client.getWidget(teammate.getTeammate()); - if (widget == null) + Widget inventory = client.getWidget(WidgetInfo.INVENTORY); + + if (config.highlightItems() && inventory != null && !inventory.isHidden() && ((role == Role.DEFENDER || role == Role.HEALER))) { + int listenItemId = plugin.getListenItemId(role.getListen()); + + if (listenItemId != -1) { + Color color = config.highlightColor(); + BufferedImage highlight = ImageUtil.fillImage(itemManager.getImage(listenItemId), new Color(color.getRed(), color.getGreen(), color.getBlue(), 150)); + + for (WidgetItem item : inventory.getWidgetItems()) { - continue; + if (item.getId() == listenItemId) + { + OverlayUtil.renderImageLocation(graphics, item.getCanvasLocation(), highlight); + } } - - String[] teammateHealth = widget.getText().split(" / "); - final int curHealth = Integer.parseInt(teammateHealth[0]); - final int maxHealth = Integer.parseInt(teammateHealth[1]); - - int width = teammate.getWidth(); - final int filledWidth = getBarWidth(maxHealth, curHealth, width); - - int offsetX = teammate.getOffset().getX(); - int offsetY = teammate.getOffset().getY(); - int x = widget.getCanvasLocation().getX() - offsetX; - int y = widget.getCanvasLocation().getY() - offsetY; - - graphics.setColor(HEALTH_BAR_COLOR); - graphics.fillRect(x, y, filledWidth, HEALTH_BAR_HEIGHT); } } + + if (role == Role.HEALER) + { + for (HealerTeam teammate : HealerTeam.values()) + { + Widget widget = client.getWidget(teammate.getTeammate()); + if (widget == null) + { + continue; + } + + String[] teammateHealth = widget.getText().split(" / "); + final int curHealth = Integer.parseInt(teammateHealth[0]); + final int maxHealth = Integer.parseInt(teammateHealth[1]); + + int width = teammate.getWidth(); + final int filledWidth = getBarWidth(maxHealth, curHealth, width); + + int offsetX = teammate.getOffset().getX(); + int offsetY = teammate.getOffset().getY(); + int x = widget.getCanvasLocation().getX() - offsetX; + int y = widget.getCanvasLocation().getY() - offsetY; + + graphics.setColor(HEALTH_BAR_COLOR); + graphics.fillRect(x, y, filledWidth, HEALTH_BAR_HEIGHT); + } + } + return null; } + private static int getBarWidth(int base, int current, int size) + { + final double ratio = (double) current / base; + + if (ratio >= 1) + { + return size; + } + + return (int) Math.round(ratio * size); + } + private void renderEggLocations(Graphics2D graphics, Map eggMap, Color color) { Player player = client.getLocalPlayer(); @@ -201,16 +240,4 @@ class BarbarianAssaultOverlay extends Overlay graphics.setStroke(originalStroke); } - - private static int getBarWidth(int base, int current, int size) - { - final double ratio = (double) current / base; - - if (ratio >= 1) - { - return size; - } - - return (int) Math.round(ratio * size); - } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java index 6033ae28a3..155cf11cff 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/BarbarianAssaultPlugin.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2018, Cameron - * Copyright (c) 2018, Jacob M + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,12 +42,14 @@ import net.runelite.api.Client; import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.InventoryID; import net.runelite.api.Item; +import net.runelite.api.GameState; import net.runelite.api.ItemID; import net.runelite.api.Varbits; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ItemContainerChanged; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.events.GameStateChanged; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetInfo; @@ -60,6 +61,7 @@ import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.util.ColorUtil; @@ -71,9 +73,10 @@ import lombok.extern.slf4j.Slf4j; @PluginDescriptor( - name = "Barbarian Assault", - description = "Show a timer to the next call change and game/wave duration in chat.", - tags = {"minigame", "overlay", "timer"} + name = "Barbarian Assault+", + description = "Custom barbarian assault plugin, use along with BA Tools", + tags = {"minigame", "overlay", "timer"}, + type = PluginType.PVM // don't remove this, added this because our barbarian assault plugin is big time modified ) public class BarbarianAssaultPlugin extends Plugin { @@ -95,35 +98,27 @@ public class BarbarianAssaultPlugin extends Plugin private int totalHpHealed = 0; private boolean hasAnnounced; - - private int[] pointsList; - - String[] descriptions = {"Runners: ", - "Hitpoints: ", - "Wrong heal packs: ", - "Eggs: ", - "Failed attacks: ", - "Honour Points: "}; - - private Font font; - private Image clockImage; + private Font font; + private final Image clockImage = ImageUtil.getResourceStreamFromClass(getClass(), "clock.png"); private int inGameBit = 0; private String currentWave = START_WAVE; private GameTimer gameTime; @Getter(AccessLevel.PACKAGE) - private HashMap redEggs; + private final HashMap redEggs = new HashMap<>(); @Getter(AccessLevel.PACKAGE) - private HashMap greenEggs; + private final HashMap greenEggs = new HashMap<>(); @Getter(AccessLevel.PACKAGE) - private HashMap blueEggs; + private final HashMap blueEggs = new HashMap<>(); @Getter(AccessLevel.PACKAGE) - private HashMap yellowEggs; + private final HashMap yellowEggs = new HashMap<>(); + @Inject + @Getter private Client client; @Inject @@ -138,33 +133,45 @@ public class BarbarianAssaultPlugin extends Plugin @Inject private BarbarianAssaultOverlay overlay; - @Provides + private final ImmutableList WIDGETS = ImmutableList.of( + WidgetInfo.BA_FAILED_ATTACKER_ATTACKS, + WidgetInfo.BA_RUNNERS_PASSED, + WidgetInfo.BA_EGGS_COLLECTED, + WidgetInfo.BA_HITPOINTS_REPLENISHED, + WidgetInfo.BA_WRONG_POISON_PACKS, + WidgetInfo.BA_HONOUR_POINTS_REWARD + ); + private final ImmutableList POINTSWIDGETS = ImmutableList.of( + //base + WidgetInfo.BA_BASE_POINTS, + //att + WidgetInfo.BA_FAILED_ATTACKER_ATTACKS_POINTS, + WidgetInfo.BA_RANGERS_KILLED, + WidgetInfo.BA_FIGHTERS_KILLED, + //def + WidgetInfo.BA_RUNNERS_PASSED_POINTS, + WidgetInfo.BA_RUNNERS_KILLED, + //coll + WidgetInfo.BA_EGGS_COLLECTED_POINTS, + //heal + WidgetInfo.BA_HEALERS_KILLED, + WidgetInfo.BA_HITPOINTS_REPLENISHED_POINTS, + WidgetInfo.BA_WRONG_POISON_PACKS_POINTS + ); + + @Provides BarbarianAssaultConfig provideConfig(ConfigManager configManager) { return configManager.getConfig(BarbarianAssaultConfig.class); } - private static final ImmutableList WIDGETS = ImmutableList.of( - WidgetInfo.BA_RUNNERS_PASSED, - WidgetInfo.BA_HITPOINTS_REPLENISHED, - WidgetInfo.BA_WRONG_POISON_PACKS, - WidgetInfo.BA_EGGS_COLLECTED, - WidgetInfo.BA_FAILED_ATTACKER_ATTACKS, - WidgetInfo.BA_HONOUR_POINTS_REWARD - ); + private Game game; + private Wave wave; @Override protected void startUp() throws Exception { overlayManager.add(overlay); font = FontManager.getRunescapeFont() .deriveFont(Font.BOLD, 24); - - clockImage = ImageUtil.getResourceStreamFromClass(getClass(), "clock.png"); - - redEggs = new HashMap<>(); - greenEggs = new HashMap<>(); - blueEggs = new HashMap<>(); - yellowEggs = new HashMap<>(); - pointsList = new int[6]; } @Override @@ -178,6 +185,16 @@ public class BarbarianAssaultPlugin extends Plugin positiveEggCount = 0; wrongEggs = 0; HpHealed = 0; + clearAllEggMaps(); + } + + @Subscribe + public void onGameStateChanged(final GameStateChanged event) + { + if (event.getGameState() == GameState.LOADING) + { + clearAllEggMaps(); + } } @Subscribe @@ -185,25 +202,25 @@ public class BarbarianAssaultPlugin extends Plugin { if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID) { + wave = new Wave(client); Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT); if (rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null) { if (config.waveTimes()) announceTime("Game finished, duration: ", gameTime.getTime(false)); if (config.showTotalRewards()) - announceSomething("Game Summary: " + "Total Runners: " + pointsList[0] - + "; Total Hp Replenished: " + pointsList[1] - + "; Total Wrong Heal Packs: " + pointsList[2] - + "; Total Eggs: " + pointsList[3] - + "; Total Failed attacks: " + pointsList[4] - + "; Total Honour Points: " + (80 + pointsList[5])); + { + announceSomething(game.getGameSummary()); + } } Widget pointsWidget = client.getWidget(WidgetInfo.BA_RUNNERS_PASSED); if (!rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && pointsWidget != null && config.showSummaryOfPoints() && !hasAnnounced && client.getVar(Varbits.IN_GAME_BA) == 0) { - announceSomething("Wave Points Summary: " + giveSummaryOfPoints()); - hasAnnounced = true; + wave.setWaveAmounts(); + wave.setWavePoints(); + game.getWaves().add(wave); + announceSomething(wave.getWaveSummary()); } } } @@ -211,10 +228,31 @@ public class BarbarianAssaultPlugin extends Plugin @Subscribe public void onChatMessage(ChatMessage chatMessage) { - if (!chatMessage.getType().equals(ChatMessageType.GAMEMESSAGE)) + if (chatMessage.getMessage().toLowerCase().contains("testing")) { - return; + ArrayList waves = new ArrayList<>(); + for (int i = 0; i < 1; i++) + { + Wave wave1 = new Wave(client); + int[] amounts = {4, 0, 30, 10, 1, 38}; + int[] points = {-3, -2, 6, -4, -8, -11}; + int[] otherPoints = {38, 35, 33, 30}; + wave1.setWaveAmounts(amounts); + wave1.setWavePoints(points, otherPoints); + waves.add(wave1); + announceSomething(wave1.getWaveSummary()); + } + Game game1 = new Game(client, waves); + announceSomething(game1.getGameSummary()); } + if (chatMessage.getMessage().toLowerCase().startsWith("wave points")) + { + hasAnnounced = true; + } + if (!chatMessage.getType().equals(ChatMessageType.GAMEMESSAGE)) + { + return; + } int inGame = client.getVar(Varbits.IN_GAME_BA); if (inGameBit != inGame) return; @@ -235,7 +273,7 @@ public class BarbarianAssaultPlugin extends Plugin gameTime = new GameTimer(); totalHpHealed = 0; totalCollectedEggCount = 0; - pointsList = new int[]{0,0,0,0,0,0}; + game = new Game(client); } else if (gameTime != null) { @@ -429,41 +467,17 @@ public class BarbarianAssaultPlugin extends Plugin } } - private void announceSomething(String something) + private void announceSomething(final ChatMessageBuilder chatMessage) { - final String chatMessage = new ChatMessageBuilder() - .append(something) - .build(); chatMessageManager.queue(QueuedMessage.builder() .type(ChatMessageType.CONSOLE) - .runeLiteFormattedMessage(chatMessage) + .runeLiteFormattedMessage(chatMessage.build()) .build()); } - private String giveSummaryOfPoints() - { - StringBuilder message = new StringBuilder(); - for (int i = 0; i < WIDGETS.size(); i++) - { - Widget w = client.getWidget(WIDGETS.get(i)); - if (w != null && !w.getText().equals("")) - { - pointsList[i] += Integer.parseInt(w.getText()); - } - else - { - log.info("widget null"); - } - message.append(descriptions[i]) - .append(Integer.parseInt(w.getText())) - .append("; "); - } - return message.toString(); - } - String getCollectorHeardCall() { - Widget widget = client.getWidget(WidgetInfo.BA_COLL_HEARD_TEXT); + Widget widget = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT); String call = null; if (widget != null) @@ -589,6 +603,14 @@ public class BarbarianAssaultPlugin extends Plugin return (tile.getWorldLocation().equals(local.getWorldLocation())); } + private void clearAllEggMaps() + { + redEggs.clear(); + greenEggs.clear(); + blueEggs.clear(); + yellowEggs.clear(); + } + public Font getFont() { return font; @@ -598,4 +620,30 @@ public class BarbarianAssaultPlugin extends Plugin { return clockImage; } + + public int getListenItemId(WidgetInfo listenInfo) + { + Widget listenWidget = client.getWidget(listenInfo); + + if (listenWidget != null) + { + switch (listenWidget.getText()) + { + case "Tofu": + return ItemID.TOFU; + case "Crackers": + return ItemID.CRACKERS; + case "Worms": + return ItemID.WORMS; + case "Pois. Worms": + return ItemID.POISONED_WORMS; + case "Pois. Tofu": + return ItemID.POISONED_TOFU; + case "Pois. Meat": + return ItemID.POISONED_MEAT; + } + } + + return -1; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Calls.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Calls.java index 23d726f10e..5cba373d95 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Calls.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Calls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Cameron + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Game.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Game.java new file mode 100644 index 0000000000..8ee06f4339 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Game.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.barbarianassault; + +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.events.ChatMessage; +import net.runelite.client.chat.ChatColorType; +import net.runelite.client.chat.ChatMessageBuilder; +import net.runelite.client.eventbus.Subscribe; + +import java.util.ArrayList; + +public class Game +{ + @Getter + private Client client; + + @Getter + private String currentWave; + @Getter + private ArrayList waves = new ArrayList<>(); + private String[] totalDescriptions = { + "A: ", + "; D: ", + "; C: ", + "; Vial: ", + "; H packs: ", + "; Total: "}; + private String[] otherPointsDescriptions = { + " A: ", + "; D: ", + "; C: ", + "; H: " + }; + private int[] totalPoints = new int[6]; + private int[] totalAmounts = new int[6]; + private int[] otherRolesPoints = new int[4]; + + Game(Client client) + { + this.client = client; + } + Game(Client client, ArrayList waves) + { + this.client = client; + this.waves = waves; + } + @Subscribe + public void onChatMessage(ChatMessage chatMessage) + { + if (chatMessage.getMessage().startsWith("---- Wave:")) + { + String[] tempMessage = chatMessage.getMessage().split(" "); + currentWave = tempMessage[2]; + String[] temp = currentWave.split(" "); + } + if (currentWave.equals("1")) + { + waves = null; + totalPoints = new int[6]; + totalAmounts = new int[6]; + } + } + ChatMessageBuilder getGameSummary() + { + int[] amountsList; + int[] pointsList; + int[] otherRolesPointsList; + ChatMessageBuilder message = new ChatMessageBuilder(); + message.append("Round points: "); + for (Wave w : waves) + { + amountsList = w.getWaveAmounts(); + pointsList = w.getWavePoints(); + otherRolesPointsList = w.getOtherRolesPointsList(); + for (int j = 0; j < totalAmounts.length; j++) { + totalAmounts[j] += amountsList[j]; + } + for (int k = 0; k < totalPoints.length; k++) { + totalPoints[k] += pointsList[k]; + } + for (int z = 0; z < otherRolesPoints.length; z++) { + otherRolesPoints[z] += otherRolesPointsList[z]; + } + } + for (int i = 0; i < otherRolesPoints.length; i++) + { + otherRolesPoints[i] += 80; + } + totalAmounts[5] += 80; + for (int i = 0; i < totalDescriptions.length; i++) + { + if (i != 4) + { + message.append(totalDescriptions[i]); + message.append(String.valueOf(totalAmounts[i])); + message.append("("); + if (totalPoints[i] < 0) + { + message.append(ChatColorType.HIGHLIGHT); + message.append(String.valueOf(totalPoints[i])); + message.append(ChatColorType.NORMAL); + } + else + { + message.append(String.valueOf(totalPoints[i])); + } + message.append(")"); + } + } + message.append(System.getProperty("line.separator")); + message.append("All roles points this game: "); + for(int i = 0; i < otherPointsDescriptions.length; i++) + { + message.append(otherPointsDescriptions[i]); + message.append(String.valueOf(otherRolesPoints[i])); + } + return message; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java index 6ed8c4957c..948ab8bc85 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/GameTimer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Jacob M + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,6 +28,7 @@ import java.time.Duration; import java.time.Instant; import java.time.LocalTime; import java.time.format.DateTimeFormatter; +import net.runelite.api.Constants; class GameTimer { @@ -45,7 +46,7 @@ class GameTimer } else { - elapsed = Duration.between(startTime, now).minusMillis(600); + elapsed = Duration.between(startTime, now).minusMillis(Constants.GAME_TICK_LENGTH); } return formatTime(LocalTime.ofSecondOfDay(elapsed.getSeconds())); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java index 64cf11fa8b..627551cd6e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Role.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Cameron + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java index 7da563d9cd..4428d504b4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Round.java @@ -29,6 +29,7 @@ import java.time.Instant; import javax.inject.Inject; import lombok.Getter; import lombok.Setter; +import net.runelite.api.Constants; class Round { @@ -52,7 +53,7 @@ class Round public Round(Role role) { this.roundRole = role; - this.roundStartTime = Instant.now().plusMillis(1200); + this.roundStartTime = Instant.now().plusMillis(2 * Constants.GAME_TICK_LENGTH); } public long getRoundTime() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Wave.java b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Wave.java new file mode 100644 index 0000000000..e8e290354d --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Wave.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2018, https://runelitepl.us + * 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.barbarianassault; + +import com.google.common.collect.ImmutableList; +import lombok.Getter; +import net.runelite.api.Client; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.chat.ChatMessageBuilder; +import net.runelite.client.chat.ChatMessageManager; + +import javax.inject.Inject; +import java.awt.*; + + +class Wave +{ + @Getter + private Client client; + private final ImmutableList WIDGETS = ImmutableList.of( + WidgetInfo.BA_FAILED_ATTACKER_ATTACKS, + WidgetInfo.BA_RUNNERS_PASSED, + WidgetInfo.BA_EGGS_COLLECTED, + WidgetInfo.BA_HITPOINTS_REPLENISHED, + WidgetInfo.BA_WRONG_POISON_PACKS, + WidgetInfo.BA_HONOUR_POINTS_REWARD + ); + private final ImmutableList POINTSWIDGETS = ImmutableList.of( + //base + WidgetInfo.BA_BASE_POINTS, + //att + WidgetInfo.BA_FAILED_ATTACKER_ATTACKS_POINTS, + WidgetInfo.BA_RANGERS_KILLED, + WidgetInfo.BA_FIGHTERS_KILLED, + //def + WidgetInfo.BA_RUNNERS_PASSED_POINTS, + WidgetInfo.BA_RUNNERS_KILLED, + //coll + WidgetInfo.BA_EGGS_COLLECTED_POINTS, + //heal + WidgetInfo.BA_HEALERS_KILLED, + WidgetInfo.BA_HITPOINTS_REPLENISHED_POINTS, + WidgetInfo.BA_WRONG_POISON_PACKS_POINTS + ); + private int[] amountsList = new int[6]; + private int[] allPointsList = new int[10]; + private int[] importantPointsList = new int[6]; + private int[] otherRolesPointsList = new int[4]; + private String[] descriptions = { + " A: ", + " D: ", + " C: ", + " Vial: ", + " H packs: ", + " Total: "}; + + private String[] otherPointsDescriptions = { + " A: ", + " D: ", + " C: ", + " H: " + }; + Wave(Client client) + { + this.client = client; + } + int[] getOtherRolesPointsList() + { + return otherRolesPointsList; + } + int[] getWaveAmounts() + { + return amountsList; + } + int[] getWavePoints() + { + return importantPointsList; + } + void setWaveAmounts(int[] amounts) + { + for (int i = 0; i < amounts.length; i++) + { + amountsList[i] = amounts[i]; + } + } + + void setWavePoints(int[] points, int[] otherRolesPoints) + { + for (int i = 0; i < points.length; i++) + { + importantPointsList[i] = points[i]; + } + for (int i = 0; i < otherRolesPoints.length; i++) + { + otherRolesPointsList[i] = otherRolesPoints[i]; + } + } + void setWaveAmounts() + { + for (int i = 0; i < WIDGETS.size(); i++) + { + Widget w = client.getWidget(WIDGETS.get(i)); + if (w != null) + { + amountsList[i] = Integer.parseInt(w.getText()); + } + } + } + void setWavePoints() + { + for (int i = 0; i < POINTSWIDGETS.size(); i++) + { + Widget w = client.getWidget(POINTSWIDGETS.get(i)); + allPointsList[i] = Integer.parseInt(w.getText()); + switch (i) + { + case 1: + importantPointsList[0] += allPointsList[i]; + break; + case 4: + importantPointsList[1] += allPointsList[i]; + break; + case 6: + importantPointsList[2] += allPointsList[i]; + break; + case 8: + case 9: + importantPointsList[3] += allPointsList[i]; + break; + default: + break; + } + } + importantPointsList[5] = 0; + for (int i = 0; i < importantPointsList.length-1; i++) + { + importantPointsList[5] += importantPointsList[i]; + } + for (int i = 0; i < POINTSWIDGETS.size(); i++) + { + Widget w = client.getWidget(POINTSWIDGETS.get(i)); + switch (i) + { + case 0: + otherRolesPointsList[0] += Integer.parseInt(w.getText()); + otherRolesPointsList[1] += Integer.parseInt(w.getText()); + otherRolesPointsList[2] += Integer.parseInt(w.getText()); + otherRolesPointsList[3] += Integer.parseInt(w.getText()); + break; + case 1: + case 2: + case 3: + otherRolesPointsList[0] += Integer.parseInt(w.getText()); + break; + case 4: + case 5: + otherRolesPointsList[1] += Integer.parseInt(w.getText()); + break; + case 6: + otherRolesPointsList[2] += Integer.parseInt(w.getText()); + break; + case 7: + case 8: + case 9: + otherRolesPointsList[3] += Integer.parseInt(w.getText()); + break; + default: + break; + } + } + } + ChatMessageBuilder getWaveSummary() + { + ChatMessageBuilder message = new ChatMessageBuilder(); + message.append("Wave points:"); + for(int i = 0; i < descriptions.length; i++) + { + if (i != 4) + { + message.append(descriptions[i]); + message.append(String.valueOf(amountsList[i])); + message.append("("); + if (importantPointsList[i] < 0) + { + message.append(Color.RED, String.valueOf(importantPointsList[i])); + } + else + { + message.append(String.valueOf(importantPointsList[i])); + } + message.append(")"); + } + } + message.append(System.getProperty("line.separator")); + message.append("All roles points this wave: "); + for(int i = 0; i < otherPointsDescriptions.length; i++) + { + message.append(otherPointsDescriptions[i]); + message.append(String.valueOf(otherRolesPointsList[i])); + } + return message; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/clock.png b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/clock.png new file mode 100644 index 0000000000..c0f39269e1 Binary files /dev/null and b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/clock.png differ diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java index 41f2bbc67d..663e03fbb3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsConfig.java @@ -97,4 +97,15 @@ public interface BarrowsConfig extends Config { return true; } + + @ConfigItem( + keyName = "showPrayerDrainTimer", + name = "Show Prayer Drain Timer", + description = "Configure whether or not a countdown until the next prayer drain is displayed", + position = 6 + ) + default boolean showPrayerDrainTimer() + { + return true; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java index bc505755ff..72bf08fe7e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPlugin.java @@ -42,6 +42,7 @@ import net.runelite.api.ItemContainer; import net.runelite.api.NullObjectID; import net.runelite.api.ObjectID; import net.runelite.api.WallObject; +import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameObjectChanged; import net.runelite.api.events.GameObjectDespawned; import net.runelite.api.events.GameObjectSpawned; @@ -60,9 +61,11 @@ import net.runelite.client.chat.QueuedMessage; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.StackFormatter; @PluginDescriptor( @@ -89,12 +92,16 @@ public class BarrowsPlugin extends Plugin WidgetInfo.BARROWS_PUZZLE_ANSWER3 ); + private static final int CRYPT_REGION_ID = 14231; + @Getter(AccessLevel.PACKAGE) private final Set walls = new HashSet<>(); @Getter(AccessLevel.PACKAGE) private final Set ladders = new HashSet<>(); + private boolean wasInCrypt = false; + @Getter private Widget puzzleAnswer; @@ -113,6 +120,12 @@ public class BarrowsPlugin extends Plugin @Inject private ItemManager itemManager; + @Inject + private SpriteManager spriteManager; + + @Inject + private InfoBoxManager infoBoxManager; + @Inject private ChatMessageManager chatMessageManager; @@ -140,6 +153,8 @@ public class BarrowsPlugin extends Plugin walls.clear(); ladders.clear(); puzzleAnswer = null; + wasInCrypt = false; + stopPrayerDrainTimer(); // Restore widgets final Widget potential = client.getWidget(WidgetInfo.BARROWS_POTENTIAL); @@ -155,6 +170,15 @@ public class BarrowsPlugin extends Plugin } } + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("barrows") && !config.showPrayerDrainTimer()) + { + stopPrayerDrainTimer(); + } + } + @Subscribe public void onWallObjectSpawned(WallObjectSpawned event) { @@ -220,11 +244,24 @@ public class BarrowsPlugin extends Plugin { if (event.getGameState() == GameState.LOADING) { + wasInCrypt = isInCrypt(); // on region changes the tiles get set to null walls.clear(); ladders.clear(); puzzleAnswer = null; } + else if (event.getGameState() == GameState.LOGGED_IN) + { + boolean isInCrypt = isInCrypt(); + if (wasInCrypt && !isInCrypt) + { + stopPrayerDrainTimer(); + } + else if (!wasInCrypt && isInCrypt) + { + startPrayerDrainTimer(); + } + } } @Subscribe @@ -271,4 +308,22 @@ public class BarrowsPlugin extends Plugin } } } + + private void startPrayerDrainTimer() + { + if (config.showPrayerDrainTimer()) + { + infoBoxManager.addInfoBox(new BarrowsPrayerDrainTimer(this, spriteManager)); + } + } + + private void stopPrayerDrainTimer() + { + infoBoxManager.removeIf(BarrowsPrayerDrainTimer.class::isInstance); + } + + private boolean isInCrypt() + { + return client.getLocalPlayer().getWorldLocation().getRegionID() == CRYPT_REGION_ID; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java new file mode 100644 index 0000000000..4428a54f07 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barrows/BarrowsPrayerDrainTimer.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, Ryan + * 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.barrows; + +import java.awt.Color; +import java.time.Duration; +import java.time.Instant; +import net.runelite.api.SpriteID; +import net.runelite.client.game.SpriteManager; +import net.runelite.client.ui.overlay.infobox.InfoBox; +import net.runelite.client.ui.overlay.infobox.InfoBoxPriority; + +class BarrowsPrayerDrainTimer extends InfoBox +{ + private static final long PRAYER_DRAIN_INTERVAL_MS = 18200; + + private final Instant startTime; + + BarrowsPrayerDrainTimer(BarrowsPlugin plugin, SpriteManager spriteManager) + { + super(spriteManager.getSprite(SpriteID.TAB_PRAYER, 0), plugin); + setPriority(InfoBoxPriority.MED); + setTooltip("Prayer Drain"); + startTime = Instant.now(); + } + + @Override + public String getText() + { + Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime()); + int seconds = (int) (timeLeft.toMillis() / 1000L); + return String.format("0:%02d", seconds); + } + + @Override + public Color getTextColor() + { + Duration timeLeft = Duration.between(Instant.now(), getNextPrayerDrainTime()); + + //check if timer has 10% of time left + if (timeLeft.getSeconds() < (PRAYER_DRAIN_INTERVAL_MS / 1000 * .10)) + { + return Color.RED.brighter(); + } + + return Color.WHITE; + } + + private Instant getNextPrayerDrainTime() + { + Duration timePassed = Duration.between(startTime, Instant.now()); + // Get how many intervals have passed so far and add one more to find the next prayer drain time + return startTime.plusMillis((timePassed.toMillis() / PRAYER_DRAIN_INTERVAL_MS + 1) * PRAYER_DRAIN_INTERVAL_MS); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java index 3f3f156ea2..c8747828f9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsConfig.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2018, Cameron - * Copyright (c) 2018, Jacob M + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,9 +32,9 @@ import net.runelite.client.config.ConfigItem; public interface BAToolsConfig extends Config { @ConfigItem( - keyName = "defTimer", - name = "Defender Tick Timer", - description = "Shows the current cycle tick of runners." + keyName = "defTimer", + name = "Defender Tick Timer", + description = "Shows the current cycle tick of runners." ) default boolean defTimer() { @@ -43,9 +42,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "calls", - name = "Remove Incorrect Calls", - description = "Remove incorrect calls." + keyName = "calls", + name = "Remove Incorrect Calls", + description = "Remove incorrect calls." ) default boolean calls() { @@ -53,9 +52,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "swapLadder", - name = "Swap ladder option", - description = "Swap Climb-down with Quick-start in the wave lobbies" + keyName = "swapLadder", + name = "Swap ladder option", + description = "Swap Climb-down with Quick-start in the wave lobbies" ) default boolean swapLadder() { @@ -63,9 +62,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "healerCodes", - name = "Healer Codes", - description = "Overlay to show healer codes" + keyName = "healerCodes", + name = "Healer Codes", + description = "Overlay to show healer codes" ) default boolean healerCodes() { @@ -73,9 +72,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "healerMenuOption", - name = "Healer menu options", - description = "asd" + keyName = "healerMenuOption", + name = "Healer menu options", + description = "asd" ) default boolean healerMenuOption() { @@ -83,9 +82,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "antiDrag", - name = "Anti Drag", - description = "asd" + keyName = "antiDrag", + name = "Anti Drag", + description = "asd" ) default boolean antiDrag() { @@ -93,9 +92,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "antiDragDelay", - name = "Anti Drag Delay", - description = "asd" + keyName = "antiDragDelay", + name = "Anti Drag Delay", + description = "asd" ) default int antiDragDelay() { @@ -103,9 +102,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "eggBoi", - name = "Collector helper", - description = "asd" + keyName = "eggBoi", + name = "Collector helper", + description = "asd" ) default boolean eggBoi() { @@ -113,9 +112,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "osHelp", - name = "Shift OS", - description = "asd" + keyName = "osHelp", + name = "Shift OS", + description = "asd" ) default boolean osHelp() { @@ -123,9 +122,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "prayerMetronome", - name = "Prayer Metronome", - description = "asd" + keyName = "prayerMetronome", + name = "Prayer Metronome", + description = "asd" ) default boolean prayerMetronome() { @@ -133,9 +132,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "prayerMetronomeVolume", - name = "Prayer Metronome Volume", - description = "asd" + keyName = "prayerMetronomeVolume", + name = "Prayer Metronome Volume", + description = "asd" ) default int prayerMetronomeVolume() { @@ -143,9 +142,9 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "attackStyles", - name = "Attack Styles", - description = "asd" + keyName = "attackStyles", + name = "Attack Styles", + description = "Hide attack styles depending on weapon." ) default boolean attackStyles() { @@ -153,13 +152,24 @@ public interface BAToolsConfig extends Config } @ConfigItem( - keyName = "tagging", - name = "Attack Tags", - description = "asd" + keyName = "removeBA", + name = "*Barbarian Assault Helper*", + description = "Remove unnecessary menu options in Barbarian Assault depending on role
Examples: Remove attack options when not attacker
Remove take options when not collector" ) - default boolean tagging() - { - return false; - } + default boolean removeBA() { return true; } -} + @ConfigItem( + keyName = "removeWrongEggs", + name = "Remove wrong eggs - *Barbarian Assault Helper*", + description = "Remove unnecessary menu options in Barbarian Assault depending on role
Examples: Remove attack options when not attacker
Remove take options when not collector" + ) + default boolean removeWrongEggs() { return false; } + + @ConfigItem( + keyName = "removeWrongHealFood", + name = "Remove wrong Heal Food - *Barbarian Assault Helper*", + description = "Remove unnecessary menu options in Barbarian Assault depending on role
Examples: Remove attack options when not attacker
Remove take options when not collector" + ) + default boolean removeHealWrongFood() { return false; } + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java index 5b227bae9c..083945d9b6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsOverlay.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Woox + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,59 +69,57 @@ public class BAToolsOverlay extends Overlay @Override public Dimension render(Graphics2D graphics) { - if(config.healerCodes()) + if(!config.healerCodes()) { - for (Healer healer : plugin.getHealers().values()) - { - NPCComposition composition = healer.getNpc().getComposition(); - Color color = composition.getCombatLevel() > 1 ? YELLOW : ORANGE; - if (composition.getConfigs() != null) - { - NPCComposition transformedComposition = composition.transform(); - if (transformedComposition == null) - { - color = GRAY; - } - else - { - composition = transformedComposition; - } - } - int timeLeft = healer.getLastFoodTime() - (int) Duration.between(plugin.getWave_start(), Instant.now()).getSeconds(); - timeLeft = timeLeft < 1 ? 0 : timeLeft; + return null; + } - if (healer.getFoodRemaining() > 1) + for (Healer healer : plugin.getHealers().values()) + { + NPCComposition composition = healer.getNpc().getComposition(); + Color color = composition.getCombatLevel() > 1 ? YELLOW : ORANGE; + if (composition.getConfigs() != null) + { + NPCComposition transformedComposition = composition.transform(); + if (transformedComposition == null) { - color = GREEN; - } - else if (healer.getFoodRemaining() == 1) - { - if (timeLeft > 0) - { - color = RED; - } - else - { - color = GREEN; - } + color = GRAY; } else { - continue; + composition = transformedComposition; } - - String text = String.format("%d %d", - healer.getFoodRemaining(), - timeLeft); - - - OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color); } - } + int timeLeft = healer.getLastFoodTime() - (int)Duration.between(plugin.getWave_start(), Instant.now()).getSeconds(); + timeLeft = timeLeft < 1 ? 0 : timeLeft; - if(!config.eggBoi()) - { - return null; + if(healer.getFoodRemaining() > 1) + { + color = GREEN; + } + else if(healer.getFoodRemaining() == 1) + { + if(timeLeft > 0) + { + color = RED; + } + else + { + color = GREEN; + } + } + else + { + continue; + } + + String text = String.format("%d %d", + healer.getFoodRemaining(), + timeLeft); + + + + OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color); } return null; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java index 20ddb31326..ebc17a3421 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/BAToolsPlugin.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2018, Cameron - * Copyright (c) 2018, Jacob M + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,10 +35,7 @@ import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.time.Duration; import java.time.Instant; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import javax.inject.Inject; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -64,7 +60,6 @@ import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.events.WidgetHiddenChanged; import net.runelite.api.widgets.Widget; import net.runelite.api.widgets.WidgetID; import net.runelite.api.widgets.WidgetInfo; @@ -79,13 +74,14 @@ import net.runelite.client.plugins.PluginType; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.util.Text; +import org.apache.commons.lang3.ArrayUtils; @Slf4j @PluginDescriptor( - name = "BA Tools", - description = "Custom tools for Barbarian Assault", - tags = {"minigame", "overlay", "timer"}, - type = PluginType.PVM + name = "BA Tools", + description = "Custom tools for Barbarian Assault", + tags = {"minigame", "overlay", "timer"}, + type = PluginType.PVM ) public class BAToolsPlugin extends Plugin implements KeyListener { @@ -167,15 +163,65 @@ public class BAToolsPlugin extends Plugin implements KeyListener } @Subscribe - public void onWidgetHiddenChanged(WidgetHiddenChanged event) + public void onWidgetLoaded(WidgetLoaded event) { + switch (event.getGroupId()) + { + case WidgetID.BA_REWARD_GROUP_ID: + { + Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT); + + if (rewardWidget != null && rewardWidget.getText().contains("
5")) + { + tickNum = 0; + } + } + } + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (config.antiDrag()) + { + client.setInventoryDragDelay(config.antiDragDelay()); + } + + Widget callWidget = getWidget(); + + if (callWidget != null) + { + if (callWidget.getTextColor() != pastCall && callWidget.getTextColor() == 16316664) + { + tickNum = 0; + } + pastCall = callWidget.getTextColor(); + } + if (inGameBit == 1) + { + if (tickNum > 9) + { + tickNum = 0; + } + if (counter == null) + { + addCounter(); + } + counter.setCount(tickNum); + if (config.defTimer()) + { + //log.info("" + tickNum++); + tickNum++; + } + } + Widget weapon = client.getWidget(593, 1); if(config.attackStyles() - && weapon!=null - && inGameBit == 1 - && (weapon.getText().contains("Crystal halberd") || weapon.getText().contains("Dragon claws")) - && client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT)!=null) + && weapon!=null + && inGameBit == 1 + && weapon.getText().contains("Crystal halberd") || weapon.getText().contains("Dragon claws") + && client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT)!=null) { String style = client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT).getText(); @@ -226,75 +272,10 @@ public class BAToolsPlugin extends Plugin implements KeyListener } else { - if(client.getWidget(WidgetInfo.COMBAT_STYLE_ONE)!=null) - { - client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false); - } - if(client.getWidget(WidgetInfo.COMBAT_STYLE_TWO)!=null) - { - client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(false); - } - if(client.getWidget(WidgetInfo.COMBAT_STYLE_THREE)!=null) - { - client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(false); - } - if(client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR)!=null) - { - client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(false); - } - } - } - - @Subscribe - public void onWidgetLoaded(WidgetLoaded event) - { - switch (event.getGroupId()) - { - case WidgetID.BA_REWARD_GROUP_ID: - { - Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT); - - if (rewardWidget != null && rewardWidget.getText().contains("
5")) - { - tickNum = 0; - } - } - } - } - - @Subscribe - public void onGameTick(GameTick event) - { - if (config.antiDrag()) - { - client.setInventoryDragDelay(config.antiDragDelay()); - } - - Widget callWidget = getWidget(); - - if (callWidget != null) - { - if (callWidget.getTextColor() != pastCall && callWidget.getTextColor() == 16316664) - { - tickNum = 0; - } - pastCall = callWidget.getTextColor(); - } - if (inGameBit == 1) - { - if (tickNum > 9) - { - tickNum = 0; - } - if (counter == null) - { - addCounter(); - } - counter.setCount(tickNum); - if (config.defTimer()) - { - log.info("" + tickNum++); - } + client.getWidget(WidgetInfo.COMBAT_STYLE_ONE).setHidden(false); + client.getWidget(WidgetInfo.COMBAT_STYLE_TWO).setHidden(false); + client.getWidget(WidgetInfo.COMBAT_STYLE_THREE).setHidden(false); + client.getWidget(WidgetInfo.COMBAT_STYLE_FOUR).setHidden(false); } if(config.prayerMetronome() && isAnyPrayerActive()) @@ -353,7 +334,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener public void onChatMessage(ChatMessage event) { if (event.getType() == ChatMessageType.GAMEMESSAGE - && event.getMessage().startsWith("---- Wave:")) + && event.getMessage().startsWith("---- Wave:")) { String[] message = event.getMessage().split(" "); currentWave = Integer.parseInt(message[BA_WAVE_NUM_INDEX]); @@ -373,7 +354,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener { int spawnNumber = healers.size(); healers.put(npc, new Healer(npc, spawnNumber, currentWave)); - log.info("spawn number: " + spawnNumber + " on wave " + currentWave); + //log.info("spawn number: " + spawnNumber + " on wave " + currentWave); } } } @@ -420,15 +401,15 @@ public class BAToolsPlugin extends Plugin implements KeyListener public static boolean isNpcHealer(int npcId) { return npcId == NpcID.PENANCE_HEALER || - npcId == NpcID.PENANCE_HEALER_5766 || - npcId == NpcID.PENANCE_HEALER_5767 || - npcId == NpcID.PENANCE_HEALER_5768 || - npcId == NpcID.PENANCE_HEALER_5769 || - npcId == NpcID.PENANCE_HEALER_5770 || - npcId == NpcID.PENANCE_HEALER_5771 || - npcId == NpcID.PENANCE_HEALER_5772 || - npcId == NpcID.PENANCE_HEALER_5773 || - npcId == NpcID.PENANCE_HEALER_5774; + npcId == NpcID.PENANCE_HEALER_5766 || + npcId == NpcID.PENANCE_HEALER_5767 || + npcId == NpcID.PENANCE_HEALER_5768 || + npcId == NpcID.PENANCE_HEALER_5769 || + npcId == NpcID.PENANCE_HEALER_5770 || + npcId == NpcID.PENANCE_HEALER_5771 || + npcId == NpcID.PENANCE_HEALER_5772 || + npcId == NpcID.PENANCE_HEALER_5773 || + npcId == NpcID.PENANCE_HEALER_5774; } @Subscribe @@ -461,21 +442,124 @@ public class BAToolsPlugin extends Plugin implements KeyListener client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()])); } } - else if (config.calls() && event.getTarget().endsWith("horn")) - { - entries.clear(); - client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()])); - } + final int itemId = event.getIdentifier(); String option = Text.removeTags(event.getOption()).toLowerCase(); String target = Text.removeTags(event.getTarget()).toLowerCase(); + if (config.swapLadder() && option.equals("climb-down") && target.equals("ladder")) { swap("quick-start", option, target, true); } + else if(config.removeBA() && client.getVar(Varbits.IN_GAME_BA) == 1 && !option.contains("tell-"))//if in barbarian assault and menu isnt from a horn + { + if(itemId == ItemID.LOGS && !target.contains("healing vial")) + { + if(client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null) + remove(new String[]{"take", "light"}, target, true); + else//remove "Light" option (and "Take" option if not defender). + remove("light", target, true); + } + else if(option.equals("use")) + { + if (config.removeHealWrongFood()) { + Widget healer = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT); + if (healer != null) { + String item = target.split("-")[0].trim(); + List poison = Arrays.asList("poisoned tofu", "poisoned meat", "poisoned worms"); + List vials = Arrays.asList("healing vial", "healing vial(1)", "healing vial(2)", "healing vial(3)", "healing vial(4)");//"healing vial(4)" + if (poison.contains(item)) {//if item is a poison item + int calledPoison = 0; + switch (healer.getText())//choose which poison to hide the use/destroy option for + { + case "Pois. Tofu": + calledPoison = ItemID.POISONED_TOFU; + break; + case "Pois. Meat": + calledPoison = ItemID.POISONED_MEAT; + break; + case "Pois. Worms": + calledPoison = ItemID.POISONED_WORMS; + break; + } + System.out.println(target.equals(item)); + if (target.equals(item))//if targeting the item itself + { + if (calledPoison != 0 && itemId != calledPoison)//if no call or chosen item is not the called one + { + remove(new String[]{"use", "destroy", "examine"}, target, true);//remove options + } + } else if (!target.contains("penance healer")) { + remove(option, target, true); + } + } else if (vials.contains(item))//if item is the healer's healing vial + { - if ((event.getTarget().contains("Penance Healer") || event.getTarget().contains("Penance Fighter") || event.getTarget().contains("Penance Ranger"))) + if (!target.equals(item))//if target is not the vial itself + { + + if (!target.contains("level") || target.contains("penance") || target.contains("queen spawn"))//if someone has "penance" or "queen spawn" in their name, gg... + { + remove(option, target, true); + } + } + } + } + } + } + else if(option.equals("attack") && client.getWidget(WidgetInfo.BA_ATK_ROLE_TEXT) == null && !target.equals("queen spawn"))//if not attacker + {//remove attack option from everything but queen spawns + remove(option, target, true); + } + else if((option.equals("fix") || (option.equals("block") && target.equals("penance cave"))) && client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null)//if not defender + {//the check for option requires checking target as well because defensive attack style option is also called "block". + remove(option, target, true); + } + else if((option.equals("load")) && client.getWidget(WidgetInfo.BA_COLL_ROLE_TEXT) == null)//if not collector, remove hopper options + { + remove(new String[]{option, "look-in"}, target, true); + } + else if(config.removeWrongEggs() && option.equals("take")) + { + Widget eggToColl = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT); + if(eggToColl != null)//if we're a collector + { + List eggsToHide = new ArrayList<>(); + eggsToHide.add(ItemID.HAMMER); + switch(eggToColl.getText())//choose which eggs to hide take option for + { + case "Red eggs": + eggsToHide.add(ItemID.BLUE_EGG); + eggsToHide.add(ItemID.GREEN_EGG); + break; + case "Blue eggs": + eggsToHide.add(ItemID.RED_EGG); + eggsToHide.add(ItemID.GREEN_EGG); + break; + case "Green eggs": + eggsToHide.add(ItemID.RED_EGG); + eggsToHide.add(ItemID.BLUE_EGG); + break; + } + if(eggsToHide.contains(itemId)) + { + remove(option, target, true);//hide wrong eggs + } + } + else + { + List defenderItems = Arrays.asList(ItemID.HAMMER, ItemID.TOFU, ItemID.CRACKERS, ItemID.WORMS);//logs are handled separately due to hiding "light" option too. + if(client.getWidget(WidgetInfo.BA_DEF_ROLE_TEXT) == null || !defenderItems.contains(itemId))//if not defender, or item is not a defenderItem + { + remove(option, target, true);//hide everything except hammer/logs and bait if Defender + } + } + } + } + + + if (inGameBit == 1 && config.healerMenuOption() && event.getTarget().contains("Penance Healer")) { MenuEntry[] menuEntries = client.getMenuEntries(); @@ -502,7 +586,7 @@ public class BAToolsPlugin extends Plugin implements KeyListener if (client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT) != null && inGameBit == 1 && config.eggBoi() && event.getTarget().endsWith("egg") && shiftDown) { String[] currentCall = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT).getText().split(" "); - log.info("1 " + currentCall[0]); + //log.info("1 " + currentCall[0]); MenuEntry[] menuEntries = client.getMenuEntries(); MenuEntry correctEgg = null; entries.clear(); @@ -525,22 +609,6 @@ public class BAToolsPlugin extends Plugin implements KeyListener client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()])); } - if (client.getWidget(WidgetInfo.BA_ATK_LISTEN_TEXT) != null && inGameBit == 1 && config.attackStyles() && shiftDown) - { - MenuEntry[] menuEntries = client.getMenuEntries(); - MenuEntry correctEgg = null; - entries.clear(); - - for (MenuEntry entry : menuEntries) - { - if (entry.getOption().contains("Walk here")) - { - entries.add(entry); - } - } - client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()])); - } - if (client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT) != null && inGameBit == 1 && config.osHelp() && event.getTarget().equals("Healer item machine") && shiftDown) { String[] currentCall = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT).getText().split(" "); @@ -573,26 +641,25 @@ public class BAToolsPlugin extends Plugin implements KeyListener @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { - if(config.tagging() && (event.getMenuTarget().contains("Penance Ranger") || event.getMenuTarget().contains("Penance Fighter"))) + if (!config.healerMenuOption() || !event.getMenuTarget().contains("Penance Healer") || client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) == null) { - String target = event.getMenuTarget(); - if (event.getMenuOption().contains("Attack")) - { - foodPressed.put(event.getId(), Instant.now()); - } - log.info(target); + return; } - if (config.healerMenuOption() && event.getMenuTarget().contains("Penance Healer")) + String currentCall = client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT).getText(); + String target = event.getMenuTarget(); + + if ((currentCall.equals("Pois. Worms") && (target.contains("Poisoned worms") && target.contains("->") && target.contains("Penance Healer"))) + || (currentCall.equals("Pois. Meat") && (target.contains("Poisoned meat") && target.contains("->") && target.contains("Penance Healer"))) + || (currentCall.equals("Pois. Tofu") && (target.contains("Poisoned tofu") && target.contains("->") && target.contains("Penance Healer")))) { - String target = event.getMenuTarget(); - if (target.contains("->")) - { - foodPressed.put(event.getId(), Instant.now()); - } + foodPressed.put(event.getId(), Instant.now()); } - + if (target.contains("->") && target.contains("Penance Healer")) + { + foodPressed.put(event.getId(), Instant.now()); + } } @Subscribe @@ -630,6 +697,30 @@ public class BAToolsPlugin extends Plugin implements KeyListener counter = null; } + private void remove(String option, String target, boolean strict) + { + MenuEntry[] entries = client.getMenuEntries(); + int idx = searchIndex(entries, option, target, strict); + if(idx >= 0 && entries[idx] != null) + { + entries = ArrayUtils.removeElement(entries, entries[idx]); + client.setMenuEntries(entries); + } + } + + private void remove(String[] options, String target, boolean strict) + { + MenuEntry[] entries = client.getMenuEntries(); + for(int i = 0; i < options.length; i++) + { + int idx = searchIndex(entries, options[i], target, strict); + if(idx >= 0 && entries[idx] != null) + entries = ArrayUtils.removeElement(entries, entries[idx]); + } + + client.setMenuEntries(entries); + } + private void swap(String optionA, String optionB, String target, boolean strict) { MenuEntry[] entries = client.getMenuEntries(); @@ -701,9 +792,9 @@ public class BAToolsPlugin extends Plugin implements KeyListener // world point of the tile marker WorldPoint worldPoint = new WorldPoint( - ((regionId >>> 8) << 6) + regionX, - ((regionId & 0xff) << 6) + regionY, - z + ((regionId >>> 8) << 6) + regionX, + ((regionId & 0xff) << 6) + regionY, + z ); int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks(); @@ -716,11 +807,11 @@ public class BAToolsPlugin extends Plugin implements KeyListener int templateChunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE; int templateChunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE; if (worldPoint.getX() >= templateChunkX && worldPoint.getX() < templateChunkX + CHUNK_SIZE - && worldPoint.getY() >= templateChunkY && worldPoint.getY() < templateChunkY + CHUNK_SIZE) + && worldPoint.getY() >= templateChunkY && worldPoint.getY() < templateChunkY + CHUNK_SIZE) { WorldPoint p = new WorldPoint(client.getBaseX() + x * CHUNK_SIZE + (worldPoint.getX() & (CHUNK_SIZE - 1)), - client.getBaseY() + y * CHUNK_SIZE + (worldPoint.getY() & (CHUNK_SIZE - 1)), - worldPoint.getPlane()); + client.getBaseY() + y * CHUNK_SIZE + (worldPoint.getY() & (CHUNK_SIZE - 1)), + worldPoint.getPlane()); p = rotate(p, rotation); if (p.distanceTo(npc.getWorldLocation()) < 5) { @@ -767,4 +858,4 @@ public class BAToolsPlugin extends Plugin implements KeyListener return false; } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java index 0c273f5be5..581039179d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Calls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Cameron + * Copyright (c) 2018, https://runelitepl.us * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,9 +24,11 @@ */ package net.runelite.client.plugins.batools; +import lombok.Getter; + import java.util.HashMap; import java.util.Map; - +@Getter public enum Calls { //Attacker Calls @@ -66,16 +68,6 @@ public enum Calls this.option = option; } - public String getCall() - { - return call; - } - - public String getOption() - { - return option; - } - public static String getOption(String call) { return CALL_MENU.get(call); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java index ee2879bf83..3653258564 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/Healer.java @@ -99,7 +99,7 @@ public class Healer return HealerCode.WAVENINE; case 10: return HealerCode.WAVETEN; - default: return null; + default: return null; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java b/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java index dcb7e7aca5..7d5211604d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/batools/HealerCode.java @@ -35,11 +35,11 @@ enum HealerCode WAVETHREE(new int[] {1,6,2}, new int[] {0,0,0}, new int[] {0,0,0}), WAVEFOUR(new int[] {2,5,2,0}, new int[] {0,0,7,10}, new int[] {0,0,0,0}), WAVEFIVE(new int[] {2,5,2,3,0}, new int[] {0,0,0,0,7}, new int[] {0,0,21,30,0}), - WAVESIX(new int[] {3,5,3,1,0,0}, new int[] {0,0,0,2,9,10}, new int[] {18,0,0,0,0,0}), - WAVESEVEN(new int[] {5,2,1,1,0,0,0}, new int[] {0,0,0,0,6,8,10}, new int[] {27,33,0,0,51,0,0}), - WAVEEIGHT(new int[] {2,8,1,1,0,0,0}, new int[] {1,0,1,1,3,1,10}, new int[] {36,0,33,39,45,48,0}), - WAVENINE(new int[] {2,8,1,1,0,0,0,0}, new int[] {1,1,1,1,1,1,1,10}, new int[] {0,21,0,0,0,0,0,0,0}), - WAVETEN(new int[] {5,2,1,1,0,0,0}, new int[] {0,1,1,1,3,3,10}, new int[] {27,33,0,0,51,0,0}); + WAVESIX(new int[] {3,5,2,2,0,0}, new int[] {0,0,0,2,9,10}, new int[] {12,18,21,0,0,0}), + WAVESEVEN(new int[] {3,7,1,1,0,0,0}, new int[] {2,0,1,1,2,4,10}, new int[] {0,21,0,0,30,45,0}), + WAVEEIGHT(new int[] {1,9,1,1,0,0,0}, new int[] {1,0,1,1,2,2,10}, new int[] {0,0,0,0,33,42,0}), + WAVENINE(new int[] {2,8,1,1,0,0,0,0}, new int[] {1,0,1,1,2,1,1,10}, new int[] {0,21,0,0,0,0,0,0,0}), + WAVETEN(new int[] {2,5,1,1,0,0,0}, new int[] {1,0,1,1,4,4,8}, new int[] {21,33,0,33,30,45,0}); @Getter 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 086e2535f3..eb255b81b9 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 @@ -35,6 +35,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import lombok.Getter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.Prayer; import net.runelite.api.Skill; import net.runelite.api.events.BoostedLevelChanged; @@ -411,6 +412,6 @@ public class BoostsPlugin extends Plugin int getChangeTime(final int time) { final long diff = System.currentTimeMillis() - lastTickMillis; - return time != -1 ? (int)(time * 0.6 - (diff / 1000d)) : time; + return time != -1 ? (int)((time * Constants.GAME_TICK_LENGTH - diff) / 1000d) : time; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java index d27886c1aa..2f55bf8158 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fishing/FishingPlugin.java @@ -396,6 +396,11 @@ public class FishingPlugin extends Plugin } long timeLeft = TRAWLER_TIME_LIMIT_IN_SECONDS - Duration.between(trawlerStartTime, Instant.now()).getSeconds(); + if (timeLeft < 0) + { + timeLeft = 0; + } + int minutes = (int) timeLeft / 60; int seconds = (int) timeLeft % 60; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java index 45c1095d6d..38b56f8505 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/idlenotifier/IdleNotifierPlugin.java @@ -38,6 +38,7 @@ import net.runelite.api.Actor; import net.runelite.api.AnimationID; import static net.runelite.api.AnimationID.*; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.GameState; import net.runelite.api.GraphicID; import net.runelite.api.Hitsplat; @@ -71,9 +72,10 @@ import net.runelite.client.util.PvPUtil; public class IdleNotifierPlugin extends Plugin { // This must be more than 500 client ticks (10 seconds) before you get AFK kicked - private static final int LOGOUT_WARNING_CLIENT_TICKS = ((4 * 60) + 40) * 50;// 4 minutes and 40 seconds + private static final int LOGOUT_WARNING_MILLIS = (4 * 60 + 40) * 1000; // 4 minutes and 40 seconds private static final int COMBAT_WARNING_MILLIS = 19 * 60 * 1000; // 19 minutes - private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / 20; + private static final int LOGOUT_WARNING_CLIENT_TICKS = LOGOUT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH; + private static final int COMBAT_WARNING_CLIENT_TICKS = COMBAT_WARNING_MILLIS / Constants.CLIENT_TICK_LENGTH; private static final int HIGHEST_MONSTER_ATTACK_SPEED = 8; // Except Scarab Mage, but they are with other monsters private static final Duration SIX_HOUR_LOGOUT_WARNING_AFTER_DURATION = Duration.ofMinutes(340); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java index 3f8b225d59..e84b6106e9 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcSceneOverlay.java @@ -36,6 +36,7 @@ import java.time.Instant; import java.util.Locale; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.NPC; import net.runelite.api.NPCComposition; import net.runelite.api.Perspective; @@ -57,9 +58,6 @@ public class NpcSceneOverlay extends Overlay // a dark background private static final Color TEXT_COLOR = Color.WHITE; - // Estimated time of a game tick in seconds - private static final double ESTIMATED_TICK_LENGTH = 0.6; - private static final NumberFormat TIME_LEFT_FORMATTER = DecimalFormat.getInstance(Locale.US); static @@ -128,7 +126,7 @@ public class NpcSceneOverlay extends Overlay } final Instant now = Instant.now(); - final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * ESTIMATED_TICK_LENGTH; + final double baseTick = ((npc.getDiedOnTick() + npc.getRespawnTime()) - client.getTickCount()) * (Constants.GAME_TICK_LENGTH / 1000.0); final double sinceLast = (now.toEpochMilli() - plugin.getLastTickUpdate().toEpochMilli()) / 1000.0; final double timeLeft = Math.max(0.0, baseTick - sinceLast); final String timeLeftStr = TIME_LEFT_FORMATTER.format(timeLeft); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java index b824f17157..2d7bddc3a6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/party/PartyPlugin.java @@ -37,6 +37,7 @@ import java.util.Map; import java.util.UUID; import javax.annotation.Nullable; import javax.inject.Inject; +import javax.inject.Named; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.ChatMessageType; @@ -48,6 +49,7 @@ import net.runelite.api.Skill; import net.runelite.api.SoundEffectID; import net.runelite.api.Tile; import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.CommandExecuted; import net.runelite.api.events.FocusChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.MenuOptionClicked; @@ -120,6 +122,10 @@ public class PartyPlugin extends Plugin implements KeyListener @Inject private ChatMessageManager chatMessageManager; + @Inject + @Named("developerMode") + boolean developerMode; + @Getter private final Map partyDataMap = Collections.synchronizedMap(new HashMap<>()); @@ -448,6 +454,23 @@ public class PartyPlugin extends Plugin implements KeyListener worldMapManager.removeIf(PartyWorldMapPoint.class::isInstance); } + @Subscribe + public void onCommandExecuted(CommandExecuted commandExecuted) + { + if (!developerMode || !commandExecuted.getCommand().equals("partyinfo")) + { + return; + } + + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Party " + party.getPartyId()).build()); + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local Party " + party.getLocalPartyId()).build()); + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value("Local ID " + party.getLocalMember().getMemberId()).build()); + for (PartyMember partyMember : party.getMembers()) + { + chatMessageManager.queue(QueuedMessage.builder().type(ChatMessageType.GAMEMESSAGE).value(" " + partyMember.getName() + " " + partyMember.getMemberId()).build()); + } + } + @Nullable PartyData getPartyData(final UUID uuid) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java index 03a3f02729..04df91d05c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/poh/PohPlugin.java @@ -39,6 +39,7 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Actor; import net.runelite.api.AnimationID; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.DecorativeObject; import net.runelite.api.GameObject; import net.runelite.api.GameState; @@ -74,7 +75,6 @@ public class PohPlugin extends Plugin { static final Set BURNER_UNLIT = Sets.newHashSet(ObjectID.INCENSE_BURNER, ObjectID.INCENSE_BURNER_13210, ObjectID.INCENSE_BURNER_13212); static final Set BURNER_LIT = Sets.newHashSet(ObjectID.INCENSE_BURNER_13209, ObjectID.INCENSE_BURNER_13211, ObjectID.INCENSE_BURNER_13213); - private static final double ESTIMATED_TICK_LENGTH = 0.6; @Getter(AccessLevel.PACKAGE) private final Map pohObjects = new HashMap<>(); @@ -243,7 +243,8 @@ public class PohPlugin extends Plugin private static void updateBurner(IncenseBurner incenseBurner, int fmLevel) { - incenseBurner.setCountdownTimer((200 + fmLevel) * ESTIMATED_TICK_LENGTH); - incenseBurner.setRandomTimer(fmLevel * ESTIMATED_TICK_LENGTH); + final double tickLengthSeconds = Constants.GAME_TICK_LENGTH / 1000.0; + incenseBurner.setCountdownTimer((200 + fmLevel) * tickLengthSeconds); + incenseBurner.setRandomTimer(fmLevel * tickLengthSeconds); } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java index 6798d4e545..ab1d91fb16 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerDoseOverlay.java @@ -35,6 +35,7 @@ import javax.inject.Inject; import lombok.AccessLevel; import lombok.Setter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.Point; import net.runelite.api.Prayer; import net.runelite.api.Skill; @@ -50,7 +51,7 @@ import org.apache.commons.lang3.StringUtils; class PrayerDoseOverlay extends Overlay { - private static final float PULSE_TIME = 1200f; + private static final float PULSE_TIME = 2f * Constants.GAME_TICK_LENGTH; private static final Color START_COLOR = new Color(0, 255, 255); private static final Color END_COLOR = new Color(0, 92, 92); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java index 04b7ec194c..2755703f8f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/prayer/PrayerPlugin.java @@ -32,6 +32,7 @@ import javax.inject.Inject; import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; @@ -268,7 +269,7 @@ public class PrayerPlugin extends Plugin { long timeSinceLastTick = Duration.between(startOfLastTick, Instant.now()).toMillis(); - float tickProgress = (timeSinceLastTick % 600) / 600f; + float tickProgress = (timeSinceLastTick % Constants.GAME_TICK_LENGTH) / (float) Constants.GAME_TICK_LENGTH; return tickProgress * Math.PI; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java index b3b4dd546c..2e8b577381 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterConfig.java @@ -57,4 +57,14 @@ public interface RegenMeterConfig extends Config { return false; } + + @ConfigItem( + keyName = "notifyBeforeHpRegenDuration", + name = "Hitpoint Regen Notification (seconds)", + description = "Notify approximately when your next hitpoint is about to regen. A value of 0 will disable notification." + ) + default int getNotifyBeforeHpRegenSeconds() + { + return 0; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java index 8620b7fac3..004441b6e3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/regenmeter/RegenMeterPlugin.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2018 Abex + * Copyright (c) 2019, Sean Dewar + * Copyright (c) 2018, Abex * Copyright (c) 2018, Zimaya * Copyright (c) 2017, Adam * All rights reserved. @@ -30,6 +31,7 @@ import com.google.inject.Provides; import javax.inject.Inject; import lombok.Getter; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.GameState; import net.runelite.api.Prayer; import net.runelite.api.Skill; @@ -37,6 +39,7 @@ import net.runelite.api.VarPlayer; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.VarbitChanged; +import net.runelite.client.Notifier; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; @@ -46,7 +49,7 @@ import net.runelite.client.ui.overlay.OverlayManager; @PluginDescriptor( name = "Regeneration Meter", description = "Track and show the hitpoints and special attack regeneration timers", - tags = {"combat", "health", "hitpoints", "special", "attack", "overlay"} + tags = {"combat", "health", "hitpoints", "special", "attack", "overlay", "notifications"} ) public class RegenMeterPlugin extends Plugin { @@ -59,6 +62,9 @@ public class RegenMeterPlugin extends Plugin @Inject private OverlayManager overlayManager; + @Inject + private Notifier notifier; + @Inject private RegenMeterOverlay overlay; @@ -149,5 +155,18 @@ public class RegenMeterPlugin extends Plugin // Show it going down hitpointsPercentage = 1 - hitpointsPercentage; } + + if (config.getNotifyBeforeHpRegenSeconds() > 0 && currentHP < maxHP && shouldNotifyHpRegenThisTick(ticksPerHPRegen)) + { + notifier.notify("[" + client.getLocalPlayer().getName() + "] regenerates their next hitpoint soon!"); + } + } + + private boolean shouldNotifyHpRegenThisTick(int ticksPerHPRegen) + { + // if the configured duration lies between two ticks, choose the earlier tick + final int ticksBeforeHPRegen = ticksPerHPRegen - ticksSinceHPRegen; + final int notifyTick = (int) Math.ceil(config.getNotifyBeforeHpRegenSeconds() * 1000d / Constants.GAME_TICK_LENGTH); + return ticksBeforeHPRegen == notifyTick; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java index 7cef60a826..fff84a100d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java @@ -28,6 +28,7 @@ import com.google.common.collect.ImmutableSet; import com.google.inject.Provides; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.InventoryID; import net.runelite.api.Item; @@ -171,7 +172,7 @@ public class RunEnergyPlugin extends Plugin String getEstimatedRunTimeRemaining(boolean inSeconds) { - // Calculate the amount of energy lost every 2 ticks (0.6 seconds). + // Calculate the amount of energy lost every tick. // Negative weight has the same depletion effect as 0 kg. final int effectiveWeight = Math.max(client.getWeight(), 0); double lossRate = (Math.min(effectiveWeight, 64) / 100.0) + 0.64; @@ -182,7 +183,7 @@ public class RunEnergyPlugin extends Plugin } // Calculate the number of seconds left - final double secondsLeft = (client.getEnergy() * 0.6) / lossRate; + final double secondsLeft = (client.getEnergy() * Constants.GAME_TICK_LENGTH) / (lossRate * 1000.0); // Return the text if (inSeconds) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java index d688779b2f..92c8a548c7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java @@ -286,7 +286,7 @@ class XpInfoBox extends JPanel static String htmlLabel(String key, int value) { - String valueStr = StackFormatter.quantityToRSDecimalStack(value); + String valueStr = StackFormatter.quantityToRSDecimalStack(value, true); return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr); } } diff --git a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java index 40dda01a4e..c9282f7f46 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java +++ b/runelite-client/src/main/java/net/runelite/client/util/StackFormatter.java @@ -61,6 +61,14 @@ public class StackFormatter DecimalFormatSymbols.getInstance(Locale.ENGLISH) ); + /** + * A more precise decimal number formatter, outputting thousandths + */ + private static final NumberFormat PRECISE_DECIMAL_FORMATTER = new DecimalFormat( + "#,###.###", + DecimalFormatSymbols.getInstance(Locale.ENGLISH) + ); + /** * Convert a quantity to a nicely formatted stack size. * See the StackFormatterTest to see expected output. @@ -152,6 +160,24 @@ public class StackFormatter * with K after 100,000 and M after 10,000,000 */ public static String quantityToRSDecimalStack(int quantity) + { + return quantityToRSDecimalStack(quantity, false); + } + + /** + * Convert a quantity to stack size as it would + * appear in RuneScape. (with decimals) + *

+ * This differs from quantityToRSStack in that it displays + * decimals. Ex: 27100 is 27.1k (not 27k) + *

+ * + * @param quantity The quantity to convert. + * @param precise If true, the returned string will have thousandths precision if quantity is larger than 1 million. + * @return The stack size as it would appear in RS, with decimals, + * with K after 100,000 and M after 10,000,000 + */ + public static String quantityToRSDecimalStack(int quantity, boolean precise) { String quantityStr = String.valueOf(quantity); if (quantityStr.length() <= 4) @@ -160,7 +186,13 @@ public class StackFormatter } int power = (int) Math.log10(quantity); - return DECIMAL_FORMATTER.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3]; + + // Output thousandths for values above a million + NumberFormat format = precise && power >= 6 + ? PRECISE_DECIMAL_FORMATTER + : DECIMAL_FORMATTER; + + return format.format(quantity / (Math.pow(10, (power / 3) * 3))) + SUFFIXES[power / 3]; } /** diff --git a/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java b/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java index 47e9c18148..caec527320 100644 --- a/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java +++ b/runelite-client/src/main/java/net/runelite/client/ws/PartyService.java @@ -114,6 +114,13 @@ public class PartyService @Subscribe public void onUserJoin(final UserJoin message) { + if (!partyId.equals(message.getPartyId())) + { + // This can happen when a session is resumed server side after the client party + // changes when disconnected. + return; + } + final PartyMember partyMember = new PartyMember(message.getMemberId(), message.getName()); members.add(partyMember); diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/customcursor/cursor-dragon-scimitar.png b/runelite-client/src/main/resources/net/runelite/client/plugins/customcursor/cursor-dragon-scimitar.png index 1db7d1a0bc..b1a4bd230c 100644 Binary files a/runelite-client/src/main/resources/net/runelite/client/plugins/customcursor/cursor-dragon-scimitar.png and b/runelite-client/src/main/resources/net/runelite/client/plugins/customcursor/cursor-dragon-scimitar.png differ diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/smelting/SmeltingPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/smelting/SmeltingPluginTest.java new file mode 100644 index 0000000000..1c8573f26c --- /dev/null +++ b/runelite-client/src/test/java/net/runelite/client/plugins/smelting/SmeltingPluginTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019, Stephen + * 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.smelting; + +import com.google.inject.Guice; +import com.google.inject.testing.fieldbinder.Bind; +import com.google.inject.testing.fieldbinder.BoundFieldModule; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import net.runelite.api.events.ChatMessage; +import net.runelite.client.ui.overlay.OverlayManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SmeltingPluginTest +{ + private static final String SMELT_CANNONBALL = "You remove the cannonballs from the mould"; + private static final String SMELT_BAR = "You retrieve a bar of steel."; + + @Inject + SmeltingPlugin smeltingPlugin; + + @Mock + @Bind + SmeltingConfig config; + + @Mock + @Bind + SmeltingOverlay smeltingOverlay; + + @Mock + @Bind + OverlayManager overlayManager; + + @Before + public void before() + { + Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); + } + + @Test + public void testCannonballs() + { + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", SMELT_CANNONBALL, "", 0); + smeltingPlugin.onChatMessage(chatMessage); + + SmeltingSession smeltingSession = smeltingPlugin.getSession(); + assertNotNull(smeltingSession); + assertEquals(4, smeltingSession.getCannonBallsSmelted()); + } + + @Test + public void testBars() + { + ChatMessage chatMessage = new ChatMessage(null, ChatMessageType.SPAM, "", SMELT_BAR, "", 0); + smeltingPlugin.onChatMessage(chatMessage); + + SmeltingSession smeltingSession = smeltingPlugin.getSession(); + assertNotNull(smeltingSession); + assertEquals(1, smeltingSession.getBarsSmelted()); + } +} diff --git a/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java b/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java index 53a1c963d1..1e297a8513 100644 --- a/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java +++ b/runelite-client/src/test/java/net/runelite/client/util/StackFormatterTest.java @@ -97,6 +97,31 @@ public class StackFormatterTest assertEquals("-400B", StackFormatter.quantityToStackSize(-400_000_000_000L)); } + @Test + public void quantityToPreciseStackSize() + { + assertEquals("0", StackFormatter.quantityToRSDecimalStack(0)); + assertEquals("8500", StackFormatter.quantityToRSDecimalStack(8_500, true)); + assertEquals("10K", StackFormatter.quantityToRSDecimalStack(10_000, true)); + assertEquals("21.7K", StackFormatter.quantityToRSDecimalStack(21_710, true)); + assertEquals("100K", StackFormatter.quantityToRSDecimalStack(100_000, true)); + assertEquals("100.3K", StackFormatter.quantityToRSDecimalStack(100_310, true)); + assertEquals("1M", StackFormatter.quantityToRSDecimalStack(1_000_000, true)); + assertEquals("8.45M", StackFormatter.quantityToRSDecimalStack(8_450_000, true)); + assertEquals("8.451M", StackFormatter.quantityToRSDecimalStack(8_451_000, true)); + assertEquals("10M", StackFormatter.quantityToRSDecimalStack(10_000_000, true)); + assertEquals("12.8M", StackFormatter.quantityToRSDecimalStack(12_800_000, true)); + assertEquals("12.85M", StackFormatter.quantityToRSDecimalStack(12_850_000, true)); + assertEquals("12.851M", StackFormatter.quantityToRSDecimalStack(12_851_000, true)); + assertEquals("100M", StackFormatter.quantityToRSDecimalStack(100_000_000, true)); + assertEquals("250.1M", StackFormatter.quantityToRSDecimalStack(250_100_000, true)); + assertEquals("250.151M", StackFormatter.quantityToRSDecimalStack(250_151_000, true)); + assertEquals("1B", StackFormatter.quantityToRSDecimalStack(1_000_000_000, true)); + assertEquals("1.5B", StackFormatter.quantityToRSDecimalStack(1500_000_000, true)); + assertEquals("1.55B", StackFormatter.quantityToRSDecimalStack(1550_000_000, true)); + assertEquals("2.147B", StackFormatter.quantityToRSDecimalStack(Integer.MAX_VALUE, true)); + } + @Test public void stackSizeToQuantity() throws ParseException {