From 05fdc2877d7e28b8f527bd22901c95490ece48b9 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 13 Apr 2019 10:34:00 -0400 Subject: [PATCH] clue plugin: add music clues Co-authored-by: Hydrox6 --- .../net/runelite/api/widgets/WidgetID.java | 7 ++ .../net/runelite/api/widgets/WidgetInfo.java | 3 + .../cluescrolls/ClueScrollMusicOverlay.java | 102 ++++++++++++++++ .../plugins/cluescrolls/ClueScrollPlugin.java | 11 ++ .../plugins/cluescrolls/clues/MusicClue.java | 109 ++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollMusicOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java 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 d56fa63c6c..f5ac6f4d8a 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 @@ -128,6 +128,7 @@ public class WidgetID public static final int QUESTLIST_GROUP_ID = 399; public static final int SKILLS_GROUP_ID = 320; public static final int QUESTTAB_GROUP_ID = 629; + public static final int MUSIC_GROUP_ID = 239; static class WorldMap { @@ -764,4 +765,10 @@ public class WidgetID { static final int QUEST_TAB = 3; } + + static class Music + { + static final int CONTAINER = 0; + static final int LIST = 3; + } } 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 db8c9e59e4..01ba6a0e49 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 @@ -76,6 +76,9 @@ public enum WidgetInfo EMOTE_WINDOW(WidgetID.EMOTES_GROUP_ID, WidgetID.Emotes.EMOTE_WINDOW), EMOTE_CONTAINER(WidgetID.EMOTES_GROUP_ID, WidgetID.Emotes.EMOTE_CONTAINER), + MUSIC_WINDOW(WidgetID.MUSIC_GROUP_ID, WidgetID.Music.CONTAINER), + MUSIC_TRACK_LIST(WidgetID.MUSIC_GROUP_ID, WidgetID.Music.LIST), + DIARY_QUEST_WIDGET_TITLE(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TITLE), DIARY_QUEST_WIDGET_TEXT(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TEXT), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollMusicOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollMusicOverlay.java new file mode 100644 index 0000000000..f220399f72 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollMusicOverlay.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019, Hydrox6 + * 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.cluescrolls; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.plugins.cluescrolls.clues.ClueScroll; +import net.runelite.client.plugins.cluescrolls.clues.MusicClue; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayLayer; +import net.runelite.client.ui.overlay.OverlayPosition; + +class ClueScrollMusicOverlay extends Overlay +{ + private static final Rectangle PADDING = new Rectangle(2, 1, 0, 1); + + private final ClueScrollPlugin plugin; + private final Client client; + + @Inject + private ClueScrollMusicOverlay(ClueScrollPlugin plugin, Client client) + { + setPosition(OverlayPosition.DYNAMIC); + setLayer(OverlayLayer.ABOVE_WIDGETS); + this.plugin = plugin; + this.client = client; + } + + @Override + public Dimension render(Graphics2D graphics) + { + ClueScroll clue = plugin.getClue(); + + if (!(clue instanceof MusicClue)) + { + return null; + } + + MusicClue musicClue = (MusicClue) clue; + + Widget musicContainer = client.getWidget(WidgetInfo.MUSIC_WINDOW); + + if (musicContainer == null || musicContainer.isHidden()) + { + return null; + } + + Widget trackList = client.getWidget(WidgetInfo.MUSIC_TRACK_LIST); + String trackToFind = musicClue.getSong(); + Widget found = null; + + if (trackList == null) + { + return null; + } + + for (Widget track : trackList.getDynamicChildren()) + { + if (track.getText().equals(trackToFind)) + { + found = track; + break; + } + } + + if (found == null) + { + return null; + } + + plugin.highlightWidget(graphics, found, trackList, PADDING, null); + + return null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java index 7a00f88c73..3231b8277d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/ClueScrollPlugin.java @@ -85,6 +85,7 @@ import net.runelite.client.plugins.cluescrolls.clues.HotColdClue; import net.runelite.client.plugins.cluescrolls.clues.LocationClueScroll; import net.runelite.client.plugins.cluescrolls.clues.LocationsClueScroll; import net.runelite.client.plugins.cluescrolls.clues.MapClue; +import net.runelite.client.plugins.cluescrolls.clues.MusicClue; import net.runelite.client.plugins.cluescrolls.clues.NpcClueScroll; import net.runelite.client.plugins.cluescrolls.clues.ObjectClueScroll; import net.runelite.client.plugins.cluescrolls.clues.TextClueScroll; @@ -139,6 +140,9 @@ public class ClueScrollPlugin extends Plugin @Inject private ClueScrollEmoteOverlay clueScrollEmoteOverlay; + @Inject + private ClueScrollMusicOverlay clueScrollMusicOverlay; + @Inject private ClueScrollWorldOverlay clueScrollWorldOverlay; @@ -173,6 +177,7 @@ public class ClueScrollPlugin extends Plugin overlayManager.add(clueScrollOverlay); overlayManager.add(clueScrollEmoteOverlay); overlayManager.add(clueScrollWorldOverlay); + overlayManager.add(clueScrollMusicOverlay); } @Override @@ -181,6 +186,7 @@ public class ClueScrollPlugin extends Plugin overlayManager.remove(clueScrollOverlay); overlayManager.remove(clueScrollEmoteOverlay); overlayManager.remove(clueScrollWorldOverlay); + overlayManager.remove(clueScrollMusicOverlay); npcsToMark.clear(); inventoryItems = null; equippedItems = null; @@ -469,6 +475,11 @@ public class ClueScrollPlugin extends Plugin return CipherClue.forText(text); } + if (text.startsWith("i'd like to hear some music.")) + { + return MusicClue.forText(clueScrollText.getText()); + } + if (text.contains("degrees") && text.contains("minutes")) { return coordinatesToWorldPoint(text); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java new file mode 100644 index 0000000000..d3a1400c20 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MusicClue.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019, Hydrox6 + * 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.cluescrolls.clues; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.Getter; +import net.runelite.api.NPC; +import net.runelite.api.coords.WorldPoint; +import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR; +import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin; +import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET; +import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.ui.overlay.components.LineComponent; +import net.runelite.client.ui.overlay.components.PanelComponent; +import net.runelite.client.ui.overlay.components.TitleComponent; + +@Getter +public class MusicClue extends ClueScroll implements NpcClueScroll +{ + private static final WorldPoint LOCATION = new WorldPoint(2990, 3384, 0); + private static final String CECILIA = "Cecilia"; + private static final Pattern SONG_PATTERN = Pattern.compile("([A-Za-z !&',.]+)"); + + private final String song; + + private MusicClue(String song) + { + this.song = song; + } + + @Override + public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin) + { + panelComponent.getChildren().add(TitleComponent.builder().text("Music Clue").build()); + panelComponent.getChildren().add(LineComponent.builder().left("NPC:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(CECILIA) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + + panelComponent.getChildren().add(LineComponent.builder().left("Area:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left("Falador Park") + .leftColor(TITLED_CONTENT_COLOR) + .build()); + + panelComponent.getChildren().add(LineComponent.builder().left("Song:").build()); + panelComponent.getChildren().add(LineComponent.builder() + .left(song) + .leftColor(TITLED_CONTENT_COLOR) + .build()); + } + + @Override + public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin) + { + if (!LOCATION.isInScene(plugin.getClient())) + { + return; + } + + for (NPC npc : plugin.getNpcsToMark()) + { + OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET); + } + } + + @Override + public String[] getNpcs() + { + return new String[] {CECILIA}; + } + + public static MusicClue forText(String text) + { + final Matcher m = SONG_PATTERN.matcher(text); + if (m.find()) + { + final String song = m.group(1); + return new MusicClue(song); + } + return null; + } +}