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 5445f804da..c76971fbef 100644 --- a/runelite-api/src/main/java/net/runelite/api/AnimationID.java +++ b/runelite-api/src/main/java/net/runelite/api/AnimationID.java @@ -268,4 +268,13 @@ public final class AnimationID public static final int JALTOK_JAD_RANGE_ATTACK = 7593; public static final int TZKAL_ZUK = 7566; public static final int JAL_MEJJAK = 2858; + + //General Graardor + public static final int MINION_AUTO1 = 6154; + public static final int MINION_AUTO2 = 6156; + public static final int MINION_AUTO3 = 7071; + public static final int MINION_AUTO4 = 7073; + public static final int GENERAL_AUTO1 = 7018; + public static final int GENERAL_AUTO2 = 7020; + public static final int GENERAL_AUTO3 = 7021; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/FontStyle.java b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/FontStyle.java new file mode 100644 index 0000000000..cf826093d7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/FontStyle.java @@ -0,0 +1,46 @@ +/* + * 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.ticktimers; + +import java.awt.Font; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum FontStyle +{ + BOLD("Bold", Font.BOLD), + ITALIC("Italic", Font.ITALIC), + PLAIN("Plain", Font.PLAIN); + + private String name; + private int font; + + @Override + public String toString() + { + return getName(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/NPCContainer.java b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/NPCContainer.java new file mode 100644 index 0000000000..04990583b9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/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.ticktimers; + +import lombok.Getter; +import lombok.Setter; +import net.runelite.api.Actor; +import net.runelite.api.NPC; +import net.runelite.api.NPCDefinition; + +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 NPCDefinition composition = npc.getTransformedDefinition(); + + 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/ticktimers/TickTimersConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TickTimersConfig.java new file mode 100644 index 0000000000..34ace17ef9 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TickTimersConfig.java @@ -0,0 +1,108 @@ +/* + * 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.ticktimers; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; +import net.runelite.client.config.Stub; + +@ConfigGroup("TickTimers") +public interface TickTimersConfig extends Config +{ + @ConfigItem( + position = 0, + keyName = "bosses", + name = "Bosses", + description = "" + ) + default Stub bosses() + { + return new Stub(); + } + + @ConfigItem( + position = 1, + keyName = "graardor", + name = "General Graardor", + description = "Show tick timers for General Graardor", + parent = "bosses" + ) + default boolean graardor() + { + return true; + } + + @ConfigItem( + position = 22, + keyName = "text", + name = "Text", + description = "" + ) + default Stub text() + { + return new Stub(); + } + + @ConfigItem( + position = 23, + keyName = "fontStyle", + name = "Font Style", + description = "Plain | Bold | Italics", + parent = "text" + ) + default FontStyle fontStyle() + { + return FontStyle.PLAIN; + } + + @Range( + min = 14, + max = 40 + ) + @ConfigItem( + position = 24, + keyName = "textSize", + name = "Text Size", + description = "Text Size for Timers.", + parent = "text" + ) + default int textSize() + { + return 32; + } + + @ConfigItem( + position = 25, + keyName = "shadows", + name = "Shadows", + description = "Adds Shadows to text.", + parent = "text" + ) + default boolean shadows() + { + return false; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TickTimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TickTimersPlugin.java new file mode 100644 index 0000000000..5f9d7d4200 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TickTimersPlugin.java @@ -0,0 +1,258 @@ +/* + * 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.ticktimers; + +import com.google.inject.Provides; +import java.util.HashMap; +import java.util.Map; +import javax.inject.Inject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.AnimationID; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.NPC; +import net.runelite.api.NpcID; +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.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.PluginType; +import net.runelite.client.ui.overlay.OverlayManager; +import org.apache.commons.lang3.ArrayUtils; + +@PluginDescriptor( + name = "Boss Tick Timers", + description = "Tick timers for bosses", + tags = {"pvm", "bossing"}, + enabledByDefault = false, + type = PluginType.PVM +) + +@Slf4j +public class TickTimersPlugin extends Plugin +{ + private static final int GENERAL_REGION = 11347; + + @Inject + private Client client; + + @Inject + private OverlayManager overlayManager; + + @Inject + private TimersOverlay timersOverlay; + + @Inject + private TickTimersConfig config; + + @Getter(AccessLevel.PACKAGE) + private Map Strongstack = new HashMap<>(); + + @Getter(AccessLevel.PACKAGE) + private Map Steelwill = new HashMap<>(); + + @Getter(AccessLevel.PACKAGE) + private Map Grimspike = new HashMap<>(); + + @Getter(AccessLevel.PACKAGE) + private Map General = new HashMap<>(); + + @Provides + TickTimersConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(TickTimersConfig.class); + } + + @Override + public void startUp() + { + Strongstack.clear(); + Steelwill.clear(); + Grimspike.clear(); + General.clear(); + } + + @Override + public void shutDown() + { + Strongstack.clear(); + Steelwill.clear(); + Grimspike.clear(); + General.clear(); + } + + @Subscribe + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + if (gameStateChanged.getGameState() == GameState.LOGGED_IN) + { + if (isInGeneralRegion()) + { + overlayManager.add(timersOverlay); + } + else + { + overlayManager.remove(timersOverlay); + } + } + if (gameStateChanged.getGameState() != GameState.LOGGED_IN) + { + return; + } + Strongstack.clear(); + Steelwill.clear(); + Grimspike.clear(); + General.clear(); + + } + + @Subscribe + public void onNpcSpawned(NpcSpawned event) + { + NPC npc = event.getNpc(); + switch (npc.getId()) + { + case NpcID.SERGEANT_STRONGSTACK: + Strongstack.put(npc, new NPCContainer(npc)); + break; + case NpcID.SERGEANT_STEELWILL: + Steelwill.put(npc, new NPCContainer(npc)); + break; + case NpcID.SERGEANT_GRIMSPIKE: + Grimspike.put(npc, new NPCContainer(npc)); + break; + case NpcID.GENERAL_GRAARDOR: + case NpcID.GENERAL_GRAARDOR_6494: + General.put(npc, new NPCContainer(npc)); + break; + } + } + + @Subscribe + public void onNpcDespawned(NpcDespawned event) + { + if (Grimspike.remove(event.getNpc()) != null && !Grimspike.isEmpty()) + { + Grimspike.clear(); + } + if (Steelwill.remove(event.getNpc()) != null && !Steelwill.isEmpty()) + { + Steelwill.clear(); + } + if (Strongstack.remove(event.getNpc()) != null && !Strongstack.isEmpty()) + { + Strongstack.clear(); + } + if (General.remove(event.getNpc()) != null && !General.isEmpty()) + { + General.clear(); + } + } + + @Subscribe + public void onGameTick(GameTick Event) + { + if (config.graardor()) + { + graardorHandler(); + } + } + + private void graardorHandler() + { + for (NPCContainer grimspike : getGrimspike().values()) + { + grimspike.setTicksUntilAttack(grimspike.getTicksUntilAttack() - 1); + switch (grimspike.getNpc().getAnimation()) + { + case AnimationID.MINION_AUTO1: + case AnimationID.MINION_AUTO2: + case AnimationID.MINION_AUTO4: + if (grimspike.getTicksUntilAttack() < 1) + { + grimspike.setTicksUntilAttack(5); + } + break; + } + } + + for (NPCContainer strongstack : getStrongstack().values()) + { + strongstack.setTicksUntilAttack(strongstack.getTicksUntilAttack() - 1); + switch (strongstack.getNpc().getAnimation()) + { + case AnimationID.MINION_AUTO1: + case AnimationID.MINION_AUTO2: + if (strongstack.getTicksUntilAttack() < 1) + { + strongstack.setTicksUntilAttack(5); + } + break; + } + } + + for (NPCContainer steelwill : getSteelwill().values()) + { + steelwill.setTicksUntilAttack(steelwill.getTicksUntilAttack() - 1); + switch (steelwill.getNpc().getAnimation()) + { + case AnimationID.MINION_AUTO1: + case AnimationID.MINION_AUTO2: + case AnimationID.MINION_AUTO3: + if (steelwill.getTicksUntilAttack() < 1) + { + steelwill.setTicksUntilAttack(5); + } + break; + } + } + + for (NPCContainer boss : getGeneral().values()) + { + boss.setTicksUntilAttack(boss.getTicksUntilAttack() - 1); + switch (boss.getNpc().getAnimation()) + { + case AnimationID.GENERAL_AUTO1: + case AnimationID.GENERAL_AUTO2: + case AnimationID.GENERAL_AUTO3: + if (boss.getTicksUntilAttack() < 1) + { + boss.setTicksUntilAttack(6); + } + break; + } + } + } + + private boolean isInGeneralRegion() + { + return ArrayUtils.contains(client.getMapRegions(), GENERAL_REGION); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TimersOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TimersOverlay.java new file mode 100644 index 0000000000..06214a86a4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ticktimers/TimersOverlay.java @@ -0,0 +1,193 @@ +/* + * 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.ticktimers; + +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.NPCDefinition; +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 TickTimersPlugin plugin; + private Client client; + private TickTimersConfig config; + + @Inject + TimersOverlay(TickTimersPlugin plugin, Client client, TickTimersConfig config) + { + this.plugin = plugin; + this.client = client; + this.config = config; + setPosition(OverlayPosition.DYNAMIC); + setPriority(OverlayPriority.HIGHEST); + setLayer(OverlayLayer.ALWAYS_ON_TOP); + } + + @Override + public Dimension render(Graphics2D graphics) + { + Color tickcolor; + + for (NPCContainer npc : plugin.getStrongstack().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), Color.RED, 100, 10); + final int ticksLeft = npc.getTicksUntilAttack(); + if (ticksLeft > 0) + { + if (ticksLeft == 1) + { + tickcolor = Color.RED; + } + else + { + tickcolor = Color.WHITE; + } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0); + renderTextLocation(graphics, ticksLeftStr, config.textSize(), config.fontStyle().getFont(), tickcolor, canvasPoint); + } + } + + for (NPCContainer npc : plugin.getSteelwill().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), Color.CYAN, 100, 10); + final int ticksLeft = npc.getTicksUntilAttack(); + if (ticksLeft > 0) + { + if (ticksLeft == 1) + { + tickcolor = Color.CYAN; + } + else + { + + tickcolor = Color.WHITE; + } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0); + renderTextLocation(graphics, ticksLeftStr, config.textSize(), config.fontStyle().getFont(), tickcolor, canvasPoint); + } + } + + for (NPCContainer npc : plugin.getGrimspike().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), Color.GREEN, 100, 10); + final int ticksLeft = npc.getTicksUntilAttack(); + if (ticksLeft > 0) + { + if (ticksLeft == 1) + { + tickcolor = Color.GREEN; + } + else + { + + tickcolor = Color.WHITE; + } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0); + renderTextLocation(graphics, ticksLeftStr, config.textSize(), config.fontStyle().getFont(), tickcolor, canvasPoint); + } + } + + for (NPCContainer npc : plugin.getGeneral().values()) + { + renderNpcOverlay(graphics, npc.getNpc(), Color.RED, 100, 10); + final int ticksLeft = npc.getTicksUntilAttack(); + if (ticksLeft > 0) + { + if (ticksLeft == 1) + { + tickcolor = Color.RED; + } + else + { + + tickcolor = Color.WHITE; + } + final String ticksLeftStr = String.valueOf(ticksLeft); + Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0); + renderTextLocation(graphics, ticksLeftStr, config.textSize(), config.fontStyle().getFont(), tickcolor, canvasPoint); + } + } + + return null; + } + + private void renderNpcOverlay(Graphics2D graphics, NPC actor, Color color, int outlineAlpha, int fillAlpha) + { + int size = 1; + NPCDefinition composition = actor.getTransformedDefinition(); + 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(2)); + 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); + if (config.shadows()) + { + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK); + } + OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor); + } + } +}