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 8577438af2..fb3825b8e1 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 @@ -556,7 +556,7 @@ public class WidgetID static final int CURRENT_WAVE_WIDGET = 4; static final int CURRENT_WAVE = 5; static final int CALL_WIDGET = 6; - static final int CALL_TEXT = 7; + static final int HEARD_CALL = 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 65e82471d7..c6a818fc63 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 @@ -351,6 +351,7 @@ 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_ROLE_TEXT(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE), BA_COLL_ROLE_SPRITE(WidgetID.BA_COLLECTOR_GROUP_ID, WidgetID.BarbarianAssault.ROLE_SPRITE), 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 52d6a18af5..8ff9ead8da 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 @@ -37,17 +37,52 @@ public interface BarbarianAssaultConfig extends Config name = "Show call change timer", description = "Show time to next call change" ) - default boolean showTimer() - { - return true; - } + default boolean showTimer() { return true; } @ConfigItem( keyName = "waveTimes", name = "Show wave and game duration", description = "Displays wave and game duration" + ) + 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 + ) + default boolean showEggCount() { return false; } + + @ConfigItem( + keyName = "showEggCountOverlay", + name = "Overlay of eggs counted", + description = "Display current egg count as collector", + position = 1 + ) + default boolean showEggCountOverlay() { return false; } + + @ConfigItem( + keyName = "showHpCountMessage", + name = "Show count of Hp healed as healer.", + description = "Display healed count as healer after each wave", + position = 2 + ) + 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 = "highlightCollectorEggs", + name = "Highlight collector eggs", + description = "Highlight called egg colors" ) - default boolean waveTimes() + default boolean highlightCollectorEggs() { return true; } 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 0fdf9edc2e..5bc5959622 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 @@ -24,24 +24,37 @@ */ package net.runelite.client.plugins.barbarianassault; +import java.awt.BasicStroke; +import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; +import java.awt.Polygon; import java.awt.Rectangle; +import java.awt.Stroke; +import java.util.Map; import javax.inject.Inject; import lombok.Getter; import lombok.Setter; import net.runelite.api.Client; import net.runelite.api.GameState; import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; +import net.runelite.api.Perspective; +import net.runelite.api.Player; +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.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; class BarbarianAssaultOverlay extends Overlay { + private static final int MAX_EGG_DISTANCE = 2500; + private final Client client; private final BarbarianAssaultPlugin plugin; private final BarbarianAssaultConfig config; @@ -82,12 +95,95 @@ class BarbarianAssaultOverlay extends Overlay if (config.showTimer() && roleText != null && roleSprite != null) { - roleText.setText(String.format("00:%02d", currentRound.getTimeToChange())); + if (config.showEggCountOverlay() && role.equals(Role.COLLECTOR)) + { + roleText.setText(String.format("(%d) 00:%02d", plugin.getCollectedEggCount(), currentRound.getTimeToChange())); + } + else if (config.showHpCountOverlay() && role.equals(Role.HEALER)) + { + roleText.setText(String.format("(%d) 00:%02d", plugin.getHpHealed(), currentRound.getTimeToChange())); + } + else + { + roleText.setText(String.format("00:%02d", currentRound.getTimeToChange())); + } Rectangle spriteBounds = roleSprite.getBounds(); roleSprite.setHidden(true); graphics.drawImage(plugin.getClockImage(), spriteBounds.x, spriteBounds.y, null); } + if (role == Role.COLLECTOR && config.highlightCollectorEggs()) + { + String heardCall = plugin.getCollectorHeardCall(); + Color highlightColor; + Map calledEggMap; + + Map yellowEggMap = plugin.getYellowEggs(); + + switch (heardCall) + { + case "Red eggs": + calledEggMap = plugin.getRedEggs(); + highlightColor = Color.RED; + break; + case "Green eggs": + calledEggMap = plugin.getGreenEggs(); + highlightColor = Color.GREEN; + break; + case "Blue eggs": + calledEggMap = plugin.getBlueEggs(); + highlightColor = Color.BLUE; + break; + default: + calledEggMap = null; + highlightColor = null; + } + + if (calledEggMap != null) + { + for (WorldPoint worldPoint : calledEggMap.keySet()) + { + int quantity = calledEggMap.get(worldPoint); + renderEggLocation(graphics, worldPoint, quantity, highlightColor); + } + } + + // Always show yellow eggs + for (WorldPoint worldPoint : yellowEggMap.keySet()) + { + int quantity = yellowEggMap.get(worldPoint); + renderEggLocation(graphics, worldPoint, quantity, highlightColor); + } + } + return null; } + + private void renderEggLocation(Graphics2D graphics, WorldPoint location, int quantity, Color color) + { + LocalPoint groundPoint = LocalPoint.fromWorld(client, location); + Player player = client.getLocalPlayer(); + + if (groundPoint == null || player == null) + { + return; + } + + if (player.getLocalLocation().distanceTo(groundPoint) > MAX_EGG_DISTANCE) + { + return; + } + + Polygon poly = Perspective.getCanvasTilePoly(client, groundPoint); + final Stroke originalStroke = graphics.getStroke(); + + graphics.setColor(color); + graphics.setStroke(new BasicStroke(2)); + graphics.drawPolygon(poly); + graphics.setStroke(originalStroke); + + String quantityText = "x" + quantity; + Point textPoint = Perspective.getCanvasTextLocation(client, graphics, groundPoint, quantityText, 0); + OverlayUtil.renderTextLocation(graphics, textPoint, quantityText, Color.WHITE); + } } 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 985ef626f5..30e6a56b90 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 @@ -28,13 +28,21 @@ package net.runelite.client.plugins.barbarianassault; import com.google.inject.Provides; import java.awt.Font; import java.awt.Image; +import java.util.HashMap; import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; import net.runelite.api.ItemID; +import net.runelite.api.Player; +import net.runelite.api.Tile; import net.runelite.api.Varbits; +import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.GameTick; +import net.runelite.api.events.ItemDespawned; +import net.runelite.api.events.ItemSpawned; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetLoaded; import net.runelite.api.kit.KitType; @@ -58,18 +66,42 @@ import net.runelite.client.util.ImageUtil; description = "Show a timer to the next call change and game/wave duration in chat.", tags = {"minigame", "overlay", "timer"} ) -public class BarbarianAssaultPlugin extends Plugin -{ +public class BarbarianAssaultPlugin extends Plugin { private static final int BA_WAVE_NUM_INDEX = 2; private static final String START_WAVE = "1"; private static final String ENDGAME_REWARD_NEEDLE_TEXT = "
5"; + @Getter + private int collectedEggCount = 0; + @Getter + private int positiveEggCount = 0; + @Getter + private int wrongEggs = 0; + @Getter + private int HpHealed = 0; + @Getter + private int totalCollectedEggCount = 0; + @Getter + private int totalHpHealed = 0; + private Font font; private Image clockImage; private int inGameBit = 0; private String currentWave = START_WAVE; private GameTimer gameTime; + @Getter(AccessLevel.PACKAGE) + private HashMap redEggs; + + @Getter(AccessLevel.PACKAGE) + private HashMap greenEggs; + + @Getter(AccessLevel.PACKAGE) + private HashMap blueEggs; + + @Getter(AccessLevel.PACKAGE) + private HashMap yellowEggs; + @Inject private Client client; @@ -86,45 +118,69 @@ public class BarbarianAssaultPlugin extends Plugin private BarbarianAssaultOverlay overlay; @Provides - BarbarianAssaultConfig provideConfig(ConfigManager configManager) - { + BarbarianAssaultConfig provideConfig(ConfigManager configManager) { return configManager.getConfig(BarbarianAssaultConfig.class); } @Override - protected void startUp() throws Exception - { + protected void startUp() throws Exception { overlayManager.add(overlay); font = FontManager.getRunescapeFont() - .deriveFont(Font.BOLD, 24); + .deriveFont(Font.BOLD, 24); clockImage = ImageUtil.getResourceStreamFromClass(getClass(), "clock.png"); + + redEggs = new HashMap<>(); + greenEggs = new HashMap<>(); + blueEggs = new HashMap<>(); + yellowEggs = new HashMap<>(); } @Override - protected void shutDown() throws Exception - { + protected void shutDown() throws Exception { overlayManager.remove(overlay); gameTime = null; currentWave = START_WAVE; inGameBit = 0; + collectedEggCount = 0; + positiveEggCount = 0; + wrongEggs = 0; + HpHealed = 0; } @Subscribe - public void onWidgetLoaded(WidgetLoaded event) - { - if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID) - { + public void onWidgetLoaded(WidgetLoaded event) { + if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID) { Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT); + String amt,type,totalMsg,total; + amt=type=totalMsg=total=""; + if (config.waveTimes() && rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null) { + if (config.showHpCount() && HpHealed > 0) { + totalMsg = "; Total Healed: "; + total = ""+totalHpHealed; + if (HpHealed > 504) + { + total = ""+504; + } + } + else if (config.showEggCount() && collectedEggCount > 0) { + collectedEggCount -= wrongEggs; //true positive egg count + if (collectedEggCount > 60) + { + collectedEggCount = 60; + } + collectedEggCount -= wrongEggs; //true positive - negative egg count\ + totalMsg = "; Total Collected: "; + total = "" + totalCollectedEggCount; - if (config.waveTimes() && rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null) - { - announceTime("Game finished, duration: ", gameTime.getTime(false)); + } + announceTime("Game finished, duration: ", gameTime.getTime(false),type, amt, totalMsg, total); } } } @Subscribe + public void onChatMessage(ChatMessage event) { if (event.getType() == ChatMessageType.GAMEMESSAGE @@ -132,28 +188,36 @@ public class BarbarianAssaultPlugin extends Plugin { String[] message = event.getMessage().split(" "); currentWave = message[BA_WAVE_NUM_INDEX]; + collectedEggCount = 0; + HpHealed = 0; - if (currentWave.equals(START_WAVE)) - { + if (currentWave.equals(START_WAVE)) { gameTime = new GameTimer(); - } - else if (gameTime != null) - { + totalHpHealed = 0; + totalCollectedEggCount = 0; + } else if (gameTime != null) { gameTime.setWaveStartTime(); } + } else if (event.getType() == ChatMessageType.GAMEMESSAGE + && event.getMessage().contains("egg explode")) { + wrongEggs --; + } else if (event.getType() == ChatMessageType.GAMEMESSAGE + && event.getMessage().contains("healed")) { + String message = event.getMessage(); + String[] tokens = message.split(" "); + if (Integer.parseInt(tokens[2]) > 0) { + int Hp = Integer.parseInt(tokens[2]); + HpHealed += Hp; + } } } @Subscribe - public void onGameTick(GameTick event) - { - if (client.getVar(Varbits.IN_GAME_BA) == 0 || client.getLocalPlayer() == null || overlay.getCurrentRound() != null) - { + public void onGameTick(GameTick event) { + if (client.getVar(Varbits.IN_GAME_BA) == 0 || client.getLocalPlayer() == null || overlay.getCurrentRound() != null) { return; } - - switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE)) - { + switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE)) { case ItemID.ATTACKER_ICON: overlay.setCurrentRound(new Round(Role.ATTACKER)); break; @@ -170,39 +234,159 @@ public class BarbarianAssaultPlugin extends Plugin } @Subscribe - public void onVarbitChanged(VarbitChanged event) - { + public void onVarbitChanged(VarbitChanged event) { int inGame = client.getVar(Varbits.IN_GAME_BA); - - if (inGameBit != inGame) - { - if (inGameBit == 1) - { + String amt,type,totalMsg,total; + amt=type=totalMsg=total=""; + if (inGameBit != inGame) { + if (inGameBit == 1) { overlay.setCurrentRound(null); - if (config.waveTimes() && gameTime != null) - { - announceTime("Wave " + currentWave + " duration: ", gameTime.getTime(true)); + if (config.waveTimes() && gameTime != null) { + totalCollectedEggCount += collectedEggCount; + totalHpHealed += HpHealed; + if (config.showHpCount() && HpHealed > 0) { + amt = "" + HpHealed; + type = "; Healed: "; + totalMsg = "; Total Healed: "; + total = ""+totalHpHealed; + } + else if (config.showEggCount() && collectedEggCount > 0) { + amt = "" + collectedEggCount; + type = "; Collected: "; + totalMsg = "; Total Collected: "; + total = ""+totalCollectedEggCount; + } + if (currentWave.equals("10")) + { + totalMsg=total=""; + } + announceTime("Wave " + currentWave + " duration: ", gameTime.getTime(true), type, amt, totalMsg, total); } + } } inGameBit = inGame; } - private void announceTime(String preText, String time) + @Subscribe + public void onItemSpawned(ItemSpawned itemSpawned) { + int itemId = itemSpawned.getItem().getId(); + WorldPoint worldPoint = itemSpawned.getTile().getWorldLocation(); + HashMap eggMap = getEggMap(itemId); + + if (eggMap != null) + { + Integer existingQuantity = eggMap.putIfAbsent(worldPoint, 1); + if (existingQuantity != null) + { + eggMap.put(worldPoint, existingQuantity + 1); + } + } + } + + @Subscribe + public void onItemDespawned(ItemDespawned itemDespawned) + { + int itemId = itemDespawned.getItem().getId(); + WorldPoint worldPoint = itemDespawned.getTile().getWorldLocation(); + HashMap eggMap = getEggMap(itemId); + + if (eggMap != null && eggMap.containsKey(worldPoint)) + { + int quantity = eggMap.get(worldPoint); + if (quantity > 1) + { + eggMap.put(worldPoint, quantity - 1); + } + else + { + eggMap.remove(worldPoint); + } + } + if (client.getVar(Varbits.IN_GAME_BA) == 0 || !isEgg(itemDespawned.getItem().getId())) + { + return; + } + if (isUnderPlayer(itemDespawned.getTile())) + { + collectedEggCount++; + } + } + + String getCollectorHeardCall() + { + Widget widget = client.getWidget(WidgetInfo.BA_COLL_HEARD_TEXT); + String call = null; + + if (widget != null) + { + call = widget.getText(); + } + + return call; + } + + private HashMap getEggMap(int itemID) + { + switch (itemID) + { + case ItemID.RED_EGG: + return redEggs; + case ItemID.GREEN_EGG: + return greenEggs; + case ItemID.BLUE_EGG: + return blueEggs; + case ItemID.YELLOW_EGG: + return yellowEggs; + default: + return null; + } + } + + + private void announceTime(String preText, String time, String type, String amt, String totalMsg, String total) { final String chatMessage = new ChatMessageBuilder() - .append(ChatColorType.NORMAL) - .append(preText) - .append(ChatColorType.HIGHLIGHT) - .append(time) - .build(); + .append(ChatColorType.NORMAL) + .append(preText) + .append(ChatColorType.HIGHLIGHT) + .append(time) + .append(ChatColorType.NORMAL) + .append(type) + .append(ChatColorType.HIGHLIGHT) + .append(amt) + .append(ChatColorType.NORMAL) + .append(totalMsg) + .append(ChatColorType.HIGHLIGHT) + .append(total) + .build(); chatMessageManager.queue(QueuedMessage.builder() - .type(ChatMessageType.CONSOLE) - .runeLiteFormattedMessage(chatMessage) - .build()); + .type(ChatMessageType.CONSOLE) + .runeLiteFormattedMessage(chatMessage) + .build()); + } + + private boolean isEgg(int itemID) + { + if (itemID == ItemID.RED_EGG || itemID == ItemID.GREEN_EGG + || itemID == ItemID.BLUE_EGG || itemID == ItemID.YELLOW_EGG) + { + return true; + } + return false; + } + + private boolean isUnderPlayer(Tile tile) { + Player local = client.getLocalPlayer(); + if (local == null) + { + return false; + } + + return (tile.getWorldLocation().equals(local.getWorldLocation())); } public Font getFont() 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 new file mode 100644 index 0000000000..23d726f10e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/barbarianassault/Calls.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, Cameron + * 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 java.util.HashMap; +import java.util.Map; + +public enum Calls +{ //Attacker Calls + RED_EGG("Red egg", "Tell-red"), + GREEN_EGG("Green egg", "Tell-green"), + BLUE_EGG("Blue egg", "Tell-blue"), + //Collector Calls + CONTROLLED("Controlled/Bullet/Wind", "Tell-controlled"), + ACCURATE("Accurate/Field/Water", "Tell-accurate"), + AGGRESSIVE("Aggressive/Blunt/Earth", "Tell-aggressive"), + DEFENSIVE("Defensive/Barbed/Fire", "Tell-defensive"), + //Healer Calls + TOFU("Tofu", "Tell-tofu"), + CRACKERS("Crackers", "Tell-crackers"), + WORMS("Worms", "Tell-worms"), + //Defender Calls + POIS_WORMS("Pois. Worms", "Tell-worms"), + POIS_TOFU("Pois. Tofu", "Tell-tofu"), + POIS_MEAT("Pois. Meat", "Tell-meat"); + + private final String call; + private final String option; + + private static final Map CALL_MENU = new HashMap<>(); + + static + { + for (Calls s : values()) + { + CALL_MENU.put(s.getCall(), s.getOption()); + } + } + + Calls(String call, String option) + { + this.call = call; + this.option = option; + } + + public String getCall() + { + return call; + } + + public String getOption() + { + return option; + } + + public static String getOption(String call) + { + return CALL_MENU.get(call); + } + +} \ No newline at end of file