From 79ab610e969cf73f30733721d3b67b790cad26d2 Mon Sep 17 00:00:00 2001 From: Nickolaj Jepsen Date: Fri, 9 Feb 2018 11:34:45 +0100 Subject: [PATCH] Add NMZ plugin --- .../main/java/net/runelite/api/Varbits.java | 8 +- .../net/runelite/api/widgets/WidgetID.java | 1 + .../net/runelite/api/widgets/WidgetInfo.java | 4 +- .../nightmarezone/AbsorptionCounter.java | 41 +++++ .../nightmarezone/NightmareZoneConfig.java | 114 +++++++++++++ .../nightmarezone/NightmareZoneOverlay.java | 147 +++++++++++++++++ .../nightmarezone/NightmareZonePlugin.java | 156 ++++++++++++++++++ 7 files changed, 469 insertions(+), 2 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java 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 9a969b5e2c..e2008c38ae 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -192,7 +192,13 @@ public enum Varbits /** * Raids */ - IN_RAID(5432, 1431, 31, 31); + IN_RAID(5432, 1431, 31, 31), + + /** + * Nightmare Zone + */ + NMZ_ABSORPTION(3956, 1067, 5, 14), + NMZ_POINTS(3949, 1059, 0, 19); /** * varbit id diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index f77a94a7dd..09e3e3d187 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -63,6 +63,7 @@ public class WidgetID public static final int MOTHERLODE_MINE_GROUP_ID = 382; public static final int EXPERIENCE_DROP_GROUP_ID = 122; public static final int PUZZLE_BOX_GROUP_ID = 306; + public static final int NIGHTMARE_ZONE_GROUP_ID = 202; static class WorldMap { diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index c1c415e847..826f9154d9 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -167,7 +167,9 @@ public enum WidgetInfo MOTHERLODE_MINE(WidgetID.MOTHERLODE_MINE_GROUP_ID, 0), - PUZZLE_BOX(WidgetID.PUZZLE_BOX_GROUP_ID, WidgetID.PuzzleBox.VISIBLE_BOX); + PUZZLE_BOX(WidgetID.PUZZLE_BOX_GROUP_ID, WidgetID.PuzzleBox.VISIBLE_BOX), + + NIGHTMARE_ZONE(WidgetID.NIGHTMARE_ZONE_GROUP_ID, 1); private final int groupId; private final int childId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java new file mode 100644 index 0000000000..bdc19ac805 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/AbsorptionCounter.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018, Nickolaj + * 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.nightmarezone; + +import java.awt.image.BufferedImage; +import net.runelite.client.ui.overlay.infobox.Counter; + +public class AbsorptionCounter extends Counter +{ + public AbsorptionCounter(BufferedImage image, String text) + { + super(image, text); + } + + public void setAbsorption(int value) + { + setText(String.valueOf(value)); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneConfig.java new file mode 100644 index 0000000000..f9d3b8355a --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneConfig.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018, Nickolaj + * 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.nightmarezone; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup( + keyName = "nightmareZone", + name = "Nightmare Zone", + description = "Configuration for the nightmare zone plugin" +) +public interface NightmareZoneConfig extends Config +{ + @ConfigItem( + keyName = "enabled", + name = "Enable plugin", + description = "Configures whether or not the plugin is enabled", + position = 1 + ) + default boolean enabled() + { + return true; + } + + @ConfigItem( + keyName = "tray", + name = "Send Tray Notification", + description = "Toggles tray notifications", + position = 2 + ) + default boolean sendTrayNotification() + { + return true; + } + + @ConfigItem( + keyName = "request", + name = "Request Window Focus", + description = "Toggles window focus request", + position = 3 + ) + default boolean requestFocus() + { + return true; + } + + @ConfigItem( + keyName = "overloadnotification", + name = "Overload notification", + description = "Toggles notifications when your overload runs out", + position = 4 + ) + default boolean overloadNotification() + { + return true; + } + + @ConfigItem( + keyName = "absorptionnotification", + name = "Absorption notification", + description = "Toggles notifications when your absorption points gets below your threshold", + position = 5 + ) + default boolean absorptionNotification() + { + return true; + } + + @ConfigItem( + keyName = "absorptionthreshold", + name = "Absorption Threshold", + description = "The amount of absorption points to send a notification at", + position = 6 + ) + default int absorptionThreshold() + { + return 50; + } + + @ConfigItem( + keyName = "moveoverlay", + name = "Override NMZ overlay", + description = "Overrides the overlay so it doesn't conflict with other RuneLite plugins", + position = 7 + ) + default boolean moveOverlay() + { + return true; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java new file mode 100644 index 0000000000..b43e646071 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZoneOverlay.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018, Nickolaj + * 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.nightmarezone; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.ItemID; +import net.runelite.api.Varbits; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.game.ItemManager; +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.infobox.InfoBoxManager; + +class NightmareZoneOverlay extends Overlay +{ + private final Client client; + private final NightmareZoneConfig config; + private final NightmareZonePlugin plugin; + private final InfoBoxManager infoBoxManager; + private final ItemManager itemManager; + + private AbsorptionCounter absorptionCounter; + private final PanelComponent panelComponent = new PanelComponent(); + + @Inject + NightmareZoneOverlay( + Client client, + NightmareZoneConfig config, + NightmareZonePlugin plugin, + InfoBoxManager infoBoxManager, + ItemManager itemManager) + { + setPosition(OverlayPosition.TOP_LEFT); + setPriority(OverlayPriority.LOW); + this.client = client; + this.config = config; + this.plugin = plugin; + this.infoBoxManager = infoBoxManager; + this.itemManager = itemManager; + } + + @Override + public Dimension render(Graphics2D graphics, Point parent) + { + if (!config.enabled() || !plugin.isInNightmareZone() || !config.moveOverlay()) + { + if (absorptionCounter != null) + { + removeAbsorptionCounter(); + // Restore original widget + Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); + if (nmzWidget != null) + { + nmzWidget.setHidden(false); + } + } + return null; + } + + Widget nmzWidget = client.getWidget(WidgetInfo.NIGHTMARE_ZONE); + + if (nmzWidget != null) + { + nmzWidget.setHidden(true); + } + + renderAbsorptionCounter(); + + panelComponent.getLines().clear(); + panelComponent.getLines().add(new PanelComponent.Line( + "Points: ", + Color.WHITE, + Integer.toString(client.getSetting(Varbits.NMZ_POINTS)), + Color.WHITE + )); + + return panelComponent.render(graphics, parent); + } + + private void renderAbsorptionCounter() + { + int absorptionPoints = client.getSetting(Varbits.NMZ_ABSORPTION); + if (absorptionPoints == 0) + { + if (absorptionCounter != null) + { + removeAbsorptionCounter(); + absorptionCounter = null; + } + } + else if (config.moveOverlay()) + { + if (absorptionCounter == null) + { + addAbsorptionCounter(absorptionPoints); + } + else + { + absorptionCounter.setAbsorption(absorptionPoints); + } + } + } + + private void addAbsorptionCounter(int startValue) + { + absorptionCounter = new AbsorptionCounter(itemManager.getImage(ItemID.ABSORPTION_4), "0"); + absorptionCounter.setAbsorption(startValue); + infoBoxManager.addInfoBox(absorptionCounter); + } + + private void removeAbsorptionCounter() + { + infoBoxManager.removeInfoBox(absorptionCounter); + absorptionCounter = null; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java new file mode 100644 index 0000000000..a63bf43e80 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/nightmarezone/NightmareZonePlugin.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2018, Nickolaj + * 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.nightmarezone; + +import com.google.common.eventbus.Subscribe; +import com.google.inject.Binder; +import com.google.inject.Provides; +import java.util.Arrays; +import javax.inject.Inject; +import net.runelite.api.ChatMessageType; +import net.runelite.api.Client; +import net.runelite.api.Varbits; +import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; +import net.runelite.client.Notifier; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ClientUI; +import net.runelite.client.ui.overlay.Overlay; + +@PluginDescriptor( + name = "Nightmare Zone Plugin" +) +public class NightmareZonePlugin extends Plugin +{ + private static final int[] NMZ_MAP_REGION = {9033}; + + @Inject + private Notifier notifier; + + @Inject + private ClientUI gui; + + @Inject + private Client client; + + @Inject + private NightmareZoneConfig config; + + @Inject + private NightmareZoneOverlay overlay; + + // This starts as true since you need to get + // above the threshold before sending notifications + private boolean absorptionNotificationSend = true; + + @Provides + NightmareZoneConfig getConfig(ConfigManager configManager) + { + return configManager.getConfig(NightmareZoneConfig.class); + } + + @Override + public void configure(Binder binder) + { + binder.bind(NightmareZoneOverlay.class); + } + + @Override + public Overlay getOverlay() + { + return overlay; + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (!config.enabled() || !isInNightmareZone()) + { + return; + } + if (config.absorptionNotification()) + { + checkAbsorption(); + } + } + + @Subscribe + public void onChatMessage(ChatMessage event) + { + if (!config.enabled() + || event.getType() != ChatMessageType.SERVER + || !isInNightmareZone() + || !config.overloadNotification()) + { + return; + } + + String msg = event.getMessage().replaceAll("<[^>]*>", " "); //remove color and linebreaks + if (msg.contains("The effects of overload have worn off, and you feel normal again.")) + { + sendNotification("Your overload has worn off"); + } + } + + private void checkAbsorption() + { + int absorptionPoints = client.getSetting(Varbits.NMZ_ABSORPTION); + + if (!absorptionNotificationSend) + { + if (absorptionPoints < config.absorptionThreshold()) + { + sendNotification("Absorption points below: " + config.absorptionThreshold()); + absorptionNotificationSend = true; + } + } + else + { + if (absorptionPoints > config.absorptionThreshold()) + { + absorptionNotificationSend = false; + } + } + } + + public boolean isInNightmareZone() + { + return Arrays.equals(client.getMapRegions(), NMZ_MAP_REGION); + } + + private void sendNotification(String message) + { + if (!gui.isFocused() && config.requestFocus()) + { + gui.requestFocus(); + } + if (config.sendTrayNotification()) + { + notifier.notify(message); + } + } +}