From faed3ec1bf7d03d572ad9d2f5e5c5bdc6f0f0b48 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 11 May 2019 14:22:24 -0400 Subject: [PATCH] dps --- .../client/plugins/dpscounter/Boss.java | 78 +++++++++ .../plugins/dpscounter/DpsCounterPlugin.java | 159 ++++++++++++++++++ .../client/plugins/dpscounter/DpsMember.java | 26 +++ .../client/plugins/dpscounter/DpsOverlay.java | 73 ++++++++ .../client/plugins/dpscounter/DpsUpdate.java | 13 ++ 5 files changed, 349 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/Boss.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/Boss.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/Boss.java new file mode 100644 index 0000000000..bfd4587e25 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/Boss.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018, Raqes + * 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.dpscounter; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import lombok.Getter; +import lombok.ToString; +import net.runelite.api.NpcID; + +@Getter +@ToString +enum Boss +{ + ABYSSAL_SIRE(1.25f, NpcID.ABYSSAL_SIRE, NpcID.ABYSSAL_SIRE_5887, NpcID.ABYSSAL_SIRE_5888, NpcID.ABYSSAL_SIRE_5889, NpcID.ABYSSAL_SIRE_5890, NpcID.ABYSSAL_SIRE_5891, NpcID.ABYSSAL_SIRE_5908), + CALLISTO(1.225f, NpcID.CALLISTO, NpcID.CALLISTO_6609), + CERBERUS(1.15f, NpcID.CERBERUS, NpcID.CERBERUS_5863, NpcID.CERBERUS_5866), + CHAOS_ELEMENTAL(1.075f, NpcID.CHAOS_ELEMENTAL, NpcID.CHAOS_ELEMENTAL_6505), + CORPOREAL_BEAST(1.55f, NpcID.CORPOREAL_BEAST), + GENERAL_GRAARDOR(1.325f, NpcID.GENERAL_GRAARDOR, NpcID.GENERAL_GRAARDOR_6494), + GIANT_MOLE(1.075f, NpcID.GIANT_MOLE, NpcID.GIANT_MOLE_6499), + KALPHITE_QUEEN(1.05f, NpcID.KALPHITE_QUEEN, NpcID.KALPHITE_QUEEN_963, NpcID.KALPHITE_QUEEN_965, NpcID.KALPHITE_QUEEN_4303, NpcID.KALPHITE_QUEEN_4304, NpcID.KALPHITE_QUEEN_6500, NpcID.KALPHITE_QUEEN_6501), + KING_BLACK_DRAGON(1.075f, NpcID.KING_BLACK_DRAGON, NpcID.KING_BLACK_DRAGON_2642, NpcID.KING_BLACK_DRAGON_6502), + KRIL_TSUROTH(1.375f, NpcID.KRIL_TSUTSAROTH, NpcID.KRIL_TSUTSAROTH_6495), + VENETENATIS(1.4f, NpcID.VENENATIS, NpcID.VENENATIS_6610), + VETION(1.225f, NpcID.VETION, NpcID.VETION_REBORN); + + private final int[] ids; + private final float modifier; // Some NPCs have a modifier to the experience a player receives. + + Boss(float modifier, int... ids) + { + this.modifier = modifier; + this.ids = ids; + } + + private static final Map BOSS_MAP; + + static Boss findBoss(int id) + { + return BOSS_MAP.get(id); + } + + static + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Boss boss : values()) + { + for (int id : boss.ids) + { + builder.put(id, boss); + } + } + BOSS_MAP = builder.build(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java new file mode 100644 index 0000000000..af9eef5dba --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsCounterPlugin.java @@ -0,0 +1,159 @@ +package net.runelite.client.plugins.dpscounter; + +import com.google.inject.Binder; +import com.google.inject.Inject; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.api.Actor; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.Player; +import net.runelite.api.Skill; +import net.runelite.api.events.ExperienceChanged; +import net.runelite.api.events.InteractingChanged; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.overlay.OverlayManager; +import net.runelite.client.ws.PartyMember; +import net.runelite.client.ws.PartyService; +import net.runelite.client.ws.WSClient; + +@PluginDescriptor( + name = "DPS Counter", + description = "counts dps?" +// +) +public class DpsCounterPlugin extends Plugin +{ + private int lastXp = -1; + + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private PartyService partyService; + + @Inject + private WSClient wsClient; + + @Inject + private DpsOverlay dpsOverlay; + + private Boss boss; + private NPC npc; + @Getter(AccessLevel.PACKAGE) + private final Map members = new ConcurrentHashMap<>(); + + @Override + public void configure(Binder binder) + { + //super.configure(binder); + } + + @Override + protected void startUp() + { + overlayManager.add(dpsOverlay); + //super.startUp(); + } + + @Override + protected void shutDown() + { + overlayManager.remove(dpsOverlay); + boss = null; + //super.shutDown(); + } + + @Subscribe + public void onInteractingChanged(InteractingChanged interactingChanged) { + Actor source = interactingChanged.getSource(); + Actor target = interactingChanged.getTarget(); + + if (source != client.getLocalPlayer()) { + return; + } + + if (target instanceof NPC) { + int npcId = ((NPC) target).getId(); + Boss boss = Boss.findBoss(npcId); + if (boss != null) { + this.boss = boss; + npc = (NPC) target; + // boss = Boss.ABYSSAL_SIRE; + } + } + } + + @Subscribe + public void onExperienceChanged(ExperienceChanged experienceChanged) + { + if (experienceChanged.getSkill() != Skill.HITPOINTS) + { + return; + } + + final int xp = client.getSkillExperience(Skill.HITPOINTS); + if (boss == null || lastXp < 0 || xp < lastXp) + { + lastXp = xp; + return; + } + + final int delta = xp - lastXp; + final int hit = getHit(boss.getModifier(), delta); +// final int hit = getHit(1.0f, delta); + lastXp = xp; + + // Update local member + PartyMember localMember = partyService.getLocalMember(); + Player player = client.getLocalPlayer(); + // If not in a party, user local player name + final String name = localMember == null ? player.getName() : localMember.getName(); + DpsMember dpsMember = members.computeIfAbsent(name, n -> new DpsMember(name)); + dpsMember.addDamage(hit); +// System.out.println("HIT "+ hit); + + if (!partyService.getMembers().isEmpty()) + { + // Check the player is attacking the boss + if (npc != null && player.getInteracting() == npc) + { + final DpsUpdate specialCounterUpdate = new DpsUpdate(npc.getId(), hit); + specialCounterUpdate.setMemberId(partyService.getLocalMember().getMemberId()); + wsClient.send(specialCounterUpdate); + } + } + } + + @Subscribe + public void onDpsUpdate(DpsUpdate dpsUpdate) { + if (partyService.getLocalMember().getMemberId().equals(dpsUpdate.getMemberId())) + { + return; + } + + String name = partyService.getMemberById(dpsUpdate.getMemberId()).getName(); + if (name == null) + { + return; + } + + DpsMember dpsMember = members.computeIfAbsent(name, n -> new DpsMember(name)); + dpsMember.addDamage(dpsUpdate.getHit()); + + } + + private int getHit(float modifier, int deltaExperience) + { + float modifierBase = 1f / modifier; + float damageOutput = (deltaExperience * modifierBase) / 1.3333f; + return Math.round(damageOutput); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java new file mode 100644 index 0000000000..6b5693a37f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsMember.java @@ -0,0 +1,26 @@ +package net.runelite.client.plugins.dpscounter; + +import java.time.Instant; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +class DpsMember +{ + private final String name; + private Instant start = Instant.now(); + private int damage; + + void addDamage(int amount) + { + damage += amount; + } + + int getDps() + { + int diff = (int) (Instant.now().toEpochMilli() - start.toEpochMilli()) / 1000; + if (diff == 0) return 0; + return damage / diff; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java new file mode 100644 index 0000000000..42254ab92e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsOverlay.java @@ -0,0 +1,73 @@ +package net.runelite.client.plugins.dpscounter; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.util.Map; +import javax.inject.Inject; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; +import net.runelite.client.ws.PartyService; + +public class DpsOverlay extends Overlay +{ + private final DpsCounterPlugin dpsCounterPlugin; + private final PartyService partyService; + + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + DpsOverlay(DpsCounterPlugin dpsCounterPlugin, PartyService partyService) + { + super(dpsCounterPlugin); + this.dpsCounterPlugin = dpsCounterPlugin; + this.partyService = partyService; + //setPosition(OverlayPosition.TOP_LEFT); + } + + @Override + public Dimension render(Graphics2D graphics) + { + Map dpsMembers = dpsCounterPlugin.getMembers(); + + panelComponent.getChildren().clear(); + panelComponent.getChildren().add( + TitleComponent.builder() + .text("DPS") + //olor(HIGHLIGHT_COLOR) + .build()); + +// panelComponent.getChildren().add( +// LineComponent.builder() +// .left("Player") +// // .leftColor(HIGHLIGHT_COLOR) +// .right("DPS") +// // .rightColor(HIGHLIGHT_COLOR) +// .build()); + + for (DpsMember dpsMember : dpsMembers.values()) { + panelComponent.getChildren().add( + LineComponent.builder() + .left(dpsMember.getName()) + .right(Integer.toString(dpsMember.getDps())) + //.right(Integer.toString(playerSkillLevel) + "/" + Integer.toString(opponentSkillLevel)) + //.rightColor(comparisonStatColor(playerSkillLevel, opponentSkillLevel)) + .build()); + } + + //partyService.getMemberByName() +// for (PartyMember member : partyService.getMembers()) { +// DpsMember dpsMember = dpsMembers.get(member.getName()); +// if (dpsMember == null) continue; +// panelComponent.getChildren().add( +// LineComponent.builder() +// .left(member.getName()) +// .right(Integer.toString(dpsMember.getDps())) +// //.right(Integer.toString(playerSkillLevel) + "/" + Integer.toString(opponentSkillLevel)) +// //.rightColor(comparisonStatColor(playerSkillLevel, opponentSkillLevel)) +// .build()); +// } + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java new file mode 100644 index 0000000000..5aa02da373 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/dpscounter/DpsUpdate.java @@ -0,0 +1,13 @@ +package net.runelite.client.plugins.dpscounter; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import net.runelite.http.api.ws.messages.party.PartyMemberMessage; + +@Value +@EqualsAndHashCode(callSuper = true) +public class DpsUpdate extends PartyMemberMessage +{ + private int npcId; + private int hit; +}