From abf3b33338e83e0049d8ed2b5f6fea4944d315cf Mon Sep 17 00:00:00 2001 From: Devin Date: Mon, 18 Dec 2017 19:20:33 -0800 Subject: [PATCH] Update zulrah plugin overlay --- .../client/plugins/zulrah/ZulrahPlugin.java | 19 +- .../overlays/ZulrahCurrentPhaseOverlay.java | 80 ++++++ .../zulrah/overlays/ZulrahImageManager.java | 130 ++++++++++ .../overlays/ZulrahNextPhaseOverlay.java | 78 ++++++ .../zulrah/{ => overlays}/ZulrahOverlay.java | 238 +----------------- .../zulrah/overlays/ZulrahPrayerOverlay.java | 86 +++++++ .../plugins/zulrah/phase/ZulrahPhase.java | 28 +++ .../client/plugins/zulrah/zulrah_magic.png | Bin 18929 -> 19749 bytes ...ah_melee_small.png => zulrah_magic_sm.png} | Bin 17530 -> 17379 bytes .../client/plugins/zulrah/zulrah_melee.png | Bin 18838 -> 19573 bytes ...ah_range_small.png => zulrah_melee_sm.png} | Bin 17476 -> 17319 bytes .../client/plugins/zulrah/zulrah_range.png | Bin 18644 -> 19586 bytes ...ah_magic_small.png => zulrah_range_sm.png} | Bin 17552 -> 17332 bytes 13 files changed, 428 insertions(+), 231 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahCurrentPhaseOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahImageManager.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahNextPhaseOverlay.java rename runelite-client/src/main/java/net/runelite/client/plugins/zulrah/{ => overlays}/ZulrahOverlay.java (53%) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahPrayerOverlay.java rename runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/{zulrah_melee_small.png => zulrah_magic_sm.png} (80%) rename runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/{zulrah_range_small.png => zulrah_melee_sm.png} (80%) rename runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/{zulrah_magic_small.png => zulrah_range_sm.png} (80%) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java index 1871af12b0..c374aa4772 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahPlugin.java @@ -29,6 +29,8 @@ package net.runelite.client.plugins.zulrah; import com.google.inject.Binder; import com.google.inject.Provides; import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Collection; import javax.annotation.Nullable; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; @@ -41,6 +43,10 @@ import net.runelite.client.RuneLite; import net.runelite.client.config.ConfigManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.zulrah.overlays.ZulrahCurrentPhaseOverlay; +import net.runelite.client.plugins.zulrah.overlays.ZulrahNextPhaseOverlay; +import net.runelite.client.plugins.zulrah.overlays.ZulrahOverlay; +import net.runelite.client.plugins.zulrah.overlays.ZulrahPrayerOverlay; import net.runelite.client.plugins.zulrah.patterns.ZulrahPattern; import net.runelite.client.plugins.zulrah.patterns.ZulrahPatternA; import net.runelite.client.plugins.zulrah.patterns.ZulrahPatternB; @@ -69,6 +75,15 @@ public class ZulrahPlugin extends Plugin @Inject ZulrahOverlay overlay; + @Inject + ZulrahCurrentPhaseOverlay currentPhaseOverlay; + + @Inject + ZulrahNextPhaseOverlay nextPhaseOverlay; + + @Inject + ZulrahPrayerOverlay zulrahPrayerOverlay; + private final ZulrahPattern[] patterns = new ZulrahPattern[] { new ZulrahPatternA(), @@ -92,9 +107,9 @@ public class ZulrahPlugin extends Plugin } @Override - public Overlay getOverlay() + public Collection getOverlays() { - return overlay; + return Arrays.asList(overlay, currentPhaseOverlay, nextPhaseOverlay, zulrahPrayerOverlay); } @Schedule( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahCurrentPhaseOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahCurrentPhaseOverlay.java new file mode 100644 index 0000000000..767d466eee --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahCurrentPhaseOverlay.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017, Devin French + * 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.zulrah.overlays; + +import net.runelite.client.plugins.zulrah.ZulrahInstance; +import net.runelite.client.plugins.zulrah.ZulrahPlugin; +import net.runelite.client.plugins.zulrah.phase.ZulrahPhase; +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.ImagePanelComponent; + +import javax.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.image.BufferedImage; + +public class ZulrahCurrentPhaseOverlay extends Overlay +{ + private final ZulrahPlugin plugin; + + @Inject + ZulrahCurrentPhaseOverlay(ZulrahPlugin plugin) + { + setPosition(OverlayPosition.BOTTOM_RIGHT); + setPriority(OverlayPriority.HIGH); + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D graphics, Point parent) + { + ZulrahInstance instance = plugin.getInstance(); + + if (instance == null) + { + return null; + } + + ZulrahPhase currentPhase = instance.getPhase(); + if (currentPhase == null) + { + return null; + } + + String pattern = instance.getPattern() != null ? instance.getPattern().toString() : "Unknown"; + String title = currentPhase.isJad() ? "JAD PHASE" : pattern; + Color backgroundColor = currentPhase.getColor(); + BufferedImage zulrahImage = ZulrahImageManager.getZulrahBufferedImage(currentPhase.getType()); + ImagePanelComponent imagePanelComponent = new ImagePanelComponent(); + imagePanelComponent.setTitle(title); + imagePanelComponent.setBackgroundColor(backgroundColor); + imagePanelComponent.setImage(zulrahImage); + return imagePanelComponent.render(graphics, parent); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahImageManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahImageManager.java new file mode 100644 index 0000000000..2d9c25ff50 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahImageManager.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2017, Devin French + * 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.zulrah.overlays; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Prayer; +import net.runelite.client.plugins.zulrah.ZulrahPlugin; +import net.runelite.client.plugins.zulrah.phase.ZulrahType; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +@Slf4j +public class ZulrahImageManager +{ + private static final BufferedImage[] zulrahBufferedImages = new BufferedImage[3]; + private static final BufferedImage[] smallZulrahBufferedImages = new BufferedImage[3]; + private static final BufferedImage[] prayerBufferedImages = new BufferedImage[2]; + + public static BufferedImage getZulrahBufferedImage(ZulrahType type) + { + switch (type) + { + case RANGE: + if (zulrahBufferedImages[0] == null) + { + zulrahBufferedImages[0] = getBufferedImage("zulrah_range.png"); + } + return zulrahBufferedImages[0]; + case MAGIC: + if (zulrahBufferedImages[1] == null) + { + zulrahBufferedImages[1] = getBufferedImage("zulrah_magic.png"); + } + return zulrahBufferedImages[1]; + case MELEE: + if (zulrahBufferedImages[2] == null) + { + zulrahBufferedImages[2] = getBufferedImage("zulrah_melee.png"); + } + return zulrahBufferedImages[2]; + } + return null; + } + + public static BufferedImage getSmallZulrahBufferedImage(ZulrahType type) + { + switch (type) + { + case RANGE: + if (smallZulrahBufferedImages[0] == null) + { + smallZulrahBufferedImages[0] = getBufferedImage("zulrah_range_sm.png"); + } + return smallZulrahBufferedImages[0]; + case MAGIC: + if (smallZulrahBufferedImages[1] == null) + { + smallZulrahBufferedImages[1] = getBufferedImage("zulrah_magic_sm.png"); + } + return smallZulrahBufferedImages[1]; + case MELEE: + if (smallZulrahBufferedImages[2] == null) + { + smallZulrahBufferedImages[2] = getBufferedImage("zulrah_melee_sm.png"); + } + return smallZulrahBufferedImages[2]; + } + return null; + } + + public static BufferedImage getProtectionPrayerBufferedImage(Prayer prayer) + { + switch (prayer) + { + case PROTECT_FROM_MAGIC: + if (prayerBufferedImages[0] == null) + { + prayerBufferedImages[0] = getBufferedImage("/prayers/protect_from_magic.png"); + } + return prayerBufferedImages[0]; + case PROTECT_FROM_MISSILES: + if (prayerBufferedImages[1] == null) + { + prayerBufferedImages[1] = getBufferedImage("/prayers/protect_from_missiles.png"); + } + return prayerBufferedImages[1]; + } + return null; + } + + private static BufferedImage getBufferedImage(String path) + { + BufferedImage image = null; + try + { + InputStream in = ZulrahPlugin.class.getResourceAsStream(path); + image = ImageIO.read(in); + } + catch (IOException e) + { + log.debug("Error loading image {}", e); + } + return image; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahNextPhaseOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahNextPhaseOverlay.java new file mode 100644 index 0000000000..c45e9dd72d --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahNextPhaseOverlay.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, Devin French + * 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.zulrah.overlays; + +import net.runelite.client.plugins.zulrah.ZulrahInstance; +import net.runelite.client.plugins.zulrah.ZulrahPlugin; +import net.runelite.client.plugins.zulrah.phase.ZulrahPhase; +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.ImagePanelComponent; + +import javax.inject.Inject; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.image.BufferedImage; + +public class ZulrahNextPhaseOverlay extends Overlay +{ + private final ZulrahPlugin plugin; + + @Inject + ZulrahNextPhaseOverlay(ZulrahPlugin plugin) + { + setPosition(OverlayPosition.BOTTOM_RIGHT); + setPriority(OverlayPriority.HIGH); + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D graphics, Point parent) + { + ZulrahInstance instance = plugin.getInstance(); + + if (instance == null) + { + return null; + } + + ZulrahPhase nextPhase = instance.getNextPhase(); + if (nextPhase == null) + { + return null; + } + + Color backgroundColor = nextPhase.getColor(); + BufferedImage zulrahImage = ZulrahImageManager.getSmallZulrahBufferedImage(nextPhase.getType()); + ImagePanelComponent imagePanelComponent = new ImagePanelComponent(); + imagePanelComponent.setTitle("Next"); + imagePanelComponent.setBackgroundColor(backgroundColor); + imagePanelComponent.setImage(zulrahImage); + return imagePanelComponent.render(graphics, parent); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahOverlay.java similarity index 53% rename from runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahOverlay.java rename to runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahOverlay.java index 938de383b1..0fd1954022 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/ZulrahOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahOverlay.java @@ -23,7 +23,7 @@ * (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.zulrah; +package net.runelite.client.plugins.zulrah.overlays; import java.awt.BasicStroke; import java.awt.Color; @@ -32,44 +32,27 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Polygon; -import java.awt.Rectangle; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; import javax.annotation.Nullable; -import javax.imageio.ImageIO; import javax.inject.Inject; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.Perspective; import net.runelite.api.Point; -import net.runelite.api.Prayer; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.plugins.zulrah.ZulrahInstance; +import net.runelite.client.plugins.zulrah.ZulrahPlugin; import net.runelite.client.plugins.zulrah.phase.ZulrahPhase; -import net.runelite.client.plugins.zulrah.phase.ZulrahType; import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; @Slf4j public class ZulrahOverlay extends Overlay { - private static final int CURRENT_PHASE_WIDTH = 86; - private static final int NEXT_PHASE_WIDTH = 54; - private static final int SPACER = 6; - private static final int BOTTOM_BORDER = 4; private static final Color TILE_BORDER_COLOR = new Color(0, 0, 0, 100); private static final Color NEXT_TEXT_COLOR = new Color(255, 255, 255, 100); - private static final Color RANGE_BACKGROUND_COLOR = new Color(150, 255, 0, 100); - private static final Color MAGIC_BACKGROUND_COLOR = new Color(20, 170, 200, 100); - private static final Color MELEE_BACKGROUND_COLOR = new Color(180, 50, 20, 100); - private static final Color JAD_BACKGROUND_COLOR = new Color(255, 115, 0, 100); private final Client client; private final ZulrahPlugin plugin; - private final Image[] zulrahImages = new Image[3]; - private final Image[] smallZulrahImages = new Image[3]; - private final Image[] prayerImages = new Image[2]; @Inject ZulrahOverlay(@Nullable Client client, ZulrahPlugin plugin) @@ -89,12 +72,6 @@ public class ZulrahOverlay extends Overlay return null; } - Rectangle viewport = getViewportBounds(); - if (viewport == null) - { - return null; - } - ZulrahPhase currentPhase = instance.getPhase(); ZulrahPhase nextPhase = instance.getNextPhase(); if (currentPhase == null) @@ -102,7 +79,6 @@ public class ZulrahOverlay extends Overlay return null; } - String pattern = instance.getPattern() != null ? instance.getPattern().toString() : "Unknown"; Point startTile = instance.getStartLocation(); if (nextPhase != null && currentPhase.getStandLocation() == nextPhase.getStandLocation()) { @@ -115,9 +91,6 @@ public class ZulrahOverlay extends Overlay } drawZulrahTileMinimap(graphics, startTile, currentPhase, false); drawZulrahTileMinimap(graphics, startTile, nextPhase, true); - drawCurrentPhaseBox(graphics, viewport, currentPhase, pattern); - drawNextPhaseBox(graphics, viewport, nextPhase); - drawPrayerOutline(graphics, currentPhase.getPrayer()); return null; } @@ -132,8 +105,8 @@ public class ZulrahOverlay extends Overlay Point textLoc = Perspective.getCanvasTextLocation(client, graphics, localTile, "Next", 0); if (northPoly != null && southPoly != null && poly != null && textLoc != null) { - Color northColor = getBackgroundColor(currentPhase.getType()); - Color southColor = getBackgroundColor(nextPhase.getType()); + Color northColor = currentPhase.getColor(); + Color southColor = nextPhase.getColor(); graphics.setColor(northColor); graphics.fillPolygon(northPoly); graphics.setColor(southColor); @@ -146,7 +119,7 @@ public class ZulrahOverlay extends Overlay } if (nextPhase.isJad()) { - Image jadPrayerImg = getProtectionPrayerImage(nextPhase.getPrayer()); + Image jadPrayerImg = ZulrahImageManager.getProtectionPrayerBufferedImage(nextPhase.getPrayer()); if (jadPrayerImg != null) { Point imageLoc = Perspective.getCanvasImageLocation(client, graphics, localTile, (BufferedImage) jadPrayerImg, 0); @@ -168,7 +141,7 @@ public class ZulrahOverlay extends Overlay Point localTile = Perspective.worldToLocal(client, phase.getStandTile(startTile)); localTile = new Point(localTile.getX() + Perspective.LOCAL_TILE_SIZE / 2, localTile.getY() + Perspective.LOCAL_TILE_SIZE / 2); Polygon poly = Perspective.getCanvasTilePoly(client, localTile); - Color color = getBackgroundColor(phase.getType()); + Color color = phase.getColor(); if (poly != null) { graphics.setColor(TILE_BORDER_COLOR); @@ -187,7 +160,7 @@ public class ZulrahOverlay extends Overlay } if (phase.isJad()) { - Image jadPrayerImg = getProtectionPrayerImage(phase.getPrayer()); + Image jadPrayerImg = ZulrahImageManager.getProtectionPrayerBufferedImage(phase.getPrayer()); if (jadPrayerImg != null) { Point imageLoc = Perspective.getCanvasImageLocation(client, graphics, localTile, (BufferedImage) jadPrayerImg, 0); @@ -208,7 +181,7 @@ public class ZulrahOverlay extends Overlay } Point zulrahLocalTile = Perspective.worldToLocal(client, phase.getZulrahTile(startTile)); Point zulrahMinimapPoint = Perspective.worldToMiniMap(client, zulrahLocalTile.getX(), zulrahLocalTile.getY()); - Color color = getBackgroundColor(phase.getType()); + Color color = phase.getColor(); graphics.setColor(color); graphics.fillOval(zulrahMinimapPoint.getX(), zulrahMinimapPoint.getY(), 5, 5); graphics.setColor(TILE_BORDER_COLOR); @@ -222,98 +195,6 @@ public class ZulrahOverlay extends Overlay } } - private void drawCurrentPhaseBox(Graphics2D graphics, Rectangle viewport, ZulrahPhase phase, String pattern) - { - Image zulrahImg = getZulrahImage(phase.getType()); - if (zulrahImg == null) - { - return; - } - - FontMetrics fm = graphics.getFontMetrics(); - int height = fm.getHeight() * 2 + zulrahImg.getHeight(null) + SPACER + BOTTOM_BORDER; - int bgX = (int) (viewport.getX() + viewport.getWidth() - CURRENT_PHASE_WIDTH); - int bgY = (int) (viewport.getY() + viewport.getHeight() - height); - Color backgroundColor = phase.isJad() ? JAD_BACKGROUND_COLOR : getBackgroundColor(phase.getType()); - - graphics.setColor(backgroundColor); - graphics.fillRect(bgX, bgY, CURRENT_PHASE_WIDTH, height); - graphics.setColor(Color.WHITE); - graphics.drawString(pattern, bgX + (CURRENT_PHASE_WIDTH - fm.stringWidth(pattern)) / 2, bgY + fm.getHeight()); - graphics.drawImage(zulrahImg, bgX + (CURRENT_PHASE_WIDTH - zulrahImg.getWidth(null)) / 2, bgY + fm.getHeight() + SPACER, null); - if (phase.isJad()) - { - graphics.setColor(Color.RED.darker()); - graphics.drawString("JAD PHASE", bgX + (CURRENT_PHASE_WIDTH - fm.stringWidth("JAD PHASE")) / 2, bgY + height - BOTTOM_BORDER); - } - } - - private void drawNextPhaseBox(Graphics2D graphics, Rectangle viewport, ZulrahPhase phase) - { - if (phase == null) - { - return; - } - Image zulrahImg = getSmallZulrahImage(phase.getType()); - if (zulrahImg == null) - { - return; - } - - FontMetrics fm = graphics.getFontMetrics(); - int height = fm.getHeight() + zulrahImg.getHeight(null) + SPACER + BOTTOM_BORDER; - int bgX = (int) (viewport.getX() + viewport.getWidth() - NEXT_PHASE_WIDTH - CURRENT_PHASE_WIDTH); - int bgY = (int) (viewport.getY() + viewport.getHeight() - height); - Color backgroundColor = phase.isJad() ? JAD_BACKGROUND_COLOR : getBackgroundColor(phase.getType()); - graphics.setColor(backgroundColor); - graphics.fillRect(bgX, bgY, NEXT_PHASE_WIDTH, height); - graphics.drawImage(zulrahImg, bgX + (NEXT_PHASE_WIDTH - zulrahImg.getWidth(null)) / 2, bgY + fm.getHeight() + SPACER, null); - if (phase.isJad()) - { - Image jadFirstPrayerImg = getProtectionPrayerImage(phase.getPrayer()); - graphics.drawImage(jadFirstPrayerImg, bgX + (NEXT_PHASE_WIDTH - zulrahImg.getWidth(null)) / 2, bgY + fm.getHeight() + SPACER, null); - graphics.setColor(Color.RED.darker()); - graphics.drawString("Jad Next", bgX + (NEXT_PHASE_WIDTH - fm.stringWidth("Jad Next")) / 2, bgY + fm.getHeight()); - } - else - { - graphics.setColor(Color.WHITE); - graphics.drawString("Next", bgX + (NEXT_PHASE_WIDTH - fm.stringWidth("Next")) / 2, bgY + fm.getHeight()); - } - } - - private Rectangle getViewportBounds() - { - Widget viewport = client.getViewportWidget(); - return viewport != null ? viewport.getBounds() : null; - } - - private void drawPrayerOutline(Graphics2D graphics, Prayer prayer) - { - if (prayer == null || client.isPrayerActive(prayer)) - { - return; - } - Widget prayerWidget; - if (prayer == Prayer.PROTECT_FROM_MISSILES) - { - prayerWidget = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES); - } - else - { - prayerWidget = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC); - } - if (prayerWidget != null) - { - Rectangle prayerBounds = prayerWidget.getBounds(); - if (prayerBounds != null) - { - graphics.setColor(Color.RED.darker()); - graphics.draw(prayerBounds); - } - } - } - private Polygon getCanvasTileNorthPoly(Client client, Point localLocation) { int plane = client.getPlane(); @@ -357,105 +238,4 @@ public class ZulrahOverlay extends Overlay return poly; } - - private Color getBackgroundColor(ZulrahType type) - { - switch (type) - { - case RANGE: - return RANGE_BACKGROUND_COLOR; - case MAGIC: - return MAGIC_BACKGROUND_COLOR; - case MELEE: - return MELEE_BACKGROUND_COLOR; - } - return Color.DARK_GRAY; - } - - private Image getZulrahImage(ZulrahType type) - { - switch (type) - { - case RANGE: - if (zulrahImages[0] == null) - { - zulrahImages[0] = getImage("zulrah_range.png"); - } - return zulrahImages[0]; - case MAGIC: - if (zulrahImages[1] == null) - { - zulrahImages[1] = getImage("zulrah_magic.png"); - } - return zulrahImages[1]; - case MELEE: - if (zulrahImages[2] == null) - { - zulrahImages[2] = getImage("zulrah_melee.png"); - } - return zulrahImages[2]; - } - return null; - } - - private Image getSmallZulrahImage(ZulrahType type) - { - switch (type) - { - case RANGE: - if (smallZulrahImages[0] == null) - { - smallZulrahImages[0] = getImage("zulrah_range_small.png"); - } - return smallZulrahImages[0]; - case MAGIC: - if (smallZulrahImages[1] == null) - { - smallZulrahImages[1] = getImage("zulrah_magic_small.png"); - } - return smallZulrahImages[1]; - case MELEE: - if (smallZulrahImages[2] == null) - { - smallZulrahImages[2] = getImage("zulrah_melee_small.png"); - } - return smallZulrahImages[2]; - } - return null; - } - - private Image getProtectionPrayerImage(Prayer prayer) - { - switch (prayer) - { - case PROTECT_FROM_MAGIC: - if (prayerImages[0] == null) - { - prayerImages[0] = getImage("/prayers/protect_from_magic.png"); - } - return prayerImages[0]; - case PROTECT_FROM_MISSILES: - if (prayerImages[1] == null) - { - prayerImages[1] = getImage("/prayers/protect_from_missiles.png"); - } - return prayerImages[1]; - } - return null; - } - - private Image getImage(String path) - { - Image image = null; - try - { - InputStream in = ZulrahOverlay.class.getResourceAsStream(path); - image = ImageIO.read(in); - } - catch (IOException e) - { - log.debug("Error loading image {}", e); - } - return image; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahPrayerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahPrayerOverlay.java new file mode 100644 index 0000000000..a1f7fb3353 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/overlays/ZulrahPrayerOverlay.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017, Devin French + * 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.zulrah.overlays; + +import net.runelite.api.Client; +import net.runelite.api.Prayer; +import net.runelite.client.plugins.zulrah.ZulrahInstance; +import net.runelite.client.plugins.zulrah.ZulrahPlugin; +import net.runelite.client.plugins.zulrah.phase.ZulrahPhase; +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.ImagePanelComponent; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.image.BufferedImage; + +public class ZulrahPrayerOverlay extends Overlay +{ + private final Client client; + private final ZulrahPlugin plugin; + + @Inject + ZulrahPrayerOverlay(@Nullable Client client, ZulrahPlugin plugin) + { + setPosition(OverlayPosition.BOTTOM_RIGHT); + setPriority(OverlayPriority.MED); + this.client = client; + this.plugin = plugin; + } + + @Override + public Dimension render(Graphics2D graphics, Point parent) + { + ZulrahInstance instance = plugin.getInstance(); + + if (client == null || instance == null) + { + return null; + } + + ZulrahPhase currentPhase = instance.getPhase(); + if (currentPhase == null) + { + return null; + } + + Prayer prayer = currentPhase.isJad() ? null : currentPhase.getPrayer(); + if (prayer == null || client.isPrayerActive(prayer)) + { + return null; + } + + BufferedImage prayerImage = ZulrahImageManager.getProtectionPrayerBufferedImage(prayer); + ImagePanelComponent imagePanelComponent = new ImagePanelComponent(); + imagePanelComponent.setTitle("Switch!"); + imagePanelComponent.setImage(prayerImage); + return imagePanelComponent.render(graphics, parent); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/phase/ZulrahPhase.java b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/phase/ZulrahPhase.java index ce6c9fa0e2..ae64d3fcc7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/phase/ZulrahPhase.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/zulrah/phase/ZulrahPhase.java @@ -29,8 +29,15 @@ import net.runelite.api.NPC; import net.runelite.api.Point; import net.runelite.api.Prayer; +import java.awt.Color; + public class ZulrahPhase { + private static final Color RANGE_COLOR = new Color(150, 255, 0, 100); + private static final Color MAGIC_COLOR = new Color(20, 170, 200, 100); + private static final Color MELEE_COLOR = new Color(180, 50, 20, 100); + private static final Color JAD_COLOR = new Color(255, 115, 0, 100); + private final ZulrahLocation zulrahLocation; private final ZulrahType type; private final boolean jad; @@ -157,4 +164,25 @@ public class ZulrahPhase ZulrahPhase other = (ZulrahPhase) obj; return this.jad == other.jad && this.zulrahLocation == other.zulrahLocation && this.type == other.type; } + + public Color getColor() + { + if (jad) + { + return JAD_COLOR; + } + else + { + switch (type) + { + case RANGE: + return RANGE_COLOR; + case MAGIC: + return MAGIC_COLOR; + case MELEE: + return MELEE_COLOR; + } + } + return RANGE_COLOR; + } } diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_magic.png b/runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_magic.png index a0d06b0b956612828f947b1032652c6a60dd3c28..c4a6d7e339fe352273df812da598a6c79a6d876c 100644 GIT binary patch delta 4957 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 delta 4823 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 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_melee_small.png b/runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_magic_sm.png similarity index 80% rename from runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_melee_small.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_magic_sm.png index 46b5d17129cce5d0101d4dad98e9388d76dd10f0..899191b7aa66dea0b9c996a411d505e789b129f2 100644 GIT binary patch delta 2495 zcma);dpHw{8^_tqw3LxUZkdx4P7RycjYw#ea9AUkn2nk`Oq?jImE1}y=6)wjmr*SJ4rikfebXhbd$9bOL^PK1RoPYY`{l3rheZJ58yzl3)cQsjlCQ07lin}Xe z3q%_tCnvYX*~!6Uqw8;!j*{Yr#@iCj(hRoC=Tzg-KqwN9Kob!bcmx8EvV@ysSr>t* z|Ct!P1qN@4{KxD7qW^0`6!HvFSS%Vr##q8BWE2i=X}%#rmX>5V3X7)Ts5m4QgF>(b z3TAs^ey5vKX;eHe2#v$wED&&WbIV}3MG%S#4>HGK;UQ=Y21^McW67ux76N3u>qmmt zW-K?57V811!|+GqtQ|_&{~ip3Fj>dI1%?(VEQLZ2M#8CNBxQpN3JWJ&Qju`91ug`M z3!)-7cKg2xNG#q0^$#5wM8GoLl=x#X{@vkUzFZhY8vw9Cu&k9a03?R{hjO@?!W`!4 z3~S!XlnL&1cCaJHjAvw?rxU%jx{4zg`OzzjM){NR3?oL3!6t`G05~t%T~}SP{JF;| zf^LNRcv}Cc#>uz(QR>xO3u!!0j!)_MnLRae_A(R?q?W#KzZ2k;n$pd_r@N@ptcAtN z#@OcT%o5&_NAnhu1G#)=!IbsD*{Kz1Kkhr588=tEPZ#j!UZ?v>9fY*8BJigxuqJB_@{Q}RW)~~c=v951$*#}NwVUjZa_k(Jmg}F4}N@TwM)=+&gAUgt^7yQ-$_2q zY9VzxSgxyszMtwH|8{$BWolw`2XgW5<9JHTqp{0*<SRiWH=)e#YLe zD|2(*f<=c;RK@$Ye2=+lOQ&JS7eI}r!y?#}Wx@9~xxb9!BY*J>On7=;*g|uwx%J^& zW7^LdD!pUcAK!^?uKO@@lndSC`nLSp`HAT|PW4Kuy3q+_^GO#oK72j2sX0b}O?PaR1 zKZvi91$cdv>8ooS%R8TZ?^?O<#Z~^p=y|btc;y-!z-Mobz>iEeXs$?_ytz}Vwnd|e zrM%^*_k-^p`uHTf|2upeOEt1#5S6Ox&jK2CY&lf2T3B)wTC1RX^tHp|OPS(J5ak1Y zpWnP}Xligv;hZPf_&DhvAEw+!nYaSk>5tb@>JxM{B&WQyahXF5T%3>uhy`mFMk2 z77;lQcQMdaYWM63BIVrcw(pbO71`u*YlN8Khl)LUDVd49Fo-NXPL2%JRqAf|Iy!q(Coqf6_}0V_9RDc z7B4p>{!HH6bb<0Y<5k~ILeN=?+d-QFyBJAyvcGzmWZkch28$N0)zO8irlgp;G;r5W z;N#T>@)WEq&#EN~&IxClZI8|(W(L!L3K4_UO}NiUqu1geK%y;69=38OFR^=k^-}KH z7cYw|ep%MK!e3-EXs`cE5|o__Mrq3 z(z-!Xy{T}DRB#z-D(JI5lM~xKAxSI{r0nA5%|42$z|OHEqKtv zS}t>r1xIrM+)<`2{PGZXsHo_5^{v!WE3CLy+@p|38$CgwZ)*JW$g^3j3>v$9fAh!e zy&r1cDD9Ny`{(fPLvezV6B%VsC(CzK;Y8!2k>8SG!V^dD9x`5b6CRU13|l$|lVkhc zuO|+)wI?xlGZiHC381jgAI*cG*c8f%Sg+0RN%EEX3Yht`$(8C}lGGgw6{kD>s!!oL zP5s?*AsqRKvh|d;5iW>|NZRGDuZ!p6J5yQD*}Kyni8&Do_a%G##wbSHT1?~zyaiEGyQLckNe8^=7*VR9ziv@J zkR%`8&kS@u_;Sg`GkBtxKJyVZRUW!Se;~BztVpobGUN=3A?D5$H5h4C*OVC?fTL zRqg@>*=_4&?+|Ke_vzjInh4c*YxTD{vb)kWiLEvET69^xIX$`x}|1i>GUj5eQXvgnW?-rlSo&^We&Yh_{tkZWvyh}2> z)p)oIDA%R!~rrCjN=zD@pLeo7U(~mBXI=I{2;i`Wgf}6{xUS&;0h<`gIh)AA3 zvy0njtc*f-741y>0wn|P7|Le=6g2j{yG~f6$mJ?t_eG8X7B@aJIcG;#hpPR7aeo7> CD0VOa delta 2674 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 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_melee.png b/runelite-client/src/main/resources/net/runelite/client/plugins/zulrah/zulrah_melee.png index 344abc8fd38e9cd3fefb45f0d2ec1317b0b55844..012e8e9e0a4838cc23d05e1249170f91339674b2 100644 GIT binary patch delta 4782 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 L!%(vpXCLt|c~+Ac delta 4538 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 i3Ehlks^CA)H;R{-qY64 zI!a-8S+Jgmk5*+Lg zz@QtUAP@*tAvoejXSec7gLEDMjNkT_@x7Dq+y~boe}pdB459q@;H^+V@awu9B!@yhMZ!@jXci9Zi6*fKUT7+oYJ%oa@Dw76 zNF{Nw`2SZRm=ehUxU&`7Ai${de$0%2clg&|@mAwz)YR2h$o9f)cuW>*#YV0 zg3-MgV4cvGZp94iE)=@@F*|>%UmeM*X&!U^GR>=KxpcPal(i*iJ$QGvrGl=5bO!EN z=9Jv|rjMr1I27(a%+QrO(o~JnzAn&0W$4b#k8K{TO_yOT&1&yg^SzII zs70E-NC?(!&REvDv?N@W*Iu_lO=k&#GDRRwD>I2txAFS58=S9Ur1)uuLg^A`&@H8>dg?ptu}xr(qmQ` zF`(0%UD`4aR5sBiZ|5%W8oTh*K!+H1E!3m?ffK*<8gyU;MA^|F3u0QOq81dD6@lbY zgyMFsIu)elW_8Phmwa`Yo*s$!?7$P}gm|?*dM!5!_lpnA_7I)^fO$-A?|005rC0d8 z*>kga$jI&m!vNWD`l(V><6Uy!Fwj8iy`=w?tP*Fd-mBsDL5;>(Y1d8A4w+JUF%{Oc zC0kmtg}r!WxnVYZcI0xc=0p&*u>>HK?7CswG*xcZ^|YQI3c1KA4@947i5>dGC4HOu zONHg8YPo`z>d7lMHX|2L8du%bY2=A3T%}D2bE3S$H{+?#joWy*^qa%}s?-2fK>X66 zefVQK7CF@)E}edok)~@h@-|n32yv5434GtIc!{*1dIm~$@(>oK#p5dCG@$)J)#R~b zBjuqN+)QGmad6nJ!>@?pq4a0EbLG&a)BqYXb8LG`s)J6x<_FIsIcDWXC$O7PSs9Q+ zx=iDOK<&H5aUG3}At*5q>mGzNh3~5l)h<=qKxQO{@o0Yr ztS`E+QE+y`h`y{6d_q3&!HSr0-v7RpQIur;PU+G4J5T9dR?nz$<0TF{DYFI~pj9W= zGr@y<_1m8TOxec6+IH;d95*fSRrM#~qjm(i&CU%~80&rSCF|8N0OIDk=M57=(>~Nh zf|D~>5cJ(xvc+icN>taRoB|=I3Ld`;*^?Hz8vDEWBHxk8g?*UAYWvm8k9+&S7iCm11cGgS$-|8%5ZGtWpS0Pd*A;>E`nn5Fn-N%^z^qQ!-F7&Fbg4=ZX%#kl*2L@ew}rHS1)$+e*I&&#LLb z7*_tv@#d?|-TwEMzYUMzs=6*a3l-j+aan9vHfY~3@yG=5FJl>BxV}+-VUdl^RUXsY z*38~>$4~c?PNc7V4H#X|BD@PP<4Wa4rF>0@;0F;UT*_YrdqIOPGo zsXId$KUYA({Nu+D)1Ml?mRBBgHtN4iLsZ(*EHwkKii}iVM)K-OH9hu zxCxjA>Kp1s2G%|q$(aOKM&tRd(YuXKene~#_8*c>J9S179}v$I+KP6@-~KE;UM8yi zmcq$Mp5kgIgvl1EWt(!PUx81KOW;hA3|ystSGXhPN-?CEmB+6=x>(UJE>dUtK&GNN z6!^4%dMpt9dGgNv4gK474ib(ziSoy-fZ}L}P`vhJiQUVTL~Vyxo?XGyL%o&e(4*VL z8^QQ1iNT>Yd-*RVYS#lJecx%9N(l9<7lxbjGxlQoXiEoV>&gB@iM&N*usNjXg5J=* z(Hr~i6WW{y1HJ3^72aEB9y&CZ==oNwfO_K{ z&#b@-!pRzG6^SC09!F`1iZ{Bsof_^L?y!d3CoG@tj7tsZn=c)h&W6EY=wvVDto{_s z-bALZovJOBnZ6PO`Q>!Yr)vd<3Y`3TUVMw8uw4nk_FZU^?Ag)p$luh}TDwIVK z&HwIVM&1F3-F8u*2)gN|cSkvU11MkJu}R^Te(+)WT=~V=v?bWS&3pHrQbouTKlebk zS$s2_Egq@7nS;`}qXUP}01U^2iij;2M*z{P254a}<7jT#%Z9ZV3uL>`o?cG#i1{07 C!%-Ii delta 2697 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 MlTOx;to&&I2Ea|ghyVZp