From e6169ab79b5923213dac57bb5c68663e5f7a265b Mon Sep 17 00:00:00 2001 From: dekvall Date: Tue, 3 Nov 2020 21:12:03 +0100 Subject: [PATCH] zalcano: add damage counter Adds a panel which tracks damage dealt to Zalcano's health and shield to make it easier prioritising what to focus on at a low level. Co-authored-by: Adam --- .../main/java/net/runelite/api/VarPlayer.java | 9 +- .../client/plugins/zalcano/ZalcanoPanel.java | 85 ++++++++++++++++++ .../client/plugins/zalcano/ZalcanoPlugin.java | 86 ++++++++++++++++++- 3 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPanel.java diff --git a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java index a18acd81ba..d4653aeb9c 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java +++ b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java @@ -185,7 +185,14 @@ public enum VarPlayer /** * 0 = 2 buttons, 1 = 1 button */ - MOUSE_BUTTONS(170); + MOUSE_BUTTONS(170), + + /** + * Zalcano's form + * -1 : Player is outside or Zalcano is dead i.e. there's no healthbar to show + * Anything else : The {@link NpcID} of the current form + */ + ZALCANO_FORM(1683); private final int id; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPanel.java new file mode 100644 index 0000000000..b30b29ca7e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPanel.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, dekvall + * 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 HOLDER 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.zalcano; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import net.runelite.client.ui.overlay.OverlayPanel; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.components.LineComponent; + +class ZalcanoPanel extends OverlayPanel +{ + private final ZalcanoPlugin plugin; + + @Inject + public ZalcanoPanel(ZalcanoPlugin plugin) + { + super(plugin); + setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT); + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D g) + { + if (!plugin.isInCavern()) + { + return null; + } + + panelComponent.getChildren().add(LineComponent.builder() + .left("Health damage:") + .leftColor(colorFromCount(plugin.getHealthDamage())) + .right(Integer.toString(plugin.getHealthDamage())) + .build()); + + panelComponent.getChildren().add(LineComponent.builder() + .left("Shield damage:") + .leftColor(colorFromCount(plugin.getShieldDamage())) + .right(Integer.toString(plugin.getShieldDamage())) + .build()); + + return super.render(g); + } + + private static Color colorFromCount(int damage) + { + if (damage >= 50) + { + // Eligible for uniques/pet + return Color.GREEN; + } + if (damage >= 30) + { + // Eligible for drops + return Color.YELLOW; + } + return Color.RED; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPlugin.java index b1a606156c..fdaa151b29 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zalcano/ZalcanoPlugin.java @@ -28,26 +28,32 @@ import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import lombok.Getter; +import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.GameObject; import net.runelite.api.GameState; import static net.runelite.api.GraphicID.GRAPHICS_OBJECT_ROCKFALL; import net.runelite.api.GraphicsObject; +import net.runelite.api.Hitsplat; import net.runelite.api.NPC; import net.runelite.api.NpcID; import static net.runelite.api.NpcID.ZALCANO; import net.runelite.api.ObjectID; import net.runelite.api.Projectile; import static net.runelite.api.ProjectileID.ZALCANO_PROJECTILE_FIREBALL; +import net.runelite.api.VarPlayer; import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.GameObjectSpawned; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GraphicsObjectCreated; +import net.runelite.api.events.HitsplatApplied; import net.runelite.api.events.NpcChanged; import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.ProjectileMoved; +import net.runelite.api.events.VarbitChanged; +import net.runelite.client.callback.ClientThread; import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -72,6 +78,12 @@ public class ZalcanoPlugin extends Plugin @Inject private ZalcanoOverlay overlay; + @Inject + private ZalcanoPanel panel; + + @Inject + private ClientThread clientThread; + @Getter private LocalPoint targetedGlowingRock; @Getter @@ -81,17 +93,35 @@ public class ZalcanoPlugin extends Plugin @Getter private final List rocks = new ArrayList<>(); + @Getter + private int healthDamage; + @Getter + private int shieldDamage; + @Getter + private boolean inCavern; + @Override protected void startUp() { overlayManager.add(overlay); + overlayManager.add(panel); rocks.clear(); + + resetDamageCounter(); + clientThread.invokeLater(() -> + { + if (client.getGameState() == GameState.LOGGED_IN) + { + inCavern = isHealthbarActive(); + } + }); } @Override protected void shutDown() { overlayManager.remove(overlay); + overlayManager.remove(panel); } @Subscribe @@ -107,12 +137,25 @@ public class ZalcanoPlugin extends Plugin @Subscribe public void onGameStateChanged(GameStateChanged event) { - if (event.getGameState() != GameState.LOGGED_IN) + GameState gameState = event.getGameState(); + if (gameState == GameState.LOADING) { rocks.clear(); } } + @Subscribe + public void onVarbitChanged(VarbitChanged event) + { + boolean wasInCavern = inCavern; + inCavern = isHealthbarActive(); + + if (!inCavern && wasInCavern) + { + resetDamageCounter(); + } + } + @Subscribe public void onNpcSpawned(NpcSpawned event) { @@ -142,6 +185,12 @@ public class ZalcanoPlugin extends Plugin } } + private void resetDamageCounter() + { + healthDamage = 0; + shieldDamage = 0; + } + @Subscribe public void onGameObjectSpawned(GameObjectSpawned event) { @@ -183,4 +232,39 @@ public class ZalcanoPlugin extends Plugin targetedGlowingRockEndCycle = projectile.getEndCycle(); } } + + @Subscribe + public void onHitsplatApplied(HitsplatApplied event) + { + final Actor actor = event.getActor(); + + if (!(actor instanceof NPC)) + { + return; + } + + int npcId = ((NPC) actor).getId(); + if (!(npcId == ZALCANO_WEAKENED || npcId == ZALCANO)) + { + return; + } + + Hitsplat hitsplat = event.getHitsplat(); + int damage = hitsplat.getAmount(); + + switch (hitsplat.getHitsplatType()) + { + case DAMAGE_ME: + healthDamage += damage; + break; + case DAMAGE_ME_ORANGE: + shieldDamage += damage; + break; + } + } + + private boolean isHealthbarActive() + { + return client.getVar(VarPlayer.ZALCANO_FORM) != -1; + } }