diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java index 5d1252fd1f..b0c578cd3f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/FightCavePlugin.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Jordan Atwood + * Copyright (c) 2019, Ganom * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,7 +28,9 @@ package net.runelite.client.plugins.fightcave; import com.google.inject.Provides; import java.util.ArrayList; import java.util.EnumMap; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nullable; @@ -41,11 +44,13 @@ import net.runelite.api.NPC; import net.runelite.api.NpcID; import net.runelite.api.events.AnimationChanged; import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameStateChanged; +import net.runelite.api.events.GameTick; import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcSpawned; -import net.runelite.api.events.GameStateChanged; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.flexo.Flexo; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginType; @@ -59,6 +64,7 @@ import org.apache.commons.lang3.ArrayUtils; type = PluginType.PVM, enabledByDefault = false ) + public class FightCavePlugin extends Plugin { private static final Pattern WAVE_PATTERN = Pattern.compile(".*Wave: (\\d+).*"); @@ -85,6 +91,30 @@ public class FightCavePlugin extends Plugin @Inject private JadOverlay jadOverlay; + @Inject + private TimersOverlay timersOverlay; + + @Inject + private ConfigManager externalConfig; + + @Getter(AccessLevel.PACKAGE) + private Map Rangers = new HashMap<>(); + + @Getter(AccessLevel.PACKAGE) + private Map Magers = new HashMap<>(); + + @Getter(AccessLevel.PACKAGE) + private Map Meleers = new HashMap<>(); + + @Getter(AccessLevel.PACKAGE) + private Map Drainers = new HashMap<>(); + + @Getter(AccessLevel.PACKAGE) + private Map Ignore = new HashMap<>(); + + private boolean runMage; + private boolean runRange; + @Getter(AccessLevel.PACKAGE) @Nullable private JadAttack attack; @@ -142,6 +172,8 @@ public class FightCavePlugin extends Plugin { overlayManager.add(waveOverlay); overlayManager.add(jadOverlay); + overlayManager.add(timersOverlay); + Flexo.client = client; } @Override @@ -149,7 +181,7 @@ public class FightCavePlugin extends Plugin { overlayManager.remove(waveOverlay); currentWave = -1; - + overlayManager.remove(timersOverlay); overlayManager.remove(jadOverlay); jad = null; attack = null; @@ -170,6 +202,46 @@ public class FightCavePlugin extends Plugin } } + @Subscribe + public void onGameTick(GameTick Event) + { + for (NPCContainer ranger : getRangers().values()) + { + ranger.setTicksUntilAttack(ranger.getTicksUntilAttack() - 1); + if (ranger.getNpc().getAnimation() == 2633) + { + if (ranger.getTicksUntilAttack() < 1) + { + ranger.setTicksUntilAttack(4); + } + } + } + + for (NPCContainer meleer : getMeleers().values()) + { + meleer.setTicksUntilAttack(meleer.getTicksUntilAttack() - 1); + if (meleer.getNpc().getAnimation() == 2637 || meleer.getNpc().getAnimation() == 2639) + { + if (meleer.getTicksUntilAttack() < 1) + { + meleer.setTicksUntilAttack(4); + } + } + } + + for (NPCContainer mager : getMagers().values()) + { + mager.setTicksUntilAttack(mager.getTicksUntilAttack() - 1); + if (mager.getNpc().getAnimation() == 2647) + { + if (mager.getTicksUntilAttack() < 1) + { + mager.setTicksUntilAttack(4); + } + } + } + } + @Subscribe public void onChatMessage(ChatMessage event) { @@ -185,39 +257,69 @@ public class FightCavePlugin extends Plugin currentWave = Integer.parseInt(waveMatcher.group(1)); } - boolean inFightCave() - { - return ArrayUtils.contains(client.getMapRegions(), FIGHT_CAVE_REGION); - } - - static String formatMonsterQuantity(final WaveMonster monster, final int quantity) - { - return String.format("%dx %s", quantity, monster); - } @Subscribe - public void onNpcSpawned(final NpcSpawned event) + public void onNpcSpawned(NpcSpawned event) { - final int id = event.getNpc().getId(); - - if (id == NpcID.TZTOKJAD || id == NpcID.TZTOKJAD_6506) + NPC npc = event.getNpc(); + switch (npc.getId()) { - jad = event.getNpc(); + case NpcID.TZKIH_3116: + case NpcID.TZKIH_3117: + Drainers.put(npc, new NPCContainer(npc)); + break; + case NpcID.TZKEK_3118: + case NpcID.TZKEK_3119: + case NpcID.TZKEK_3120: + Ignore.put(npc, new NPCContainer(npc)); + break; + case NpcID.TOKXIL_3121: + case NpcID.TOKXIL_3122: + Rangers.put(npc, new NPCContainer(npc)); + break; + case NpcID.YTMEJKOT: + case NpcID.YTMEJKOT_3124: + Meleers.put(npc, new NPCContainer(npc)); + break; + case NpcID.KETZEK: + case NpcID.KETZEK_3126: + Magers.put(npc, new NPCContainer(npc)); + break; + case NpcID.TZTOKJAD: + case NpcID.TZTOKJAD_6506: + jad = npc; + break; } } @Subscribe - public void onNpcDespawned(final NpcDespawned event) + public void onNpcDespawned(NpcDespawned event) { - if (jad == event.getNpc()) + if (Rangers.remove(event.getNpc()) != null && Rangers.isEmpty()) { - jad = null; - attack = null; + Rangers.clear(); } + if (Meleers.remove(event.getNpc()) != null && Meleers.isEmpty()) + { + Meleers.clear(); + } + if (Magers.remove(event.getNpc()) != null && Magers.isEmpty()) + { + Magers.clear(); + } + if (Drainers.remove(event.getNpc()) != null && Drainers.isEmpty()) + { + Drainers.clear(); + } + if (Ignore.remove(event.getNpc()) != null && Ignore.isEmpty()) + { + Ignore.clear(); + } + } @Subscribe - public void onAnimationChanged(final AnimationChanged event) + public void onAnimationChanged(AnimationChanged event) { if (event.getActor() != jad) { @@ -227,10 +329,23 @@ public class FightCavePlugin extends Plugin if (jad.getAnimation() == JadAttack.MAGIC.getAnimation()) { attack = JadAttack.MAGIC; + runMage = true; } + else if (jad.getAnimation() == JadAttack.RANGE.getAnimation()) { attack = JadAttack.RANGE; + runRange = true; } } + + boolean inFightCave() + { + return ArrayUtils.contains(client.getMapRegions(), FIGHT_CAVE_REGION); + } + + static String formatMonsterQuantity(final WaveMonster monster, final int quantity) + { + return String.format("%dx %s", quantity, monster); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/NPCContainer.java b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/NPCContainer.java new file mode 100644 index 0000000000..06f8c12877 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/NPCContainer.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, Woox + * 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.fightcave; + +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Actor; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; + +class NPCContainer +{ + + @Getter + private NPC npc; + + @Getter + private int npcIndex; + + @Getter + private String npcName; + + @Getter + private int npcSize; + + @Setter + @Getter + private int TicksUntilAttack; + + @Setter + @Getter + private int npcSpeed; + + @Setter + @Getter + private Actor npcInteracting; + + + NPCContainer(NPC npc) + { + this.npc = npc; + this.npcName = npc.getName(); + this.npcIndex = npc.getIndex(); + this.npcInteracting = npc.getInteracting(); + this.npcSpeed = 0; + this.TicksUntilAttack = 0; + final NPCComposition composition = npc.getTransformedComposition(); + + if (composition != null) + { + this.npcSize = composition.getSize(); + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/TimersOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/TimersOverlay.java new file mode 100644 index 0000000000..f609cacab1 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fightcave/TimersOverlay.java @@ -0,0 +1,184 @@ +/* + * 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.fightcave; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Polygon; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.NPC; +import net.runelite.api.NPCComposition; +import net.runelite.api.Perspective; +import net.runelite.api.Point; +import net.runelite.api.coords.LocalPoint; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; +import net.runelite.client.ui.overlay.OverlayPriority; +import net.runelite.client.ui.overlay.OverlayUtil; + +public class TimersOverlay extends Overlay +{ + private FightCavePlugin plugin; + private Client client; + private Color tickcolor = new Color(255, 255, 255, 255); + + @Inject + TimersOverlay(FightCavePlugin plugin, Client client) + { + this.plugin = plugin; + this.client = client; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGHEST); + setLayer(OverlayLayer.ALWAYS_ON_TOP); + } + + @Override + public Dimension render(Graphics2D graphics) + { + for (NPCContainer npc : plugin.getDrainers().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), new Color(255, 0, 0, 255), 2, 255, 20); + String str = "drainer"; + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, str, 0); + renderTextLocation(graphics, str, 12, Font.BOLD, new Color(255, 255, 255, 255), canvasPoint); + } + + for (NPCContainer npc : plugin.getIgnore().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), new Color(0, 0, 0, 255), 2, 50, 5); + String str = "ignore"; + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, str, 0); + renderTextLocation(graphics, str, 10, Font.BOLD, new Color(255, 255, 255, 255), canvasPoint); + } + + for (NPCContainer npc : plugin.getRangers().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), new Color(0, 255, 0, 255), 2, 100, 10); + final int ticksLeft = npc.getTicksUntilAttack(); + if (ticksLeft > 0) + { + if (ticksLeft == 1) + { + tickcolor = new Color(0, 255, 0, 255); + } + else + { + + tickcolor = new Color(255, 255, 255, 255); + } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0); + renderTextLocation(graphics, ticksLeftStr, 32, Font.BOLD, tickcolor, canvasPoint); + } + } + + for (NPCContainer npc : plugin.getMagers().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), new Color(0, 255, 255, 255), 2, 100, 10); + final int ticksLeft = npc.getTicksUntilAttack(); + if (ticksLeft > 0) + { + if (ticksLeft == 1) + { + tickcolor = new Color(0, 255, 255, 255); + } + else + { + + tickcolor = new Color(255, 255, 255, 255); + } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0); + renderTextLocation(graphics, ticksLeftStr, 32, Font.BOLD, tickcolor, canvasPoint); + } + } + + for (NPCContainer npc : plugin.getMeleers().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), new Color(255, 0, 0, 255), 2, 100, 10); + final int ticksLeft = npc.getTicksUntilAttack(); + if (ticksLeft > 0) + { + if (ticksLeft == 1) + { + tickcolor = new Color(255, 0, 0, 255); + } + else + { + + tickcolor = new Color(255, 255, 255, 255); + } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0); + renderTextLocation(graphics, ticksLeftStr, 32, Font.BOLD, tickcolor, canvasPoint); + } + } + + return null; + } + + private void renderNpcOverlay(Graphics2D graphics, NPC actor, Color color, int outlineWidth, int outlineAlpha, int fillAlpha) + { + int size = 1; + NPCComposition composition = actor.getTransformedComposition(); + if (composition != null) + { + size = composition.getSize(); + } + LocalPoint lp = actor.getLocalLocation(); + Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size); + + if (tilePoly != null) + { + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha)); + graphics.setStroke(new BasicStroke(outlineWidth)); + graphics.draw(tilePoly); + graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha)); + graphics.fill(tilePoly); + } + } + + private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, Point canvasPoint) + { + graphics.setFont(new Font("Arial", fontStyle, fontSize)); + if (canvasPoint != null) + { + final Point canvasCenterPoint = new Point( + canvasPoint.getX(), + canvasPoint.getY()); + final Point canvasCenterPoint_shadow = new Point( + canvasPoint.getX() + 1, + canvasPoint.getY() + 1); + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); + } + } +}