diff --git a/runelite-api/src/main/java/net/runelite/api/AnimationID.java b/runelite-api/src/main/java/net/runelite/api/AnimationID.java index 22c5da122b..12dc9b068c 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -323,6 +323,7 @@ public final class AnimationID public static final int CHIN_ANIMATION = 7618; // Gauntlet Hunleff + public static final int HUNLEFF_TRAMPLE = 8420; public static final int HUNLEFF_ATTACK = 8419; public static final int HUNLEFF_TORNADO = 8418; } \ No newline at end of file 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 48c138e013..d12beffb45 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -683,7 +683,12 @@ public enum Varbits /** * The y coordinate of the final safespace (world coord) */ - LMS_SAFE_Y(5320); + LMS_SAFE_Y(5320), + + /** + * 1 is true, 0 is false. + */ + GAUNTLET_FINAL_ROOM_ENTERED(9177); /** * The raw varbit ID. diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletCounter.java new file mode 100644 index 0000000000..d16684fb66 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletCounter.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019, ganom + * 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.gauntlet; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import javax.inject.Inject; +import javax.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; +import net.runelite.client.ui.overlay.components.table.TableAlignment; +import net.runelite.client.ui.overlay.components.table.TableComponent; +import net.runelite.client.util.ColorUtil; + +@Singleton +@Slf4j +public class GauntletCounter extends Overlay +{ + private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150); + private final GauntletPlugin plugin; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + GauntletCounter(final GauntletPlugin plugin) + { + this.plugin = plugin; + setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT); + setPriority(OverlayPriority.HIGH); + } + + @Override + public Dimension render(Graphics2D graphics) + { + panelComponent.getChildren().clear(); + + if (plugin.getHunllef() == null || !plugin.isInRoom()) + { + return null; + } + + panelComponent.getChildren().add(TitleComponent.builder() + .text("Hunllef") + .color(Color.pink) + .build()); + + Color color = plugin.getPlayerAttacks() == 1 ? Color.RED : Color.WHITE; + final String pHits = ColorUtil.prependColorTag(Integer.toString(plugin.getPlayerAttacks()), color); + + TableComponent tableComponent = new TableComponent(); + tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT); + tableComponent.addRow("Hunllef Hits: ", Integer.toString(plugin.getAttacks())); + tableComponent.addRow("Player Hits Left: ", pHits); + panelComponent.getChildren().add(tableComponent); + return panelComponent.render(graphics); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletInfoBox.java index 5dc00462c7..c07d509a3d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletInfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletInfoBox.java @@ -1,5 +1,4 @@ /* - * Copyright (c) 2019, lyzrds * Copyright (c) 2019, ganom * All rights reserved. * @@ -70,7 +69,7 @@ public class GauntletInfoBox extends Overlay { panelComponent.getChildren().clear(); - if (plugin.getHunllef() == null) + if (plugin.getHunllef() == null || !plugin.isInRoom()) { return null; } @@ -81,6 +80,7 @@ public class GauntletInfoBox extends Overlay { return null; } + InfoBoxComponent prayComponent = new InfoBoxComponent(); BufferedImage prayImg = scaleImg(getPrayerImage(prayer)); prayComponent.setImage(prayImg); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletPlugin.java index 102e85423d..d30057300f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gauntlet/GauntletPlugin.java @@ -33,12 +33,15 @@ import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.AnimationID; +import net.runelite.api.Client; import net.runelite.api.HeadIcon; import net.runelite.api.NPC; import net.runelite.api.NPCDefinition; import net.runelite.api.Prayer; import net.runelite.api.ProjectileID; +import net.runelite.api.Varbits; import net.runelite.api.events.AnimationChanged; +import net.runelite.api.events.GameTick; import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; import net.runelite.api.events.ProjectileSpawned; @@ -58,37 +61,48 @@ import net.runelite.client.ui.overlay.OverlayManager; @Singleton @Slf4j +@Getter(AccessLevel.PACKAGE) +@Setter(AccessLevel.PACKAGE) public class GauntletPlugin extends Plugin { - + private static final Set PLAYER_ANIMATIONS = ImmutableSet.of(426, 1167, 422, 423, 440); private static final Set HUNLEFF_ANIMATIONS = ImmutableSet.of(AnimationID.HUNLEFF_ATTACK, AnimationID.HUNLEFF_TORNADO); private static final Set HUNLEFF_MAGE_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLEFF_MAGE_ATTACK, ProjectileID.HUNLEFF_CORRUPTED_MAGE_ATTACK); private static final Set HUNLEFF_RANGE_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLEFF_RANGE_ATTACK, ProjectileID.HUNLEFF_CORRUPTED_RANGE_ATTACK); @Inject + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private Client client; + @Inject + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) private EventBus eventBus; @Inject + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) private OverlayManager overlayManager; @Inject + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) private GauntletInfoBox GauntletInfoBox; - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) + @Inject + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + private GauntletCounter GauntletCounter; private int attacks = 0; - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) + private int playerAttacks = 0; private Prayer nextPrayer; - @Getter(AccessLevel.PACKAGE) - @Setter(AccessLevel.PACKAGE) private NPC hunllef; - @Getter(AccessLevel.PRIVATE) - @Setter(AccessLevel.PRIVATE) private boolean firstHitDetected; - + private HeadIcon currentPrayer; @Override protected void startUp() throws Exception { addSubscriptions(); overlayManager.add(GauntletInfoBox); + overlayManager.add(GauntletCounter); + reset(); } @Override @@ -96,29 +110,84 @@ public class GauntletPlugin extends Plugin { eventBus.unregister(this); overlayManager.remove(GauntletInfoBox); + overlayManager.remove(GauntletCounter); reset(); } private void addSubscriptions() { - + eventBus.subscribe(AnimationChanged.class, this, this::onAnimationChanged); eventBus.subscribe(NpcSpawned.class, this, this::onNpcSpawned); eventBus.subscribe(NpcDespawned.class, this, this::onNpcDespawned); + eventBus.subscribe(ProjectileSpawned.class, this, this::onProjectileSpawned); + eventBus.subscribe(GameTick.class, this, this::onGameTick); } - private void onNpcSpawned(NpcSpawned event) + private void onAnimationChanged(AnimationChanged event) { - final NPC npc = event.getNpc(); - - if (npc.getName() == null || !npc.getName().toLowerCase().contains("hunllef")) + if (getHunllef() == null || !isInRoom()) { return; } - setHunllef(npc); + final int anim = event.getActor().getAnimation(); - eventBus.subscribe(AnimationChanged.class, "gauntlet", this::onAnimationChanged); - eventBus.subscribe(ProjectileSpawned.class, "gauntlet", this::onProjectileSpawned); + if (HUNLEFF_ANIMATIONS.contains(anim)) + { + setAttacks(getAttacks() + 1); + + if (getAttacks() == 4) + { + if (getNextPrayer() == Prayer.PROTECT_FROM_MISSILES) + { + log.debug("Attacks are: {}, switching to prot mage", getAttacks()); + setNextPrayer(Prayer.PROTECT_FROM_MAGIC); + } + else if (getNextPrayer() == Prayer.PROTECT_FROM_MAGIC) + { + log.debug("Attacks are: {}, switching to prot missiles", getAttacks()); + setNextPrayer(Prayer.PROTECT_FROM_MISSILES); + } + setAttacks(0); + } + } + else if (PLAYER_ANIMATIONS.contains(anim)) + { + setPlayerAttacks(getPlayerAttacks() - 1); + if (getPlayerAttacks() == 0) + { + setPlayerAttacks(6); + } + } + } + + private void onGameTick(GameTick event) + { + if (getHunllef() == null || !isInRoom()) + { + return; + } + + HeadIcon overhead = getOverheadIcon(getHunllef()); + + if (overhead == null) + { + return; + } + + switch (overhead) + { + case MELEE: + case MAGIC: + case RANGED: + if (currentPrayer == overhead) + { + return; + } + currentPrayer = overhead; + setPlayerAttacks(6); + break; + } } private void onNpcDespawned(NpcDespawned event) @@ -130,13 +199,26 @@ public class GauntletPlugin extends Plugin return; } - eventBus.unregister("gauntlet"); reset(); } + private void onNpcSpawned(NpcSpawned event) + { + final NPC npc = event.getNpc(); + + if (npc.getName() == null || !npc.getName().toLowerCase().contains("hunllef")) + { + return; + } + + setPlayerAttacks(6); + setAttacks(0); + setHunllef(npc); + } + private void onProjectileSpawned(ProjectileSpawned event) { - if (getHunllef() == null || isFirstHitDetected()) + if (getHunllef() == null || !isInRoom() || isFirstHitDetected()) { return; } @@ -155,44 +237,15 @@ public class GauntletPlugin extends Plugin } } - private void onAnimationChanged(AnimationChanged event) - { - if (hunllef == null) - { - return; - } - - final int anim = event.getActor().getAnimation(); - - if (!HUNLEFF_ANIMATIONS.contains(anim)) - { - return; - } - - setAttacks(getAttacks() + 1); - - if (getAttacks() == 4) - { - if (getNextPrayer() == Prayer.PROTECT_FROM_MISSILES) - { - log.debug("Attacks are: {}, switching to prot mage", getAttacks()); - setNextPrayer(Prayer.PROTECT_FROM_MAGIC); - } - else if (getNextPrayer() == Prayer.PROTECT_FROM_MAGIC) - { - log.debug("Attacks are: {}, switching to prot missiles", getAttacks()); - setNextPrayer(Prayer.PROTECT_FROM_MISSILES); - } - setAttacks(0); - } - } private void reset() { setHunllef(null); setNextPrayer(null); + setCurrentPrayer(null); setFirstHitDetected(false); setAttacks(0); + setPlayerAttacks(6); } private HeadIcon getOverheadIcon(NPC npc) @@ -205,4 +258,8 @@ public class GauntletPlugin extends Plugin return null; } + boolean isInRoom() + { + return client.getVar(Varbits.GAUNTLET_FINAL_ROOM_ENTERED) == 1; + } }