From 4139fc29fd02d62e7638c4f53afc87a63b93cd15 Mon Sep 17 00:00:00 2001 From: bjornenalfa Date: Sun, 10 Mar 2019 01:34:44 +0100 Subject: [PATCH] Add party info display to raids plugin --- .../client/plugins/raids/RaidsConfig.java | 11 ++ .../plugins/raids/RaidsPartyOverlay.java | 174 ++++++++++++++++++ .../client/plugins/raids/RaidsPlugin.java | 111 +++++++++-- 3 files changed, 279 insertions(+), 17 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPartyOverlay.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java index 2323a15a49..0b225afe43 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsConfig.java @@ -162,4 +162,15 @@ public interface RaidsConfig extends Config { return true; } + + @ConfigItem( + position = 12, + keyName = "partyDisplay", + name = "Party Info Display", + description = "Display an overlay that shows information about the current party" + ) + default boolean partyDisplay() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPartyOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPartyOverlay.java new file mode 100644 index 0000000000..140bdc32c3 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPartyOverlay.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2019, Bjornenalfa + * 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.raids; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Color; +import java.util.List; +import java.util.HashSet; +import java.util.Set; +import javax.inject.Inject; + +import net.runelite.api.ClanMember; +import net.runelite.api.Client; +import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG; + +import net.runelite.api.VarPlayer; +import net.runelite.api.Varbits; +import net.runelite.client.ui.overlay.Overlay; +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.OverlayPriority; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; + +public class RaidsPartyOverlay extends Overlay +{ + @Inject + private Client client; + + @Inject + private RaidsPlugin plugin; + + private final PanelComponent panel = new PanelComponent(); + + @Inject + private RaidsPartyOverlay(RaidsPlugin plugin) + { + super(plugin); + setPosition(OverlayPosition.TOP_RIGHT); + setPriority(OverlayPriority.HIGH); + getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Raids overlay")); + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!plugin.isInRaidChambers()) + { + return null; + } + + // Leaver display doesn't quite work yet + + + boolean inLobby = client.getVar(VarPlayer.IN_RAID_PARTY) != -1; // -1 if raid started + //boolean inRaid = client.getVar(Varbits.IN_RAID) == 1; // 1 while in raids + + int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); + + int playerCount = client.getPlayers().size(); + + String partyCountString; + + Color countColor = Color.WHITE; + if (inLobby) { + partyCountString = String.format("%d/%d", playerCount, partySize); + if (partySize <= playerCount) { + countColor = Color.GREEN; + } else { + countColor = Color.RED; + } + } else { + // If raid has started then we compare the current party size to what it was whe + partyCountString = String.format("%d/%d", partySize, plugin.getStartPlayerCount()); + if (partySize < plugin.getStartPlayerCount()) { + countColor = Color.RED; // Somebody is missing + } + } + + panel.getChildren().clear(); + + // Show amount of people currently in raid vs total in the party + panel.getChildren().add(LineComponent.builder() + .left("Party size:") + .right(partyCountString) + .rightColor(countColor) + .build()); + + if (inLobby) { + int world = client.getWorld(); + int wrongWorldClanMembers = 0; + HashSet members = new HashSet<>(); + for (ClanMember clanMember : client.getClanMembers()) { + if (clanMember != null) { + if (clanMember.getWorld() != world) { + wrongWorldClanMembers++; + } else { + members.add(clanMember.getUsername()); + //System.out.println("Added clanmember: " + clanMember.getUsername()); + } + } + } + + // Show amount of people on the right world but not at the raids area + Color notInPartyColor = Color.GREEN; + int notInParty = Math.max(members.size() - partySize, 0); + + if (notInParty > 0) { + notInPartyColor = Color.WHITE; + } + + panel.getChildren().add(LineComponent.builder() + .left("Not in party:") + .right(String.valueOf(notInParty)) + .rightColor(notInPartyColor) + .build()); + + // Show amount of clan members that are not in the right world. + Color wrongWorldColor; + if (wrongWorldClanMembers == 0) { + wrongWorldColor = Color.GREEN; + } else { + wrongWorldColor = Color.WHITE; + } + + panel.getChildren().add(LineComponent.builder() + .left("Wrong world:") + .right(String.valueOf(wrongWorldClanMembers)) + .rightColor(wrongWorldColor) + .build()); + + } else { + Set missingPartyMembers = plugin.getMissingPartyMembers(); + if (missingPartyMembers != null && missingPartyMembers.size() > 0) { + panel.getChildren().add(LineComponent.builder() + .left("Missing players:") + .build()); + + for (String member : missingPartyMembers) { + panel.getChildren().add(LineComponent.builder() + .left(member) + .leftColor(Color.RED) + .build()); + } + } + } + + return panel.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java index 46570b3b5a..952701a22f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/raids/RaidsPlugin.java @@ -28,27 +28,20 @@ import com.google.inject.Binder; import com.google.inject.Provides; import java.text.DecimalFormat; import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.InstanceTemplates; -import net.runelite.api.NullObjectID; +import net.runelite.api.*; + import static net.runelite.api.Perspective.SCENE_SIZE; -import net.runelite.api.Point; import static net.runelite.api.SpriteID.TAB_QUESTS_BROWN_RAIDING_PARTY; -import net.runelite.api.Tile; -import net.runelite.api.VarPlayer; -import net.runelite.api.Varbits; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.VarbitChanged; + +import net.runelite.api.events.*; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.callback.ClientThread; import net.runelite.client.chat.ChatColorType; import net.runelite.client.chat.ChatMessageBuilder; @@ -101,6 +94,9 @@ public class RaidsPlugin extends Plugin @Inject private RaidsOverlay overlay; + @Inject + private RaidsPartyOverlay partyOverlay; + @Inject private LayoutSolver layoutSolver; @@ -130,6 +126,19 @@ public class RaidsPlugin extends Plugin private RaidsTimer timer; + @Getter + private int startPlayerCount; + + private int storedVarPartySize; + + @Getter + private List partyMembers; + + private List startingPartyMembers; + + @Getter + private Set missingPartyMembers; + @Provides RaidsConfig provideConfig(ConfigManager configManager) { @@ -146,6 +155,9 @@ public class RaidsPlugin extends Plugin protected void startUp() throws Exception { overlayManager.add(overlay); + if (config.partyDisplay()) { + overlayManager.add(partyOverlay); + } updateLists(); clientThread.invokeLater(() -> checkRaidPresence(true)); } @@ -154,6 +166,9 @@ public class RaidsPlugin extends Plugin protected void shutDown() throws Exception { overlayManager.remove(overlay); + if (config.partyDisplay()) { + overlayManager.remove(partyOverlay); + } infoBoxManager.removeInfoBox(timer); inRaidChambers = false; raid = null; @@ -174,6 +189,14 @@ public class RaidsPlugin extends Plugin return; } + if (event.getKey().equals("partyDisplay")) { + if (config.partyDisplay()) { + overlayManager.add(partyOverlay); + } else { + overlayManager.remove(partyOverlay); + } + } + updateLists(); clientThread.invokeLater(() -> checkRaidPresence(true)); } @@ -182,6 +205,7 @@ public class RaidsPlugin extends Plugin public void onVarbitChanged(VarbitChanged event) { checkRaidPresence(false); + updatePartyMembers(); } @Subscribe @@ -191,10 +215,21 @@ public class RaidsPlugin extends Plugin { String message = Text.removeTags(event.getMessage()); - if (config.raidsTimer() && message.startsWith(RAID_START_MESSAGE)) + if (message.startsWith(RAID_START_MESSAGE)) { - timer = new RaidsTimer(spriteManager.getSprite(TAB_QUESTS_BROWN_RAIDING_PARTY, 0), this, Instant.now()); - infoBoxManager.addInfoBox(timer); + if (config.raidsTimer()) { + timer = new RaidsTimer(spriteManager.getSprite(TAB_QUESTS_BROWN_RAIDING_PARTY, 0), this, Instant.now()); + infoBoxManager.addInfoBox(timer); + } + if (config.partyDisplay()) { + updatePartyMembers(); + startPlayerCount = client.getVar(Varbits.RAID_PARTY_SIZE); + if (partyMembers == null) { + startingPartyMembers = new ArrayList<>(); + } else { + startingPartyMembers = new ArrayList<>(partyMembers); + } + } } if (timer != null && message.contains(LEVEL_COMPLETE_MESSAGE)) @@ -243,6 +278,48 @@ public class RaidsPlugin extends Plugin } } + private void updatePartyMembers() { + int partySize = client.getVar(Varbits.RAID_PARTY_SIZE); + if (partySize <= 0) { + partyMembers = null; + return; + } + + partyMembers = new ArrayList<>(); + try { + Widget[] widgets = client.getWidget(WidgetInfo.RAIDING_PARTY).getStaticChildren()[2].getStaticChildren()[3].getDynamicChildren(); + for (int i = 0; i < widgets.length; i++) { + if (widgets[i] != null) { + String name = widgets[i].getName(); + if (name.length() > 1) { + partyMembers.add(name.substring(name.indexOf('>') + 1, name.indexOf('<', 1))); + } + } + } + } catch (NullPointerException e) { + // Raid widget not loaded yet + } + + if (client.getVar(VarPlayer.IN_RAID_PARTY) == -1 && + (startingPartyMembers == null || startingPartyMembers.size() < partyMembers.size())) { + // If raid started and there are more people now than there were then, update + startingPartyMembers = new ArrayList<>(partyMembers); + } + + if (config.partyDisplay()) { + if (client.getVar(VarPlayer.IN_RAID_PARTY) == -1) { + // Raid started, check if anyone left + if (startingPartyMembers != null && startingPartyMembers.size() < partyMembers.size()) { + missingPartyMembers = new HashSet<>(startingPartyMembers); + for (String player : partyMembers) { + missingPartyMembers.remove(player); + } + } + } + } + + } + private void checkRaidPresence(boolean force) { if (client.getGameState() != GameState.LOGGED_IN)