From b5124659bc121d5b4f54d78ddaf55105fe678233 Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Tue, 23 Jul 2019 22:57:22 +0200 Subject: [PATCH] stonedloottracker: Update plugin And fix that ugly reset icon in the regular loot tracker --- .../plugins/loottracker/LootTrackerPanel.java | 2 +- .../loottracker/LootTrackerPlugin.java | 116 ++- .../localstorage/LTItemEntry.java} | 54 +- .../localstorage/LTRecord.java} | 35 +- .../localstorage}/LootRecordWriter.java | 155 ++- .../localstorage/events/LTNameChange.java} | 4 +- .../localstorage/events/LTRecordStored.java} | 8 +- .../StonedLootTrackerPlugin.java | 717 -------------- .../stonedloottracker/data/LootRecord.java | 62 -- .../data/LootRecordCustom.java | 111 --- .../plugins/stonedloottracker/data/Pet.java | 74 -- .../stonedloottracker/data/UniqueItem.java | 931 ------------------ .../stonedloottracker/ui/LootPanel.java | 301 ------ .../stonedloottracker/ui/LootTrackerBox.java | 293 ------ .../ItemSortTypes.java | 8 +- .../StonedTrackerConfig.java} | 69 +- .../stonedtracker/StonedTrackerPlugin.java | 271 +++++ .../data/BossTab.java | 110 +-- .../stonedtracker/data/UniqueItem.java | 897 +++++++++++++++++ .../ui/ItemPanel.java | 83 +- .../ui/LootGrid.java | 40 +- .../plugins/stonedtracker/ui/LootPanel.java | 302 ++++++ .../ui/LootTrackerPanel.java | 154 ++- .../ui/SelectionPanel.java | 210 ++-- .../ui/TextPanel.java | 50 +- .../ui/UniqueItemPanel.java | 92 +- .../delete-white.png | Bin .../client/plugins/loottracker/reset.png | Bin 275 -> 0 bytes .../stonedloottracker/back-arrow-white.png | Bin 128 -> 0 bytes .../stonedloottracker/grouped_loot_icon.png | Bin 15596 -> 0 bytes .../stonedloottracker/invisible_icon.png | Bin 398 -> 0 bytes .../stonedloottracker/single_loot_icon.png | Bin 15393 -> 0 bytes .../stonedloottracker/visible_icon.png | Bin 312 -> 0 bytes .../back-arrow-white.png} | Bin .../plugins/stonedtracker/delete-white.png | Bin 0 -> 139 bytes .../panel-icon.png} | Bin .../refresh-white.png | Bin .../replay-white.png | Bin 38 files changed, 2102 insertions(+), 3047 deletions(-) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker/data/LootTrackerItemEntry.java => loottracker/localstorage/LTItemEntry.java} (61%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker/data/UniqueItemPrepared.java => loottracker/localstorage/LTRecord.java} (66%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker/data => loottracker/localstorage}/LootRecordWriter.java (52%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker/data/events/LootTrackerNameChange.java => loottracker/localstorage/events/LTNameChange.java} (93%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker/data/events/LootTrackerRecordStored.java => loottracker/localstorage/events/LTRecordStored.java} (86%) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/StonedLootTrackerPlugin.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecord.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecordCustom.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/Pet.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/UniqueItem.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootPanel.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootTrackerBox.java rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/ItemSortTypes.java (64%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker/StonedLootTrackerConfig.java => stonedtracker/StonedTrackerConfig.java} (73%) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/StonedTrackerPlugin.java rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/data/BossTab.java (60%) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/data/UniqueItem.java rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/ui/ItemPanel.java (64%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/ui/LootGrid.java (75%) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootPanel.java rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/ui/LootTrackerPanel.java (63%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/ui/SelectionPanel.java (54%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/ui/TextPanel.java (71%) rename runelite-client/src/main/java/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/ui/UniqueItemPanel.java (58%) rename runelite-client/src/main/resources/net/runelite/client/plugins/{stonedloottracker => loottracker}/delete-white.png (100%) delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/loottracker/reset.png delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/back-arrow-white.png delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/grouped_loot_icon.png delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/invisible_icon.png delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/single_loot_icon.png delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/visible_icon.png rename runelite-client/src/main/resources/net/runelite/client/plugins/{stonedloottracker/back_icon.png => stonedtracker/back-arrow-white.png} (100%) create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/delete-white.png rename runelite-client/src/main/resources/net/runelite/client/plugins/{stonedloottracker/panel_icon.png => stonedtracker/panel-icon.png} (100%) rename runelite-client/src/main/resources/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/refresh-white.png (100%) rename runelite-client/src/main/resources/net/runelite/client/plugins/{stonedloottracker => stonedtracker}/replay-white.png (100%) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java index 6ea60ecc2a..addffcee41 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPanel.java @@ -132,7 +132,7 @@ class LootTrackerPanel extends PluginPanel final BufferedImage backArrowImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "back_icon.png"); final BufferedImage visibleImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "visible_icon.png"); final BufferedImage invisibleImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "invisible_icon.png"); - final BufferedImage resetImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "reset.png"); + final BufferedImage resetImg = ImageUtil.getResourceStreamFromClass(LootTrackerPlugin.class, "delete-white.png"); SINGLE_LOOT_VIEW = new ImageIcon(singleLootImg); SINGLE_LOOT_VIEW_FADED = new ImageIcon(ImageUtil.alphaOffset(singleLootImg, -180)); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java index fde940be1d..68e9278fe6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/LootTrackerPlugin.java @@ -46,6 +46,7 @@ import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -101,6 +102,9 @@ import net.runelite.client.game.ItemStack; import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.loottracker.localstorage.LTItemEntry; +import net.runelite.client.plugins.loottracker.localstorage.LTRecord; +import net.runelite.client.plugins.loottracker.localstorage.LootRecordWriter; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.ImageUtil; @@ -126,6 +130,9 @@ public class LootTrackerPlugin extends Plugin private static final Pattern CLUE_SCROLL_PATTERN = Pattern.compile("You have completed [0-9]+ ([a-z]+) Treasure Trails."); private static final int THEATRE_OF_BLOOD_REGION = 12867; + private static final Pattern BOSS_NAME_NUMBER_PATTERN = Pattern.compile("Your (.*) kill count is: ([0-9]*)."); + private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)"); + // Herbiboar loot handling private static final String HERBIBOAR_LOOTED_MESSAGE = "You harvest herbs from the herbiboar, whereupon it escapes."; private static final String HERBIBOR_EVENT = "Herbiboar"; @@ -174,6 +181,8 @@ public class LootTrackerPlugin extends Plugin private ScheduledExecutorService executor; @Inject private EventBus eventBus; + @Inject + private LootRecordWriter writer; private LootTrackerPanel panel; private NavigationButton navButton; private String eventType; @@ -185,6 +194,8 @@ public class LootTrackerPlugin extends Plugin @Getter(AccessLevel.PACKAGE) private LootTrackerClient lootTrackerClient; + private Map killCountMap = new HashMap<>(); + private static Collection stack(Collection items) { final List list = new ArrayList<>(); @@ -412,6 +423,35 @@ public class LootTrackerPlugin extends Plugin { chestLooted = false; } + + if (event.getGameState() == GameState.LOGGING_IN) + { + clientThread.invokeLater(() -> + { + switch (client.getGameState()) + { + case LOGGED_IN: + break; + case LOGGING_IN: + case LOADING: + return false; + default: + // Quit running if any other state + return true; + } + + String name = client.getLocalPlayer().getName(); + if (name != null) + { + writer.setPlayerUsername(name); + return true; + } + else + { + return false; + } + }); + } } private void onNpcLootReceived(final NpcLootReceived npcLootReceived) @@ -423,6 +463,8 @@ public class LootTrackerPlugin extends Plugin final LootTrackerItem[] entries = buildEntries(stack(items)); String localUsername = client.getLocalPlayer().getName(); + final int killCount = killCountMap.getOrDefault(name.toUpperCase(), -1); + if (this.whitelistEnabled) { final String configNpcs = this.getWhitelist.toLowerCase(); @@ -454,6 +496,9 @@ public class LootTrackerPlugin extends Plugin { saveLocalLootRecord(lootRecord); } + + LTRecord record = new LTRecord(npc.getId(), npc.getName(), combat, killCount, convertToLTItemEntries(items)); + writer.addLootTrackerRecord(record); } private void onPlayerSpawned(PlayerSpawned event) @@ -496,6 +541,9 @@ public class LootTrackerPlugin extends Plugin { saveLocalLootRecord(lootRecord); } + + LTRecord record = new LTRecord(-1, name, combat, -1, convertToLTItemEntries(items)); + writer.addLootTrackerRecord(record); } private void onWidgetLoaded(WidgetLoaded event) @@ -590,6 +638,8 @@ public class LootTrackerPlugin extends Plugin LootRecord lootRecord = new LootRecord(eventType, client.getLocalPlayer().getName(), LootRecordType.EVENT, toGameItems(items), Instant.now()); + final int killCount = killCountMap.getOrDefault(eventType.toUpperCase(), -1); + if (lootTrackerClient != null && this.saveLoot) { lootTrackerClient.submit(lootRecord); @@ -598,6 +648,9 @@ public class LootTrackerPlugin extends Plugin { saveLocalLootRecord(lootRecord); } + + LTRecord record = new LTRecord(-1, eventType, -1, killCount, convertToLTItemEntries(items)); + writer.addLootTrackerRecord(record); } private void onChatMessage(ChatMessage event) @@ -631,8 +684,11 @@ public class LootTrackerPlugin extends Plugin return; } + // Remove all tags + final String chatMessage = Text.removeTags(message); + // Check if message is for a clue scroll reward - final Matcher m = CLUE_SCROLL_PATTERN.matcher(Text.removeTags(message)); + final Matcher m = CLUE_SCROLL_PATTERN.matcher(chatMessage); if (m.find()) { final String type = m.group(1).toLowerCase(); @@ -657,6 +713,50 @@ public class LootTrackerPlugin extends Plugin eventType = "Clue Scroll (Master)"; break; } + + int killCount = Integer.valueOf(m.group(1)); + killCountMap.put(eventType.toUpperCase(), killCount); + return; + } + + // Barrows KC + if (chatMessage.startsWith("Your Barrows chest count is")) + { + Matcher n = NUMBER_PATTERN.matcher(chatMessage); + if (n.find()) + { + killCountMap.put("BARROWS", Integer.valueOf(n.group())); + return; + } + } + + // Raids KC + if (chatMessage.startsWith("Your completed Chambers of Xeric count is")) + { + Matcher n = NUMBER_PATTERN.matcher(chatMessage); + if (n.find()) + { + killCountMap.put("CHAMBERS OF XERIC", Integer.valueOf(n.group())); + return; + } + } + // Raids KC + if (chatMessage.startsWith("Your completed Theatre of Blood count is")) + { + Matcher n = NUMBER_PATTERN.matcher(chatMessage); + if (n.find()) + { + killCountMap.put("THEATRE OF BLOOD", Integer.valueOf(n.group())); + return; + } + } + // Handle all other boss + Matcher boss = BOSS_NAME_NUMBER_PATTERN.matcher(chatMessage); + if (boss.find()) + { + String bossName = boss.group(1); + int killCount = Integer.valueOf(boss.group(2)); + killCountMap.put(bossName.toUpperCase(), killCount); } } @@ -825,6 +925,9 @@ public class LootTrackerPlugin extends Plugin saveLocalLootRecord(lootRecord); } + LTRecord record = new LTRecord(-1, chestType, -1, -1, convertToLTItemEntries(items)); + writer.addLootTrackerRecord(record); + inventorySnapshot = null; } } @@ -931,6 +1034,17 @@ public class LootTrackerPlugin extends Plugin return trackerRecords; } + private Collection convertToLTItemEntries(Collection stacks) + { + return stacks.stream().map(i -> + { + final ItemDefinition c = itemManager.getItemDefinition(i.getId()); + final int id = c.getNote() == -1 ? c.getId() : c.getLinkedNoteId(); + final int price = itemManager.getItemPrice(id); + return new LTItemEntry(c.getName(), i.getId(), i.getQuantity(), price); + }).collect(Collectors.toList()); + } + private void updateConfig() { this.getIgnoredItems = config.getIgnoredItems(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootTrackerItemEntry.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LTItemEntry.java similarity index 61% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootTrackerItemEntry.java rename to runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LTItemEntry.java index 5d764ac750..8fac07f376 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootTrackerItemEntry.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LTItemEntry.java @@ -23,38 +23,48 @@ * (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.stonedloottracker.data; +package net.runelite.client.plugins.loottracker.localstorage; -import lombok.AccessLevel; -import lombok.Getter; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Data; -@Getter(AccessLevel.PUBLIC) -public class LootTrackerItemEntry +@Data +@AllArgsConstructor +public class LTItemEntry { private final String name; private final int id; private int quantity; - private final long price; - private final long haPrice; - private long total; - private long haTotal; - private final boolean stackable; + private long price; - public LootTrackerItemEntry(final String name, final int id, final int quantity, final long price, final long haPrice, final boolean stackable) + public long getTotal() { - this.name = name; - this.id = id; - this.quantity = quantity; - this.price = price; - this.haPrice = haPrice; - this.stackable = stackable; - this.total = price * quantity; - this.haTotal = haPrice * quantity; + return this.quantity * this.price; } - @Override - public String toString() + public static Map consolidateItemEntires(final Collection drops) { - return "LootTrackerItemEntry(name=" + name + ",id=" + id + ",quantity=" + quantity + ",price=" + price + ",haprice=" + haPrice + ",total=" + total + ",haTotal=" + haTotal + ",stackable=" + stackable + ")"; + // Store LootTrackerItemEntry by ItemID + final Map itemMap = new HashMap<>(); + for (final LTItemEntry e : drops) + { + final LTItemEntry oldEntry = itemMap.get(e.getId()); + if (oldEntry != null) + { + // Use the most recent price + oldEntry.setPrice(e.getPrice()); + oldEntry.setQuantity(oldEntry.getQuantity() + e.getQuantity()); + } + else + { + // Create a new instance for consolidated records + itemMap.put(e.getId(), new LTItemEntry(e.getName(), e.getId(), e.getQuantity(), e.getPrice())); + } + } + + return itemMap; } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/UniqueItemPrepared.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LTRecord.java similarity index 66% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/UniqueItemPrepared.java rename to runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LTRecord.java index b82fd0936a..da6518593b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/UniqueItemPrepared.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LTRecord.java @@ -22,14 +22,35 @@ * (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.stonedloottracker.data; +package net.runelite.client.plugins.loottracker.localstorage; -import lombok.Value; +import java.util.ArrayList; +import java.util.Collection; +import lombok.AllArgsConstructor; +import lombok.Data; -@Value -public class UniqueItemPrepared +@Data +@AllArgsConstructor +public class LTRecord { - private int linkedID; - private int price; - private UniqueItem uniqueItem; + private final int id; + private final String name; + private final int level; + private final int killCount; + final Collection drops; + + public void addDropEntry(LTItemEntry itemEntry) + { + drops.add(itemEntry); + } + + public static Collection consolidateLTItemEntries(final Collection records) + { + final Collection recordEntries = new ArrayList<>(); + for (final LTRecord r : records) + { + recordEntries.addAll(r.getDrops()); + } + return recordEntries; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecordWriter.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LootRecordWriter.java similarity index 52% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecordWriter.java rename to runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LootRecordWriter.java index 7b9f74b2f7..18cbfb2c90 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecordWriter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/LootRecordWriter.java @@ -22,7 +22,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.stonedloottracker.data; +package net.runelite.client.plugins.loottracker.localstorage; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -41,8 +41,8 @@ import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import static net.runelite.client.RuneLite.RUNELITE_DIR; import net.runelite.client.eventbus.EventBus; -import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerNameChange; -import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerRecordStored; +import net.runelite.client.plugins.loottracker.localstorage.events.LTNameChange; +import net.runelite.client.plugins.loottracker.localstorage.events.LTRecordStored; import net.runelite.http.api.RuneLiteAPI; @Slf4j @@ -52,38 +52,45 @@ public class LootRecordWriter private static final String FILE_EXTENSION = ".log"; private static final File LOOT_RECORD_DIR = new File(RUNELITE_DIR, "loots"); + private final EventBus bus; + // Data is stored in a folder with the players in-game username private File playerFolder = LOOT_RECORD_DIR; - - private final EventBus bus; + private String name; @Inject public LootRecordWriter(EventBus bus) { this.bus = bus; - playerFolder.mkdir(); + LOOT_RECORD_DIR.mkdir(); } - private static String npcNameToFileName(String npcName) + private static String npcNameToFileName(final String npcName) { return npcName.toLowerCase().trim() + FILE_EXTENSION; } - public void setPlayerUsername(String username) + public void setPlayerUsername(final String username) { + if (username.equalsIgnoreCase(name)) + { + return; + } + playerFolder = new File(LOOT_RECORD_DIR, username); playerFolder.mkdir(); - bus.post(LootTrackerNameChange.class, new LootTrackerNameChange()); + name = username; + bus.post(LTNameChange.class, new LTNameChange()); } public Set getKnownFileNames() { - Set fileNames = new HashSet<>(); + final Set fileNames = new HashSet<>(); - File[] files = playerFolder.listFiles((dir, name) -> name.endsWith(FILE_EXTENSION)); + final File[] files = playerFolder.listFiles((dir, name) -> name.endsWith(FILE_EXTENSION)); if (files != null) { - for (File f : files) + for (final File f : files) { fileNames.add(f.getName().replace(FILE_EXTENSION, "")); } @@ -92,25 +99,29 @@ public class LootRecordWriter return fileNames; } - public synchronized Collection loadLootTrackerRecords(String npcName) + public synchronized Collection loadLootTrackerRecords(String npcName) { - String fileName = npcNameToFileName(npcName); - File file = new File(playerFolder, fileName); - Collection data = new ArrayList<>(); + final String fileName = npcNameToFileName(npcName); + final File file = new File(playerFolder, fileName); + final Collection data = new ArrayList<>(); - try (BufferedReader br = new BufferedReader(new FileReader(file))) + StringBuilder sb = new StringBuilder(); + + try (final BufferedReader br = new BufferedReader(new FileReader(file))) { + + // read line by line String line; while ((line = br.readLine()) != null) { - // Skip empty line at end of file - if (line.length() > 0) - { - LootRecordCustom r = RuneLiteAPI.GSON.fromJson(line, LootRecordCustom.class); - data.add(r); - } + sb.append(line).append("\n"); } + if (sb.length() > 0) + { + final LTRecord r = RuneLiteAPI.GSON.fromJson(sb.toString(), LTRecord.class); + data.add(r); + } } catch (FileNotFoundException e) { @@ -124,135 +135,85 @@ public class LootRecordWriter return data; } - public synchronized void addLootTrackerRecord(LootRecordCustom rec) + public synchronized boolean addLootTrackerRecord(LTRecord rec) { // Grab file - String fileName = npcNameToFileName(rec.getName()); - File lootFile = new File(playerFolder, fileName); + final String fileName = npcNameToFileName(rec.getName()); + final File lootFile = new File(playerFolder, fileName); // Convert entry to JSON - String dataAsString = RuneLiteAPI.GSON.toJson(rec); + final String dataAsString = RuneLiteAPI.GSON.toJson(rec); // Open File in append mode and write new data try { - BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), true)); + final BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), true)); file.append(dataAsString); file.newLine(); file.close(); - bus.post(LootTrackerRecordStored.class, new LootTrackerRecordStored(rec)); + bus.post(LTRecordStored.class, new LTRecordStored(rec)); + return true; } catch (IOException ioe) { log.warn("Error writing loot data to file {}: {}", fileName, ioe.getMessage()); + return false; } } // Mostly used to adjust previous loot entries such as adding pet drops/abyssal sire drops - public synchronized void writeLootTrackerFile(String npcName, Collection loots) + public synchronized boolean writeLootTrackerFile(String npcName, Collection loots) { - String fileName = npcNameToFileName(npcName); - File lootFile = new File(playerFolder, fileName); + final String fileName = npcNameToFileName(npcName); + final File lootFile = new File(playerFolder, fileName); try { - BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), false)); - for (LootRecordCustom rec : loots) + final BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), false)); + for (final LTRecord rec : loots) { // Convert entry to JSON - String dataAsString = RuneLiteAPI.GSON.toJson(rec); + final String dataAsString = RuneLiteAPI.GSON.toJson(rec); file.append(dataAsString); file.newLine(); } file.close(); + return true; } catch (IOException ioe) { log.warn("Error rewriting loot data to file {}: {}", fileName, ioe.getMessage()); + return false; } } - public synchronized void deleteLootTrackerRecords(String npcName) + public synchronized boolean deleteLootTrackerRecords(String npcName) { - String fileName = npcNameToFileName(npcName); - - File lootFile = new File(playerFolder, fileName); + final String fileName = npcNameToFileName(npcName); + final File lootFile = new File(playerFolder, fileName); if (lootFile.delete()) { log.debug("Deleted loot file: {}", fileName); + return true; } else { log.debug("Couldn't delete file: {}", fileName); + return false; } } - public Collection loadAllLootTrackerRecords() + public Collection loadAllLootTrackerRecords() { - List recs = new ArrayList<>(); + final List recs = new ArrayList<>(); - for (String n : getKnownFileNames()) + for (final String n : getKnownFileNames()) { recs.addAll(loadLootTrackerRecords(n)); } return recs; } - - public void convertFileFormats() - { - for (String f : getKnownFileNames()) - { - updateFileFormat(npcNameToFileName(f)); - } - log.info("Done converting"); - } - - private void updateFileFormat(String fileName) - { - File lootFile = new File(playerFolder, fileName); - Collection data = new ArrayList<>(); - - try (BufferedReader br = new BufferedReader(new FileReader(lootFile))) - { - String line; - while ((line = br.readLine()) != null) - { - // Skip empty line at end of file - if (line.length() > 0) - { - LootRecordCustom r = RuneLiteAPI.GSON.fromJson(line, LootRecord.class).toNewFormat(); - data.add(r); - } - } - - } - catch (FileNotFoundException e) - { - log.info("File not found: {}", fileName); - } - catch (IOException e) - { - log.warn("IOException for file {}: {}", fileName, e.getMessage()); - } - - try - { - BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), false)); - for (LootRecordCustom rec : data) - { - // Convert entry to JSON - String dataAsString = RuneLiteAPI.GSON.toJson(rec); - file.append(dataAsString); - file.newLine(); - } - file.close(); - } - catch (IOException ioe) - { - log.warn("Error rewriting loot data to file {}: {}", fileName, ioe.getMessage()); - } - } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/events/LootTrackerNameChange.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/events/LTNameChange.java similarity index 93% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/events/LootTrackerNameChange.java rename to runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/events/LTNameChange.java index 679344dd6e..c5b166aacd 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/events/LootTrackerNameChange.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/events/LTNameChange.java @@ -22,8 +22,8 @@ * (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.stonedloottracker.data.events; +package net.runelite.client.plugins.loottracker.localstorage.events; -public class LootTrackerNameChange +public class LTNameChange { } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/events/LootTrackerRecordStored.java b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/events/LTRecordStored.java similarity index 86% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/events/LootTrackerRecordStored.java rename to runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/events/LTRecordStored.java index 48b63b504f..31c4da4426 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/events/LootTrackerRecordStored.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/loottracker/localstorage/events/LTRecordStored.java @@ -22,13 +22,13 @@ * (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.stonedloottracker.data.events; +package net.runelite.client.plugins.loottracker.localstorage.events; import lombok.Data; -import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom; +import net.runelite.client.plugins.loottracker.localstorage.LTRecord; @Data -public class LootTrackerRecordStored +public class LTRecordStored { - private final LootRecordCustom record; + private final LTRecord record; } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/StonedLootTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/StonedLootTrackerPlugin.java deleted file mode 100644 index edae7b42d1..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/StonedLootTrackerPlugin.java +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (c) 2018, Psikoi - * Copyright (c) 2018, Adam - * 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.stonedloottracker; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multiset; -import com.google.common.collect.Multisets; -import com.google.inject.Provides; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import javax.inject.Inject; -import javax.inject.Singleton; -import javax.swing.SwingUtilities; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.ChatMessageType; -import net.runelite.api.Client; -import net.runelite.api.GameState; -import net.runelite.api.InventoryID; -import net.runelite.api.ItemDefinition; -import net.runelite.api.ItemContainer; -import net.runelite.api.NPC; -import net.runelite.api.NpcID; -import net.runelite.api.Player; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.ChatMessage; -import net.runelite.api.events.ConfigChanged; -import net.runelite.api.events.GameStateChanged; -import net.runelite.api.events.ItemContainerChanged; -import net.runelite.api.events.WidgetLoaded; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetID; -import net.runelite.api.widgets.WidgetInfo; -import net.runelite.client.callback.ClientThread; -import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.EventBus; -import net.runelite.client.events.NpcLootReceived; -import net.runelite.client.events.PlayerLootReceived; -import net.runelite.client.game.ItemManager; -import net.runelite.client.game.ItemStack; -import net.runelite.client.plugins.Plugin; -import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.PluginType; -import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom; -import net.runelite.client.plugins.stonedloottracker.data.LootRecordWriter; -import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry; -import net.runelite.client.plugins.stonedloottracker.data.Pet; -import net.runelite.client.plugins.stonedloottracker.data.UniqueItem; -import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared; -import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerNameChange; -import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerRecordStored; -import net.runelite.client.plugins.stonedloottracker.ui.LootTrackerPanel; -import net.runelite.client.ui.ClientToolbar; -import net.runelite.client.ui.NavigationButton; -import net.runelite.client.util.ImageUtil; -import net.runelite.client.util.Text; - -@PluginDescriptor( - name = "Stoned Loot Tracker", - description = "Tracks loot from monsters and minigames", - tags = {"drops"}, - type = PluginType.UTILITY, - enabledByDefault = false -) -@Singleton -@Slf4j -public class StonedLootTrackerPlugin extends Plugin -{ - // Activity/Event loot handling - private static final Pattern CLUE_SCROLL_PATTERN = Pattern.compile("You have completed ([0-9]+) ([a-z]+) Treasure Trails."); - private static final Pattern BOSS_NAME_NUMBER_PATTERN = Pattern.compile("Your (.*) kill count is: ([0-9]*)."); - private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)"); - private static final ImmutableList PET_MESSAGES = ImmutableList.of("You have a funny feeling like you're being followed", - "You feel something weird sneaking into your backpack", - "You have a funny feeling like you would have been followed"); - private static final int THEATRE_OF_BLOOD_REGION = 12867; - - // Herbiboar loot handling - private static final String HERBIBOAR_LOOTED_MESSAGE = "Your herbiboar harvest count is"; - private static final String HERBIBOR_EVENT = "Herbiboar"; - - // Chest loot handling - private static final String CHEST_LOOTED_MESSAGE = "You find some treasure in the chest!"; - private static final Map CHEST_EVENT_TYPES = ImmutableMap.of( - 5179, "Brimstone Chest", - 11573, "Crystal Chest" - ); - - @Inject - private ClientToolbar clientToolbar; - - @Inject - private ItemManager itemManager; - - @Inject - private Client client; - - @Inject - public StonedLootTrackerConfig config; - - @Inject - private ClientThread clientThread; - - @Inject - private LootRecordWriter writer; - - @Inject - private EventBus eventBus; - - private Multiset inventorySnapshot; - - @Provides - StonedLootTrackerConfig provideConfig(ConfigManager configManager) - { - return configManager.getConfig(StonedLootTrackerConfig.class); - } - - private void onConfigChanged(ConfigChanged event) - { - if (event.getGroup().equals("stonedloottracker")) - { - panel.refreshUI(); - } - } - - private LootTrackerPanel panel; - private NavigationButton navButton; - private String eventType; - - private final Multimap lootRecordMultimap = ArrayListMultimap.create(); - private final Multimap uniques = ArrayListMultimap.create(); - private final Map killCountMap = new HashMap<>(); - - // key = name, value=current killCount - private boolean loaded = false; - private boolean gotPet = false; - - @Override - protected void startUp() throws Exception - { - addSubscriptions(); - - panel = new LootTrackerPanel(itemManager, this); - - final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "panel_icon.png"); - - navButton = NavigationButton.builder() - .tooltip("Stoned Loot Tracker") - .icon(icon) - .priority(5) - .panel(panel) - .build(); - - clientToolbar.addNavigation(navButton); - - if (!loaded) - { - clientThread.invokeLater(() -> - { - switch (client.getGameState()) - { - case UNKNOWN: - case STARTING: - return false; - } - - prepareUniqueItems(); - return true; - }); - } - } - - private void prepareUniqueItems() - { - loaded = true; - for (UniqueItem i : UniqueItem.values()) - { - ItemDefinition c = itemManager.getItemDefinition(i.getItemID()); - for (String s : i.getActivities()) - { - uniques.put(s.toUpperCase(), new UniqueItemPrepared(c.getLinkedNoteId(), itemManager.getItemPrice(i.getItemID()), i)); - } - } - } - - public Collection getUniques(String name) - { - return uniques.get(name.toUpperCase()); - } - - @Override - protected void shutDown() - { - eventBus.unregister(this); - - clientToolbar.removeNavigation(navButton); - } - - private void addSubscriptions() - { - eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged); - eventBus.subscribe(LootTrackerRecordStored.class, this, this::onLootTrackerRecordStored); - eventBus.subscribe(LootTrackerNameChange.class, this, this::onLootTrackerNameChange); - eventBus.subscribe(NpcLootReceived.class, this, this::onNpcLootReceived); - eventBus.subscribe(PlayerLootReceived.class, this, this::onPlayerLootReceived); - eventBus.subscribe(WidgetLoaded.class, this, this::onWidgetLoaded); - eventBus.subscribe(ChatMessage.class, this, this::onChatMessage); - eventBus.subscribe(ItemContainerChanged.class, this, this::onItemContainerChanged); - eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged); - } - - private void onLootTrackerRecordStored(LootTrackerRecordStored s) - { - SwingUtilities.invokeLater(() -> panel.addLog(s.getRecord())); - } - - - private void onLootTrackerNameChange(LootTrackerNameChange c) - { - refreshData(); - SwingUtilities.invokeLater(() -> panel.updateNames()); - } - - private void onNpcLootReceived(final NpcLootReceived npcLootReceived) - { - final NPC npc = npcLootReceived.getNpc(); - final Collection items = npcLootReceived.getItems(); - final String name = npc.getName().toLowerCase().contains("vet'ion reborn") ? "Vet'ion" : npc.getName(); - final int combat = npc.getCombatLevel(); - final int killCount = killCountMap.getOrDefault(name.toUpperCase(), -1); - final LootTrackerItemEntry[] entries = buildEntries(items); - - if (gotPet) - { - ItemStack pet = handlePet(name); - if (pet == null) - { - log.warn("Error finding pet for npc name: {}", name); - } - else - { - items.add(pet); - } - } - - LootRecordCustom rec = new LootRecordCustom(npc.getId(), name, combat, killCount, Arrays.asList(entries)); - addLog(name, rec); - } - - private void onPlayerLootReceived(final PlayerLootReceived playerLootReceived) - { - final Player player = playerLootReceived.getPlayer(); - final Collection items = playerLootReceived.getItems(); - final String name = player.getName(); - final int combat = player.getCombatLevel(); - final int killCount = killCountMap.getOrDefault(name.toUpperCase(), -1); - final LootTrackerItemEntry[] entries = buildEntries(items); - LootRecordCustom rec = new LootRecordCustom(-1, name, combat, killCount, Arrays.asList(entries)); - addLog(name, rec); - } - - private void onWidgetLoaded(WidgetLoaded event) - { - final ItemContainer container; - switch (event.getGroupId()) - { - case (WidgetID.BARROWS_REWARD_GROUP_ID): - eventType = "Barrows"; - container = client.getItemContainer(InventoryID.BARROWS_REWARD); - break; - case (WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID): - eventType = "Chambers of Xeric"; - container = client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST); - break; - case (WidgetID.THEATRE_OF_BLOOD_REWARD_GROUP_ID): - int region = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID(); - if (region != THEATRE_OF_BLOOD_REGION) - { - return; - } - eventType = "Theatre of Blood"; - container = client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST); - break; - case (WidgetID.CLUE_SCROLL_REWARD_GROUP_ID): - // event type should be set via ChatMessage for clue scrolls. - // Clue Scrolls use same InventoryID as Barrows - container = client.getItemContainer(InventoryID.BARROWS_REWARD); - break; - // Unsired redemption tracking - case (WidgetID.DIALOG_SPRITE_GROUP_ID): - Widget text = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT); - if ("you place the unsired into the font of consumption...".equals(text.getText().toLowerCase())) - { - checkUnsiredWidget(); - } - return; - default: - return; - } - - if (container == null) - { - return; - } - - // Convert container items to array of ItemStack - final Collection items = Arrays.stream(container.getItems()) - .filter(item -> item.getId() > 0) - .map(item -> new ItemStack(item.getId(), item.getQuantity(), client.getLocalPlayer().getLocalLocation())) - .collect(Collectors.toList()); - - if (items.isEmpty()) - { - log.debug("No items to find for Event: {} | Container: {}", eventType, container); - return; - } - - final LootTrackerItemEntry[] entries = buildEntries(items); - final int killCount = killCountMap.getOrDefault(eventType.toUpperCase(), -1); - LootRecordCustom rec = new LootRecordCustom(-1, eventType, -1, killCount, Arrays.asList(entries)); - addLog(eventType, rec); - } - - private void addLog(String name, LootRecordCustom record) - { - lootRecordMultimap.put(name, record); - writer.addLootTrackerRecord(record); - } - - private void onChatMessage(ChatMessage event) - { - if (event.getType() != ChatMessageType.GAMEMESSAGE && event.getType() != ChatMessageType.SPAM) - { - return; - } - - String chatMessage = Text.removeTags(event.getMessage()); - - // Check if message is for a clue scroll reward - final Matcher m = CLUE_SCROLL_PATTERN.matcher(chatMessage); - if (m.find()) - { - final String type = m.group(2).toLowerCase(); - switch (type) - { - case "beginner": - eventType = "Clue Scroll (Beginner)"; - break; - case "easy": - eventType = "Clue Scroll (Easy)"; - break; - case "medium": - eventType = "Clue Scroll (Medium)"; - break; - case "hard": - eventType = "Clue Scroll (Hard)"; - break; - case "elite": - eventType = "Clue Scroll (Elite)"; - break; - case "master": - eventType = "Clue Scroll (Master)"; - break; - } - - - int killCount = Integer.valueOf(m.group(1)); - killCountMap.put(eventType.toUpperCase(), killCount); - return; - } - // TODO: Figure out better way to handle Barrows and Raids/Raids 2 - // Barrows KC - if (chatMessage.startsWith("Your Barrows chest count is")) - { - Matcher n = NUMBER_PATTERN.matcher(chatMessage); - if (n.find()) - { - killCountMap.put("BARROWS", Integer.valueOf(n.group())); - return; - } - } - - // Raids KC - if (chatMessage.startsWith("Your completed Chambers of Xeric count is")) - { - Matcher n = NUMBER_PATTERN.matcher(chatMessage); - if (n.find()) - { - killCountMap.put("RAIDS", Integer.valueOf(n.group())); - return; - } - } - // Raids KC - if (chatMessage.startsWith("Your completed Theatre of Blood count is")) - { - Matcher n = NUMBER_PATTERN.matcher(chatMessage); - if (n.find()) - { - killCountMap.put("THEATRE OF BLOOD", Integer.valueOf(n.group())); - return; - } - } - // Handle all other boss - Matcher boss = BOSS_NAME_NUMBER_PATTERN.matcher(chatMessage); - if (boss.find()) - { - String bossName = boss.group(1); - int killCount = Integer.valueOf(boss.group(2)); - killCountMap.put(bossName.toUpperCase(), killCount); - } - - if (PET_MESSAGES.stream().anyMatch(chatMessage::contains)) - { - gotPet = true; - } - - if (chatMessage.equals(CHEST_LOOTED_MESSAGE)) - { - final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID(); - if (!CHEST_EVENT_TYPES.containsKey(regionID)) - { - return; - } - - eventType = CHEST_EVENT_TYPES.get(regionID); - - takeInventorySnapshot(); - - Matcher n = NUMBER_PATTERN.matcher(chatMessage); - if (n.find()) - { - killCountMap.put(eventType, Integer.valueOf(n.group())); - } - } - - if (chatMessage.startsWith(HERBIBOAR_LOOTED_MESSAGE)) - { - eventType = HERBIBOR_EVENT; - takeInventorySnapshot(); - - Matcher n = NUMBER_PATTERN.matcher(chatMessage); - - if (n.find()) - { - killCountMap.put(HERBIBOR_EVENT, Integer.valueOf(n.group())); - } - } - } - - private void onItemContainerChanged(ItemContainerChanged event) - { - if (eventType != null && (CHEST_EVENT_TYPES.containsValue(eventType) || HERBIBOR_EVENT.equals(eventType))) - { - if (event.getItemContainer() != client.getItemContainer(InventoryID.INVENTORY)) - { - return; - } - - processInventoryLoot(eventType, event.getItemContainer()); - eventType = null; - } - } - - private void takeInventorySnapshot() - { - final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY); - if (itemContainer != null) - { - inventorySnapshot = HashMultiset.create(); - Arrays.stream(itemContainer.getItems()) - .forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity())); - } - } - - private void processInventoryLoot(String eventType, ItemContainer inventoryContainer) - { - if (inventorySnapshot != null) - { - Multiset currentInventory = HashMultiset.create(); - Arrays.stream(inventoryContainer.getItems()) - .forEach(item -> currentInventory.add(item.getId(), item.getQuantity())); - - final Multiset diff = Multisets.difference(currentInventory, inventorySnapshot); - - List items = diff.entrySet().stream() - .map(e -> new ItemStack(e.getElement(), e.getCount(), client.getLocalPlayer().getLocalLocation())) - .collect(Collectors.toList()); - - final LootTrackerItemEntry[] entries = buildEntries(items); - - LootRecordCustom rec = new LootRecordCustom(-1, eventType, -1, killCountMap.getOrDefault(eventType, -1), Arrays.asList(entries)); - addLog(eventType, rec); - - inventorySnapshot = null; - } - } - - private LootTrackerItemEntry[] buildEntries(final Collection itemStacks) - { - return itemStacks.stream().map(itemStack -> - { - final ItemDefinition itemComposition = itemManager.getItemDefinition(itemStack.getId()); - final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemStack.getId(); - final long price = itemManager.getItemPrice(realItemId); - final long haPrice = itemManager.getAlchValue(realItemId); - - return new LootTrackerItemEntry( - itemComposition.getName(), - itemStack.getId(), - itemStack.getQuantity(), - price, - haPrice, - itemComposition.isStackable()); - }).toArray(LootTrackerItemEntry[]::new); - } - - public Collection getData() - { - return lootRecordMultimap.values(); - } - - public Collection getDataByName(String name) - { - return lootRecordMultimap.get(name); - } - - private void refreshData() - { - // Pull data from files - lootRecordMultimap.clear(); - Collection recs = writer.loadAllLootTrackerRecords(); - for (LootRecordCustom r : recs) - { - lootRecordMultimap.put(r.getName(), r); - } - } - - public void refreshDataByName(String name) - { - lootRecordMultimap.removeAll(name); - Collection recs = writer.loadLootTrackerRecords(name); - lootRecordMultimap.putAll(name, recs); - } - - public void clearStoredDataByName(String name) - { - lootRecordMultimap.removeAll(name); - writer.deleteLootTrackerRecords(name); - } - - public Set getNames() - { - return new TreeSet<>(lootRecordMultimap.keySet()); - } - - // Pet Handling - private ItemStack handlePet(String name) - { - gotPet = false; - - int petID = getPetId(name); - if (petID == -1) - { - return null; - } - - return new ItemStack(petID, 1, client.getLocalPlayer().getLocalLocation()); - } - - private int getPetId(String name) - { - Pet pet = Pet.getByBossName(name); - if (pet != null) - { - return pet.getPetID(); - } - return -1; - } - - // Handles adding the unsired loot to the tracker - private void receivedUnsiredLoot(int itemID) - { - clientThread.invokeLater(() -> - { - Collection data = getDataByName("Abyssal sire"); - ItemDefinition c = itemManager.getItemDefinition(itemID); - LootTrackerItemEntry itemEntry = new LootTrackerItemEntry(c.getName(), itemID, 1, 0, 0, false); - - log.debug("Received Unsired item: {}", c.getName()); - - // Don't have data for sire, create a new record with just this data. - if (data == null) - { - log.debug("No previous Abyssal sire loot, creating new loot record"); - LootRecordCustom r = new LootRecordCustom(NpcID.ABYSSAL_SIRE, "Abyssal sire", 350, -1, Collections.singletonList(itemEntry)); - writer.addLootTrackerRecord(r); - return; - } - - log.debug("Adding drop to last abyssal sire loot record"); - // Add data to last kill count - List items = new ArrayList<>(data); - LootRecordCustom r = items.get(items.size() - 1); - r.addDropEntry(itemEntry); - writer.writeLootTrackerFile("Abyssal sire", items); - }); - } - - private boolean unsiredThreadRunning = false; - private int unsiredThreadTries = 0; - - // Handles checking for unsired loot reclamation - private void checkUnsiredWidget() - { - if (unsiredThreadRunning) - { - return; - } - unsiredThreadRunning = true; - unsiredThreadTries = 0; - - clientThread.invokeLater(() -> - { - log.debug("Checking for text widget change..."); - Widget text = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT); - if ("the font consumes the unsired and returns you a reward.".equals(text.getText().toLowerCase())) - { - Widget sprite = client.getWidget(WidgetInfo.DIALOG_SPRITE); - log.debug("Sprite: {}", sprite); - log.debug("Sprite Item ID: {}", sprite.getItemId()); - log.debug("Sprite Model ID: {}", sprite.getModelId()); - receivedUnsiredLoot(sprite.getItemId()); - unsiredThreadRunning = false; - return true; - } - else - { - if (unsiredThreadTries >= 10) - { - log.debug("Tried 10 times, canceling..."); - return true; - } - unsiredThreadTries++; - return false; - } - }); - } - - private void onGameStateChanged(GameStateChanged c) - { - if (c.getGameState().equals(GameState.LOGGED_IN)) - { - clientThread.invokeLater(() -> - { - switch (client.getGameState()) - { - case LOGGED_IN: - break; - case LOGGING_IN: - case LOADING: - return false; - default: - // Quit running if any other state - return true; - } - - String name = client.getLocalPlayer().getName(); - if (name != null) - { - writer.setPlayerUsername(name); - return true; - } - else - { - return false; - } - }); - } - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecord.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecord.java deleted file mode 100644 index 3a8ae0a843..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecord.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2018, TheStonedTurtle - * 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.stonedloottracker.data; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import lombok.AccessLevel; -import lombok.Getter; - -@Getter(AccessLevel.PUBLIC) -@Deprecated -public class LootRecord -{ - private final int id; - private final String name; - private final int level; - private final int killCount; - final Collection drops; - - public LootRecord(final int id, final String name, final int level, final int kc, final Collection drops) - { - this.id = id; - this.name = name; - this.level = level; - this.killCount = kc; - this.drops = (drops == null ? new ArrayList<>() : drops); - } - - LootRecordCustom toNewFormat() - { - List drops = new ArrayList<>(); - for (LootTrackerItemEntry e : this.getDrops()) - { - drops.add(new LootTrackerItemEntry(e.getName(), e.getId(), e.getQuantity(), e.getPrice(), e.getHaPrice(), e.isStackable())); - } - - return new LootRecordCustom(this.getId(), this.getName(), this.getLevel(), this.getKillCount(), drops); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecordCustom.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecordCustom.java deleted file mode 100644 index 2d098b17f3..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/LootRecordCustom.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2018, TheStonedTurtle - * 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.stonedloottracker.data; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import lombok.AccessLevel; -import lombok.Getter; - -@Getter(AccessLevel.PUBLIC) -public class LootRecordCustom -{ - private final int id; - private final String name; - private final int level; - private final int killCount; - final Collection drops; - - public LootRecordCustom(final int id, final String name, final int level, final int kc, final Collection drops) - { - this.id = id; - this.name = name; - this.level = level; - this.killCount = kc; - this.drops = (drops == null ? new ArrayList<>() : drops); - } - - /** - * Add the requested ItemStack to this LootRecord - * @param drop ItemStack to add - */ - public void addDropEntry(LootTrackerItemEntry drop) - { - drops.add(drop); - } - - public static Map consolidateLootTrackerItemEntries(Collection records) - { - // Store LootTrackerItemEntry by ItemID - Map itemMap = new HashMap<>(); - for (LootRecordCustom r : records) - { - for (LootTrackerItemEntry e : r.getDrops()) - { - int old = 0; - if (itemMap.containsKey(e.getId())) - { - old = itemMap.get(e.getId()).getQuantity(); - itemMap.remove(e.getId()); - } - itemMap.put(e.getId(), new LootTrackerItemEntry(e.getName(), e.getId(), e.getQuantity() + old, e.getPrice(), e.getHaPrice(), e.isStackable())); - } - } - - return itemMap; - } - - @Override - public String toString() - { - StringBuilder m = new StringBuilder(); - m.append("LootRecord{id=") - .append(id) - .append(",name=") - .append(name) - .append(",level=") - .append(level) - .append(",killCount=") - .append(killCount) - .append(",drops=["); - - boolean addComma = false; - for (LootTrackerItemEntry d : drops) - { - if (addComma) - { - m.append(","); - } - - m.append(d.toString()); - addComma = true; - } - m.append("]}"); - - return m.toString(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/Pet.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/Pet.java deleted file mode 100644 index 35ff366e9c..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/Pet.java +++ /dev/null @@ -1,74 +0,0 @@ -package net.runelite.client.plugins.stonedloottracker.data; - -import java.util.HashMap; -import java.util.Map; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.api.ItemID; - -@Getter(AccessLevel.PUBLIC) -public enum Pet -{ - // GWD Pets - PET_GENERAL_GRAARDOR(ItemID.PET_GENERAL_GRAARDOR, "General graador"), - PET_KREEARRA(ItemID.PET_KREEARRA, "Kree'arra"), - PET_KRIL_TSUTSAROTH(ItemID.PET_KRIL_TSUTSAROTH, "K'ril tsutsaroth"), - PET_ZILYANA(ItemID.PET_ZILYANA, "Commander zilyana"), - // Wildy Pets - CALLISTO_CUB(ItemID.CALLISTO_CUB, "Callisto"), - PET_CHAOS_ELEMENTAL(ItemID.PET_CHAOS_ELEMENTAL, "Chaos Elemental", "Chaos Fanatic"), - SCORPIAS_OFFSPRING(ItemID.SCORPIAS_OFFSPRING, "Scorpia"), - VENENATIS_SPIDERLING(ItemID.VENENATIS_SPIDERLING, "Venenatis"), - VETION_JR(ItemID.VETION_JR, "Vet'ion"), - // KBD isn't really in wildy but meh - PRINCE_BLACK_DRAGON(ItemID.PRINCE_BLACK_DRAGON, "King Black Dragon"), - // Slayer Pets - ABYSSAL_ORPHAN(ItemID.ABYSSAL_ORPHAN, "Abyssal Sire"), - HELLPUPPY(ItemID.HELLPUPPY, "Cerberus"), - NOON(ItemID.NOON, "Noon", "Dusk"), - PET_KRAKEN(ItemID.PET_KRAKEN, "Kraken"), - PET_SMOKE_DEVIL(ItemID.PET_SMOKE_DEVIL, "Thermonuclear Smoke Devil"), - SKOTOS(ItemID.SKOTOS, "Skotizo"), - // Other Bosses - BABY_MOLE(ItemID.BABY_MOLE, "Giant Mole"), - KALPHITE_PRINCESS(ItemID.KALPHITE_PRINCESS, "Kalphite Queen"), - OLMLET(ItemID.OLMLET, "Chambers of Xeric"), - LIL_ZIK(ItemID.LIL_ZIK, "Theatre of Blood"), - PET_DARK_CORE(ItemID.PET_DARK_CORE, "Corporeal Beast"), - PET_SNAKELING(ItemID.PET_SNAKELING, "Zulrah"), - PET_DAGANNOTH_REX(ItemID.PET_DAGANNOTH_REX, "Dagannoth Rex"), - PET_DAGANNOTH_PRIME(ItemID.PET_DAGANNOTH_PRIME, "Dagannoth Prime"), - PET_DAGANNOTH_SUPREME(ItemID.PET_DAGANNOTH_SUPREME, "Dagannoth Supreme"), - VORKI(ItemID.VORKI, "Vorkath"), - BLOODHOUND(ItemID.BLOODHOUND, "Clue Scroll Master"), - HERBI(ItemID.HERBI, "Herbiboar"); - - private final int petID; - private final String[] bossNames; - private static final Map byBossName = buildBossMap(); - - Pet(final int id, final String... bossNames) - { - this.petID = id; - this.bossNames = bossNames; - } - - public static Pet getByBossName(String name) - { - return byBossName.get(name.toUpperCase()); - } - - private static Map buildBossMap() - { - Map byName = new HashMap<>(); - for (Pet pet : values()) - { - String[] droppingBosses = pet.getBossNames(); - for (String bossName : droppingBosses) - { - byName.put(bossName.toUpperCase(), pet); - } - } - return byName; - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/UniqueItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/UniqueItem.java deleted file mode 100644 index 7af2acf699..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/UniqueItem.java +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (c) 2018, TheStonedTurtle - * 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.stonedloottracker.data; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import net.runelite.api.ItemID; - -@RequiredArgsConstructor -@Getter(AccessLevel.PUBLIC) -public enum UniqueItem -{ - // Shared "Uniques" (Dropped by multiple activities) - // God Wars - GODSWORD_SHARD_1("Godsword shard 1", ItemID.GODSWORD_SHARD_1, "Kree'arra", "General Graardor", "Commander Zilyana", "K'ril Tsutsaroth"), - GODSWORD_SHARD_2("Godsword shard 2", ItemID.GODSWORD_SHARD_2, "Kree'arra", "General Graardor", "Commander Zilyana", "K'ril Tsutsaroth"), - GODSWORD_SHARD_3("Godsword shard 3", ItemID.GODSWORD_SHARD_3, "Kree'arra", "General Graardor", "Commander Zilyana", "K'ril Tsutsaroth"), - // Wildy - PET_CHAOS_ELEMENTAL("Pet chaos elemental", ItemID.PET_CHAOS_ELEMENTAL, "Chaos Elemental", "Chaos Fanatic"), - // MYSTERIOUS_EMBLEM("Mysterious emblem", ItemID.MYSTERIOUS_EMBLEM , ""), - CURVED_BONE("Curved bone", ItemID.CURVED_BONE, "Callisto", "Vet'ion", "Venenatis", "Giant Mole"), - DRAGON_PICKAXE("Dragon pickaxe", ItemID.DRAGON_PICKAXE , "Callisto", "Vet'ion", "Venenatis", "King Black Dragon", "Chaos Elemental"), - DRAGON_2H_SWORD("Dragon 2h sword", ItemID.DRAGON_2H_SWORD , "Callisto", "Vet'ion", "Venenatis", "Kalphite Queen"), - // Other - DRAGON_CHAINBODY("Dragon chainbody", ItemID.DRAGON_CHAINBODY_3140, "Thermonuclear Smoke Devil", "Kalphite Queen"), - DRAGON_AXE("Dragon axe", ItemID.DRAGON_AXE, "Dagannoth Rex", "Dagannoth Prime", "Dagannoth Supreme"), - UNCUT_ONYX("Uncut onyx", ItemID.UNCUT_ONYX, "Zulrah", "Skotizo"), - DRACONIC_VISAGE("Draconic visage", ItemID.DRACONIC_VISAGE, "Vorkath", "King Black Dragon"), - - // Unique Items - // Barrows Uniques - // Ahrim - AHRIMS_HOOD("Ahrim's hood", ItemID.AHRIMS_HOOD, "Barrows", "Ahrims", 0), - AHRIMS_ROBETOP("Ahrim's robetop", ItemID.AHRIMS_ROBETOP, "Barrows", "Ahrims", 0), - AHRIMS_ROBESKIRT("Ahrim's robeskirt", ItemID.AHRIMS_ROBESKIRT, "Barrows", "Ahrims", 0), - AHRIMS_STAFF("Ahrim's staff", ItemID.AHRIMS_STAFF, "Barrows", "Ahrims", 0), - // Dharok - DHAROKS_HELM("Dharok's helm", ItemID.DHAROKS_HELM, "Barrows", "Dharoks", 1), - DHAROKS_PLATEBODY("Dharok's platebody", ItemID.DHAROKS_PLATEBODY, "Barrows", "Dharoks", 1), - DHAROKS_PLATELEGS("Dharok's platelegs", ItemID.DHAROKS_PLATELEGS, "Barrows", "Dharoks", 1), - DHAROKS_GREATAXE("Dharok's greataxe", ItemID.DHAROKS_GREATAXE, "Barrows", "Dharoks", 1), - // Guthans - GUTHANS_HELM("Guthan's helm", ItemID.GUTHANS_HELM, "Barrows", "Guthans", 2), - GUTHANS_PLATEBODY("Guthan's platebody", ItemID.GUTHANS_PLATEBODY, "Barrows", "Guthans", 2), - GUTHANS_CHAINSKIRT("Guthan's Chainskirt", ItemID.GUTHANS_CHAINSKIRT, "Barrows", "Guthans", 2), - GUTHANS_WARSPEAR("Guthan's warspear", ItemID.GUTHANS_WARSPEAR, "Barrows", "Guthans", 2), - // Karils - KARILS_COIF("Karil's coif", ItemID.KARILS_COIF, "Barrows", "Karils", 3), - KARILS_LEATHERTOP("Karil's leathertop", ItemID.KARILS_LEATHERTOP, "Barrows", "Karils", 3), - KARILS_LEATHERSKIRT("Karil's leatherskirt", ItemID.KARILS_LEATHERSKIRT, "Barrows", "Karils", 3), - KARILS_CROSSBOW("Karil's crossbow ", ItemID.KARILS_CROSSBOW, "Barrows", "Karils", 3), - //Torag - TORAGS_HELM("Torag's helm", ItemID.TORAGS_HELM, "Barrows", "Torags", 4), - TORAGS_PLATEBODY("Torags's platebody", ItemID.TORAGS_PLATEBODY, "Barrows", "Torags", 4), - TORAGS_PLATELEGS("Torags's platelegs", ItemID.TORAGS_PLATELEGS, "Barrows", "Torags", 4), - TORAGS_HAMMERS("Torag's hammers", ItemID.TORAGS_HAMMERS, "Barrows", "Torags", 4), - // Veracs - VERACS_HELM("Verac's helm", ItemID.VERACS_HELM, "Barrows", "Veracs", 5), - VERACS_BRASSARD("Verac's brassard", ItemID.VERACS_BRASSARD, "Barrows", "Veracs", 5), - VERACS_PLATESKIRT("Verac's plateskirt", ItemID.VERACS_PLATESKIRT, "Barrows", "Veracs", 5), - VERACS_FLAIL("Verac's flail", ItemID.VERACS_FLAIL, "Barrows", "Veracs", 5), - - // Raids Uniques - // Mage - KODAI_INSIGNIA("Kodai insignia", ItemID.KODAI_INSIGNIA, "Chambers of Xeric", "Mage", 0), - ANCESTRAL_HAT("Ancestral hat", ItemID.ANCESTRAL_HAT, "Chambers of Xeric", "Mage", 0), - ANCESTRAL_ROBE_TOP("Ancestral robe top", ItemID.ANCESTRAL_ROBE_TOP, "Chambers of Xeric", "Mage", 0), - ANCESTRAL_ROBE_BOTTOM("Ancestral robe bottom", ItemID.ANCESTRAL_ROBE_BOTTOM, "Chambers of Xeric", "Mage", 0), - // Range - DRAGON_THROWNAXE("Dragon thrownaxe", ItemID.DRAGON_THROWNAXE, "Chambers of Xeric", "Range", 1), - DRAGON_HUNTER_CROSSBOW("Dragon hunter crossbow", ItemID.DRAGON_HUNTER_CROSSBOW, "Chambers of Xeric", "Range", 1), - TWISTED_BUCKLER("Twisted buckler", ItemID.TWISTED_BUCKLER, "Chambers of Xeric", "Range", 1), - TWISTED_BOW("Twisted bow", ItemID.TWISTED_BOW, "Chambers of Xeric", "Range", 1), - // Melee - DRAGON_SWORD("Dragon sword", ItemID.DRAGON_SWORD, "Chambers of Xeric", "Melee", 2), - DRAGON_CLAWS("Dragon claws", ItemID.DRAGON_CLAWS, "Chambers of Xeric", "Melee", 2), - DINHS_BULWARK("Dinh's bulwark", ItemID.DINHS_BULWARK, "Chambers of Xeric", "Melee", 2), - ELDER_MAUL("Elder maul", ItemID.ELDER_MAUL, "Chambers of Xeric", "Melee", 2), - // Prayers - TORN_PRAYER_SCROLL("Torn prayer scroll", ItemID.TORN_PRAYER_SCROLL, "Chambers of Xeric", "Prayer", 3), - ARCANE_PRAYER_SCROLL("Arcane prayer scroll", ItemID.ARCANE_PRAYER_SCROLL, "Chambers of Xeric", "Prayer", 3), - DEXTEROUS_PRAYER_SCROLL("Dexterous prayer scroll", ItemID.DEXTEROUS_PRAYER_SCROLL, "Chambers of Xeric", "Prayer", 3), - // Other - DRAGON_HARPOON("Dragon harpoon", ItemID.DRAGON_HARPOON, "Chambers of Xeric", "Other", 4), - DARK_RELIC("Dark relic", ItemID.DARK_RELIC, "Chambers of Xeric", "Other", 4), - - // Raids 2 Unqiues (Theater of Blood) - // Weapons / Pet - GHRAZI_RAPIER("Ghrazi rapier", ItemID.GHRAZI_RAPIER, "Theatre of Blood", "Weapons", 0), - SCYTHE_OF_VITUR_UNCHARGED("Scythe of vitur (uncharged)", ItemID.SCYTHE_OF_VITUR_UNCHARGED, "Theatre of Blood", "Weapons", 0), - SANGUINESTI_STAFF_UNCHAGRED("Sanguinesti staff (uncharged)", ItemID.SANGUINESTI_STAFF_UNCHARGED, "Theatre of Blood", "Weapons", 0), - LIL_ZIK("Lil' zik", ItemID.LIL_ZIK, "Theatre of Blood", "Weapons", 0), - // Armor - AVERNIC_DEFENDER_HILT("Avernic defender hilt", ItemID.AVERNIC_DEFENDER_HILT, "Theatre of Blood", "Armor", 1), - JUSTICIAR_FACEGUARD("Justiciar faceguard", ItemID.JUSTICIAR_FACEGUARD, "Theatre of Blood", "Armor", 1), - JUSTICIAR_CHESTGUARD("Justiciar chestguard", ItemID.JUSTICIAR_CHESTGUARD, "Theatre of Blood", "Armor", 1), - JUSTICIAR_LEGGUARDS("Justiciar legguards", ItemID.JUSTICIAR_LEGGUARDS, "Theatre of Blood", "Armor", 1), - - - // Zulrah - // Uniques - TANZANITE_FANG("Tanzanite fang", ItemID.TANZANITE_FANG, "Zulrah", "Uniques", -1), - MAGIC_FANG("Magic fang", ItemID.MAGIC_FANG, "Zulrah", "Uniques", -1), - SERPENTINE_VISAGE("Serpentine visage", ItemID.SERPENTINE_VISAGE, "Zulrah", "Uniques", -1), - // Rares - PET_SNAKELING("Pet snakeling", ItemID.PET_SNAKELING, "Zulrah", "Rares", 0), - TANZANITE_MUTAGEN("Tanzanite mutagen", ItemID.TANZANITE_MUTAGEN, "Zulrah", "Rares", 0), - MAGMA_MUTAGEN("Magma mutagen", ItemID.MAGMA_MUTAGEN, "Zulrah", "Rares", 0), - JAR_OF_SWAMP("Jar of swamp", ItemID.JAR_OF_SWAMP, "Zulrah", "Rares", 0), - - // Vorkath - DRAGONBONE_NECKLACE("Dragonbone necklace", ItemID.DRAGONBONE_NECKLACE, "Vorkath", "Uniques", 0), - VORKATHS_HEAD("Vorkath's head", ItemID.VORKATHS_HEAD_21907, "Vorkath", "Uniques", 0), - JAR_OF_DECAY("Jar of decay", ItemID.JAR_OF_DECAY, "Vorkath", "Uniques", 0), - SKELETAL_VISAGE("Skeletal visage", ItemID.SKELETAL_VISAGE, "Vorkath", "Uniques", -1), - VORKI("Vorki", ItemID.VORKI, "Vorkath", "Uniques", -1), - - - // God Wars Dungeon - // Kree'arra (Armadyl) - ARMADYL_HELMET("Armadyl helmet", ItemID.ARMADYL_HELMET, "Kree'arra", "Uniques", 0), - ARMADYL_CHESTPLATE("Armadyl chestplate", ItemID.ARMADYL_CHESTPLATE, "Kree'arra", "Uniques", 0), - ARMADYL_CHAINSKIRT("Armadyl chainskirt", ItemID.ARMADYL_CHAINSKIRT, "Kree'arra", "Uniques", 0), - ARMADYL_HILT("Armadyl hilt", ItemID.ARMADYL_HILT, "Kree'arra", "Uniques", 0), - PET_KREEARRA("Pet Kree'arra", ItemID.PET_KREEARRA, "Kree'arra", "Pet", -1), - // General Graardor (Bandos) - BANDOS_CHESTPLATE("Bandos chestplate", ItemID.BANDOS_CHESTPLATE, "General Graardor", "Uniques", 0), - BANDOS_TASSETS("Bandos tassets", ItemID.BANDOS_TASSETS, "General Graardor", "Uniques", 0), - BANDOS_BOOTS("Bandos boots", ItemID.BANDOS_BOOTS, "General Graardor", "Uniques", 0), - BANDOS_HILT("Bandos hilt", ItemID.BANDOS_HILT, "General Graardor", "Uniques", 0), - PET_GENERAL_GRAARDOR("Pet general graardor", ItemID.PET_GENERAL_GRAARDOR, "General Graardor", "Pet", -1), - // Command Zilyana (Saradomin) - SARADOMIN_SWORD("Saradomin sword", ItemID.SARADOMIN_SWORD, "Commander Zilyana", "Uniques", 0), - ARMADYL_CROSSBOW("Armadyl crossbow", ItemID.ARMADYL_CROSSBOW, "Commander Zilyana", "Uniques", 0), - SARADOMINS_LIGHT("Saradomins light", ItemID.SARADOMINS_LIGHT, "Commander Zilyana", "Uniques", 0), - SARADOMIN_HILT("Saradomin hilt", ItemID.SARADOMIN_HILT, "Commander Zilyana", "Uniques", 0), - PET_ZILYANA("Pet zilyana", ItemID.PET_ZILYANA, "Commander Zilyana", "Pet", -1), - // K'ril Tsutsaroth (Zammy) - STEAM_BATTLESTAFF("Steam battlestaff", ItemID.STEAM_BATTLESTAFF, "K'ril Tsutsaroth", "Uniques", 0), - STAFF_OF_THE_DEAD("Staff of the dead", ItemID.STAFF_OF_THE_DEAD, "K'ril Tsutsaroth", "Uniques", 0), - ZAMORAKIAN_SPEAR("Zamorakian spear", ItemID.ZAMORAKIAN_SPEAR, "K'ril Tsutsaroth", "Uniques", 0), - ZAMORAK_HILT("Zamorak hilt", ItemID.ZAMORAK_HILT, "K'ril Tsutsaroth", "Uniques", 0), - PET_KRIL_TSUTSAROTH("Pet k'ril tsutsaroth", ItemID.PET_KRIL_TSUTSAROTH, "K'ril Tsutsaroth", "Pet", -1), - - - // Wildy Bosses - // Vet'ion - RING_OF_THE_GODS("Ring of the gods", ItemID.RING_OF_THE_GODS , "Vet'ion", "Uniques", 0), - VETION_JR("Vet'ion jr.", ItemID.VETION_JR , "Vet'ion", "Uniques", 0), - SKELETON_CHAMPION_SCROLL("Skeleton champion scroll", ItemID.SKELETON_CHAMPION_SCROLL , "Vet'ion", "Uniques", 0), - // Venenatis - TREASONOUS_RING("Treasonous ring", ItemID.TREASONOUS_RING , "Venenatis", "Uniques", -1), - VENENATIS_SPIDERLING("Venenatis spiderling", ItemID.VENENATIS_SPIDERLING , "Venenatis", "Uniques", -1), - // Callisto - TYRANNICAL_RING("Tyrannical ring", ItemID.TYRANNICAL_RING , "Callisto", "Uniques", -1), - CALLISTO_CUB("Callisto cub", ItemID.CALLISTO_CUB , "Callisto", "Uniques", -1), - // Chaos Elemental Uniques are all in Shared - // Chaos Fanatic - ODIUM_SHARD_1("Odium shard 1", ItemID.ODIUM_SHARD_1 , "Chaos Fanatic", "Uniques", -1), - MALEDICTION_SHARD_1("Malediction shard 1", ItemID.MALEDICTION_SHARD_1 , "Chaos Fanatic", "Uniques", -1), - // Crazy Archaeologist - ODIUM_SHARD_2("Odium shard 2", ItemID.ODIUM_SHARD_2 , "Crazy Archaeologist", "Uniques", 0), - MALEDICTION_SHARD_2("Malediction shard 2", ItemID.MALEDICTION_SHARD_2 , "Crazy Archaeologist", "Uniques", 0), - FEDORA("Fedora", ItemID.FEDORA , "Crazy Archaeologist", "Uniques", 0), - // Scorpia - ODIUM_SHARD_3("Odium shard 3", ItemID.ODIUM_SHARD_3 , "Scorpia", "Uniques", 0), - MALEDICTION_SHARD_3("Malediction shard 3", ItemID.MALEDICTION_SHARD_3 , "Scorpia", "Uniques", 0), - SCORPIAS_OFFSPRING("Scorpia's offspring", ItemID.SCORPIAS_OFFSPRING , "Scorpia", "Uniques", 0), - // King Black Dragon, - KBD_HEADS("Kbd heads", ItemID.KBD_HEADS , "King Black Dragon", "Uniques", -1), - PRINCE_BLACK_DRAGON("Prince black dragon", ItemID.PRINCE_BLACK_DRAGON , "King Black Dragon", "Uniques", -1), - - // Slayer Bosses - // Skotizo - DARK_CLAW("Dark claw", ItemID.DARK_CLAW, "Skotizo", "Uniques", -1), - SKOTOS("Skotos", ItemID.SKOTOS, "Skotizo", "Uniques", -1), - JAR_OF_DARKNESS("Jar of darkness", ItemID.JAR_OF_DARKNESS, "Skotizo", "Uniques", -1), - // Grotesque Guardians - GRANITE_GLOVES("Granite gloves", ItemID.GRANITE_GLOVES, "Dusk", "Uniques", 0), - GRANITE_RING("Granite ring", ItemID.GRANITE_RING, "Dusk", "Uniques", 0), - GRANITE_HAMMER("Granite hammer", ItemID.GRANITE_HAMMER, "Dusk", "Uniques", 0), - BLACK_TOURMALINE_CORE("Black touramline core", ItemID.BLACK_TOURMALINE_CORE, "Dusk", "Uniques 2", 1), - NOON("Noon", ItemID.NOON, "Dusk", "Uniques 2", 1), - JAR_OF_STONE("Jar of stone", ItemID.JAR_OF_STONE, "Dusk", "Uniques 2", 1), - // Abyssal Sire - UNSIRED("Unsired", ItemID.UNSIRED, "Abyssal Sire", "Uniques", 0), - BLUDGEON_CLAW("Bludgeon claw", ItemID.BLUDGEON_CLAW, "Abyssal Sire", "Uniques", 0), - BLUDGEON_SPINE("Bludgeon spine", ItemID.BLUDGEON_SPINE, "Abyssal Sire", "Uniques", 0), - BLUDGEON_AXON("Bludgeon axon", ItemID.BLUDGEON_AXON, "Abyssal Sire", "Uniques", 0), - ABYSSAL_DAGGER("Abyssal dagger", ItemID.ABYSSAL_DAGGER, "Abyssal Sire", "Uniques 2", 1), - ABYSSAL_WHIP("Abyssal whip", ItemID.ABYSSAL_WHIP, "Abyssal Sire", "Uniques 2", 1), - ABYSSAL_ORPHAN("Abyssal orphan", ItemID.ABYSSAL_ORPHAN, "Abyssal Sire", "Uniques 2", 1), - JAR_OF_MIASMA("Jar of miasma", ItemID.JAR_OF_MIASMA, "Abyssal Sire", "Uniques 2", 1), - ABYSSAL_HEAD("Abyssal head", ItemID.ABYSSAL_HEAD, "Abyssal Sire", "Uniques 2", 1), - // Kraken - TRIDENT_OF_THE_SEAS_FULL("Trident of the seas (full)", ItemID.TRIDENT_OF_THE_SEAS_FULL, "Kraken", "Uniques", 0), - KRAKEN_TENTACLE("Kraken tentacle", ItemID.KRAKEN_TENTACLE, "Kraken", "Uniques", 0), - JAR_OF_DIRT("Jar of dirt", ItemID.JAR_OF_DIRT, "Kraken", "Uniques", 0), - PET_KRAKEN("Pet kraken", ItemID.PET_KRAKEN, "Kraken", "Uniques", 0), - // Cerberus - PRIMORDIAL_CRYSTAL("Primordial crystal", ItemID.PRIMORDIAL_CRYSTAL, "Cerberus", "Uniques", 0), - PEGASIAN_CRYSTAL("Pegasian crystal", ItemID.PEGASIAN_CRYSTAL, "Cerberus", "Uniques", 0), - ETERNAL_CRYSTAL("Eternal crystal", ItemID.ETERNAL_CRYSTAL, "Cerberus", "Uniques", 0), - SMOULDERING_STONE("Smouldering stone", ItemID.SMOULDERING_STONE, "Cerberus", "Uniques", 1), - JAR_OF_SOULS("Jar of souls", ItemID.JAR_OF_SOULS, "Cerberus", "Uniques", 1), - HELLPUPPY("Hellpuppy", ItemID.HELLPUPPY, "Cerberus", "Uniques", 1), - // Thermonuclear Smoke Devil - SMOKE_BATTLESTAFF("Smoke battlestaff", ItemID.SMOKE_BATTLESTAFF, "Thermonuclear Smoke Devil", "Uniques", -1), - OCCULT_NECKLACE("Occult necklace", ItemID.OCCULT_NECKLACE, "Thermonuclear Smoke Devil", "Uniques", -1), - PET_SMOKE_DEVIL("Pet smoke devil", ItemID.PET_SMOKE_DEVIL, "Thermonuclear Smoke Devil", "Uniques", -1), - - - // Other Bosses - // Giant Mole - BABY_MOLE("Baby Mole", ItemID.BABY_MOLE, "Giant Mole", "Uniques", -1), - // Kalphite Queen - KQ_HEAD("Kq head", ItemID.KQ_HEAD, "Kalphite Queen", "Uniques", -1), - JAR_OF_SAND("Jar of sand", ItemID.JAR_OF_SAND, "Kalphite Queen", "Uniques", -1), - KALPHITE_PRINCESS("Kalphite princess", ItemID.KALPHITE_PRINCESS, "Kalphite Queen", "Uniques", -1), - // Corporeal Beast - SPIRIT_SHIELD("Spirit shield", ItemID.SPIRIT_SHIELD, "Corporeal Beast", "Uniques", 0), - HOLY_ELIXIR("Holy elixir", ItemID.HOLY_ELIXIR, "Corporeal Beast", "Uniques", 0), - PET_DARK_CORE("Pet dark core", ItemID.PET_DARK_CORE, "Corporeal Beast", "Uniques", 0), - SPECTRAL_SIGIL("Spectral sigil", ItemID.SPECTRAL_SIGIL, "Corporeal Beast", "Sigil", 1), - ARCANE_SIGIL("Arcane sigil", ItemID.ARCANE_SIGIL, "Corporeal Beast", "Sigil", 1), - ELYSIAN_SIGIL("Elysian sigil", ItemID.ELYSIAN_SIGIL, "Corporeal Beast", "Sigil", 1), - // Dagannoth Rex - WARRIOR_RING("Warrior ring", ItemID.WARRIOR_RING, "Dagannoth Rex", "Uniques", -1), - BERSERKER_RING("Berserk ring", ItemID.BERSERKER_RING, "Dagannoth Rex", "Uniques", -1), - PET_DAGANNOTH_REX("Pet dagannoth rex", ItemID.PET_DAGANNOTH_REX, "Dagannoth Rex", "Uniques", -1), - // Dagannoth Prime - MUD_BATTLESTAFF("Mud battlestaff", ItemID.MUD_BATTLESTAFF, "Dagannoth Prime", "Uniques", -1), - SEERS_RING("Seers ring", ItemID.SEERS_RING, "Dagannoth Prime", "Uniques", -1), - PET_DAGANNOTH_PRIME("Pet dagannoth prime", ItemID.PET_DAGANNOTH_PRIME, "Dagannoth Prime", "Uniques", -1), - // Dagannoth Supreme - SEERCULL("Seercrull", ItemID.SEERCULL, "Dagannoth Supreme", "Uniques", -1), - ARCHERS_RING("Archers ring", ItemID.ARCHERS_RING, "Dagannoth Supreme", "Uniques", -1), - PET_DAGANNOTH_SUPREME("Pet dagannoth supreme", ItemID.PET_DAGANNOTH_SUPREME, "Dagannoth Supreme", "Uniques", -1), - - // Beginner Clue Scrolls - MOLE_SLIPPERS("Mole slippers", ItemID.MOLE_SLIPPERS, "Clue Scroll (Beginner)", "Slippers", -1), - FROG_SLIPPERS("Frog slippers", ItemID.FROG_SLIPPERS, "Clue Scroll (Beginner)", "Slippers", -1), - BEAR_FEET("Bear slippers", ItemID.BEAR_FEET, "Clue Scroll (Beginner)", "Slippers", -1), - DEMON_FEET("Demon slippers", ItemID.DEMON_FEET, "Clue Scroll (Beginner)", "Slippers", -1), - SANDWICH_LADY_HAT("Sandwich lady hat", ItemID.SANDWICH_LADY_HAT, "Clue Scroll (Beginner)", "Sandwich Lady", 0), - SANDWICH_LADY_TOP("Sandwich lady top", ItemID.SANDWICH_LADY_TOP, "Clue Scroll (Beginner)", "Sandwich Lady", 0), - SANDWICH_LADY_BOTTOM("Sandwich lady bottom", ItemID.SANDWICH_LADY_BOTTOM, "Clue Scroll (Beginner)", "Sandwich Lady", 0), - MONKS_ROBE_TOP_T("Monk robe top (t)", ItemID.MONKS_ROBE_TOP_T, "Clue Scroll (Beginner)", "Monk Robes", 1), - MONKS_ROBE_T("Monk robe (t)", ItemID.MONKS_ROBE_T, "Clue Scroll (Beginner)", "Monk Robes", 1), - JESTER_CAPE("Jester cape", ItemID.JESTER_CAPE, "Clue Scroll (Beginner)", "Other", 2), - SHOULDER_PARROT("Shoulder parrot", ItemID.SHOULDER_PARROT, "Clue Scroll (Beginner)", "Other", 2), - AMULET_OF_DEFENCE_T("Amulet of Defence (t)", ItemID.AMULET_OF_DEFENCE_T, "Clue Scroll (Beginner)", "Other", 2), - RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX("Rune scimitar Guthix ornament kit", ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX, "Clue Scroll (Beginner)", "God Ornament Kit", 3), - RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN("Rune scimitar Saradomin ornament kit", ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN, "Clue Scroll (Beginner)", "God Ornament Kit", 3), - RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK("Rune scimitar Zamorak ornament kit", ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK, "Clue Scroll (Beginner)", "God Ornament Kit", 3), - - // Easy Clue Scrolls - BRONZE_FULL_HELM_T("Bronze full helm (t)", ItemID.BRONZE_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", -1), - BRONZE_PLATEBODY_T("Bronze platebody (t)", ItemID.BRONZE_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", -1), - BRONZE_PLATELEGS_T("Bronze platelegs (t)", ItemID.BRONZE_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", -1), - BRONZE_PLATESKIRT_T("Bronze plateskirt (t)", ItemID.BRONZE_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", -1), - BRONZE_KITESHIELD_T("Bronze kiteshield (t)", ItemID.BRONZE_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", -1), - BRONZE_FULL_HELM_G("Bronze full helm (g)", ItemID.BRONZE_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 0), - BRONZE_PLATEBODY_G("Bronze platebody (g)", ItemID.BRONZE_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 0), - BRONZE_PLATELEGS_G("Bronze platelegs (g)", ItemID.BRONZE_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 0), - BRONZE_PLATESKIRT_G("Bronze plateskirt (g)", ItemID.BRONZE_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 0), - BRONZE_KITESHIELD_G("Bronze kiteshield (g)", ItemID.BRONZE_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 0), - IRON_FULL_HELM_T("Iron full helm (t)", ItemID.IRON_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", 1), - IRON_PLATEBODY_T("Iron platebody (t)", ItemID.IRON_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", 1), - IRON_PLATELEGS_T("Iron platelegs (t)", ItemID.IRON_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", 1), - IRON_PLATESKIRT_T("Iron plateskirt (t)", ItemID.IRON_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", 1), - IRON_KITESHIELD_T("Iron kiteshield (t)", ItemID.IRON_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", 1), - IRON_FULL_HELM_G("Iron full helm (g)", ItemID.IRON_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 2), - IRON_PLATEBODY_G("Iron platebody (g)", ItemID.IRON_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 2), - IRON_PLATELEGS_G("Iron platelegs (g)", ItemID.IRON_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 2), - IRON_PLATESKIRT_G("Iron plateskirt (g)", ItemID.IRON_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 2), - IRON_KITESHIELD_G("Iron kiteshield (g)", ItemID.IRON_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 2), - STEEL_FULL_HELM_T("Steel full helm (t)", ItemID.STEEL_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", 3), - STEEL_PLATEBODY_T("Steel platebody (t)", ItemID.STEEL_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", 3), - STEEL_PLATELEGS_T("Steel platelegs (t)", ItemID.STEEL_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", 3), - STEEL_PLATESKIRT_T("Steel plateskirt (t)", ItemID.STEEL_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", 3), - STEEL_KITESHIELD_T("Steel kiteshield (t)", ItemID.STEEL_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", 3), - STEEL_FULL_HELM_G("Steel full helm (g)", ItemID.STEEL_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 4), - STEEL_PLATEBODY_G("Steel platebody (g)", ItemID.STEEL_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 4), - STEEL_PLATELEGS_G("Steel platelegs (g)", ItemID.STEEL_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 4), - STEEL_PLATESKIRT_G("Steel plateskirt (g)", ItemID.STEEL_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 4), - STEEL_KITESHIELD_G("Steel kiteshield (g)", ItemID.STEEL_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 4), - BLACK_FULL_HELM_T("Black full helm (t)", ItemID.BLACK_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", 5), - BLACK_PLATEBODY_T("Black platebody (t)", ItemID.BLACK_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", 5), - BLACK_PLATELEGS_T("Black platelegs (t)", ItemID.BLACK_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", 5), - BLACK_PLATESKIRT_T("Black plateskirt (t)", ItemID.BLACK_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", 5), - BLACK_KITESHIELD_T("Black kiteshield (t)", ItemID.BLACK_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", 5), - BLACK_FULL_HELM_G("Black full helm (g)", ItemID.BLACK_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 6), - BLACK_PLATEBODY_G("Black platebody (g)", ItemID.BLACK_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 6), - BLACK_PLATELEGS_G("Black platelegs (g)", ItemID.BLACK_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 6), - BLACK_PLATESKIRT_G("Black plateskirt (g)", ItemID.BLACK_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 6), - BLACK_KITESHIELD_G("Black kiteshield (g)", ItemID.BLACK_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 6), - BLUE_WIZARD_HAT_T("Blue wizard hat (t)", ItemID.BLUE_WIZARD_HAT_T, "Clue Scroll (Easy)", "Wizard Robes", 7), - BLUE_WIZARD_ROBE_T("Blue wizard robe (t)", ItemID.BLUE_WIZARD_ROBE_T, "Clue Scroll (Easy)", "Wizard Robes", 7), - BLUE_SKIRT_T("Blue skirt (t)", ItemID.BLUE_SKIRT_T, "Clue Scroll (Easy)", "Wizard Robes", 7), - BLUE_WIZARD_HAT_G("Blue wizard hat (g)", ItemID.BLUE_WIZARD_HAT_G, "Clue Scroll (Easy)", "Wizard Robes", 8), - BLUE_WIZARD_ROBE_G("Blue wizard robe (g)", ItemID.BLUE_WIZARD_ROBE_G, "Clue Scroll (Easy)", "Wizard Robes", 8), - BLUE_SKIRT_G("Blue skirt (g)", ItemID.BLUE_SKIRT_G, "Clue Scroll (Easy)", "Wizard Robes", 8), - BLACK_WIZARD_HAT_T("Black wizard hat (t)", ItemID.BLACK_WIZARD_HAT_T, "Clue Scroll (Easy)", "Wizard Robes", 9), - BLACK_WIZARD_ROBE_T("Black wizard robe (t)", ItemID.BLACK_WIZARD_ROBE_T, "Clue Scroll (Easy)", "Wizard Robes", 9), - BLACK_SKIRT_T("Black skirt (t)", ItemID.BLACK_SKIRT_T, "Clue Scroll (Easy)", "Wizard Robes", 9), - BLACK_WIZARD_HAT_G("Black wizard hat (g)", ItemID.BLACK_WIZARD_HAT_G, "Clue Scroll (Easy)", "Wizard Robes", 10), - BLACK_WIZARD_ROBE_G("Black wizard robe (g)", ItemID.BLACK_WIZARD_ROBE_G, "Clue Scroll (Easy)", "Wizard Robes", 10), - BLACK_SKIRT_G("Black skirt (g)", ItemID.BLACK_SKIRT_G, "Clue Scroll (Easy)", "Wizard Robes", 10), - STUDDED_BODY_T("Studded body (t)", ItemID.STUDDED_BODY_T, "Clue Scroll (Easy)", "Leather Armor", 11), - STUDDED_CHAPS_T("Studded chaps (t)", ItemID.STUDDED_CHAPS_T, "Clue Scroll (Easy)", "Leather Armor", 11), - STUDDED_BODY_G("Studded body (g)", ItemID.STUDDED_BODY_G, "Clue Scroll (Easy)", "Leather Armor", 11), - STUDDED_CHAPS_G("Studded chaps (g)", ItemID.STUDDED_CHAPS_G, "Clue Scroll (Easy)", "Leather Armor", 11), - LEATHER_CHAPS_G("Leather chaps (g)", ItemID.LEATHER_CHAPS_G, "Clue Scroll (Easy)", "Leather Armor", 12), - LEATHER_BODY_G("Leather chaps (g)", ItemID.LEATHER_BODY_G, "Clue Scroll (Easy)", "Leather Armor", 12), - BLACK_HELM_H1("Black helm (h1)", ItemID.BLACK_HELM_H1, "Clue Scroll (Easy)", "Heralid Helm", 13), - BLACK_HELM_H2("Black helm (h2)", ItemID.BLACK_HELM_H2, "Clue Scroll (Easy)", "Heralid Helm", 13), - BLACK_HELM_H3("Black helm (h3)", ItemID.BLACK_HELM_H3, "Clue Scroll (Easy)", "Heralid Helm", 13), - BLACK_HELM_H4("Black helm (h4)", ItemID.BLACK_HELM_H4, "Clue Scroll (Easy)", "Heralid Helm", 13), - BLACK_HELM_H5("Black helm (h5)", ItemID.BLACK_HELM_H5, "Clue Scroll (Easy)", "Heralid Helm", 13), - BLACK_PLATEBODY_H1("Black platebody (h1)", ItemID.BLACK_PLATEBODY_H1, "Clue Scroll (Easy)", "Heralid Platebody", 14), - BLACK_PLATEBODY_H2("Black platebody (h2)", ItemID.BLACK_PLATEBODY_H2, "Clue Scroll (Easy)", "Heralid Platebody", 14), - BLACK_PLATEBODY_H3("Black platebody (h3)", ItemID.BLACK_PLATEBODY_H3, "Clue Scroll (Easy)", "Heralid Platebody", 14), - BLACK_PLATEBODY_H4("Black platebody (h4)", ItemID.BLACK_PLATEBODY_H4, "Clue Scroll (Easy)", "Heralid Platebody", 14), - BLACK_PLATEBODY_H5("Black platebody (h5)", ItemID.BLACK_PLATEBODY_H5, "Clue Scroll (Easy)", "Heralid Platebody", 14), - BLACK_SHIELD_H1("Black shield (h1)", ItemID.BLACK_SHIELD_H1, "Clue Scroll (Easy)", "Heralid Shield", 15), - BLACK_SHIELD_H2("Black shield (h2)", ItemID.BLACK_SHIELD_H2, "Clue Scroll (Easy)", "Heralid Shield", 15), - BLACK_SHIELD_H3("Black shield (h3)", ItemID.BLACK_SHIELD_H3, "Clue Scroll (Easy)", "Heralid Shield", 15), - BLACK_SHIELD_H4("Black shield (h4)", ItemID.BLACK_SHIELD_H4, "Clue Scroll (Easy)", "Heralid Shield", 15), - BLACK_SHIELD_H5("Black shield (h5)", ItemID.BLACK_SHIELD_H5, "Clue Scroll (Easy)", "Heralid Shield", 15), - BLUE_ELEGANT_SHIRT("Blue elegant shirt", ItemID.BLUE_ELEGANT_SHIRT, "Clue Scroll (Easy)", "Elegant", 16), - BLUE_ELEGANT_LEGS("Blue elegant legs", ItemID.BLUE_ELEGANT_LEGS, "Clue Scroll (Easy)", "Elegant", 16), - BLUE_ELEGANT_BLOUSE("Blue elegant blouse", ItemID.BLUE_ELEGANT_BLOUSE, "Clue Scroll (Easy)", "Elegant", 16), - BLUE_ELEGANT_SKIRT("Blue elegant skirt", ItemID.BLUE_ELEGANT_SKIRT, "Clue Scroll (Easy)", "Elegant", 16), - GREEN_ELEGANT_SHIRT("Green elegant shirt", ItemID.GREEN_ELEGANT_SHIRT, "Clue Scroll (Easy)", "Elegant", 17), - GREEN_ELEGANT_LEGS("Green elegant legs", ItemID.GREEN_ELEGANT_LEGS, "Clue Scroll (Easy)", "Elegant", 17), - GREEN_ELEGANT_BLOUSE("Green elegant blouse", ItemID.GREEN_ELEGANT_BLOUSE, "Clue Scroll (Easy)", "Elegant", 17), - GREEN_ELEGANT_SKIRT("Green elegant skirt", ItemID.GREEN_ELEGANT_SKIRT, "Clue Scroll (Easy)", "Elegant", 17), - RED_ELEGANT_SHIRT("Red elegant shirt", ItemID.RED_ELEGANT_SHIRT, "Clue Scroll (Easy)", "Elegant", 18), - RED_ELEGANT_LEGS("Red elegant legs", ItemID.RED_ELEGANT_LEGS, "Clue Scroll (Easy)", "Elegant", 18), - RED_ELEGANT_BLOUSE("Red elegant blouse", ItemID.RED_ELEGANT_BLOUSE, "Clue Scroll (Easy)", "Elegant", 18), - RED_ELEGANT_SKIRT("Red elegant skirt", ItemID.RED_ELEGANT_SKIRT, "Clue Scroll (Easy)", "Elegant", 18), - BOBS_RED_SHIRT("Bob's red shirt", ItemID.BOBS_RED_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19), - BOBS_BLUE_SHIRT("Bob's blue shirt", ItemID.BOBS_BLUE_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19), - BOBS_GREEN_SHIRT("Bob's green shirt", ItemID.BOBS_GREEN_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19), - BOBS_BLACK_SHIRT("Bob's black shirt", ItemID.BOBS_BLACK_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19), - BOBS_PURPLE_SHIRT("Bob's purple shirt", ItemID.BOBS_PURPLE_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19), - A_POWDERED_WIG("A powdered wig", ItemID.A_POWDERED_WIG, "Clue Scroll (Easy)", "Emote Enhancers", 20), - FLARED_TROUSERS("Flared trousers", ItemID.FLARED_TROUSERS, "Clue Scroll (Easy)", "Emote Enhancers", 20), - PANTALOONS("Pantaloons", ItemID.PANTALOONS, "Clue Scroll (Easy)", "Emote Enhancers", 20), - SLEEPING_CAP("Sleeping cap", ItemID.SLEEPING_CAP, "Clue Scroll (Easy)", "Emote Enhancers", 20), - GUTHIX_ROBE_TOP("Guthix robe top", ItemID.GUTHIX_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 21), - GUTHIX_ROBE_LEGS("Guthix robe legs", ItemID.GUTHIX_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 21), - SARADOMIN_ROBE_TOP("Saradomin robe top", ItemID.SARADOMIN_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 21), - SARADOMIN_ROBE_LEGS("Saradomin robe legs", ItemID.SARADOMIN_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 21), - ZAMORAK_ROBE_TOP("Zamorak robe top", ItemID.ZAMORAK_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 21), - ZAMORAK_ROBE_LEGS("Zamorak robe legs", ItemID.ZAMORAK_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 21), - ANCIENT_ROBE_TOP("Ancient robe top", ItemID.ANCIENT_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 22), - ANCIENT_ROBE_LEGS("Ancient robe legs", ItemID.ANCIENT_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 22), - BANDOS_ROBE_TOP("Bandos robe top", ItemID.BANDOS_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 22), - BANDOS_ROBE_LEGS("Bandos robe legs", ItemID.BANDOS_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 22), - ARMADYL_ROBE_TOP("Armadyl robe top", ItemID.ARMADYL_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 22), - ARMADYL_ROBE_LEGS("Armadyl robe legs", ItemID.ARMADYL_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 22), - BLACK_BERET("Black beret", ItemID.BLACK_BERET, "Clue Scroll (Easy)", "Berets", 23), - BLUE_BERET("Blue beret", ItemID.BLUE_BERET, "Clue Scroll (Easy)", "Berets", 23), - WHITE_BERET("White beret", ItemID.WHITE_BERET, "Clue Scroll (Easy)", "Berets", 23), - RED_BERET("Red beret", ItemID.RED_BERET, "Clue Scroll (Easy)", "Berets", 23), - HIGHWAYMAN_MASK("Highwayman mask", ItemID.HIGHWAYMAN_MASK, "Clue Scroll (Easy)", "Masks", 24), - IMP_MASK("Imp mask", ItemID.IMP_MASK, "Clue Scroll (Easy)", "Masks", 24), - GOBLIN_MASK("Goblin mask", ItemID.GOBLIN_MASK, "Clue Scroll (Easy)", "Masks", 24), - BEANIE("Beanie", ItemID.BEANIE, "Clue Scroll (Easy)", "Masks", 24), - TEAM_CAPE_I("Team cape i", ItemID.TEAM_CAPE_I, "Clue Scroll (Easy)", "Cape", 25), - TEAM_CAPE_X("Team cape x", ItemID.TEAM_CAPE_X, "Clue Scroll (Easy)", "Cape", 25), - TEAM_CAPE_ZERO("Team cape zero", ItemID.TEAM_CAPE_ZERO, "Clue Scroll (Easy)", "Cape", 25), - CAPE_OF_SKULLS("Cape of Skulls", ItemID.CAPE_OF_SKULLS, "Clue Scroll (Easy)", "CApe", 25), - AMULET_OF_MAGIC_T("Amulet of magic (t)", ItemID.AMULET_OF_MAGIC_T, "Clue Scroll (Easy)", "Other", 26), - AMULET_OF_POWER_T("Power Amulet (t)", ItemID.AMULET_OF_POWER_T, "Clue Scroll (Easy)", "Other", 26), - BLACK_CANE("Black cane", ItemID.BLACK_CANE, "Clue Scroll (Easy)", "Other", 26), - BLACK_PICKAXE("Black pickaxe", ItemID.BLACK_PICKAXE, "Clue Scroll (Easy)", "Other", 26), - LARGE_SPADE("Large spade", ItemID.LARGE_SPADE, "Clue Scroll (Easy)", "Other", 26), - WOODEN_SHIELD_G("Wooden shield (g)", ItemID.WOODEN_SHIELD_G, "Clue Scroll (Easy)", "Golden", 27), - GOLDEN_CHEFS_HAT("Golden chef's hat", ItemID.GOLDEN_CHEFS_HAT, "Clue Scroll (Easy)", "Golden", 27), - GOLDEN_APRON("Golden apron", ItemID.GOLDEN_APRON, "Clue Scroll (Easy)", "Golden", 27), - MONKS_ROBE_TOP_G("Monk robe top (g)", ItemID.MONKS_ROBE_TOP_G, "Clue Scroll (Easy)", "Golden", 27), - MONKS_ROBE_G("Monk robe (g)", ItemID.MONKS_ROBE_G, "Clue Scroll (Easy)", "Golden", 27), - RAIN_BOW("Rain bow", ItemID.RAIN_BOW, "Clue Scroll (Easy)", "Other", 28), - HAM_JOINT("Ham joint", ItemID.HAM_JOINT, "Clue Scroll (Easy)", "Other", 28), - STAFF_OF_BOB_THE_CAT("Staff of Bob the Cat", ItemID.STAFF_OF_BOB_THE_CAT, "Clue Scroll (Easy)", "Other", 28), - - // Medium Clue Scrolls - MITHRIL_FULL_HELM_T("Mithril full helm (t)", ItemID.MITHRIL_FULL_HELM_T, "Clue Scroll (Medium)", "Armor", -1), - MITHRIL_PLATEBODY_T("Mithril platebody (t)", ItemID.MITHRIL_PLATEBODY_T, "Clue Scroll (Medium)", "Armor", -1), - MITHRIL_PLATELEGS_T("Mithril platelegs (t)", ItemID.MITHRIL_PLATELEGS_T, "Clue Scroll (Medium)", "Armor", -1), - MITHRIL_PLATESKIRT_T("Mithril plateskirt (t)", ItemID.MITHRIL_PLATESKIRT_T, "Clue Scroll (Medium)", "Armor", -1), - MITHRIL_KITESHIELD_T("Mithril kiteshield (t)", ItemID.MITHRIL_KITESHIELD_T, "Clue Scroll (Medium)", "Armor", -1), - MITHRIL_FULL_HELM_G("Mithril full helm (g)", ItemID.MITHRIL_FULL_HELM_G, "Clue Scroll (Medium)", "Armor", 0), - MITHRIL_PLATEBODY_G("Mithril platebody (g)", ItemID.MITHRIL_PLATEBODY_G, "Clue Scroll (Medium)", "Armor", 0), - MITHRIL_PLATELEGS_G("Mithril platelegs (g)", ItemID.MITHRIL_PLATELEGS_G, "Clue Scroll (Medium)", "Armor", 0), - MITHRIL_PLATESKIRT_G("Mithril plateskirt (g)", ItemID.MITHRIL_PLATESKIRT_G, "Clue Scroll (Medium)", "Armor", 0), - MITHRIL_KITESHIELD_G("Mithril kiteshield (g)", ItemID.MITHRIL_KITESHIELD_G, "Clue Scroll (Medium)", "Armor", 0), - ADAMANT_FULL_HELM_T("Adamant full helm (t)", ItemID.ADAMANT_FULL_HELM_T, "Clue Scroll (Medium)", "Armor", 1), - ADAMANT_PLATEBODY_T("Adamant platebody (t)", ItemID.ADAMANT_PLATEBODY_T, "Clue Scroll (Medium)", "Armor", 1), - ADAMANT_PLATELEGS_T("Adamant platelegs (t)", ItemID.ADAMANT_PLATELEGS_T, "Clue Scroll (Medium)", "Armor", 1), - ADAMANT_PLATESKIRT_T("Adamant plateskirt (t)", ItemID.ADAMANT_PLATESKIRT_T, "Clue Scroll (Medium)", "Armor", 1), - ADAMANT_KITESHIELD_T("Adamant kiteshield (t)", ItemID.ADAMANT_KITESHIELD_T, "Clue Scroll (Medium)", "Armor", 1), - ADAMANT_FULL_HELM_G("Adamant full helm (g)", ItemID.ADAMANT_FULL_HELM_G, "Clue Scroll (Medium)", "Armor", 2), - ADAMANT_PLATEBODY_G("Adamant platebody (g)", ItemID.ADAMANT_PLATEBODY_G, "Clue Scroll (Medium)", "Armor", 2), - ADAMANT_PLATELEGS_G("Adamant platelegs (g)", ItemID.ADAMANT_PLATELEGS_G, "Clue Scroll (Medium)", "Armor", 2), - ADAMANT_PLATESKIRT_G("Adamant plateskirt (g)", ItemID.ADAMANT_PLATESKIRT_G, "Clue Scroll (Medium)", "Armor", 2), - ADAMANT_KITESHIELD_G("Adamant kiteshield (g)", ItemID.ADAMANT_KITESHIELD_G, "Clue Scroll (Medium)", "Armor", 2), - RANGER_BOOTS("Ranger boots", ItemID.RANGER_BOOTS, "Clue Scroll (Medium)", "Boots", 3), - HOLY_SANDALS("Holy sandals", ItemID.HOLY_SANDALS, "Clue Scroll (Medium)", "Boots", 3), - WIZARD_BOOTS("Wizard boots", ItemID.WIZARD_BOOTS, "Clue Scroll (Medium)", "Boots", 3), - RED_HEADBAND("Red headband", ItemID.RED_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4), - BLACK_HEADBAND("Black headband", ItemID.BLACK_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4), - BROWN_HEADBAND("Brown headband", ItemID.BROWN_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4), - PINK_HEADBAND("Pink headband", ItemID.PINK_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4), - GREEN_HEADBAND("Green headband", ItemID.GREEN_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5), - BLUE_HEADBAND("Blue headband", ItemID.BLUE_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5), - GOLD_HEADBAND("Gold headband", ItemID.GOLD_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5), - WHITE_HEADBAND("White headband", ItemID.WHITE_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5), - RED_BOATER("Red boater", ItemID.RED_BOATER, "Clue Scroll (Medium)", "Boater", 6), - ORANGE_BOATER("Orange boater", ItemID.ORANGE_BOATER, "Clue Scroll (Medium)", "Boater", 6), - GREEN_BOATER("Green boater", ItemID.GREEN_BOATER, "Clue Scroll (Medium)", "Boater", 6), - BLUE_BOATER("Blue boater", ItemID.BLUE_BOATER, "Clue Scroll (Medium)", "Boater", 6), - BLACK_BOATER("Black boater", ItemID.BLACK_BOATER, "Clue Scroll (Medium)", "Boater", 7), - PINK_BOATER("Pink boater", ItemID.PINK_BOATER, "Clue Scroll (Medium)", "Boater", 7), - PURPLE_BOATER("Purple boater", ItemID.PURPLE_BOATER, "Clue Scroll (Medium)", "Boater", 7), - WHITE_BOATER("White boater", ItemID.WHITE_BOATER, "Clue Scroll (Medium)", "Boater", 7), - ADAMANT_HELM_H1("Adamant helm (h1)", ItemID.ADAMANT_HELM_H1, "Clue Scroll (Medium)", "Heraldic", 8), - ADAMANT_HELM_H2("Adamant helm (h2)", ItemID.ADAMANT_HELM_H2, "Clue Scroll (Medium)", "Heraldic", 8), - ADAMANT_HELM_H3("Adamant helm (h3)", ItemID.ADAMANT_HELM_H3, "Clue Scroll (Medium)", "Heraldic", 8), - ADAMANT_HELM_H4("Adamant helm (h4)", ItemID.ADAMANT_HELM_H4, "Clue Scroll (Medium)", "Heraldic", 8), - ADAMANT_HELM_H5("Adamant helm (h5)", ItemID.ADAMANT_HELM_H5, "Clue Scroll (Medium)", "Heraldic", 8), - ADAMANT_SHIELD_H1("Adamant shield (h1)", ItemID.ADAMANT_SHIELD_H1, "Clue Scroll (Medium)", "Heraldic", 9), - ADAMANT_SHIELD_H2("Adamant shield (h2)", ItemID.ADAMANT_SHIELD_H2, "Clue Scroll (Medium)", "Heraldic", 9), - ADAMANT_SHIELD_H3("Adamant shield (h3)", ItemID.ADAMANT_SHIELD_H3, "Clue Scroll (Medium)", "Heraldic", 9), - ADAMANT_SHIELD_H4("Adamant shield (h4)", ItemID.ADAMANT_SHIELD_H4, "Clue Scroll (Medium)", "Heraldic", 9), - ADAMANT_SHIELD_H5("Adamant shield (h5)", ItemID.ADAMANT_SHIELD_H5, "Clue Scroll (Medium)", "Heraldic", 9), - ADAMANT_PLATEBODY_H1("Adamant platebody (h1)", ItemID.ADAMANT_PLATEBODY_H1, "Clue Scroll (Medium)", "Armor", 10), - ADAMANT_PLATEBODY_H2("Adamant platebody (h2)", ItemID.ADAMANT_PLATEBODY_H2, "Clue Scroll (Medium)", "Armor", 10), - ADAMANT_PLATEBODY_H3("Adamant platebody (h3)", ItemID.ADAMANT_PLATEBODY_H3, "Clue Scroll (Medium)", "Armor", 10), - ADAMANT_PLATEBODY_H4("Adamant platebody (h4)", ItemID.ADAMANT_PLATEBODY_H4, "Clue Scroll (Medium)", "Armor", 10), - ADAMANT_PLATEBODY_H5("Adamant platebody (h5)", ItemID.ADAMANT_PLATEBODY_H5, "Clue Scroll (Medium)", "Armor", 10), - GREEN_DHIDE_BODY_T("Green dragonhide body (t)", ItemID.GREEN_DHIDE_BODY_T, "Clue Scroll (Medium)", "Dhide", 11), - GREEN_DHIDE_CHAPS_T("Green dragonhide chaps (t)", ItemID.GREEN_DHIDE_CHAPS_T, "Clue Scroll (Medium)", "Dhide", 11), - GREEN_DHIDE_BODY_G("Green dragonhide body (g)", ItemID.GREEN_DHIDE_BODY_G, "Clue Scroll (Medium)", "Dhide", 11), - GREEN_DHIDE_CHAPS_G("Green dragonhide chaps (g)", ItemID.GREEN_DHIDE_CHAPS_G, "Clue Scroll (Medium)", "Dhide", 11), - BLACK_ELEGANT_SHIRT("Black elegant shirt", ItemID.BLACK_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 12), - BLACK_ELEGANT_LEGS("Black elegant legs", ItemID.BLACK_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 12), - WHITE_ELEGANT_BLOUSE("White elegant blouse", ItemID.WHITE_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 12), - WHITE_ELEGANT_SKIRT("White elegant skirt", ItemID.WHITE_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 12), - PURPLE_ELEGANT_SHIRT("Purple elegant shirt", ItemID.PURPLE_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 13), - PURPLE_ELEGANT_LEGS("Purple elegant legs", ItemID.PURPLE_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 13), - PURPLE_ELEGANT_BLOUSE("Purple elegant blouse", ItemID.PURPLE_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 13), - PURPLE_ELEGANT_SKIRT("Purple elegant skirt", ItemID.PURPLE_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 13), - PINK_ELEGANT_SHIRT("Pink elegant shirt", ItemID.PINK_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 14), - PINK_ELEGANT_LEGS("Pink elegant legs", ItemID.PINK_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 14), - PINK_ELEGANT_BLOUSE("Pink elegant blouse", ItemID.PINK_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 14), - PINK_ELEGANT_SKIRT("Pink elegant skirt", ItemID.PINK_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 14), - GOLD_ELEGANT_SHIRT("Gold elegant shirt", ItemID.GOLD_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 15), - GOLD_ELEGANT_LEGS("Gold elegant legs", ItemID.GOLD_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 15), - GOLD_ELEGANT_BLOUSE("Gold elegant blouse", ItemID.GOLD_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 15), - GOLD_ELEGANT_SKIRT("Gold elegant skirt", ItemID.GOLD_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 15), - GUTHIX_MITRE("Guthix mitre", ItemID.GUTHIX_MITRE, "Clue Scroll (Medium)", "Vestment", 16), - GUTHIX_CLOAK("Guthix cloak", ItemID.GUTHIX_CLOAK, "Clue Scroll (Medium)", "Vestment", 16), - SARADOMIN_MITRE("Saradomin mitre", ItemID.SARADOMIN_MITRE, "Clue Scroll (Medium)", "Vestment", 16), - SARADOMIN_CLOAK("Saradomin cloak", ItemID.SARADOMIN_CLOAK, "Clue Scroll (Medium)", "Vestment", 16), - ZAMORAK_MITRE("Zamorak mitre", ItemID.ZAMORAK_MITRE, "Clue Scroll (Medium)", "Vestment", 16), - ZAMORAK_CLOAK("Zamorak cloak", ItemID.ZAMORAK_CLOAK, "Clue Scroll (Medium)", "Vestment", 16), - ANCIENT_MITRE("Anicent mitre", ItemID.ANCIENT_MITRE, "Clue Scroll (Medium)", "Vestment", 17), - ANCIENT_CLOAK("Anicent cloak", ItemID.ANCIENT_CLOAK, "Clue Scroll (Medium)", "Vestment", 17), - BANDOS_MITRE("Bandos mitre", ItemID.BANDOS_MITRE, "Clue Scroll (Medium)", "Vestment", 17), - BANDOS_CLOAK("Bandos cloak", ItemID.BANDOS_CLOAK, "Clue Scroll (Medium)", "Vestment", 17), - ARMADYL_MITRE("Armadyl mitre", ItemID.ARMADYL_MITRE, "Clue Scroll (Medium)", "Vestment", 17), - ARMADYL_CLOAK("Armadyl cloak", ItemID.ARMADYL_CLOAK, "Clue Scroll (Medium)", "Vestment", 17), - ARMADYL_STOLE("Armadyl stole", ItemID.ARMADYL_STOLE, "Clue Scroll (Medium)", "Vestment", 18), - ARMADYL_CROZIER("Armadyl crozier", ItemID.ARMADYL_CROZIER, "Clue Scroll (Medium)", "Vestment", 18), - ANCIENT_STOLE("Anicent stole", ItemID.ANCIENT_STOLE, "Clue Scroll (Medium)", "Vestment", 18), - ANCIENT_CROZIER("Anicent crozier", ItemID.ANCIENT_CROZIER, "Clue Scroll (Medium)", "Vestment", 18), - BANDOS_STOLE("Bandos stole", ItemID.BANDOS_STOLE, "Clue Scroll (Medium)", "Vestment", 18), - BANDOS_CROZIER("Bandos crozier", ItemID.BANDOS_CROZIER, "Clue Scroll (Medium)", "Vestment", 18), - CAT_MASK("Cat mask", ItemID.CAT_MASK, "Clue Scroll (Medium)", "Masks", 19), - PENGUIN_MASK("Penguin mask", ItemID.PENGUIN_MASK, "Clue Scroll (Medium)", "Masks", 19), - BLACK_UNICORN_MASK("Black unicorn mask", ItemID.BLACK_UNICORN_MASK, "Clue Scroll (Medium)", "Masks", 19), - WHITE_UNICORN_MASK("White unicorn mask", ItemID.WHITE_UNICORN_MASK, "Clue Scroll (Medium)", "Masks", 19), - LEPRECHAUN_HAT("Leprechaun hat", ItemID.LEPRECHAUN_HAT, "Clue Scroll (Medium)", "Masks", 19), - BLACK_LEPRECHAUN_HAT("Black leprechaun hat", ItemID.BLACK_LEPRECHAUN_HAT, "Clue Scroll (Medium)", "Masks", 19), - CRIER_HAT("Crier hat", ItemID.CRIER_HAT, "Clue Scroll (Medium)", "Crier", 20), - CRIER_BELL("Crier bell", ItemID.CRIER_BELL, "Clue Scroll (Medium)", "Crier", 20), - CRIER_COAT("Crier coat", ItemID.CRIER_COAT, "Clue Scroll (Medium)", "Crier", 20), - ARCEUUS_BANNER("Arceeus banner", ItemID.ARCEUUS_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21), - HOSIDIUS_BANNER("Hosidius banner", ItemID.HOSIDIUS_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21), - LOVAKENGJ_BANNER("Lovakengj banner", ItemID.LOVAKENGJ_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21), - PISCARILIUS_BANNER("Picarilius banner", ItemID.PISCARILIUS_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21), - SHAYZIEN_BANNER("Shayzien banner", ItemID.SHAYZIEN_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21), - STRENGTH_AMULET_T("Strength amulet (t)", ItemID.STRENGTH_AMULET_T, "Clue Scroll (Medium)", "Other", 22), - ADAMANT_CANE("Adamant cane", ItemID.ADAMANT_CANE, "Clue Scroll (Medium)", "Other", 22), - GNOMISH_FIRELIGHTER("Gnomish firelighter", ItemID.GNOMISH_FIRELIGHTER, "Clue Scroll (Medium)", "Other", 22), - CABBAGE_ROUND_SHIELD("Cabbage round shield", ItemID.CABBAGE_ROUND_SHIELD, "Clue Scroll (Medium)", "Other", 22), - CLUELESS_SCROLL("Clueless scroll", ItemID.CLUELESS_SCROLL, "Clue Scroll (Medium)", "Other", 22), - SPIKED_MANACLES("Spiked manacles", ItemID.SPIKED_MANACLES, "Clue Scroll (Medium)", "Other", 23), - WOLF_MASK("Wolf mask", ItemID.WOLF_MASK, "Clue Scroll (Medium)", "Other", 23), - WOLF_CLOAK("Wolf cloak", ItemID.WOLF_CLOAK, "Clue Scroll (Medium)", "Other", 23), - CLIMBING_BOOTS_G("Climbing boots (g)", ItemID.CLIMBING_BOOTS_G, "Clue Scroll (Medium)", "Other", 23), - - // Hard Clue Scrolls - RUNE_FULL_HELM_T("Rune full helm (t)", ItemID.RUNE_FULL_HELM_T, "Clue Scroll (Hard)", "Armor", -1), - RUNE_PLATEBODY_T("Rune platebody (t)", ItemID.RUNE_PLATEBODY_T, "Clue Scroll (Hard)", "Armor", -1), - RUNE_PLATELEGS_T("Rune platelegs (t)", ItemID.RUNE_PLATELEGS_T, "Clue Scroll (Hard)", "Armor", -1), - RUNE_PLATESKIRT_T("Rune plateskirt (t)", ItemID.RUNE_PLATESKIRT_T, "Clue Scroll (Hard)", "Armor", -1), - RUNE_KITESHIELD_T("Rune kiteshield (t)", ItemID.RUNE_KITESHIELD_T, "Clue Scroll (Hard)", "Armor", -1), - RUNE_FULL_HELM_G("Rune full helm (g)", ItemID.RUNE_FULL_HELM_G, "Clue Scroll (Hard)", "Armor", 0), - RUNE_PLATEBODY_G("Rune platebody (g)", ItemID.RUNE_PLATEBODY_G, "Clue Scroll (Hard)", "Armor", 0), - RUNE_PLATELEGS_G("Rune platelegs (g)", ItemID.RUNE_PLATELEGS_G, "Clue Scroll (Hard)", "Armor", 0), - RUNE_PLATESKIRT_G("Rune plateskirt (g)", ItemID.RUNE_PLATESKIRT_G, "Clue Scroll (Hard)", "Armor", 0), - RUNE_KITESHIELD_G("Rune kiteshield (g)", ItemID.RUNE_KITESHIELD_G, "Clue Scroll (Hard)", "Armor", 0), - GUTHIX_FULL_HELM("Guthix full helm", ItemID.GUTHIX_FULL_HELM, "Clue Scroll (Hard)", "Armor", 1), - GUTHIX_PLATEBODY("Guthix platebody", ItemID.GUTHIX_PLATEBODY, "Clue Scroll (Hard)", "Armor", 1), - GUTHIX_PLATELEGS("Guthix platelegs", ItemID.GUTHIX_PLATELEGS, "Clue Scroll (Hard)", "Armor", 1), - GUTHIX_PLATESKIRT("Guthix plateskirt", ItemID.GUTHIX_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 1), - GUTHIX_KITESHIELD("Guthix kiteshield", ItemID.GUTHIX_KITESHIELD, "Clue Scroll (Hard)", "Armor", 1), - SARADOMIN_FULL_HELM("Saradomin full helm", ItemID.SARADOMIN_FULL_HELM, "Clue Scroll (Hard)", "Armor", 2), - SARADOMIN_PLATEBODY("Saradomin platebody", ItemID.SARADOMIN_PLATEBODY, "Clue Scroll (Hard)", "Armor", 2), - SARADOMIN_PLATELEGS("Saradomin platelegs", ItemID.SARADOMIN_PLATELEGS, "Clue Scroll (Hard)", "Armor", 2), - SARADOMIN_PLATESKIRT("Saradomin plateskirt", ItemID.SARADOMIN_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 2), - SARADOMIN_KITESHIELD("Saradomin kiteshield", ItemID.SARADOMIN_KITESHIELD, "Clue Scroll (Hard)", "Armor", 2), - ZAMORAK_FULL_HELM("Zamorak full helm", ItemID.ZAMORAK_FULL_HELM, "Clue Scroll (Hard)", "Armor", 3), - ZAMORAK_PLATEBODY("Zamorak platebody", ItemID.ZAMORAK_PLATEBODY, "Clue Scroll (Hard)", "Armor", 3), - ZAMORAK_PLATELEGS("Zamorak platelegs", ItemID.ZAMORAK_PLATELEGS, "Clue Scroll (Hard)", "Armor", 3), - ZAMORAK_PLATESKIRT("Zamorak plateskirt", ItemID.ZAMORAK_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 3), - ZAMORAK_KITESHIELD("Zamorak kiteshield", ItemID.ZAMORAK_KITESHIELD, "Clue Scroll (Hard)", "Armor", 3), - ANCIENT_FULL_HELM("Ancient full helm", ItemID.ANCIENT_FULL_HELM, "Clue Scroll (Hard)", "Armor", 4), - ANCIENT_PLATEBODY("Ancient platebody", ItemID.ANCIENT_PLATEBODY, "Clue Scroll (Hard)", "Armor", 4), - ANCIENT_PLATELEGS("Ancient platelegs", ItemID.ANCIENT_PLATELEGS, "Clue Scroll (Hard)", "Armor", 4), - ANCIENT_PLATESKIRT("Ancient plateskirt", ItemID.ANCIENT_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 4), - ANCIENT_KITESHIELD("Ancient kiteshield", ItemID.ANCIENT_KITESHIELD, "Clue Scroll (Hard)", "Armor", 4), - BANDOS_FULL_HELM("Bandos full helm", ItemID.BANDOS_FULL_HELM, "Clue Scroll (Hard)", "Armor", 5), - BANDOS_PLATEBODY("Bandos platebody", ItemID.BANDOS_PLATEBODY, "Clue Scroll (Hard)", "Armor", 5), - BANDOS_PLATELEGS("Bandos platelegs", ItemID.BANDOS_PLATELEGS, "Clue Scroll (Hard)", "Armor", 5), - BANDOS_PLATESKIRT("Bandos plateskirt", ItemID.BANDOS_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 5), - BANDOS_KITESHIELD("Bandos kiteshield", ItemID.BANDOS_KITESHIELD, "Clue Scroll (Hard)", "Armor", 5), - ARMADYL_FULL_HELM("Armadyl full helm", ItemID.ARMADYL_FULL_HELM, "Clue Scroll (Hard)", "Armor", 6), - ARMADYL_PLATEBODY("Armadyl platebody", ItemID.ARMADYL_PLATEBODY, "Clue Scroll (Hard)", "Armor", 6), - ARMADYL_PLATELEGS("Armadyl platelegs", ItemID.ARMADYL_PLATELEGS, "Clue Scroll (Hard)", "Armor", 6), - ARMADYL_PLATESKIRT("Armadyl plateskirt", ItemID.ARMADYL_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 6), - ARMADYL_KITESHIELD("Armadyl kiteshield", ItemID.ARMADYL_KITESHIELD, "Clue Scroll (Hard)", "Armor", 6), - GILDED_FULL_HELM("Gilded full helm", ItemID.GILDED_FULL_HELM, "Clue Scroll (Hard)", "Gilded", 7), - GILDED_PLATEBODY("Gilded platebody", ItemID.GILDED_PLATEBODY, "Clue Scroll (Hard)", "Gilded", 7), - GILDED_PLATELEGS("Gilded platelegs", ItemID.GILDED_PLATELEGS, "Clue Scroll (Hard)", "Gilded", 7), - GILDED_PLATESKIRT("Gilded plateskirt", ItemID.GILDED_PLATESKIRT, "Clue Scroll (Hard)", "Gilded", 7), - GILDED_KITESHIELD("Gilded kiteshield", ItemID.GILDED_KITESHIELD, "Clue Scroll (Hard)", "Gilded", 7), - GILDED_MED_HELM("Gilded med helm", ItemID.GILDED_MED_HELM, "Clue Scroll (Hard)", "Gilded", 8), - GILDED_CHAINBODY("Gilded chainbody", ItemID.GILDED_CHAINBODY, "Clue Scroll (Hard)", "Gilded", 8), - GILDED_SQ_SHIELD("Gilded sq shield", ItemID.GILDED_SQ_SHIELD, "Clue Scroll (Hard)", "Gilded", 8), - GILDED_2H_SWORD("Gilded 2H sword", ItemID.GILDED_2H_SWORD, "Clue Scroll (Hard)", "Gilded", 8), - GILDED_SPEAR("Gilded spear", ItemID.GILDED_SPEAR, "Clue Scroll (Hard)", "Gilded", 8), - GILDED_HASTA("Gilded hasta", ItemID.GILDED_HASTA, "Clue Scroll (Hard)", "Gilded", 8), - RUNE_HELM_H1("Rune helm (h1)", ItemID.RUNE_HELM_H1, "Clue Scroll (Hard)", "Heraldic", 9), - RUNE_HELM_H2("Rune helm (h2)", ItemID.RUNE_HELM_H2, "Clue Scroll (Hard)", "Heraldic", 9), - RUNE_HELM_H3("Rune helm (h3)", ItemID.RUNE_HELM_H3, "Clue Scroll (Hard)", "Heraldic", 9), - RUNE_HELM_H4("Rune helm (h4)", ItemID.RUNE_HELM_H4, "Clue Scroll (Hard)", "Heraldic", 9), - RUNE_HELM_H5("Rune helm (h5)", ItemID.RUNE_HELM_H5, "Clue Scroll (Hard)", "Heraldic", 9), - RUNE_SHIELD_H1("Rune shield (h1)", ItemID.RUNE_SHIELD_H1, "Clue Scroll (Hard)", "Heraldic", 10), - RUNE_SHIELD_H2("Rune shield (h2)", ItemID.RUNE_SHIELD_H2, "Clue Scroll (Hard)", "Heraldic", 10), - RUNE_SHIELD_H3("Rune shield (h3)", ItemID.RUNE_SHIELD_H3, "Clue Scroll (Hard)", "Heraldic", 10), - RUNE_SHIELD_H4("Rune shield (h4)", ItemID.RUNE_SHIELD_H4, "Clue Scroll (Hard)", "Heraldic", 10), - RUNE_SHIELD_H5("Rune shield (h5)", ItemID.RUNE_SHIELD_H5, "Clue Scroll (Hard)", "Heraldic", 10), - RUNE_PLATEBODY_H1("Rune platebody (h1)", ItemID.RUNE_PLATEBODY_H1, "Clue Scroll (Hard)", "Heraldic", 11), - RUNE_PLATEBODY_H2("Rune platebody (h2)", ItemID.RUNE_PLATEBODY_H2, "Clue Scroll (Hard)", "Heraldic", 11), - RUNE_PLATEBODY_H3("Rune platebody (h3)", ItemID.RUNE_PLATEBODY_H3, "Clue Scroll (Hard)", "Heraldic", 11), - RUNE_PLATEBODY_H4("Rune platebody (h4)", ItemID.RUNE_PLATEBODY_H4, "Clue Scroll (Hard)", "Heraldic", 11), - RUNE_PLATEBODY_H5 ("Rune platebody (h5)", ItemID.RUNE_PLATEBODY_H5, "Clue Scroll (Hard)", "Heraldic", 11), - - BLUE_DHIDE_BODY_T("Blue dhide body (t)", ItemID.BLUE_DHIDE_BODY_T, "Clue Scroll (Hard)", "Dhide", 12), - BLUE_DHIDE_CHAPS_T("Blue dhide chaps (t)", ItemID.BLUE_DHIDE_CHAPS_T, "Clue Scroll (Hard)", "Dhide", 12), - BLUE_DHIDE_BODY_G("Blue dhide body (g)", ItemID.BLUE_DHIDE_BODY_G, "Clue Scroll (Hard)", "Dhide", 12), - BLUE_DHIDE_CHAPS_G("Blue dhide chaps (g)", ItemID.BLUE_DHIDE_CHAPS_G, "Clue Scroll (Hard)", "Dhide", 12), - RED_DHIDE_BODY_T("Red dhide body (t)", ItemID.RED_DHIDE_BODY_T, "Clue Scroll (Hard)", "Dhide", 13), - RED_DHIDE_CHAPS_T("Red dhide chaps (t)", ItemID.RED_DHIDE_CHAPS_T, "Clue Scroll (Hard)", "Dhide", 13), - RED_DHIDE_BODY_G("Red dhide body (g)", ItemID.RED_DHIDE_BODY_G, "Clue Scroll (Hard)", "Dhide", 13), - RED_DHIDE_CHAPS_G("Red dhide chaps (g)", ItemID.RED_DHIDE_CHAPS_G, "Clue Scroll (Hard)", "Dhide", 13), - ENCHANTED_HAT("Enchanted hat", ItemID.ENCHANTED_HAT, "Clue Scroll (Hard)", "Enchanted", 14), - ENCHANTED_TOP("Enchanted top", ItemID.ENCHANTED_TOP, "Clue Scroll (Hard)", "Enchanted", 14), - ENCHANTED_ROBE("Enchanted robe", ItemID.ENCHANTED_ROBE, "Clue Scroll (Hard)", "Enchanted", 14), - AMULET_OF_GLORY_T("Amulet of glory (t)", ItemID.AMULET_OF_GLORY_T, "Clue Scroll (Hard)", "Enchanted", 14), - ROBIN_HOOD_HAT("Robin hood hat", ItemID.ROBIN_HOOD_HAT, "Clue Scroll (Hard)", "Hats", 15), - PIRATE_HAT("Pirate hat", ItemID.PIRATE_HAT, "Clue Scroll (Hard)", "Hats", 15), - PITH_HELMET("Pith helmet", ItemID.PITH_HELMET, "Clue Scroll (Hard)", "Hats", 15), - EXPLORER_BACKPACK("Explorer backpack", ItemID.EXPLORER_BACKPACK, "Clue Scroll (Hard)", "Hats", 15), - RED_CAVALIER("Red cavalier", ItemID.RED_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16), - TAN_CAVALIER("Tan cavalier", ItemID.TAN_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16), - DARK_CAVALIER("Dark cavalier", ItemID.DARK_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16), - BLACK_CAVALIER("Black cavalier", ItemID.BLACK_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16), - NAVY_CAVALIER("Navy cavalier", ItemID.NAVY_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16), - WHITE_CAVALIER("White cavalier", ItemID.WHITE_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16), - _3RD_AGE_FULL_HELMET("3rd age full helm", ItemID._3RD_AGE_FULL_HELMET, "Clue Scroll (Hard)", "Third age", 17), - _3RD_AGE_PLATEBODY("3rd age platebody", ItemID._3RD_AGE_PLATEBODY, "Clue Scroll (Hard)", "Third age", 17), - _3RD_AGE_PLATELEGS("3rd age platelegs", ItemID._3RD_AGE_PLATELEGS, "Clue Scroll (Hard)", "Third age", 17), - _3RD_AGE_PLATESKIRT("3rd age plateskirt", ItemID._3RD_AGE_PLATESKIRT, "Clue Scroll (Hard)", "Third age", 17), - _3RD_AGE_KITESHIELD("3rd age kiteshield", ItemID._3RD_AGE_KITESHIELD, "Clue Scroll (Hard)", "Third age", 17), - _3RD_AGE_RANGE_COIF("3rd age range coif", ItemID._3RD_AGE_RANGE_COIF, "Clue Scroll (Hard)", "Third age", 18), - _3RD_AGE_RANGE_TOP("3rd age range top", ItemID._3RD_AGE_RANGE_TOP, "Clue Scroll (Hard)", "Third age", 18), - _3RD_AGE_RANGE_LEGS("3rd age range legs", ItemID._3RD_AGE_RANGE_LEGS, "Clue Scroll (Hard)", "Third age", 18), - _3RD_AGE_VAMBRACES("3rd age vambraces", ItemID._3RD_AGE_VAMBRACES, "Clue Scroll (Hard)", "Third age", 18), - _3RD_AGE_MAGE_HAT("3rd age mage hat", ItemID._3RD_AGE_MAGE_HAT, "Clue Scroll (Hard)", "Third age", 19), - _3RD_AGE_ROBE_TOP("3rd age robe top", ItemID._3RD_AGE_ROBE_TOP, "Clue Scroll (Hard)", "Third age", 19), - _3RD_AGE_ROBE("3rd age robe", ItemID._3RD_AGE_ROBE, "Clue Scroll (Hard)", "Third age", 19), - _3RD_AGE_AMULET("3rd age amulet", ItemID._3RD_AGE_AMULET, "Clue Scroll (Hard)", "Third age", 19), - GUTHIX_COIF("Guthix coif", ItemID.GUTHIX_COIF, "Clue Scroll (Hard)", "God Dhide", 20), - GUTHIX_DHIDE("Guthix dragonhide", ItemID.GUTHIX_DRAGONHIDE, "Clue Scroll (Hard)", "God Dhide", 20), - GUTHIX_CHAPS("Guthix chaps", ItemID.GUTHIX_CHAPS, "Clue Scroll (Hard)", "God Dhide", 20), - GUTHIX_BRACERS("Guthix bracers", ItemID.GUTHIX_BRACERS, "Clue Scroll (Hard)", "God Dhide", 20), - GUTHIX_DHIDE_BOOTS("Guthix dhide boots", ItemID.GUTHIX_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 20), - GUTHIX_DHIDE_SHIELD("Guthix dhide shield", ItemID.GUTHIX_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 20), - SARADOMIN_COIF("Saradomin coif", ItemID.SARADOMIN_COIF, "Clue Scroll (Hard)", "God Dhide", 21), - SARADOMIN_DHIDE("Saradomin dragonhide", ItemID.SARADOMIN_DHIDE, "Clue Scroll (Hard)", "God Dhide", 21), - SARADOMIN_CHAPS("Saradomin chaps", ItemID.SARADOMIN_CHAPS, "Clue Scroll (Hard)", "God Dhide", 21), - SARADOMIN_BRACERS("Saradomin bracers", ItemID.SARADOMIN_BRACERS, "Clue Scroll (Hard)", "God Dhide", 21), - SARADOMIN_DHIDE_BOOTS("Saradomin dhide boots", ItemID.SARADOMIN_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 21), - SARADOMIN_DHIDE_SHIELD("Saradomin dhide shield", ItemID.SARADOMIN_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 21), - ZAMORAK_COIF("Zamorak coif", ItemID.ZAMORAK_COIF, "Clue Scroll (Hard)", "God Dhide", 22), - ZAMORAK_DHIDE("Zamorak dragonhide", ItemID.ZAMORAK_DHIDE, "Clue Scroll (Hard)", "God Dhide", 22), - ZAMORAK_CHAPS("Zamorak chaps", ItemID.ZAMORAK_CHAPS, "Clue Scroll (Hard)", "God Dhide", 22), - ZAMORAK_BRACERS("Zamorak bracers", ItemID.ZAMORAK_BRACERS, "Clue Scroll (Hard)", "God Dhide", 22), - ZAMORAK_DHIDE_BOOTS("Zamorak dhide boots", ItemID.ZAMORAK_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 22), - ZAMORAK_DHIDE_SHIELD("Zamorak dhide shield", ItemID.ZAMORAK_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 22), - ANCIENT_COIF("Ancient coif", ItemID.ANCIENT_COIF, "Clue Scroll (Hard)", "God Dhide", 23), - ANCIENT_DHIDE("Ancient dragonhide", ItemID.ANCIENT_DHIDE, "Clue Scroll (Hard)", "God Dhide", 23), - ANCIENT_CHAPS("Ancient chaps", ItemID.ANCIENT_CHAPS, "Clue Scroll (Hard)", "God Dhide", 23), - ANCIENT_BRACERS("Ancient bracers", ItemID.ANCIENT_BRACERS, "Clue Scroll (Hard)", "God Dhide", 23), - ANCIENT_DHIDE_BOOTS("Ancient dhide boots", ItemID.ANCIENT_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 23), - ANCIENT_DHIDE_SHIELD("Ancient dhide shield", ItemID.ANCIENT_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 23), - BANDOS_COIF("Bandos coif", ItemID.BANDOS_COIF, "Clue Scroll (Hard)", "God Dhide", 24), - BANDOS_DHIDE("Bandos dragonhide", ItemID.BANDOS_DHIDE, "Clue Scroll (Hard)", "God Dhide", 24), - BANDOS_CHAPS("Bandos chaps", ItemID.BANDOS_CHAPS, "Clue Scroll (Hard)", "God Dhide", 24), - BANDOS_BRACERS("Bandos bracers", ItemID.BANDOS_BRACERS, "Clue Scroll (Hard)", "God Dhide", 24), - BANDOS_DHIDE_BOOTS("Bandos dhide boots", ItemID.BANDOS_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 24), - BANDOS_DHIDE_SHIELD("Bandos dhide shield", ItemID.BANDOS_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 24), - ARMADYL_COIF("Armadyl coif", ItemID.ARMADYL_COIF, "Clue Scroll (Hard)", "God Dhide", 25), - ARMADYL_DHIDE("Armadyl dragonhide", ItemID.ARMADYL_DHIDE, "Clue Scroll (Hard)", "God Dhide", 25), - ARMADYL_CHAPS("Armadyl chaps", ItemID.ARMADYL_CHAPS, "Clue Scroll (Hard)", "God Dhide", 25), - ARMADYL_BRACERS("Armadyl bracers", ItemID.ARMADYL_BRACERS, "Clue Scroll (Hard)", "God Dhide", 25), - ARMADYL_DHIDE_BOOTS("Armadyl dhide boots", ItemID.ARMADYL_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 25), - ARMADYL_DHIDE_SHIELD("Armadyl dhide shield", ItemID.ARMADYL_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 25), - GUTHIX_STOLE("Guthix stole", ItemID.GUTHIX_STOLE, "Clue Scroll (Hard)", "Vestment", 26), - GUTHIX_CROZIER("Guthix crozier", ItemID.GUTHIX_CROZIER, "Clue Scroll (Hard)", "Vestment", 26), - SARADOMIN_STOLE("Saradomin stole", ItemID.SARADOMIN_STOLE, "Clue Scroll (Hard)", "Vestment", 26), - SARADOMIN_CROZIER("Saradomin crozier", ItemID.SARADOMIN_CROZIER, "Clue Scroll (Hard)", "Vestment", 26), - ZAMORAK_STOLE("Zamorak stole", ItemID.ZAMORAK_STOLE, "Clue Scroll (Hard)", "Vestment", 26), - ZAMORAK_CROZIER("Zamorak crozier", ItemID.ZAMORAK_CROZIER, "Clue Scroll (Hard)", "Vestment", 26), - GREEN_DRAGON_MASK("Green dragon mask", ItemID.GREEN_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27), - RED_DRAGON_MASK("Red dragon mask", ItemID.RED_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27), - BLUE_DRAGON_MASK("Blue dragon mask", ItemID.BLUE_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27), - BLACK_DRAGON_MASK("Black dragon mask", ItemID.BLACK_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27), - RUNE_CANE("Rune cane", ItemID.RUNE_CANE, "Clue Scroll (Hard)", "Other", 28), - ZOMBIE_HEAD("Zombie head", ItemID.ZOMBIE_HEAD, "Clue Scroll (Hard)", "Other", 28), - CYCLOPS_HEAD("Cyclops head", ItemID.CYCLOPS_HEAD, "Clue Scroll (Hard)", "Other", 28), - NUNCHAKU("Nunchaku", ItemID.NUNCHAKU, "Clue Scroll (Hard)", "Other", 29), - DUAL_SAI("Dual sai", ItemID.DUAL_SAI, "Clue Scroll (Hard)", "Other", 29), - THIEVING_BAG("Thieving bag", ItemID.THIEVING_BAG, "Clue Scroll (Hard)", "Other", 29), - DRAGON_BOOTS_ORNAMENT_KIT("Dragon boots ornament kit", ItemID.DRAGON_BOOTS_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30), - RUNE_DEFENDER_ORNAMENT_KIT("Rune defender ornament kit", ItemID.RUNE_DEFENDER_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30), - TZHAARKETOM_ORNAMENT_KIT("Tzhaar-ket-om ornament kit", ItemID.TZHAARKETOM_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30), - BERSERKER_NECKLACE_ORNAMENT_KIT("Berserker necklace ornament kit", ItemID.BERSERKER_NECKLACE_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30), - - // Elite Clue Scrolls - DRAGON_FULL_HELM_ORNAMENT_KIT("Dragon full helm ornament kit", ItemID.DRAGON_FULL_HELM_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1), - DRAGON_CHAINBODY_ORNAMENT_KIT("Dragon chainbody ornament kit", ItemID.DRAGON_CHAINBODY_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1), - DRAGON_LEGSSKIRT_ORNAMENT_KIT("Dragon legs/skirt ornament kit", ItemID.DRAGON_LEGSSKIRT_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1), - DRAGON_SQ_SHIELD_ORNAMENT_KIT("Dragon sq shield ornament kit", ItemID.DRAGON_SQ_SHIELD_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1), - DRAGON_SCIMITAR_ORNAMENT_KIT("Dragon scimitar ornament kit", ItemID.DRAGON_SCIMITAR_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1), - LIGHT_INFINITY_COLOUR_KIT("Light infinity colour kit", ItemID.LIGHT_INFINITY_COLOUR_KIT, "Clue Scroll (Elite)", "Colour Kits", 0), - DARK_INFINITY_COLOUR_KIT("Dark infinity colour kit", ItemID.DARK_INFINITY_COLOUR_KIT, "Clue Scroll (Elite)", "Colour Kits", 0), - FURY_ORNAMENT_KIT("Fury ornament kit", ItemID.FURY_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", 0), - MUSKETEER_HAT("Musketeer hat", ItemID.MUSKETEER_HAT, "Clue Scroll (Elite)", "Musketeer", 1), - MUSKETEER_TABARD("Musketeer tabard", ItemID.MUSKETEER_TABARD, "Clue Scroll (Elite)", "Musketeer", 1), - MUSKETEER_PANTS("Musketeer pants", ItemID.MUSKETEER_PANTS, "Clue Scroll (Elite)", "Musketeer", 1), - DRAGON_CANE("Dragon cane", ItemID.DRAGON_CANE, "Clue Scroll (Elite)", "Musketeer", 1), - TOP_HAT("Top hat", ItemID.TOP_HAT, "Clue Scroll (Elite)", "Fancy", 2), - MONOCLE("Monocle", ItemID.MONOCLE, "Clue Scroll (Elite)", "Fancy", 2), - BRIEFCASE("Briefcase", ItemID.BRIEFCASE, "Clue Scroll (Elite)", "Fancy", 2), - SAGACIOUS_SPECTACLES("Sagacious spectacles", ItemID.SAGACIOUS_SPECTACLES, "Clue Scroll (Elite)", "Fancy", 2), - BIG_PIRATE_HAT("Big pirate hat", ItemID.BIG_PIRATE_HAT, "Clue Scroll (Elite)", "Hats", 3), - DEERSTALKER("Deerstalker", ItemID.DEERSTALKER, "Clue Scroll (Elite)", "Hats", 3), - BLACKSMITHS_HELM("Blacksmith's helm", ItemID.BLACKSMITHS_HELM, "Clue Scroll (Elite)", "Hats", 3), - BUCKET_HELM("Bucket helm", ItemID.BUCKET_HELM, "Clue Scroll (Elite)", "Hats", 3), - AFRO("Afro", ItemID.AFRO, "Clue Scroll (Elite)", "Hats", 3), - GILDED_BOOTS("Gilded boots", ItemID.GILDED_BOOTS, "Clue Scroll (Elite)", "Rare", 4), - GILDED_SCIMITAR("Gilded scimitar", ItemID.GILDED_SCIMITAR, "Clue Scroll (Elite)", "Rare", 4), - RANGERS_TUNIC("Rangers' tunic", ItemID.RANGERS_TUNIC, "Clue Scroll (Elite)", "Rare", 4), - RANGERS_TIGHTS("Rangers' tights", ItemID.RANGERS_TIGHTS, "Clue Scroll (Elite)", "Rare", 4), - RANGER_GLOVES("Ranger gloves", ItemID.RANGER_GLOVES, "Clue Scroll (Elite)", "Rare", 4), - BRONZE_DRAGON_MASK("Bronze dragon mask", ItemID.BRONZE_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5), - IRON_DRAGON_MASK("Iron dragon mask", ItemID.IRON_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5), - STEEL_DRAGON_MASK("Steel dragon mask", ItemID.STEEL_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5), - MITHRIL_DRAGON_MASK("Mithril dragon mask", ItemID.MITHRIL_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5), - ADAMANT_DRAGON_MASK("Adamant dragon mask", ItemID.ADAMANT_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 6), - RUNE_DRAGON_MASK("Rune dragon mask", ItemID.RUNE_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 6), - LAVA_DRAGON_MASK("Lava dragon mask", ItemID.LAVA_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 6), - BLACK_DHIDE_BODY_T("Black dhide body (t)", ItemID.BLACK_DHIDE_BODY_T, "Clue Scroll (Elite)", "Dhide", 7), - BLACK_DHIDE_CHAPS_T("Black dhide chaps (t)", ItemID.BLACK_DHIDE_CHAPS_T, "Clue Scroll (Elite)", "Dhide", 7), - BLACK_DHIDE_BODY_G("Black dhide body (g)", ItemID.BLACK_DHIDE_BODY_G, "Clue Scroll (Elite)", "Dhide", 7), - BLACK_DHIDE_CHAPS_G("Black dhide chaps (g)", ItemID.BLACK_DHIDE_CHAPS_G, "Clue Scroll (Elite)", "Dhide", 7), - GILDED_COIF("Gilded coif", ItemID.GILDED_COIF, "Clue Scroll (Elite)", "Dhide", 8), - GILDED_DHIDE_BODY("Gilded dhide body", ItemID.GILDED_DHIDE_BODY, "Clue Scroll (Elite)", "Dhide", 8), - GILDED_DHIDE_CHAPS("Gilded dhide chaps", ItemID.GILDED_DHIDE_CHAPS, "Clue Scroll (Elite)", "Dhide", 8), - GILDED_DHIDE_VAMBS("Gilded dhide vambs", ItemID.GILDED_DHIDE_VAMBS, "Clue Scroll (Elite)", "Dhide", 8), - _3RD_AGE_CLOAK("3rd age cloak", ItemID._3RD_AGE_CLOAK, "Clue Scroll (Elite)", "Third Age", 9), - _3RD_AGE_WAND("3rd age wand", ItemID._3RD_AGE_WAND, "Clue Scroll (Elite)", "Third Age", 9), - _3RD_AGE_BOW("3rd age bow", ItemID._3RD_AGE_BOW, "Clue Scroll (Elite)", "Third Age", 9), - _3RD_AGE_LONGSWORD("3rd age longsword", ItemID._3RD_AGE_LONGSWORD, "Clue Scroll (Elite)", "Third Age", 9), - ROYAL_CROWN("Royal crown", ItemID.ROYAL_CROWN, "Clue Scroll (Elite)", "Royal", 10), - ROYAL_GOWN_TOP("Royal gown top", ItemID.ROYAL_GOWN_TOP, "Clue Scroll (Elite)", "Royal", 10), - ROYAL_GOWN_BOTTOM("Royal gown bottom", ItemID.ROYAL_GOWN_BOTTOM, "Clue Scroll (Elite)", "Royal", 10), - ROYAL_SCEPTRE("Royal sceptre", ItemID.ROYAL_SCEPTRE, "Clue Scroll (Elite)", "Royal", 10), - GILDED_PICKAXE("Gilded pickaxe", ItemID.GILDED_PICKAXE, "Clue Scroll (Elite)", "Gilded", 11), - GILDED_AXE("Gilded axe", ItemID.GILDED_AXE, "Clue Scroll (Elite)", "Gilded", 11), - GILDED_SPADE("Gilded spade", ItemID.GILDED_SPADE, "Clue Scroll (Elite)", "Gilded", 11), - ARCEUUS_SCARF("Arceuus house scarf", ItemID.ARCEUUS_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12), - HOSIDIUS_SCARF("Hosidius house scarf", ItemID.HOSIDIUS_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12), - LOVAKENGJ_SCARF("Lovakengj house scarf", ItemID.LOVAKENGJ_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12), - PISCARILIUS_SCARF("Piscarilius house scarf", ItemID.PISCARILIUS_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12), - SHAYZIEN_SCARF("Shayzien house scarf", ItemID.SHAYZIEN_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12), - DARK_BOW_TIE("Dark bow tie", ItemID.DARK_BOW_TIE, "Clue Scroll (Elite)", "Dark Tuxedo", 13), - DARK_TUXEDO_JACKET("Dark tuxedo jacket", ItemID.DARK_TUXEDO_JACKET, "Clue Scroll (Elite)", "Dark Tuxedo", 13), - DARK_TROUSERS("Dark trousers", ItemID.DARK_TROUSERS, "Clue Scroll (Elite)", "Dark Tuxedo", 13), - DARK_TUXEDO_CUFFS("Dark tuxedo cuffs", ItemID.DARK_TUXEDO_CUFFS, "Clue Scroll (Elite)", "Dark Tuxedo", 13), - DARK_TUXEDO_SHOES("Dark tuxedo shoes", ItemID.DARK_TUXEDO_SHOES, "Clue Scroll (Elite)", "Dark Tuxedo", 13), - LIGHT_BOW_TIE("Light bow tie", ItemID.LIGHT_BOW_TIE, "Clue Scroll (Elite)", "Light Tuxedo", 14), - LIGHT_TUXEDO_JACKET("Light tuxedo jacket", ItemID.LIGHT_TUXEDO_JACKET, "Clue Scroll (Elite)", "Light Tuxedo", 14), - LIGHT_TROUSERS("Light trousers", ItemID.LIGHT_TROUSERS, "Clue Scroll (Elite)", "Light Tuxedo", 14), - LIGHT_TUXEDO_CUFFS("Light tuxedo cuffs", ItemID.LIGHT_TUXEDO_CUFFS, "Clue Scroll (Elite)", "Light Tuxedo", 14), - LIGHT_TUXEDO_SHOES("Light tuxedo shoes", ItemID.LIGHT_TUXEDO_SHOES, "Clue Scroll (Elite)", "Light Tuxedo", 14), - HOLY_WRAPS("Holy wraps", ItemID.HOLY_WRAPS, "Clue Scroll (Elite)", "Other", 15), - RING_OF_NATURE("Ring of nature", ItemID.RING_OF_NATURE, "Clue Scroll (Elite)", "Other", 15), - HEAVY_CASKET("Heavy casket", ItemID.HEAVY_CASKET, "Clue Scroll (Elite)", "Other", 15), - KATANA("Katana", ItemID.KATANA, "Clue Scroll (Elite)", "Other", 16), - URIS_HAT("Uri's hat", ItemID.URIS_HAT, "Clue Scroll (Elite)", "Other", 16), - FREMENNIK_KILT("Fremennik Kilt", ItemID.FREMENNIK_KILT, "Clue Scroll (Elite)", "Other", 16), - - // Master Clue Scrolls - DRAGON_PLATEBODY_ORNAMENT_KIT("Dragon platebody ornament kit", ItemID.DRAGON_PLATEBODY_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1), - DRAGON_KITESHIELD_ORNAMENT_KIT("Dragon kiteshield ornament kit", ItemID.DRAGON_KITESHIELD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1), - DRAGON_DEFENDER_ORNAMENT_KIT("Dragon defender ornament kit", ItemID.DRAGON_DEFENDER_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1), - TORMENTED_ORNAMENT_KIT("Tormented bracelet ornament kit", ItemID.TORMENTED_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1), - ANGUISH_ORNAMENT_KIT("Anguish ornament kit", ItemID.ANGUISH_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1), - TORTURE_ORNAMENT_KIT("Torture ornament kit", ItemID.TORTURE_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1), - OCCULT_ORNAMENT_KIT("Occult ornament kit", ItemID.OCCULT_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0), - ARMADYL_GODSWORD_ORNAMENT_KIT("Armadyl godsword ornament kit", ItemID.ARMADYL_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0), - BANDOS_GODSWORD_ORNAMENT_KIT("Bandos godsword ornament kit", ItemID.BANDOS_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0), - SARADOMIN_GODSWORD_ORNAMENT_KIT("Saradomin godsword ornament kit", ItemID.SARADOMIN_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0), - ZAMORAK_GODSWORD_ORNAMENT_KIT("Zamorak godsword ornament kit", ItemID.ZAMORAK_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0), - _3RD_AGE_AXE("3rd age axe", ItemID._3RD_AGE_AXE, "Clue Scroll (Master)", "3rd age", 1), - _3RD_AGE_PICKAXE("3rd age pickaxe", ItemID._3RD_AGE_PICKAXE, "Clue Scroll (Master)", "3rd age", 1), - _3RD_AGE_DRUIDIC_STAFF("3rd age druidic staff", ItemID._3RD_AGE_DRUIDIC_STAFF, "Clue Scroll (Master)", "3rd age", 2), - _3RD_AGE_DRUIDIC_ROBE_TOP("3rd age druidic robe top", ItemID._3RD_AGE_DRUIDIC_ROBE_TOP, "Clue Scroll (Master)", "3rd age", 2), - _3RD_AGE_DRUIDIC_ROBE_BOTTOMS("3rd age druidic robe bottom", ItemID._3RD_AGE_DRUIDIC_ROBE_BOTTOMS, "Clue Scroll (Master)", "3rd age", 2), - _3RD_AGE_DRUIDIC_CLOAK("3rd age druidic cloak", ItemID._3RD_AGE_DRUIDIC_CLOAK, "Clue Scroll (Master)", "3rd age", 2), - LESSER_DEMON_MASK("Lesser demon mask", ItemID.LESSER_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3), - GREATER_DEMON_MASK("Greater demon mask", ItemID.GREATER_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3), - BLACK_DEMON_MASK("Black demon mask", ItemID.BLACK_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3), - JUNGLE_DEMON_MASK("Jungle demon mask", ItemID.JUNGLE_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3), - OLD_DEMON_MASK("Old demon mask", ItemID.OLD_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3), - ARCEUUS_HOOD("Arceuus house hood", ItemID.ARCEUUS_HOOD, "Clue Scroll (Master)", "House Hoods", 4), - HOSIDIUS_HOOD("Hosidius house hood", ItemID.HOSIDIUS_HOOD, "Clue Scroll (Master)", "House Hoods", 4), - LOVAKENGJ_HOOD("Lovakengj house hood", ItemID.LOVAKENGJ_HOOD, "Clue Scroll (Master)", "House Hoods", 4), - PISCARILIUS_HOOD("Piscarilius house hood", ItemID.PISCARILIUS_HOOD, "Clue Scroll (Master)", "House Hoods", 4), - SHAYZIEN_HOUSE_HOOD("Shayzien house hood", ItemID.SHAYZIEN_HOOD, "Clue Scroll (Master)", "House Hoods", 4), - SAMURAI_KASA("Samurai kasa", ItemID.SAMURAI_KASA, "Clue Scroll (Master)", "Samurai Outfit", 5), - SAMURAI_SHIRT("Samurai shirt", ItemID.SAMURAI_SHIRT, "Clue Scroll (Master)", "Samurai Outfit", 5), - SAMURAI_GREAVES("Samurai greaves", ItemID.SAMURAI_GREAVES, "Clue Scroll (Master)", "Samurai Outfit", 5), - SAMURAI_GLOVES("Samurai gloves", ItemID.SAMURAI_GLOVES, "Clue Scroll (Master)", "Samurai Outfit", 5), - SAMURAI_BOOTS("Samurai boots", ItemID.SAMURAI_BOOTS, "Clue Scroll (Master)", "Samurai Outfit", 5), - MUMMYS_HEAD("Mummy's head", ItemID.MUMMYS_HEAD, "Clue Scroll (Master)", "Mummy Outfit", 6), - MUMMYS_BODY("Mummy's body", ItemID.MUMMYS_BODY, "Clue Scroll (Master)", "Mummy Outfit", 6), - MUMMYS_LEGS("Mummy's legs", ItemID.MUMMYS_LEGS, "Clue Scroll (Master)", "Mummy Outfit", 6), - MUMMYS_HANDS("Mummy's hands", ItemID.MUMMYS_HANDS, "Clue Scroll (Master)", "Mummy Outfit", 6), - MUMMYS_FEET("Mummy's feet", ItemID.MUMMYS_FEET, "Clue Scroll (Master)", "Mummy Outfit", 6), - ANKOU_MASK("Ankou mask", ItemID.ANKOU_MASK, "Clue Scroll (Master)", "Ankou Outfit", 7), - ANKOU_TOP("Ankou top", ItemID.ANKOU_TOP, "Clue Scroll (Master)", "Ankou Outfit", 7), - ANKOUS_LEGGINGS("Ankou's leggings", ItemID.ANKOUS_LEGGINGS, "Clue Scroll (Master)", "Ankou Outfit", 7), - ANKOU_GLOVES("Ankou gloves", ItemID.ANKOU_GLOVES, "Clue Scroll (Master)", "Ankou Outfit", 7), - ANKOU_SOCKS("Ankou socks", ItemID.ANKOU_SOCKS, "Clue Scroll (Master)", "Ankou Outfit", 7), - HOOD_OF_DARKNESS("Hood of darkness", ItemID.HOOD_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8), - ROBE_TOP_OF_DARKNESS("Robe top of darkness", ItemID.ROBE_TOP_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8), - ROBE_BOTTOM_OF_DARKNESS("Robe bottom of darkness", ItemID.ROBE_BOTTOM_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8), - BOOTS_OF_DARKNESS("Boots of darkness", ItemID.BOOTS_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8), - GLOVES_OF_DARKNESS("Gloves of darkness", ItemID.GLOVES_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8), - RING_OF_COINS("Ring of coins", ItemID.RING_OF_COINS, "Clue Scroll (Master)", "Other", 9), - LEFT_EYE_PATCH("Left eye patch", ItemID.LEFT_EYE_PATCH, "Clue Scroll (Master)", "Other", 9), - OBSIDIAN_CAPE_R("Obsidian cape (r)", ItemID.OBSIDIAN_CAPE_R, "Clue Scroll (Master)", "Other", 9), - FANCY_TIARA("Fancy tiara", ItemID.FANCY_TIARA, "Clue Scroll (Master)", "Other", 9), - HALF_MOON_SPECTACLES("Half moon spectacles", ItemID.HALF_MOON_SPECTACLES, "Clue Scroll (Master)", "Other", 9), - ALE_OF_THE_GODS("Ale of the gods", ItemID.ALE_OF_THE_GODS, "Clue Scroll (Master)", "Other 2", 10), - BUCKET_HELM_G("Bucket helm (g)", ItemID.BUCKET_HELM_G, "Clue Scroll (Master)", "Other 2", 10), - BOWL_WIG("Bowl wig", ItemID.BOWL_WIG, "Clue Scroll (Master)", "Other 2", 10), - BLOODHOUND("Bloodhound", ItemID.BLOODHOUND, "Clue Scroll (Master)", "Other 2", 10), - - HERBI("Herbi", ItemID.HERBI, "Herbiboar", "Pet", -1); - - // Shared Unique Items - UniqueItem(final String n, final int id, final String... activities) - { - this.name = n; - this.itemID = id; - this.activities = activities; - this.setName = "Shared"; - this.position = -1; - } - - // Non-Shared Unique Items - UniqueItem(final String n, final int id, final String a, final String set, final int position) - { - this.name = n; - this.itemID = id; - this.activities = new String[]{a}; - this.setName = set; - this.position = position; - - } - - private final String name; - private final int itemID; - private final String[] activities; - private final String setName; - private final int position; - - // Get a specific UniqueItem by Name - // Unused ATM - private static final Map byName = buildNameMap(); - public static UniqueItem getByName(String name) - { - return byName.get(name.toUpperCase()); - } - private static Map buildNameMap() - { - Map byName = new HashMap<>(); - for (UniqueItem item : values()) - { - byName.put(item.getName().toUpperCase(), item); - } - - return byName; - } - - // Returns an array of UniqueItems by an individual `activities` name - private static final Map> byActivityName = buildActivityMap(); - public static List getByActivityName(String name) - { - return byActivityName.get(name.toUpperCase()); - } - private static Map> buildActivityMap() - { - Map> byName = new HashMap<>(); - for (UniqueItem item : values()) - { - String[] activities = item.getActivities(); - for (String activity : activities) - { - byName.computeIfAbsent(activity.toUpperCase(), e -> new ArrayList<>()).add(item); - } - - } - - return byName; - } - - // Return an array of UniqueItems by `setName` - // Unused ATM - private static final Map> bySetName = buildSetMap(); - public static List getBySetName(String name) - { - return bySetName.get(name.toUpperCase()); - } - private static Map> buildSetMap() - { - Map> byName = new HashMap<>(); - for (UniqueItem item : values()) - { - byName.computeIfAbsent(item.getSetName().toUpperCase(), e -> new ArrayList<>()).add(item); - } - - return byName; - } - - // Takes a list of UniqueItems and maps them by Position to ensure adding in predefined order - public static Map> createPositionSetMap(Collection items) - { - Map> setNames = new HashMap<>(); - for (UniqueItemPrepared item : items) - { - setNames.computeIfAbsent(item.getUniqueItem().getPosition(), e -> new ArrayList<>()).add(item); - } - - // Sort them by Key - return setNames.entrySet().stream() - .sorted(Map.Entry.comparingByKey()) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootPanel.java deleted file mode 100644 index 5abe89d05c..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootPanel.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2018, TheStonedTurtle - * 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.stonedloottracker.ui; - -import com.google.common.collect.Iterators; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import javax.inject.Singleton; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.border.EmptyBorder; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.stonedloottracker.ItemSortTypes; -import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom; -import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry; -import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared; -import net.runelite.client.ui.ColorScheme; - -@Slf4j -@Singleton -class LootPanel extends JPanel -{ - private final Collection records; - private final Map> uniqueMap; - private final boolean hideUniques; - private final ItemSortTypes sortType; - private final boolean itemBreakdown; - private final ItemManager itemManager; - // Consolidate LTItemEntries stored by ItemID - private Map consolidated; - - @Getter - private boolean playbackPlaying = false; - private boolean cancelPlayback = false; - - LootPanel(final Collection records, final Map> uniqueMap, final boolean hideUnqiues, final ItemSortTypes sort, final boolean itemBreakdown, final ItemManager itemManager) - { - this.records = (records == null ? new ArrayList<>() : records); - this.uniqueMap = (uniqueMap == null ? new HashMap<>() : uniqueMap); - this.hideUniques = hideUnqiues; - this.sortType = sort; - this.itemBreakdown = itemBreakdown; - this.itemManager = itemManager; - - setLayout(new GridBagLayout()); - setBorder(new EmptyBorder(0, 10, 0, 10)); - setBackground(ColorScheme.DARK_GRAY_COLOR); - - createConsolidatedArray(this.records); - createPanel(this.records); - } - - private void createConsolidatedArray(Collection records) - { - // Consolidate all LootTrackerItemEntrys from each record for combined loot totals - // Sort them based on the config setting. - this.consolidated = LootRecordCustom.consolidateLootTrackerItemEntries(records) - .entrySet().stream() - .sorted((lt1, lt2) -> - { - LootTrackerItemEntry o1 = lt1.getValue(); - LootTrackerItemEntry o2 = lt2.getValue(); - switch (sortType) - { - case ITEM_ID: - return o1.getId() - o2.getId(); - case PRICE: - if (o1.getPrice() != o2.getPrice()) - { - return o1.getPrice() > o2.getPrice() ? -1 : 1; - } - break; - case VALUE: - if (o1.getTotal() != o2.getTotal()) - { - return o1.getTotal() > o2.getTotal() ? -1 : 1; - } - break; - case ALPHABETICAL: - // Handled below - break; - default: - log.warn("Sort Type not being handled correctly, defaulting to alphabetical."); - break; - } - - // Default to alphabetical - return o1.getName().compareTo(o2.getName()); - }) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); - } - - private void createPanel(Collection records) - { - GridBagConstraints c = SelectionPanel.constrains(); - - // Create necessary helpers for the unique toggles - final Map uniqueQtys = new HashMap<>(); - final Set uniqueIds = new HashSet<>(); - - long totalValue = 0; - long totalHaValue = 0; - - // Loop over all UniqueItems and check how many the player has received as a drop for each - // Also add all Item IDs for uniques to a Set for easy hiding later on. - for (Collection items : this.uniqueMap.values()) - { - for (UniqueItemPrepared item : items) - { - int id = item.getUniqueItem().getItemID(); - int linkedId = item.getLinkedID(); - uniqueIds.add(id); - uniqueIds.add(linkedId); - - LootTrackerItemEntry entry = this.consolidated.get(id); - LootTrackerItemEntry notedEntry = this.consolidated.get(linkedId); - int qty = (entry == null ? 0 : entry.getQuantity()) + (notedEntry == null ? 0 : notedEntry.getQuantity()); - if (qty > 0) - { - totalValue += itemManager.getItemPrice(id); - totalHaValue += itemManager.getAlchValue(id); - - uniqueQtys.put(item, qty); - } - } - } - - // Attach all the Unique Items first - this.uniqueMap.forEach((setPosition, set) -> - { - UniqueItemPanel p = new UniqueItemPanel(set, uniqueQtys, this.itemManager); - this.add(p, c); - c.gridy++; - - }); - - // Attach Kill Count Panel(s) - if (records.size() > 0) - { - int amount = records.size(); - LootRecordCustom entry = Iterators.get(records.iterator(), (amount - 1)); - if (entry.getKillCount() != -1) - { - TextPanel p = new TextPanel("Current Killcount:", entry.getKillCount()); - this.add(p, c); - c.gridy++; - } - TextPanel p2 = new TextPanel("Kills Logged:", amount); - this.add(p2, c); - c.gridy++; - } - - int totalValueIndex = c.gridy; - c.gridy += 2; - - - Collection itemsToDisplay = new ArrayList<>(); - List items = LootTrackerBox.dedupeClues(new ArrayList<>(consolidated.values())); - for (LootTrackerItemEntry item : items) - { - totalValue += item.getTotal(); - totalHaValue += item.getHaTotal(); - - if (hideUniques && uniqueIds.contains(item.getId())) - { - continue; - } - - if (itemBreakdown) - { - ItemPanel p = new ItemPanel(item, itemManager); - this.add(p, c); - c.gridy++; - } - else - { - itemsToDisplay.add(item); - } - } - - if (itemsToDisplay.size() > 0) - { - LootGrid grid = new LootGrid(itemsToDisplay.toArray(new LootTrackerItemEntry[0]), itemManager); - this.add(grid, c); - c.gridy++; - } - - // Only add the total value element if it has something useful to display - if (totalValue > 0) - { - c.gridy = totalValueIndex; - TextPanel totalPanel = new TextPanel("Total Value:", totalValue); - this.add(totalPanel, c); - } - - if (totalHaValue > 0) - { - c.gridy = totalValueIndex + 1; - TextPanel totalHaPanel = new TextPanel("Total HA Value:", totalHaValue); - this.add(totalHaPanel, c); - } - } - - //void addedRecord(LootRecordCustom record) - void addedRecord() - { - //records.add(record); - // TODO: Smarter update system so it only repaints necessary Item and Text Panels - this.removeAll(); - - this.createConsolidatedArray(this.records); - this.createPanel(this.records); - - this.revalidate(); - this.repaint(); - } - - void playback() - { - playbackPlaying = true; - - if (this.records.size() > 0) - { - Collection recs = new ArrayList<>(); - for (LootRecordCustom r : this.records) - { - recs.add(r); - - SwingUtilities.invokeLater(() -> refreshPlayback(recs)); - - try - { - if (cancelPlayback) - { - playbackPlaying = false; - cancelPlayback = false; - SwingUtilities.invokeLater(() -> refreshPlayback(this.records)); - break; - } - Thread.sleep(250); - } - catch (InterruptedException e) - { - log.warn("Error in playback: " + e.getMessage()); - } - } - } - - playbackPlaying = false; - } - - void cancelPlayback() - { - // Only cancel if actually playing - cancelPlayback = playbackPlaying; - } - - private void refreshPlayback(Collection recs) - { - this.removeAll(); - - this.createConsolidatedArray(recs); - this.createPanel(recs); - - this.revalidate(); - this.repaint(); - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootTrackerBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootTrackerBox.java deleted file mode 100644 index 3008f2d421..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootTrackerBox.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2018, Psikoi - * Copyright (c) 2018, Tomas Slusny - * 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.stonedloottracker.ui; - -import com.google.common.base.Strings; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.GridLayout; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nullable; -import javax.inject.Singleton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; -import lombok.Getter; -import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom; -import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry; -import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.FontManager; -import net.runelite.client.util.StackFormatter; -import net.runelite.client.util.Text; - -@Singleton -@Getter(AccessLevel.PACKAGE) -class LootTrackerBox extends JPanel -{ - private static final int ITEMS_PER_ROW = 5; - private final JPanel itemContainer = new JPanel(); - private final JLabel priceLabel = new JLabel(); - private final JLabel subTitleLabel = new JLabel(); - private final ItemManager itemManager; - @Getter(AccessLevel.PACKAGE) - private final String id; - - @Getter(AccessLevel.PACKAGE) - private final List records = new ArrayList<>(); - - private long totalPrice; - private long totalHaPrice; - - LootTrackerBox(final ItemManager itemManager, final String id, @Nullable final String subtitle, LootRecordCustom record) - { - this.id = id; - this.itemManager = itemManager; - this.records.add(record); - - setLayout(new BorderLayout(0, 1)); - setBorder(new EmptyBorder(5, 0, 0, 0)); - - final JPanel logTitle = new JPanel(new BorderLayout(5, 0)); - logTitle.setBorder(new EmptyBorder(7, 7, 7, 7)); - logTitle.setBackground(ColorScheme.DARKER_GRAY_COLOR.darker()); - - final JLabel titleLabel = new JLabel(Text.removeTags(id)); - titleLabel.setFont(FontManager.getSmallFont(getFont())); - titleLabel.setForeground(Color.WHITE); - - logTitle.add(titleLabel, BorderLayout.WEST); - - subTitleLabel.setFont(FontManager.getSmallFont(getFont())); - subTitleLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - logTitle.add(subTitleLabel, BorderLayout.CENTER); - - if (!Strings.isNullOrEmpty(subtitle)) - { - subTitleLabel.setText(subtitle); - } - - priceLabel.setFont(FontManager.getSmallFont(getFont())); - priceLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR); - logTitle.add(priceLabel, BorderLayout.EAST); - - add(logTitle, BorderLayout.NORTH); - add(itemContainer, BorderLayout.CENTER); - - buildItems(); - } - - /** - * This method creates stacked items from the item list, calculates total price and then - * displays all the items in the UI. - */ - private void buildItems() - { - final List allItems = new ArrayList<>(); - final List items = new ArrayList<>(); - totalPrice = 0; - totalHaPrice = 0; - - for (LootRecordCustom record : records) - { - allItems.addAll(record.getDrops()); - } - - for (final LootTrackerItemEntry entry : dedupeClues(allItems)) - { - totalPrice += (entry.getPrice() * entry.getQuantity()); - totalHaPrice += (entry.getHaPrice() * entry.getQuantity()); - - int quantity = 0; - for (final LootTrackerItemEntry i : items) - { - if (i.getId() == entry.getId()) - { - quantity = i.getQuantity(); - items.remove(i); - break; - } - } - - if (quantity > 0) - { - int newQuantity = entry.getQuantity() + quantity; - long pricePerItem = entry.getPrice(); - long haPricePerItem = entry.getHaPrice(); - - items.add(new LootTrackerItemEntry(entry.getName(), entry.getId(), newQuantity, pricePerItem, haPricePerItem, false)); - } - else - { - items.add(entry); - } - } - - items.sort((i1, i2) -> Long.compare(i2.getPrice(), i1.getPrice())); - - // Calculates how many rows need to be display to fit all items - final int rowSize = rowSize(items.size()); - - resetContainer(itemContainer, rowSize); - - for (int i = 0; i < rowSize * ITEMS_PER_ROW; i++) - { - final JPanel slotContainer = new JPanel(); - slotContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR); - - if (i < items.size()) - { - final LootTrackerItemEntry item = items.get(i); - final JLabel imageLabel = buildimageLabel(itemManager, item); - slotContainer.add(imageLabel); - } - - itemContainer.add(slotContainer); - } - - itemContainer.repaint(); - - priceLabel.setText(StackFormatter.quantityToStackSize(totalPrice) + " gp (HA: " + StackFormatter.quantityToStackSize(totalHaPrice) + ")"); - priceLabel.setToolTipText(StackFormatter.formatNumber(totalPrice) + " gp (HA: " + StackFormatter.formatNumber(totalHaPrice) + ")"); - if (records.size() > 1) - { - subTitleLabel.setText("x " + records.size()); - } - - repaint(); - } - - static List dedupeClues(List items) - { - final List newItems = new ArrayList<>(); - - int eliteClues = 0; - int hardClues = 0; - int mediumClues = 0; - int easyClues = 0; - int beginnerClues = 0; - - LootTrackerItemEntry eliteClue = null; - LootTrackerItemEntry hardClue = null; - LootTrackerItemEntry mediumClue = null; - LootTrackerItemEntry easyClue = null; - LootTrackerItemEntry beginnerClue = null; - - for (LootTrackerItemEntry lootEntry : items) - { - if (lootEntry == null) - { - continue; - } - - String name = lootEntry.getName(); - - if (lootEntry.getName().contains("Clue scroll (")) - { - if (name.contains("elite")) - { - eliteClues += lootEntry.getQuantity(); - eliteClue = lootEntry; - } - else if (name.contains("hard")) - { - hardClues += lootEntry.getQuantity(); - hardClue = lootEntry; - } - else if (name.contains("medium")) - { - mediumClues += lootEntry.getQuantity(); - mediumClue = lootEntry; - } - else if (name.contains("easy")) - { - easyClues += lootEntry.getQuantity(); - easyClue = lootEntry; - } - else if (name.contains("beginner")) - { - beginnerClues += lootEntry.getQuantity(); - beginnerClue = lootEntry; - } - - continue; - } - - newItems.add(lootEntry); - } - - LootTrackerItemEntry[] clueArray = {beginnerClue, easyClue, mediumClue, hardClue, eliteClue}; - int[] clueAmountArray = {beginnerClues, easyClues, mediumClues, hardClues, eliteClues}; - - for (int i = 0; i < 4; i++) - { - if (clueAmountArray[i] > 0) - { - newItems.add(createNewLootEntry(Objects.requireNonNull(clueArray[i]), clueAmountArray[i])); - } - } - - return newItems; - } - - private static LootTrackerItemEntry createNewLootEntry(LootTrackerItemEntry item, int amount) - { - return new LootTrackerItemEntry( - item.getName(), - item.getId(), - amount, - item.getPrice(), - item.getHaPrice(), - item.isStackable() - ); - } - - static int rowSize(int items) - { - return ((items % ITEMS_PER_ROW == 0) ? 0 : 1) + items / ITEMS_PER_ROW; - } - - private static void resetContainer(JPanel itemContainer, int rowSize) - { - itemContainer.removeAll(); - itemContainer.setLayout(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1)); - } - - private static JLabel buildimageLabel(ItemManager itemManager, LootTrackerItemEntry item) - { - final JLabel imageLabel = new JLabel(); - imageLabel.setToolTipText(UniqueItemPanel.tooltipText(item.getPrice(), item.getHaPrice(), item.getQuantity(), item.getName())); - imageLabel.setVerticalAlignment(SwingConstants.CENTER); - imageLabel.setHorizontalAlignment(SwingConstants.CENTER); - itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1).addTo(imageLabel); - - return imageLabel; - } -} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ItemSortTypes.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ItemSortTypes.java similarity index 64% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ItemSortTypes.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ItemSortTypes.java index 11680b9456..b9aae24d26 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ItemSortTypes.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ItemSortTypes.java @@ -1,18 +1,16 @@ -package net.runelite.client.plugins.stonedloottracker; +package net.runelite.client.plugins.stonedtracker; -import lombok.AccessLevel; import lombok.Getter; import lombok.RequiredArgsConstructor; -@Getter(AccessLevel.PACKAGE) +@Getter @RequiredArgsConstructor public enum ItemSortTypes { ALPHABETICAL("Alphabetical"), ITEM_ID("Item ID"), VALUE("Value"), - PRICE("Price"), - HAPRICE("HA Price"); + PRICE("Price"); private final String name; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/StonedLootTrackerConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/StonedTrackerConfig.java similarity index 73% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/StonedLootTrackerConfig.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/StonedTrackerConfig.java index e20a9b3bab..cd2df32b82 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/StonedLootTrackerConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/StonedTrackerConfig.java @@ -22,58 +22,20 @@ * (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.stonedloottracker; +package net.runelite.client.plugins.stonedtracker; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; -import net.runelite.client.config.Stub; -@ConfigGroup("stonedloottracker") -public interface StonedLootTrackerConfig extends Config +@ConfigGroup("stonedtracker") +public interface StonedTrackerConfig extends Config { @ConfigItem( - keyName = "mainStub", - name = "Main panel", - description = "", - position = 1 - ) - default Stub mainStub() - { - return new Stub(); - } - - @ConfigItem( - position = 2, - keyName = "bossButtons", - name = "Show boss icons", - description = "Toggles whether the selection screen will use the boss icons", - parent = "mainStub" - ) - default boolean bossButtons() - { - return true; - } - - @ConfigItem( - keyName = "itemsStub", - name = "Items", - description = "", - position = 3 - ) - default Stub itemsStub() - { - return new Stub(); - } - - // TODO Option is not working will look into it later - @ConfigItem( - position = 4, + position = 0, keyName = "hideUniques", name = "Hide uniques", - description = "Hides unique items from the item breakdown", - parent = "itemsStub", - hidden = true + description = "Hides unique items from the item breakdown" ) default boolean hideUniques() { @@ -81,11 +43,10 @@ public interface StonedLootTrackerConfig extends Config } @ConfigItem( - position = 5, + position = 1, keyName = "itemSortType", name = "Sort Items by", - description = "Sorts items by the requested value inside the UI. (Doesn't effect session/box view)", - parent = "itemsStub" + description = "Sorts items by the requested value inside the UI. (Doesn't effect session/box view)" ) default ItemSortTypes itemSortType() { @@ -93,14 +54,24 @@ public interface StonedLootTrackerConfig extends Config } @ConfigItem( - position = 6, + position = 2, keyName = "itemBreakdown", name = "Breakdown individual items", - description = "Toggles whether the Individual item UI should be used inside npc-specific tabs", - parent = "itemsStub" + description = "Toggles whether the Individual item UI should be used inside npc-specific tabs" ) default boolean itemBreakdown() { return true; } + + @ConfigItem( + position = 3, + keyName = "bossButtons", + name = "Show boss icons", + description = "Toggles whether the selection screen will use the boss icons" + ) + default boolean bossButtons() + { + return true; + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/StonedTrackerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/StonedTrackerPlugin.java new file mode 100644 index 0000000000..65bb0bc0f3 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/StonedTrackerPlugin.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2018, Psikoi + * Copyright (c) 2018, Adam + * 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.stonedtracker; + +import com.google.inject.Provides; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import javax.inject.Inject; +import javax.swing.SwingUtilities; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.ItemDefinition; +import net.runelite.api.NpcID; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.events.GameTick; +import net.runelite.api.events.WidgetLoaded; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetID; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.loottracker.localstorage.LTItemEntry; +import net.runelite.client.plugins.loottracker.localstorage.LTRecord; +import net.runelite.client.plugins.loottracker.localstorage.LootRecordWriter; +import net.runelite.client.plugins.loottracker.localstorage.events.LTNameChange; +import net.runelite.client.plugins.loottracker.localstorage.events.LTRecordStored; +import net.runelite.client.plugins.stonedtracker.data.BossTab; +import net.runelite.client.plugins.stonedtracker.data.UniqueItem; +import net.runelite.client.plugins.stonedtracker.ui.LootTrackerPanel; +import net.runelite.client.ui.ClientToolbar; +import net.runelite.client.ui.NavigationButton; +import net.runelite.client.util.ImageUtil; + +@PluginDescriptor( + name = "Stoned Tracker", + description = "Local data persistence and unique UI for the Loot Tracker.", + tags = {"Stoned", "Loot", "Tracker"} +) +@Slf4j +public class StonedTrackerPlugin extends Plugin +{ + private static final String SIRE_FONT_TEXT = "you place the unsired into the font of consumption..."; + private static final String SIRE_REWARD_TEXT = "the font consumes the unsired"; + + @Inject + private ClientToolbar clientToolbar; + @Inject + public StonedTrackerConfig config; + @Inject + private Client client; + @Inject + private ItemManager itemManager; + + @Inject + private ClientThread clientThread; + + @Inject + private LootRecordWriter writer; + + @Inject + private EventBus eventBus; + + private LootTrackerPanel panel; + private NavigationButton navButton; + @Getter + private Set lootNames = new TreeSet<>(); + + private boolean loaded = false; + private boolean unsiredReclaiming = false; + + @Provides + StonedTrackerConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(StonedTrackerConfig.class); + } + + private void onLTRecordStored(final LTRecordStored s) + { + final LTRecord record = s.getRecord(); + lootNames.add(record.getName()); + SwingUtilities.invokeLater(() -> panel.addLog(record)); + } + + private void onLTNameChange(final LTNameChange c) + { + lootNames = new TreeSet<>(writer.getKnownFileNames()); + SwingUtilities.invokeLater(() -> panel.showSelectionView()); + } + + private void onConfigChanged(final ConfigChanged event) + { + if (event.getGroup().equals("stonedtracker")) + { + panel.refreshUI(); + } + } + + @Override + protected void startUp() + { + addSubscriptions(); + + panel = new LootTrackerPanel(itemManager, this); + + final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "panel-icon.png"); + + navButton = NavigationButton.builder() + .tooltip("Stoned Tracker") + .icon(icon) + .priority(5) + .panel(panel) + .build(); + + clientToolbar.addNavigation(navButton); + + // Attach necessary info from item manager on load + if (!loaded) + { + loaded = true; + clientThread.invokeLater(() -> + { + switch (client.getGameState()) + { + case UNKNOWN: + case STARTING: + loaded = false; + return false; + } + + UniqueItem.prepareUniqueItems(itemManager); + return true; + }); + } + } + + @Override + protected void shutDown() + { + eventBus.unregister(this); + clientToolbar.removeNavigation(navButton); + } + + private void addSubscriptions() + { + this.eventBus.subscribe(LTRecordStored.class, this, this::onLTRecordStored); + this.eventBus.subscribe(LTNameChange.class, this, this::onLTNameChange); + this.eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged); + this.eventBus.subscribe(WidgetLoaded.class, this, this::onWidgetLoaded); + this.eventBus.subscribe(GameTick.class, this, this::onGameTick); + } + + private void onWidgetLoaded(WidgetLoaded event) + { + if (event.getGroupId() != WidgetID.DIALOG_SPRITE_GROUP_ID) + { + return; + } + + Widget text = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT); + if (SIRE_FONT_TEXT.equals(text.getText().toLowerCase())) + { + unsiredReclaiming = true; + } + } + + private void onGameTick(GameTick t) + { + if (unsiredReclaiming) + { + checkUnsiredWidget(); + } + } + + // Handles checking for unsired loot reclamation + private void checkUnsiredWidget() + { + log.info("Checking for text widget change..."); + Widget text = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT); + if (text.getText().toLowerCase().contains(SIRE_REWARD_TEXT)) + { + unsiredReclaiming = false; + log.info("Text widget changed, reclaimed an item"); + Widget sprite = client.getWidget(WidgetInfo.DIALOG_SPRITE); + log.info("Sprite Item ID: {}", sprite.getItemId()); + receivedUnsiredLoot(sprite.getItemId()); + } + else + { + log.info("Old text still..."); + } + } + + // Handles adding the unsired loot to the tracker + private void receivedUnsiredLoot(int itemID) + { + clientThread.invokeLater(() -> + { + Collection data = getDataByName("Abyssal sire"); + ItemDefinition c = itemManager.getItemDefinition(itemID); + LTItemEntry itemEntry = new LTItemEntry(c.getName(), itemID, 1, 0); + + log.debug("Received Unsired item: {}", c.getName()); + + // Don't have data for sire, create a new record with just this data. + if (data == null) + { + log.debug("No previous Abyssal sire loot, creating new loot record"); + LTRecord r = new LTRecord(NpcID.ABYSSAL_SIRE, "Abyssal sire", 350, -1, Collections.singletonList(itemEntry)); + writer.addLootTrackerRecord(r); + return; + } + + log.debug("Adding drop to last abyssal sire loot record"); + // Add data to last kill count + List items = new ArrayList<>(data); + LTRecord r = items.get(items.size() - 1); + r.addDropEntry(itemEntry); + writer.writeLootTrackerFile("Abyssal sire", items); + // Write will trigger event this plugin is subscribed too + }); + } + + public Collection getDataByName(String name) + { + final BossTab tab = BossTab.getByName(name); + if (tab != null) + { + name = tab.getName(); + } + + return writer.loadLootTrackerRecords(name); + } + + public boolean clearStoredDataByName(final String name) + { + return writer.deleteLootTrackerRecords(name); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/BossTab.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/data/BossTab.java similarity index 60% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/BossTab.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/data/BossTab.java index 12179a35de..26d74584ce 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/data/BossTab.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/data/BossTab.java @@ -22,47 +22,50 @@ * (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.stonedloottracker.data; +package net.runelite.client.plugins.stonedtracker.data; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.TreeSet; -import lombok.AccessLevel; +import javax.annotation.Nullable; +import lombok.AllArgsConstructor; import lombok.Getter; import net.runelite.api.ItemID; -@Getter(AccessLevel.PUBLIC) +@Getter +@AllArgsConstructor public enum BossTab { // Chest Rewards BARROWS("Barrows", ItemID.BARROWS_TELEPORT, "Other"), - RAIDS("Chambers of Xeric", ItemID.OLMLET, "Other"), - RAIDS_2("Theatre of Blood", ItemID.LIL_ZIK, "Other"), + CHAMBERS_OF_XERIC("Chambers of Xeric", ItemID.OLMLET, "Other"), + THEATRE_OF_BLOOD("Theatre of Blood", ItemID.LIL_ZIK, "Other"), // Loot received on NPC death ZULRAH("Zulrah", ItemID.PET_SNAKELING, "Other"), VORKATH("Vorkath", ItemID.VORKI, "Other"), // God wars dungeon - ARMADYL("Kree'arra", ItemID.PET_KREEARRA , "God Wars Dungeon"), - BANDOS("General Graardor", ItemID.PET_GENERAL_GRAARDOR , "God Wars Dungeon"), - SARADOMIN("Commander Zilyana", ItemID.PET_ZILYANA , "God Wars Dungeon"), - ZAMMY("K'ril Tsutsaroth", ItemID.PET_KRIL_TSUTSAROTH , "God Wars Dungeon"), + KREEARRA("Kree'arra", ItemID.PET_KREEARRA, "God Wars Dungeon"), + GENERAL_GRAARDOR("General Graardor", ItemID.PET_GENERAL_GRAARDOR, "God Wars Dungeon"), + COMMANDER_ZILYANA("Commander Zilyana", ItemID.PET_ZILYANA, "God Wars Dungeon"), + KRIL_TSUTSAROTH("K'ril Tsutsaroth", ItemID.PET_KRIL_TSUTSAROTH, "God Wars Dungeon"), // Wildy Bosses - VETION("Vet'ion", ItemID.VETION_JR , "Wilderness"), - VENENATIS("Venenatis", ItemID.VENENATIS_SPIDERLING , "Wilderness"), - CALLISTO("Callisto", ItemID.CALLISTO_CUB , "Wilderness"), - CHAOS_ELEMENTAL("Chaos Elemental", ItemID.PET_CHAOS_ELEMENTAL , "Wilderness"), + VETION("Vet'ion Reborn", ItemID.VETION_JR, "Wilderness"), + VENENATIS("Venenatis", ItemID.VENENATIS_SPIDERLING, "Wilderness"), + CALLISTO("Callisto", ItemID.CALLISTO_CUB, "Wilderness"), + CHAOS_ELEMENTAL("Chaos Elemental", ItemID.PET_CHAOS_ELEMENTAL, "Wilderness"), // Wildy Demi-Bosses SCORPIA("Scorpia", ItemID.SCORPIAS_OFFSPRING, "Wilderness"), - CHAOS_FANATIC("Chaos Fanatic", ItemID.ANCIENT_STAFF , "Wilderness"), - CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", ItemID.FEDORA , "Wilderness"), + CHAOS_FANATIC("Chaos Fanatic", ItemID.ANCIENT_STAFF, "Wilderness"), + CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", ItemID.FEDORA, "Wilderness"), // Wildy Other - KING_BLACK_DRAGON("King Black Dragon", ItemID.PRINCE_BLACK_DRAGON , "Wilderness"), + KING_BLACK_DRAGON("King Black Dragon", ItemID.PRINCE_BLACK_DRAGON, "Wilderness"), // Slayer Bosses KALPHITE_QUEEN("Kalphite Queen", ItemID.KALPHITE_PRINCESS, "Other"), @@ -71,7 +74,8 @@ public enum BossTab ABYSSAL_SIRE("Abyssal Sire", ItemID.ABYSSAL_ORPHAN, "Slayer"), KRAKEN("Kraken", ItemID.PET_KRAKEN, "Slayer"), CERBERUS("Cerberus", ItemID.HELLPUPPY, "Slayer"), - THERMONUCLEAR_SMOKE_DEVIL("Thermonuclear Smoke Devil", ItemID.PET_SMOKE_DEVIL, "Slayer"), + THERMONUCLEAR_SMOKE_DEVIL("Thermonuclear smoke devil", ItemID.PET_SMOKE_DEVIL, "Slayer"), + ALCHEMICAL_HYDRA("Alchemical Hydra", ItemID.IKKLE_HYDRA, "Slayer"), // Other Bosses GIANT_MOLE("Giant Mole", ItemID.BABY_MOLE, "Other"), @@ -87,65 +91,43 @@ public enum BossTab CLUE_SCROLL_MEDIUM("Clue Scroll (Medium)", ItemID.CLUE_SCROLL_MEDIUM, "Clue Scrolls"), CLUE_SCROLL_HARD("Clue Scroll (Hard)", ItemID.CLUE_SCROLL_HARD, "Clue Scrolls"), CLUE_SCROLL_ELITE("Clue Scroll (Elite)", ItemID.CLUE_SCROLL_ELITE, "Clue Scrolls"), - CLUE_SCROLL_MASTER("Clue Scroll (Master)", ItemID.CLUE_SCROLL_MASTER, "Clue Scrolls"), + CLUE_SCROLL_MASTER("Clue Scroll (Master)", ItemID.CLUE_SCROLL_MASTER, "Clue Scrolls"); - // Hunter - HERBIBOAR("Herbiboar", ItemID.HERBI, "Hunter"); + private static final Map NAME_MAP; + private static final Multimap CATEGORY_MAP; - BossTab(String name, int iconItem, String category) + static { - this.name = name; - this.itemID = iconItem; - this.category = category; + final ImmutableMap.Builder byName = ImmutableMap.builder(); + final ImmutableMultimap.Builder categoryMap = ImmutableMultimap.builder(); + + for (BossTab tab : values()) + { + byName.put(tab.getName().toUpperCase(), tab); + categoryMap.put(tab.getCategory(), tab); + } + + NAME_MAP = byName.build(); + CATEGORY_MAP = categoryMap.build(); } private final String name; private final int itemID; private final String category; - // By Boss Name - private static final Map byName = buildMap(); - public static BossTab getByName(String name) + @Nullable + public static BossTab getByName(final String name) { - return byName.get(name.toUpperCase()); - } - private static Map buildMap() - { - Map byName = new HashMap<>(); - for (BossTab tab : values()) - { - byName.put(tab.getName().toUpperCase(), tab); - } - - return byName; + return NAME_MAP.get(name.toUpperCase()); } - // By Category Name - private static final Map> byCategoryName = buildCategoryMap(); - public static List getByCategoryName(String name) + public static Collection getByCategoryName(final String name) { - return byCategoryName.get(name.toUpperCase()); - } - private static Map> buildCategoryMap() - { - Map> map = new HashMap<>(); - for (BossTab tab : values()) - { - map.computeIfAbsent(tab.getCategory().toUpperCase(), e -> new ArrayList<>()).add(tab); - } - - return map; + return CATEGORY_MAP.get(name); } - // All Categories - public static final Set categories = getCategories(); - private static Set getCategories() + public static Set getCategories() { - Set s = new TreeSet<>(); - for (BossTab tab : values()) - { - s.add(tab.getCategory()); - } - return s; + return new TreeSet<>(CATEGORY_MAP.keySet()); } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/data/UniqueItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/data/UniqueItem.java new file mode 100644 index 0000000000..e9c90c33ff --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/data/UniqueItem.java @@ -0,0 +1,897 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * 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.stonedtracker.data; + +import com.google.common.collect.ImmutableMultimap; +import java.util.Collection; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import net.runelite.api.ItemDefinition; +import net.runelite.api.ItemID; +import net.runelite.client.game.ItemManager; + +@RequiredArgsConstructor +@Getter +public enum UniqueItem +{ + // "Uniques" which are actually dropped by multiple bosses + // God Wars + GODSWORD_SHARD_1(ItemID.GODSWORD_SHARD_1, BossTab.KREEARRA, BossTab.GENERAL_GRAARDOR, BossTab.COMMANDER_ZILYANA, BossTab.KRIL_TSUTSAROTH), + GODSWORD_SHARD_2(ItemID.GODSWORD_SHARD_2, BossTab.KREEARRA, BossTab.GENERAL_GRAARDOR, BossTab.COMMANDER_ZILYANA, BossTab.KRIL_TSUTSAROTH), + GODSWORD_SHARD_3(ItemID.GODSWORD_SHARD_3, BossTab.KREEARRA, BossTab.GENERAL_GRAARDOR, BossTab.COMMANDER_ZILYANA, BossTab.KRIL_TSUTSAROTH), + // Wildy + PET_CHAOS_ELEMENTAL(ItemID.PET_CHAOS_ELEMENTAL, BossTab.CHAOS_ELEMENTAL, BossTab.CHAOS_FANATIC), + // MYSTERIOUS_EMBLEM(BossTab.MYSTERIOUS_EMBLEM, ItemID.MYSTERIOUS_EMBLEM, BossTab.), + CURVED_BONE(ItemID.CURVED_BONE, BossTab.CALLISTO, BossTab.VETION, BossTab.VENENATIS, BossTab.GIANT_MOLE), + DRAGON_PICKAXE(ItemID.DRAGON_PICKAXE, BossTab.CALLISTO, BossTab.VETION, BossTab.VENENATIS, BossTab.KING_BLACK_DRAGON), + DRAGON_2H_SWORD(ItemID.DRAGON_2H_SWORD, BossTab.CALLISTO, BossTab.VETION, BossTab.VENENATIS, BossTab.KALPHITE_QUEEN), + // Other + DRAGON_CHAINBODY(ItemID.DRAGON_CHAINBODY_3140, BossTab.THERMONUCLEAR_SMOKE_DEVIL, BossTab.KALPHITE_QUEEN), + DRAGON_AXE(ItemID.DRAGON_AXE, BossTab.DAGANNOTH_REX, BossTab.DAGANNOTH_PRIME, BossTab.DAGANNOTH_SUPREME), + UNCUT_ONYX(ItemID.UNCUT_ONYX, BossTab.ZULRAH, BossTab.SKOTIZO), + + // Unique Items + // Barrows Uniques + // Ahrim + AHRIMS_HOOD(ItemID.AHRIMS_HOOD, BossTab.BARROWS, 0), + AHRIMS_ROBETOP(ItemID.AHRIMS_ROBETOP, BossTab.BARROWS, 0), + AHRIMS_ROBESKIRT(ItemID.AHRIMS_ROBESKIRT, BossTab.BARROWS, 0), + AHRIMS_STAFF(ItemID.AHRIMS_STAFF, BossTab.BARROWS, 0), + // Dharok + DHAROKS_HELM(ItemID.DHAROKS_HELM, BossTab.BARROWS, 1), + DHAROKS_PLATEBODY(ItemID.DHAROKS_PLATEBODY, BossTab.BARROWS, 1), + DHAROKS_PLATELEGS(ItemID.DHAROKS_PLATELEGS, BossTab.BARROWS, 1), + DHAROKS_GREATAXE(ItemID.DHAROKS_GREATAXE, BossTab.BARROWS, 1), + // Guthans + GUTHANS_HELM(ItemID.GUTHANS_HELM, BossTab.BARROWS, 2), + GUTHANS_PLATEBODY(ItemID.GUTHANS_PLATEBODY, BossTab.BARROWS, 2), + GUTHANS_CHAINSKIRT(ItemID.GUTHANS_CHAINSKIRT, BossTab.BARROWS, 2), + GUTHANS_WARSPEAR(ItemID.GUTHANS_WARSPEAR, BossTab.BARROWS, 2), + // Karils + KARILS_COIF(ItemID.KARILS_COIF, BossTab.BARROWS, 3), + KARILS_LEATHERTOP(ItemID.KARILS_LEATHERTOP, BossTab.BARROWS, 3), + KARILS_LEATHERSKIRT(ItemID.KARILS_LEATHERSKIRT, BossTab.BARROWS, 3), + KARILS_CROSSBOW(ItemID.KARILS_CROSSBOW, BossTab.BARROWS, 3), + //Torag + TORAGS_HELM(ItemID.TORAGS_HELM, BossTab.BARROWS, 4), + TORAGS_PLATEBODY(ItemID.TORAGS_PLATEBODY, BossTab.BARROWS, 4), + TORAGS_PLATELEGS(ItemID.TORAGS_PLATELEGS, BossTab.BARROWS, 4), + TORAGS_HAMMERS(ItemID.TORAGS_HAMMERS, BossTab.BARROWS, 4), + // Veracs + VERACS_HELM(ItemID.VERACS_HELM, BossTab.BARROWS, 5), + VERACS_BRASSARD(ItemID.VERACS_BRASSARD, BossTab.BARROWS, 5), + VERACS_PLATESKIRT(ItemID.VERACS_PLATESKIRT, BossTab.BARROWS, 5), + VERACS_FLAIL(ItemID.VERACS_FLAIL, BossTab.BARROWS, 5), + + // Raids Uniques + // Mage + KODAI_INSIGNIA(ItemID.KODAI_INSIGNIA, BossTab.CHAMBERS_OF_XERIC, 0), + ANCESTRAL_HAT(ItemID.ANCESTRAL_HAT, BossTab.CHAMBERS_OF_XERIC, 0), + ANCESTRAL_ROBE_TOP(ItemID.ANCESTRAL_ROBE_TOP, BossTab.CHAMBERS_OF_XERIC, 0), + ANCESTRAL_ROBE_BOTTOM(ItemID.ANCESTRAL_ROBE_BOTTOM, BossTab.CHAMBERS_OF_XERIC, 0), + // Range + DRAGON_HUNTER_CROSSBOW(ItemID.DRAGON_HUNTER_CROSSBOW, BossTab.CHAMBERS_OF_XERIC, 1), + TWISTED_BUCKLER(ItemID.TWISTED_BUCKLER, BossTab.CHAMBERS_OF_XERIC, 1), + TWISTED_BOW(ItemID.TWISTED_BOW, BossTab.CHAMBERS_OF_XERIC, 1), + // Melee + DRAGON_CLAWS(ItemID.DRAGON_CLAWS, BossTab.CHAMBERS_OF_XERIC, 2), + DINHS_BULWARK(ItemID.DINHS_BULWARK, BossTab.CHAMBERS_OF_XERIC, 2), + ELDER_MAUL(ItemID.ELDER_MAUL, BossTab.CHAMBERS_OF_XERIC, 2), + // Prayers/Other + TORN_PRAYER_SCROLL(ItemID.TORN_PRAYER_SCROLL, BossTab.CHAMBERS_OF_XERIC, 3), + ARCANE_PRAYER_SCROLL(ItemID.ARCANE_PRAYER_SCROLL, BossTab.CHAMBERS_OF_XERIC, 3), + DEXTEROUS_PRAYER_SCROLL(ItemID.DEXTEROUS_PRAYER_SCROLL, BossTab.CHAMBERS_OF_XERIC, 3), + DARK_RELIC(ItemID.DARK_RELIC, BossTab.CHAMBERS_OF_XERIC, 3), + + // Raids 2 Unqiues (Theater of Blood) + // Weapons / Pet + GHRAZI_RAPIER(ItemID.GHRAZI_RAPIER, BossTab.THEATRE_OF_BLOOD, 0), + SCYTHE_OF_VITUR_UNCHARGED(ItemID.SCYTHE_OF_VITUR_UNCHARGED, BossTab.THEATRE_OF_BLOOD, 0), + SANGUINESTI_STAFF_UNCHAGRED(ItemID.SANGUINESTI_STAFF_UNCHARGED, BossTab.THEATRE_OF_BLOOD, 0), + LIL_ZIK(ItemID.LIL_ZIK, BossTab.THEATRE_OF_BLOOD, 0), + // Armor + AVERNIC_DEFENDER_HILT(ItemID.AVERNIC_DEFENDER_HILT, BossTab.THEATRE_OF_BLOOD, 1), + JUSTICIAR_FACEGUARD(ItemID.JUSTICIAR_FACEGUARD, BossTab.THEATRE_OF_BLOOD, 1), + JUSTICIAR_CHESTGUARD(ItemID.JUSTICIAR_CHESTGUARD, BossTab.THEATRE_OF_BLOOD, 1), + JUSTICIAR_LEGGUARDS(ItemID.JUSTICIAR_LEGGUARDS, BossTab.THEATRE_OF_BLOOD, 1), + + + // Zulrah + // Uniques + TANZANITE_FANG(ItemID.TANZANITE_FANG, BossTab.ZULRAH, -1), + MAGIC_FANG(ItemID.MAGIC_FANG, BossTab.ZULRAH, -1), + SERPENTINE_VISAGE(ItemID.SERPENTINE_VISAGE, BossTab.ZULRAH, -1), + // Rares + PET_SNAKELING(ItemID.PET_SNAKELING, BossTab.ZULRAH, 0), + TANZANITE_MUTAGEN(ItemID.TANZANITE_MUTAGEN, BossTab.ZULRAH, 0), + MAGMA_MUTAGEN(ItemID.MAGMA_MUTAGEN, BossTab.ZULRAH, 0), + JAR_OF_SWAMP(ItemID.JAR_OF_SWAMP, BossTab.ZULRAH, 0), + + // Vorkath + DRAGONBONE_NECKLACE(ItemID.DRAGONBONE_NECKLACE, BossTab.VORKATH, 0), + VORKATHS_HEAD(ItemID.VORKATHS_HEAD_21907, BossTab.VORKATH, 0), + JAR_OF_DECAY(ItemID.JAR_OF_DECAY, BossTab.VORKATH, 0), + VORKI(ItemID.VORKI, BossTab.VORKATH, 0), + SKELETAL_VISAGE(ItemID.SKELETAL_VISAGE, BossTab.VORKATH, 0), + + + // God Wars Dungeon + // Kreearra (Armadyl) + ARMADYL_HELMET(ItemID.ARMADYL_HELMET, BossTab.KREEARRA, 0), + ARMADYL_CHESTPLATE(ItemID.ARMADYL_CHESTPLATE, BossTab.KREEARRA, 0), + ARMADYL_CHAINSKIRT(ItemID.ARMADYL_CHAINSKIRT, BossTab.KREEARRA, 0), + ARMADYL_HILT(ItemID.ARMADYL_HILT, BossTab.KREEARRA, 0), + PET_KREEARRA(ItemID.PET_KREEARRA, BossTab.KREEARRA, -1), + // General Graardor (Bandos) + BANDOS_CHESTPLATE(ItemID.BANDOS_CHESTPLATE, BossTab.GENERAL_GRAARDOR, 0), + BANDOS_TASSETS(ItemID.BANDOS_TASSETS, BossTab.GENERAL_GRAARDOR, 0), + BANDOS_BOOTS(ItemID.BANDOS_BOOTS, BossTab.GENERAL_GRAARDOR, 0), + BANDOS_HILT(ItemID.BANDOS_HILT, BossTab.GENERAL_GRAARDOR, 0), + PET_GENERAL_GRAARDOR(ItemID.PET_GENERAL_GRAARDOR, BossTab.GENERAL_GRAARDOR, -1), + // Command Zilyana (Saradomin) + SARADOMIN_SWORD(ItemID.SARADOMIN_SWORD, BossTab.COMMANDER_ZILYANA, 0), + ARMADYL_CROSSBOW(ItemID.ARMADYL_CROSSBOW, BossTab.COMMANDER_ZILYANA, 0), + SARADOMINS_LIGHT(ItemID.SARADOMINS_LIGHT, BossTab.COMMANDER_ZILYANA, 0), + SARADOMIN_HILT(ItemID.SARADOMIN_HILT, BossTab.COMMANDER_ZILYANA, 0), + PET_ZILYANA(ItemID.PET_ZILYANA, BossTab.COMMANDER_ZILYANA, -1), + // Kril Tsutsaroth (Zammy) + STEAM_BATTLESTAFF(ItemID.STEAM_BATTLESTAFF, BossTab.KRIL_TSUTSAROTH, 0), + STAFF_OF_THE_DEAD(ItemID.STAFF_OF_THE_DEAD, BossTab.KRIL_TSUTSAROTH, 0), + ZAMORAKIAN_SPEAR(ItemID.ZAMORAKIAN_SPEAR, BossTab.KRIL_TSUTSAROTH, 0), + ZAMORAK_HILT(ItemID.ZAMORAK_HILT, BossTab.KRIL_TSUTSAROTH, 0), + PET_KRIL_TSUTSAROTH(ItemID.PET_KRIL_TSUTSAROTH, BossTab.KRIL_TSUTSAROTH, -1), + + + // Wildy Bosses + // Vetion + RING_OF_THE_GODS(ItemID.RING_OF_THE_GODS, BossTab.VETION, 0), + VETION_JR(ItemID.VETION_JR, BossTab.VETION, 0), + SKELETON_CHAMPION_SCROLL(ItemID.SKELETON_CHAMPION_SCROLL, BossTab.VETION, 0), + // Venenatis + TREASONOUS_RING(ItemID.TREASONOUS_RING, BossTab.VENENATIS, -1), + VENENATIS_SPIDERLING(ItemID.VENENATIS_SPIDERLING, BossTab.VENENATIS, -1), + // Callisto + TYRANNICAL_RING(ItemID.TYRANNICAL_RING, BossTab.CALLISTO, -1), + CALLISTO_CUB(ItemID.CALLISTO_CUB, BossTab.CALLISTO, -1), + // Chaos Elemental Uniques are all in Shared +// Chaos Fanatic + ODIUM_SHARD_1(ItemID.ODIUM_SHARD_1, BossTab.CHAOS_FANATIC, -1), + MALEDICTION_SHARD_1(ItemID.MALEDICTION_SHARD_1, BossTab.CHAOS_FANATIC, -1), + // Crazy Archaeologist + ODIUM_SHARD_2(ItemID.ODIUM_SHARD_2, BossTab.CRAZY_ARCHAEOLOGIST, 0), + MALEDICTION_SHARD_2(ItemID.MALEDICTION_SHARD_2, BossTab.CRAZY_ARCHAEOLOGIST, 0), + FEDORA(ItemID.FEDORA, BossTab.CRAZY_ARCHAEOLOGIST, 0), + // Scorpia + ODIUM_SHARD_3(ItemID.ODIUM_SHARD_3, BossTab.SCORPIA, 0), + MALEDICTION_SHARD_3(ItemID.MALEDICTION_SHARD_3, BossTab.SCORPIA, 0), + SCORPIAS_OFFSPRING(ItemID.SCORPIAS_OFFSPRING, BossTab.SCORPIA, 0), + // King Black Dragon, + KBD_HEADS(ItemID.KBD_HEADS, BossTab.KING_BLACK_DRAGON, -1), + DRACONIC_VISAGE(ItemID.DRACONIC_VISAGE, BossTab.KING_BLACK_DRAGON, -1), + PRINCE_BLACK_DRAGON(ItemID.PRINCE_BLACK_DRAGON, BossTab.KING_BLACK_DRAGON, -1), + + // Slayer Bosses +// Skotizo + DARK_CLAW(ItemID.DARK_CLAW, BossTab.SKOTIZO, -1), + SKOTOS(ItemID.SKOTOS, BossTab.SKOTIZO, -1), + JAR_OF_DARKNESS(ItemID.JAR_OF_DARKNESS, BossTab.SKOTIZO, -1), + // Grotesque Guardians + GRANITE_GLOVES(ItemID.GRANITE_GLOVES, BossTab.GROTESQUE_GUARDIANS, 0), + GRANITE_RING(ItemID.GRANITE_RING, BossTab.GROTESQUE_GUARDIANS, 0), + GRANITE_HAMMER(ItemID.GRANITE_HAMMER, BossTab.GROTESQUE_GUARDIANS, 0), + BLACK_TOURMALINE_CORE(ItemID.BLACK_TOURMALINE_CORE, BossTab.GROTESQUE_GUARDIANS, 1), + NOON(ItemID.NOON, BossTab.GROTESQUE_GUARDIANS, 1), + JAR_OF_STONE(ItemID.JAR_OF_STONE, BossTab.GROTESQUE_GUARDIANS, 1), + // Abyssal Sire + UNSIRED(ItemID.UNSIRED, BossTab.ABYSSAL_SIRE, 0), + BLUDGEON_CLAW(ItemID.BLUDGEON_CLAW, BossTab.ABYSSAL_SIRE, 0), + BLUDGEON_SPINE(ItemID.BLUDGEON_SPINE, BossTab.ABYSSAL_SIRE, 0), + BLUDGEON_AXON(ItemID.BLUDGEON_AXON, BossTab.ABYSSAL_SIRE, 0), + ABYSSAL_DAGGER(ItemID.ABYSSAL_DAGGER, BossTab.ABYSSAL_SIRE, 1), + ABYSSAL_WHIP(ItemID.ABYSSAL_WHIP, BossTab.ABYSSAL_SIRE, 1), + ABYSSAL_ORPHAN(ItemID.ABYSSAL_ORPHAN, BossTab.ABYSSAL_SIRE, 1), + JAR_OF_MIASMA(ItemID.JAR_OF_MIASMA, BossTab.ABYSSAL_SIRE, 1), + ABYSSAL_HEAD(ItemID.ABYSSAL_HEAD, BossTab.ABYSSAL_SIRE, 1), + // Kraken + TRIDENT_OF_THE_SEAS_FULL(ItemID.TRIDENT_OF_THE_SEAS_FULL, BossTab.KRAKEN, 0), + KRAKEN_TENTACLE(ItemID.KRAKEN_TENTACLE, BossTab.KRAKEN, 0), + JAR_OF_DIRT(ItemID.JAR_OF_DIRT, BossTab.KRAKEN, 0), + PET_KRAKEN(ItemID.PET_KRAKEN, BossTab.KRAKEN, 0), + // Cerberus + PRIMORDIAL_CRYSTAL(ItemID.PRIMORDIAL_CRYSTAL, BossTab.CERBERUS, 0), + PEGASIAN_CRYSTAL(ItemID.PEGASIAN_CRYSTAL, BossTab.CERBERUS, 0), + ETERNAL_CRYSTAL(ItemID.ETERNAL_CRYSTAL, BossTab.CERBERUS, 0), + SMOULDERING_STONE(ItemID.SMOULDERING_STONE, BossTab.CERBERUS, 0), + JAR_OF_SOULS(ItemID.JAR_OF_SOULS, BossTab.CERBERUS, 0), + HELLPUPPY(ItemID.HELLPUPPY, BossTab.CERBERUS, 0), + // Thermonuclear Smoke Devil + SMOKE_BATTLESTAFF(ItemID.SMOKE_BATTLESTAFF, BossTab.THERMONUCLEAR_SMOKE_DEVIL, -1), + OCCULT_NECKLACE(ItemID.OCCULT_NECKLACE, BossTab.THERMONUCLEAR_SMOKE_DEVIL, -1), + PET_SMOKE_DEVIL(ItemID.PET_SMOKE_DEVIL, BossTab.THERMONUCLEAR_SMOKE_DEVIL, -1), + // Alchemical Hydra + HYDRAS_EYE(ItemID.HYDRAS_EYE, BossTab.ALCHEMICAL_HYDRA, 0), + HYDRAS_FANG(ItemID.HYDRAS_FANG, BossTab.ALCHEMICAL_HYDRA, 0), + HYDRAS_HEART(ItemID.HYDRAS_HEART, BossTab.ALCHEMICAL_HYDRA, 0), + HYDRA_TAIL(ItemID.HYDRA_TAIL, BossTab.ALCHEMICAL_HYDRA, 0), + HYDRA_LEATHER(ItemID.HYDRA_LEATHER, BossTab.ALCHEMICAL_HYDRA, 1), + HYDRAS_CLAW(ItemID.HYDRAS_CLAW, BossTab.ALCHEMICAL_HYDRA, 1), + DRAGON_THROWNAXE(ItemID.DRAGON_THROWNAXE, BossTab.ALCHEMICAL_HYDRA, 1), + DRAGON_KNIFE(ItemID.DRAGON_KNIFE, BossTab.ALCHEMICAL_HYDRA, 1), + IKKLE_HYDRA(ItemID.IKKLE_HYDRA, BossTab.ALCHEMICAL_HYDRA, 1), + + + // Other Bosses +// Giant Mole + BABY_MOLE(ItemID.BABY_MOLE, BossTab.GIANT_MOLE, -1), + // Kalphite Queen + KQ_HEAD(ItemID.KQ_HEAD, BossTab.KALPHITE_QUEEN, -1), + JAR_OF_SAND(ItemID.JAR_OF_SAND, BossTab.KALPHITE_QUEEN, -1), + KALPHITE_PRINCESS(ItemID.KALPHITE_PRINCESS, BossTab.KALPHITE_QUEEN, -1), + // Corporeal Beast + SPIRIT_SHIELD(ItemID.SPIRIT_SHIELD, BossTab.CORPOREAL_BEAST, 0), + HOLY_ELIXIR(ItemID.HOLY_ELIXIR, BossTab.CORPOREAL_BEAST, 0), + PET_DARK_CORE(ItemID.PET_DARK_CORE, BossTab.CORPOREAL_BEAST, 0), + SPECTRAL_SIGIL(ItemID.SPECTRAL_SIGIL, BossTab.CORPOREAL_BEAST, 1), + ARCANE_SIGIL(ItemID.ARCANE_SIGIL, BossTab.CORPOREAL_BEAST, 1), + ELYSIAN_SIGIL(ItemID.ELYSIAN_SIGIL, BossTab.CORPOREAL_BEAST, 1), + // Dagannoth Rex + RING_OF_LIFE(ItemID.RING_OF_LIFE, BossTab.DAGANNOTH_REX, -1), + WARRIOR_RING(ItemID.WARRIOR_RING, BossTab.DAGANNOTH_REX, -1), + BERSERKER_RING(ItemID.BERSERKER_RING, BossTab.DAGANNOTH_REX, -1), + PET_DAGANNOTH_REX(ItemID.PET_DAGANNOTH_REX, BossTab.DAGANNOTH_REX, -1), + // Dagannoth Prime + MUD_BATTLESTAFF(ItemID.MUD_BATTLESTAFF, BossTab.DAGANNOTH_PRIME, -1), + SEERS_RING(ItemID.SEERS_RING, BossTab.DAGANNOTH_PRIME, -1), + PET_DAGANNOTH_PRIME(ItemID.PET_DAGANNOTH_PRIME, BossTab.DAGANNOTH_PRIME, -1), + // Dagannoth Supreme + SEERCULL(ItemID.SEERCULL, BossTab.DAGANNOTH_SUPREME, -1), + ARCHERS_RING(ItemID.ARCHERS_RING, BossTab.DAGANNOTH_SUPREME, -1), + PET_DAGANNOTH_SUPREME(ItemID.PET_DAGANNOTH_SUPREME, BossTab.DAGANNOTH_SUPREME, -1), + + // Beginner Clue Scrolls + BEAR_FEET(ItemID.BEAR_FEET, BossTab.CLUE_SCROLL_BEGINNER, -1), + FROG_SLIPPERS(ItemID.FROG_SLIPPERS, BossTab.CLUE_SCROLL_BEGINNER, -1), + DEMON_FEET(ItemID.DEMON_FEET, BossTab.CLUE_SCROLL_BEGINNER, -1), + MOLE_SLIPPERS(ItemID.MOLE_SLIPPERS, BossTab.CLUE_SCROLL_BEGINNER, -1), + + SANDWICH_LADY_HAT(ItemID.SANDWICH_LADY_HAT, BossTab.CLUE_SCROLL_BEGINNER, 0), + SANDWICH_LADY_TOP(ItemID.SANDWICH_LADY_TOP, BossTab.CLUE_SCROLL_BEGINNER, 0), + SANDWICH_LADY_BOTTOM(ItemID.SANDWICH_LADY_BOTTOM, BossTab.CLUE_SCROLL_BEGINNER, 0), + + JESTER_CAPE(ItemID.JESTER_CAPE, BossTab.CLUE_SCROLL_BEGINNER, 1), + SHOULDER_PARROT(ItemID.SHOULDER_PARROT, BossTab.CLUE_SCROLL_BEGINNER, 1), + AMULET_OF_DEFENCE_T(ItemID.AMULET_OF_DEFENCE_T, BossTab.CLUE_SCROLL_BEGINNER, 1), + + MONKS_ROBE_TOP_T(ItemID.MONKS_ROBE_TOP_T, BossTab.CLUE_SCROLL_BEGINNER, 2), + MONKS_ROBE_T(ItemID.MONKS_ROBE_T, BossTab.CLUE_SCROLL_BEGINNER, 2), + RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX(ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX, BossTab.CLUE_SCROLL_BEGINNER, 2), + RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN(ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN, BossTab.CLUE_SCROLL_BEGINNER, 2), + RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK(ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK, BossTab.CLUE_SCROLL_BEGINNER, 2), + + // Easy Clue Scrolls + BRONZE_FULL_HELM_T(ItemID.BRONZE_FULL_HELM_T, BossTab.CLUE_SCROLL_EASY, -1), + BRONZE_PLATEBODY_T(ItemID.BRONZE_PLATEBODY_T, BossTab.CLUE_SCROLL_EASY, -1), + BRONZE_PLATELEGS_T(ItemID.BRONZE_PLATELEGS_T, BossTab.CLUE_SCROLL_EASY, -1), + BRONZE_PLATESKIRT_T(ItemID.BRONZE_PLATESKIRT_T, BossTab.CLUE_SCROLL_EASY, -1), + BRONZE_KITESHIELD_T(ItemID.BRONZE_KITESHIELD_T, BossTab.CLUE_SCROLL_EASY, -1), + BRONZE_FULL_HELM_G(ItemID.BRONZE_FULL_HELM_G, BossTab.CLUE_SCROLL_EASY, 0), + BRONZE_PLATEBODY_G(ItemID.BRONZE_PLATEBODY_G, BossTab.CLUE_SCROLL_EASY, 0), + BRONZE_PLATELEGS_G(ItemID.BRONZE_PLATELEGS_G, BossTab.CLUE_SCROLL_EASY, 0), + BRONZE_PLATESKIRT_G(ItemID.BRONZE_PLATESKIRT_G, BossTab.CLUE_SCROLL_EASY, 0), + BRONZE_KITESHIELD_G(ItemID.BRONZE_KITESHIELD_G, BossTab.CLUE_SCROLL_EASY, 0), + IRON_FULL_HELM_T(ItemID.IRON_FULL_HELM_T, BossTab.CLUE_SCROLL_EASY, 1), + IRON_PLATEBODY_T(ItemID.IRON_PLATEBODY_T, BossTab.CLUE_SCROLL_EASY, 1), + IRON_PLATELEGS_T(ItemID.IRON_PLATELEGS_T, BossTab.CLUE_SCROLL_EASY, 1), + IRON_PLATESKIRT_T(ItemID.IRON_PLATESKIRT_T, BossTab.CLUE_SCROLL_EASY, 1), + IRON_KITESHIELD_T(ItemID.IRON_KITESHIELD_T, BossTab.CLUE_SCROLL_EASY, 1), + IRON_FULL_HELM_G(ItemID.IRON_FULL_HELM_G, BossTab.CLUE_SCROLL_EASY, 2), + IRON_PLATEBODY_G(ItemID.IRON_PLATEBODY_G, BossTab.CLUE_SCROLL_EASY, 2), + IRON_PLATELEGS_G(ItemID.IRON_PLATELEGS_G, BossTab.CLUE_SCROLL_EASY, 2), + IRON_PLATESKIRT_G(ItemID.IRON_PLATESKIRT_G, BossTab.CLUE_SCROLL_EASY, 2), + IRON_KITESHIELD_G(ItemID.IRON_KITESHIELD_G, BossTab.CLUE_SCROLL_EASY, 2), + STEEL_FULL_HELM_T(ItemID.STEEL_FULL_HELM_T, BossTab.CLUE_SCROLL_EASY, 3), + STEEL_PLATEBODY_T(ItemID.STEEL_PLATEBODY_T, BossTab.CLUE_SCROLL_EASY, 3), + STEEL_PLATELEGS_T(ItemID.STEEL_PLATELEGS_T, BossTab.CLUE_SCROLL_EASY, 3), + STEEL_PLATESKIRT_T(ItemID.STEEL_PLATESKIRT_T, BossTab.CLUE_SCROLL_EASY, 3), + STEEL_KITESHIELD_T(ItemID.STEEL_KITESHIELD_T, BossTab.CLUE_SCROLL_EASY, 3), + STEEL_FULL_HELM_G(ItemID.STEEL_FULL_HELM_G, BossTab.CLUE_SCROLL_EASY, 4), + STEEL_PLATEBODY_G(ItemID.STEEL_PLATEBODY_G, BossTab.CLUE_SCROLL_EASY, 4), + STEEL_PLATELEGS_G(ItemID.STEEL_PLATELEGS_G, BossTab.CLUE_SCROLL_EASY, 4), + STEEL_PLATESKIRT_G(ItemID.STEEL_PLATESKIRT_G, BossTab.CLUE_SCROLL_EASY, 4), + STEEL_KITESHIELD_G(ItemID.STEEL_KITESHIELD_G, BossTab.CLUE_SCROLL_EASY, 4), + BLACK_FULL_HELM_T(ItemID.BLACK_FULL_HELM_T, BossTab.CLUE_SCROLL_EASY, 5), + BLACK_PLATEBODY_T(ItemID.BLACK_PLATEBODY_T, BossTab.CLUE_SCROLL_EASY, 5), + BLACK_PLATELEGS_T(ItemID.BLACK_PLATELEGS_T, BossTab.CLUE_SCROLL_EASY, 5), + BLACK_PLATESKIRT_T(ItemID.BLACK_PLATESKIRT_T, BossTab.CLUE_SCROLL_EASY, 5), + BLACK_KITESHIELD_T(ItemID.BLACK_KITESHIELD_T, BossTab.CLUE_SCROLL_EASY, 5), + BLACK_FULL_HELM_G(ItemID.BLACK_FULL_HELM_G, BossTab.CLUE_SCROLL_EASY, 6), + BLACK_PLATEBODY_G(ItemID.BLACK_PLATEBODY_G, BossTab.CLUE_SCROLL_EASY, 6), + BLACK_PLATELEGS_G(ItemID.BLACK_PLATELEGS_G, BossTab.CLUE_SCROLL_EASY, 6), + BLACK_PLATESKIRT_G(ItemID.BLACK_PLATESKIRT_G, BossTab.CLUE_SCROLL_EASY, 6), + BLACK_KITESHIELD_G(ItemID.BLACK_KITESHIELD_G, BossTab.CLUE_SCROLL_EASY, 6), + BLUE_WIZARD_HAT_T(ItemID.BLUE_WIZARD_HAT_T, BossTab.CLUE_SCROLL_EASY, 7), + BLUE_WIZARD_ROBE_T(ItemID.BLUE_WIZARD_ROBE_T, BossTab.CLUE_SCROLL_EASY, 7), + BLUE_SKIRT_T(ItemID.BLUE_SKIRT_T, BossTab.CLUE_SCROLL_EASY, 7), + BLUE_WIZARD_HAT_G(ItemID.BLUE_WIZARD_HAT_G, BossTab.CLUE_SCROLL_EASY, 8), + BLUE_WIZARD_ROBE_G(ItemID.BLUE_WIZARD_ROBE_G, BossTab.CLUE_SCROLL_EASY, 8), + BLUE_SKIRT_G(ItemID.BLUE_SKIRT_G, BossTab.CLUE_SCROLL_EASY, 8), + BLACK_WIZARD_HAT_T(ItemID.BLACK_WIZARD_HAT_T, BossTab.CLUE_SCROLL_EASY, 9), + BLACK_WIZARD_ROBE_T(ItemID.BLACK_WIZARD_ROBE_T, BossTab.CLUE_SCROLL_EASY, 9), + BLACK_SKIRT_T(ItemID.BLACK_SKIRT_T, BossTab.CLUE_SCROLL_EASY, 9), + BLACK_WIZARD_HAT_G(ItemID.BLACK_WIZARD_HAT_G, BossTab.CLUE_SCROLL_EASY, 10), + BLACK_WIZARD_ROBE_G(ItemID.BLACK_WIZARD_ROBE_G, BossTab.CLUE_SCROLL_EASY, 10), + BLACK_SKIRT_G(ItemID.BLACK_SKIRT_G, BossTab.CLUE_SCROLL_EASY, 10), + LEATHER_BODY_G(ItemID.LEATHER_BODY_G, BossTab.CLUE_SCROLL_EASY, 11), + LEATHER_CHAPS_G(ItemID.LEATHER_CHAPS_G, BossTab.CLUE_SCROLL_EASY, 11), + STUDDED_BODY_T(ItemID.STUDDED_BODY_T, BossTab.CLUE_SCROLL_EASY, 11), + STUDDED_CHAPS_T(ItemID.STUDDED_CHAPS_T, BossTab.CLUE_SCROLL_EASY, 11), + STUDDED_BODY_G(ItemID.STUDDED_BODY_G, BossTab.CLUE_SCROLL_EASY, 11), + STUDDED_CHAPS_G(ItemID.STUDDED_CHAPS_G, BossTab.CLUE_SCROLL_EASY, 11), + BLACK_HELM_H1(ItemID.BLACK_HELM_H1, BossTab.CLUE_SCROLL_EASY, 12), + BLACK_HELM_H2(ItemID.BLACK_HELM_H2, BossTab.CLUE_SCROLL_EASY, 12), + BLACK_HELM_H3(ItemID.BLACK_HELM_H3, BossTab.CLUE_SCROLL_EASY, 12), + BLACK_HELM_H4(ItemID.BLACK_HELM_H4, BossTab.CLUE_SCROLL_EASY, 12), + BLACK_HELM_H5(ItemID.BLACK_HELM_H5, BossTab.CLUE_SCROLL_EASY, 12), + BLACK_SHIELD_H1(ItemID.BLACK_SHIELD_H1, BossTab.CLUE_SCROLL_EASY, 13), + BLACK_SHIELD_H2(ItemID.BLACK_SHIELD_H2, BossTab.CLUE_SCROLL_EASY, 13), + BLACK_SHIELD_H3(ItemID.BLACK_SHIELD_H3, BossTab.CLUE_SCROLL_EASY, 13), + BLACK_SHIELD_H4(ItemID.BLACK_SHIELD_H4, BossTab.CLUE_SCROLL_EASY, 13), + BLACK_SHIELD_H5(ItemID.BLACK_SHIELD_H5, BossTab.CLUE_SCROLL_EASY, 13), + BLUE_ELEGANT_SHIRT(ItemID.BLUE_ELEGANT_SHIRT, BossTab.CLUE_SCROLL_EASY, 14), + BLUE_ELEGANT_LEGS(ItemID.BLUE_ELEGANT_LEGS, BossTab.CLUE_SCROLL_EASY, 14), + BLUE_ELEGANT_BLOUSE(ItemID.BLUE_ELEGANT_BLOUSE, BossTab.CLUE_SCROLL_EASY, 14), + BLUE_ELEGANT_SKIRT(ItemID.BLUE_ELEGANT_SKIRT, BossTab.CLUE_SCROLL_EASY, 14), + GREEN_ELEGANT_SHIRT(ItemID.GREEN_ELEGANT_SHIRT, BossTab.CLUE_SCROLL_EASY, 15), + GREEN_ELEGANT_LEGS(ItemID.GREEN_ELEGANT_LEGS, BossTab.CLUE_SCROLL_EASY, 15), + GREEN_ELEGANT_BLOUSE(ItemID.GREEN_ELEGANT_BLOUSE, BossTab.CLUE_SCROLL_EASY, 15), + GREEN_ELEGANT_SKIRT(ItemID.GREEN_ELEGANT_SKIRT, BossTab.CLUE_SCROLL_EASY, 15), + RED_ELEGANT_SHIRT(ItemID.RED_ELEGANT_SHIRT, BossTab.CLUE_SCROLL_EASY, 16), + RED_ELEGANT_LEGS(ItemID.RED_ELEGANT_LEGS, BossTab.CLUE_SCROLL_EASY, 16), + RED_ELEGANT_BLOUSE(ItemID.RED_ELEGANT_BLOUSE, BossTab.CLUE_SCROLL_EASY, 16), + RED_ELEGANT_SKIRT(ItemID.RED_ELEGANT_SKIRT, BossTab.CLUE_SCROLL_EASY, 16), + BOBS_RED_SHIRT(ItemID.BOBS_RED_SHIRT, BossTab.CLUE_SCROLL_EASY, 17), + BOBS_BLUE_SHIRT(ItemID.BOBS_BLUE_SHIRT, BossTab.CLUE_SCROLL_EASY, 17), + BOBS_GREEN_SHIRT(ItemID.BOBS_GREEN_SHIRT, BossTab.CLUE_SCROLL_EASY, 17), + BOBS_BLACK_SHIRT(ItemID.BOBS_BLACK_SHIRT, BossTab.CLUE_SCROLL_EASY, 17), + BOBS_PURPLE_SHIRT(ItemID.BOBS_PURPLE_SHIRT, BossTab.CLUE_SCROLL_EASY, 17), + STAFF_OF_BOB_THE_CAT(ItemID.STAFF_OF_BOB_THE_CAT, BossTab.CLUE_SCROLL_EASY, 17), + A_POWDERED_WIG(ItemID.A_POWDERED_WIG, BossTab.CLUE_SCROLL_EASY, 18), + FLARED_TROUSERS(ItemID.FLARED_TROUSERS, BossTab.CLUE_SCROLL_EASY, 18), + PANTALOONS(ItemID.PANTALOONS, BossTab.CLUE_SCROLL_EASY, 18), + SLEEPING_CAP(ItemID.SLEEPING_CAP, BossTab.CLUE_SCROLL_EASY, 18), + GUTHIX_ROBE_TOP(ItemID.GUTHIX_ROBE_TOP, BossTab.CLUE_SCROLL_EASY, 19), + GUTHIX_ROBE_LEGS(ItemID.GUTHIX_ROBE_LEGS, BossTab.CLUE_SCROLL_EASY, 19), + SARADOMIN_ROBE_TOP(ItemID.SARADOMIN_ROBE_TOP, BossTab.CLUE_SCROLL_EASY, 19), + SARADOMIN_ROBE_LEGS(ItemID.SARADOMIN_ROBE_LEGS, BossTab.CLUE_SCROLL_EASY, 19), + ZAMORAK_ROBE_TOP(ItemID.ZAMORAK_ROBE_TOP, BossTab.CLUE_SCROLL_EASY, 19), + ZAMORAK_ROBE_LEGS(ItemID.ZAMORAK_ROBE_LEGS, BossTab.CLUE_SCROLL_EASY, 19), + ANCIENT_ROBE_TOP(ItemID.ANCIENT_ROBE_TOP, BossTab.CLUE_SCROLL_EASY, 20), + ANCIENT_ROBE_LEGS(ItemID.ANCIENT_ROBE_LEGS, BossTab.CLUE_SCROLL_EASY, 20), + BANDOS_ROBE_TOP(ItemID.BANDOS_ROBE_TOP, BossTab.CLUE_SCROLL_EASY, 20), + BANDOS_ROBE_LEGS(ItemID.BANDOS_ROBE_LEGS, BossTab.CLUE_SCROLL_EASY, 20), + ARMADYL_ROBE_TOP(ItemID.ARMADYL_ROBE_TOP, BossTab.CLUE_SCROLL_EASY, 20), + ARMADYL_ROBE_LEGS(ItemID.ARMADYL_ROBE_LEGS, BossTab.CLUE_SCROLL_EASY, 20), + BLACK_BERET(ItemID.BLACK_BERET, BossTab.CLUE_SCROLL_EASY, 21), + BLUE_BERET(ItemID.BLUE_BERET, BossTab.CLUE_SCROLL_EASY, 21), + WHITE_BERET(ItemID.WHITE_BERET, BossTab.CLUE_SCROLL_EASY, 21), + RED_BERET(ItemID.RED_BERET, BossTab.CLUE_SCROLL_EASY, 21), + HIGHWAYMAN_MASK(ItemID.HIGHWAYMAN_MASK, BossTab.CLUE_SCROLL_EASY, 22), + IMP_MASK(ItemID.IMP_MASK, BossTab.CLUE_SCROLL_EASY, 22), + GOBLIN_MASK(ItemID.GOBLIN_MASK, BossTab.CLUE_SCROLL_EASY, 22), + BEANIE(ItemID.BEANIE, BossTab.CLUE_SCROLL_EASY, 22), + TEAM_CAPE_I(ItemID.TEAM_CAPE_I, BossTab.CLUE_SCROLL_EASY, 23), + TEAM_CAPE_X(ItemID.TEAM_CAPE_X, BossTab.CLUE_SCROLL_EASY, 23), + TEAM_CAPE_ZERO(ItemID.TEAM_CAPE_ZERO, BossTab.CLUE_SCROLL_EASY, 23), + CAPE_OF_SKULLS(ItemID.CAPE_OF_SKULLS, BossTab.CLUE_SCROLL_EASY, 23), + AMULET_OF_MAGIC_T(ItemID.AMULET_OF_MAGIC_T, BossTab.CLUE_SCROLL_EASY, 24), + AMULET_OF_POWER_T(ItemID.AMULET_OF_POWER_T, BossTab.CLUE_SCROLL_EASY, 24), + BLACK_CANE(ItemID.BLACK_CANE, BossTab.CLUE_SCROLL_EASY, 24), + BLACK_PICKAXE(ItemID.BLACK_PICKAXE, BossTab.CLUE_SCROLL_EASY, 24), + LARGE_SPADE(ItemID.LARGE_SPADE, BossTab.CLUE_SCROLL_EASY, 24), + RAIN_BOW(ItemID.RAIN_BOW, BossTab.CLUE_SCROLL_EASY, 24), + HAM_JOINT(ItemID.HAM_JOINT, BossTab.CLUE_SCROLL_EASY, 24), + WOODEN_SHIELD_G(ItemID.WOODEN_SHIELD_G, BossTab.CLUE_SCROLL_EASY, 25), + GOLDEN_CHEFS_HAT(ItemID.GOLDEN_CHEFS_HAT, BossTab.CLUE_SCROLL_EASY, 25), + GOLDEN_APRON(ItemID.GOLDEN_APRON, BossTab.CLUE_SCROLL_EASY, 25), + MONKS_ROBE_TOP_G(ItemID.MONKS_ROBE_TOP_G, BossTab.CLUE_SCROLL_EASY, 25), + MONKS_ROBE_G(ItemID.MONKS_ROBE_G, BossTab.CLUE_SCROLL_EASY, 25), + BLACK_PLATEBODY_H1(ItemID.BLACK_PLATEBODY_H1, BossTab.CLUE_SCROLL_EASY, 26), + BLACK_PLATEBODY_H2(ItemID.BLACK_PLATEBODY_H2, BossTab.CLUE_SCROLL_EASY, 26), + BLACK_PLATEBODY_H3(ItemID.BLACK_PLATEBODY_H3, BossTab.CLUE_SCROLL_EASY, 26), + BLACK_PLATEBODY_H4(ItemID.BLACK_PLATEBODY_H4, BossTab.CLUE_SCROLL_EASY, 26), + BLACK_PLATEBODY_H5(ItemID.BLACK_PLATEBODY_H5, BossTab.CLUE_SCROLL_EASY, 26), + + // Medium Clue Scrolls + MITHRIL_FULL_HELM_T(ItemID.MITHRIL_FULL_HELM_T, BossTab.CLUE_SCROLL_MEDIUM, -1), + MITHRIL_PLATEBODY_T(ItemID.MITHRIL_PLATEBODY_T, BossTab.CLUE_SCROLL_MEDIUM, -1), + MITHRIL_PLATELEGS_T(ItemID.MITHRIL_PLATELEGS_T, BossTab.CLUE_SCROLL_MEDIUM, -1), + MITHRIL_PLATESKIRT_T(ItemID.MITHRIL_PLATESKIRT_T, BossTab.CLUE_SCROLL_MEDIUM, -1), + MITHRIL_KITESHIELD_T(ItemID.MITHRIL_KITESHIELD_T, BossTab.CLUE_SCROLL_MEDIUM, -1), + MITHRIL_FULL_HELM_G(ItemID.MITHRIL_FULL_HELM_G, BossTab.CLUE_SCROLL_MEDIUM, 0), + MITHRIL_PLATEBODY_G(ItemID.MITHRIL_PLATEBODY_G, BossTab.CLUE_SCROLL_MEDIUM, 0), + MITHRIL_PLATELEGS_G(ItemID.MITHRIL_PLATELEGS_G, BossTab.CLUE_SCROLL_MEDIUM, 0), + MITHRIL_PLATESKIRT_G(ItemID.MITHRIL_PLATESKIRT_G, BossTab.CLUE_SCROLL_MEDIUM, 0), + MITHRIL_KITESHIELD_G(ItemID.MITHRIL_KITESHIELD_G, BossTab.CLUE_SCROLL_MEDIUM, 0), + ADAMANT_FULL_HELM_T(ItemID.ADAMANT_FULL_HELM_T, BossTab.CLUE_SCROLL_MEDIUM, 1), + ADAMANT_PLATEBODY_T(ItemID.ADAMANT_PLATEBODY_T, BossTab.CLUE_SCROLL_MEDIUM, 1), + ADAMANT_PLATELEGS_T(ItemID.ADAMANT_PLATELEGS_T, BossTab.CLUE_SCROLL_MEDIUM, 1), + ADAMANT_PLATESKIRT_T(ItemID.ADAMANT_PLATESKIRT_T, BossTab.CLUE_SCROLL_MEDIUM, 1), + ADAMANT_KITESHIELD_T(ItemID.ADAMANT_KITESHIELD_T, BossTab.CLUE_SCROLL_MEDIUM, 1), + ADAMANT_FULL_HELM_G(ItemID.ADAMANT_FULL_HELM_G, BossTab.CLUE_SCROLL_MEDIUM, 2), + ADAMANT_PLATEBODY_G(ItemID.ADAMANT_PLATEBODY_G, BossTab.CLUE_SCROLL_MEDIUM, 2), + ADAMANT_PLATELEGS_G(ItemID.ADAMANT_PLATELEGS_G, BossTab.CLUE_SCROLL_MEDIUM, 2), + ADAMANT_PLATESKIRT_G(ItemID.ADAMANT_PLATESKIRT_G, BossTab.CLUE_SCROLL_MEDIUM, 2), + ADAMANT_KITESHIELD_G(ItemID.ADAMANT_KITESHIELD_G, BossTab.CLUE_SCROLL_MEDIUM, 2), + RANGER_BOOTS(ItemID.RANGER_BOOTS, BossTab.CLUE_SCROLL_MEDIUM, 3), + HOLY_SANDALS(ItemID.HOLY_SANDALS, BossTab.CLUE_SCROLL_MEDIUM, 3), + WIZARD_BOOTS(ItemID.WIZARD_BOOTS, BossTab.CLUE_SCROLL_MEDIUM, 3), + CLIMBING_BOOTS_G(ItemID.CLIMBING_BOOTS_G, BossTab.CLUE_SCROLL_MEDIUM, 3), + RED_HEADBAND(ItemID.RED_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 4), + BLACK_HEADBAND(ItemID.BLACK_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 4), + BROWN_HEADBAND(ItemID.BROWN_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 4), + PINK_HEADBAND(ItemID.PINK_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 4), + GREEN_HEADBAND(ItemID.GREEN_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 5), + BLUE_HEADBAND(ItemID.BLUE_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 5), + GOLD_HEADBAND(ItemID.GOLD_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 5), + WHITE_HEADBAND(ItemID.WHITE_HEADBAND, BossTab.CLUE_SCROLL_MEDIUM, 5), + RED_BOATER(ItemID.RED_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 6), + ORANGE_BOATER(ItemID.ORANGE_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 6), + GREEN_BOATER(ItemID.GREEN_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 6), + BLUE_BOATER(ItemID.BLUE_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 6), + BLACK_BOATER(ItemID.BLACK_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 7), + PINK_BOATER(ItemID.PINK_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 7), + PURPLE_BOATER(ItemID.PURPLE_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 7), + WHITE_BOATER(ItemID.WHITE_BOATER, BossTab.CLUE_SCROLL_MEDIUM, 7), + ADAMANT_HELM_H1(ItemID.ADAMANT_HELM_H1, BossTab.CLUE_SCROLL_MEDIUM, 8), + ADAMANT_HELM_H2(ItemID.ADAMANT_HELM_H2, BossTab.CLUE_SCROLL_MEDIUM, 8), + ADAMANT_HELM_H3(ItemID.ADAMANT_HELM_H3, BossTab.CLUE_SCROLL_MEDIUM, 8), + ADAMANT_HELM_H4(ItemID.ADAMANT_HELM_H4, BossTab.CLUE_SCROLL_MEDIUM, 8), + ADAMANT_HELM_H5(ItemID.ADAMANT_HELM_H5, BossTab.CLUE_SCROLL_MEDIUM, 8), + ADAMANT_SHIELD_H1(ItemID.ADAMANT_SHIELD_H1, BossTab.CLUE_SCROLL_MEDIUM, 9), + ADAMANT_SHIELD_H2(ItemID.ADAMANT_SHIELD_H2, BossTab.CLUE_SCROLL_MEDIUM, 9), + ADAMANT_SHIELD_H3(ItemID.ADAMANT_SHIELD_H3, BossTab.CLUE_SCROLL_MEDIUM, 9), + ADAMANT_SHIELD_H4(ItemID.ADAMANT_SHIELD_H4, BossTab.CLUE_SCROLL_MEDIUM, 9), + ADAMANT_SHIELD_H5(ItemID.ADAMANT_SHIELD_H5, BossTab.CLUE_SCROLL_MEDIUM, 9), + GREEN_DHIDE_BODY_T(ItemID.GREEN_DHIDE_BODY_T, BossTab.CLUE_SCROLL_MEDIUM, 10), + GREEN_DHIDE_CHAPS_T(ItemID.GREEN_DHIDE_CHAPS_T, BossTab.CLUE_SCROLL_MEDIUM, 10), + GREEN_DHIDE_BODY_G(ItemID.GREEN_DHIDE_BODY_G, BossTab.CLUE_SCROLL_MEDIUM, 10), + GREEN_DHIDE_CHAPS_G(ItemID.GREEN_DHIDE_CHAPS_G, BossTab.CLUE_SCROLL_MEDIUM, 10), + BLACK_ELEGANT_SHIRT(ItemID.BLACK_ELEGANT_SHIRT, BossTab.CLUE_SCROLL_MEDIUM, 11), + BLACK_ELEGANT_LEGS(ItemID.BLACK_ELEGANT_LEGS, BossTab.CLUE_SCROLL_MEDIUM, 11), + WHITE_ELEGANT_BLOUSE(ItemID.WHITE_ELEGANT_BLOUSE, BossTab.CLUE_SCROLL_MEDIUM, 11), + WHITE_ELEGANT_SKIRT(ItemID.WHITE_ELEGANT_SKIRT, BossTab.CLUE_SCROLL_MEDIUM, 11), + PURPLE_ELEGANT_SHIRT(ItemID.PURPLE_ELEGANT_SHIRT, BossTab.CLUE_SCROLL_MEDIUM, 12), + PURPLE_ELEGANT_LEGS(ItemID.PURPLE_ELEGANT_LEGS, BossTab.CLUE_SCROLL_MEDIUM, 12), + PURPLE_ELEGANT_BLOUSE(ItemID.PURPLE_ELEGANT_BLOUSE, BossTab.CLUE_SCROLL_MEDIUM, 12), + PURPLE_ELEGANT_SKIRT(ItemID.PURPLE_ELEGANT_SKIRT, BossTab.CLUE_SCROLL_MEDIUM, 12), + PINK_ELEGANT_SHIRT(ItemID.PINK_ELEGANT_SHIRT, BossTab.CLUE_SCROLL_MEDIUM, 13), + PINK_ELEGANT_LEGS(ItemID.PINK_ELEGANT_LEGS, BossTab.CLUE_SCROLL_MEDIUM, 13), + PINK_ELEGANT_BLOUSE(ItemID.PINK_ELEGANT_BLOUSE, BossTab.CLUE_SCROLL_MEDIUM, 13), + PINK_ELEGANT_SKIRT(ItemID.PINK_ELEGANT_SKIRT, BossTab.CLUE_SCROLL_MEDIUM, 13), + GOLD_ELEGANT_SHIRT(ItemID.GOLD_ELEGANT_SHIRT, BossTab.CLUE_SCROLL_MEDIUM, 14), + GOLD_ELEGANT_LEGS(ItemID.GOLD_ELEGANT_LEGS, BossTab.CLUE_SCROLL_MEDIUM, 14), + GOLD_ELEGANT_BLOUSE(ItemID.GOLD_ELEGANT_BLOUSE, BossTab.CLUE_SCROLL_MEDIUM, 14), + GOLD_ELEGANT_SKIRT(ItemID.GOLD_ELEGANT_SKIRT, BossTab.CLUE_SCROLL_MEDIUM, 14), + GUTHIX_MITRE(ItemID.GUTHIX_MITRE, BossTab.CLUE_SCROLL_MEDIUM, 15), + GUTHIX_CLOAK(ItemID.GUTHIX_CLOAK, BossTab.CLUE_SCROLL_MEDIUM, 15), + SARADOMIN_MITRE(ItemID.SARADOMIN_MITRE, BossTab.CLUE_SCROLL_MEDIUM, 15), + SARADOMIN_CLOAK(ItemID.SARADOMIN_CLOAK, BossTab.CLUE_SCROLL_MEDIUM, 15), + ZAMORAK_MITRE(ItemID.ZAMORAK_MITRE, BossTab.CLUE_SCROLL_MEDIUM, 15), + ZAMORAK_CLOAK(ItemID.ZAMORAK_CLOAK, BossTab.CLUE_SCROLL_MEDIUM, 15), + ANCIENT_MITRE(ItemID.ANCIENT_MITRE, BossTab.CLUE_SCROLL_MEDIUM, 16), + ANCIENT_CLOAK(ItemID.ANCIENT_CLOAK, BossTab.CLUE_SCROLL_MEDIUM, 16), + BANDOS_MITRE(ItemID.BANDOS_MITRE, BossTab.CLUE_SCROLL_MEDIUM, 16), + BANDOS_CLOAK(ItemID.BANDOS_CLOAK, BossTab.CLUE_SCROLL_MEDIUM, 16), + ARMADYL_MITRE(ItemID.ARMADYL_MITRE, BossTab.CLUE_SCROLL_MEDIUM, 16), + ARMADYL_CLOAK(ItemID.ARMADYL_CLOAK, BossTab.CLUE_SCROLL_MEDIUM, 16), + ARMADYL_STOLE(ItemID.ARMADYL_STOLE, BossTab.CLUE_SCROLL_MEDIUM, 17), + ARMADYL_CROZIER(ItemID.ARMADYL_CROZIER, BossTab.CLUE_SCROLL_MEDIUM, 17), + ANCIENT_STOLE(ItemID.ANCIENT_STOLE, BossTab.CLUE_SCROLL_MEDIUM, 17), + ANCIENT_CROZIER(ItemID.ANCIENT_CROZIER, BossTab.CLUE_SCROLL_MEDIUM, 17), + BANDOS_STOLE(ItemID.BANDOS_STOLE, BossTab.CLUE_SCROLL_MEDIUM, 17), + BANDOS_CROZIER(ItemID.BANDOS_CROZIER, BossTab.CLUE_SCROLL_MEDIUM, 17), + CAT_MASK(ItemID.CAT_MASK, BossTab.CLUE_SCROLL_MEDIUM, 18), + PENGUIN_MASK(ItemID.PENGUIN_MASK, BossTab.CLUE_SCROLL_MEDIUM, 18), + BLACK_UNICORN_MASK(ItemID.BLACK_UNICORN_MASK, BossTab.CLUE_SCROLL_MEDIUM, 18), + WHITE_UNICORN_MASK(ItemID.WHITE_UNICORN_MASK, BossTab.CLUE_SCROLL_MEDIUM, 18), + LEPRECHAUN_HAT(ItemID.LEPRECHAUN_HAT, BossTab.CLUE_SCROLL_MEDIUM, 18), + BLACK_LEPRECHAUN_HAT(ItemID.BLACK_LEPRECHAUN_HAT, BossTab.CLUE_SCROLL_MEDIUM, 18), + ARCEUUS_BANNER(ItemID.ARCEUUS_BANNER, BossTab.CLUE_SCROLL_MEDIUM, 19), + HOSIDIUS_BANNER(ItemID.HOSIDIUS_BANNER, BossTab.CLUE_SCROLL_MEDIUM, 19), + LOVAKENGJ_BANNER(ItemID.LOVAKENGJ_BANNER, BossTab.CLUE_SCROLL_MEDIUM, 19), + PISCARILIUS_BANNER(ItemID.PISCARILIUS_BANNER, BossTab.CLUE_SCROLL_MEDIUM, 19), + SHAYZIEN_BANNER(ItemID.SHAYZIEN_BANNER, BossTab.CLUE_SCROLL_MEDIUM, 19), + CRIER_HAT(ItemID.CRIER_HAT, BossTab.CLUE_SCROLL_MEDIUM, 20), + CRIER_BELL(ItemID.CRIER_BELL, BossTab.CLUE_SCROLL_MEDIUM, 20), + CRIER_COAT(ItemID.CRIER_COAT, BossTab.CLUE_SCROLL_MEDIUM, 20), + WOLF_MASK(ItemID.WOLF_MASK, BossTab.CLUE_SCROLL_MEDIUM, 20), + WOLF_CLOAK(ItemID.WOLF_CLOAK, BossTab.CLUE_SCROLL_MEDIUM, 20), + SPIKED_MANACLES(ItemID.SPIKED_MANACLES, BossTab.CLUE_SCROLL_MEDIUM, 21), + STRENGTH_AMULET_T(ItemID.STRENGTH_AMULET_T, BossTab.CLUE_SCROLL_MEDIUM, 21), + ADAMANT_CANE(ItemID.ADAMANT_CANE, BossTab.CLUE_SCROLL_MEDIUM, 21), + GNOMISH_FIRELIGHTER(ItemID.GNOMISH_FIRELIGHTER, BossTab.CLUE_SCROLL_MEDIUM, 21), + CABBAGE_ROUND_SHIELD(ItemID.CABBAGE_ROUND_SHIELD, BossTab.CLUE_SCROLL_MEDIUM, 21), + CLUELESS_SCROLL(ItemID.CLUELESS_SCROLL, BossTab.CLUE_SCROLL_MEDIUM, 21), + ADAMANT_PLATEBODY_H1(ItemID.ADAMANT_PLATEBODY_H1, BossTab.CLUE_SCROLL_MEDIUM, 22), + ADAMANT_PLATEBODY_H2(ItemID.ADAMANT_PLATEBODY_H2, BossTab.CLUE_SCROLL_MEDIUM, 22), + ADAMANT_PLATEBODY_H3(ItemID.ADAMANT_PLATEBODY_H3, BossTab.CLUE_SCROLL_MEDIUM, 22), + ADAMANT_PLATEBODY_H4(ItemID.ADAMANT_PLATEBODY_H4, BossTab.CLUE_SCROLL_MEDIUM, 22), + ADAMANT_PLATEBODY_H5(ItemID.ADAMANT_PLATEBODY_H5, BossTab.CLUE_SCROLL_MEDIUM, 22), + + // Hard Clue Scrolls + RUNE_FULL_HELM_T(ItemID.RUNE_FULL_HELM_T, BossTab.CLUE_SCROLL_HARD, -1), + RUNE_PLATEBODY_T(ItemID.RUNE_PLATEBODY_T, BossTab.CLUE_SCROLL_HARD, -1), + RUNE_PLATELEGS_T(ItemID.RUNE_PLATELEGS_T, BossTab.CLUE_SCROLL_HARD, -1), + RUNE_PLATESKIRT_T(ItemID.RUNE_PLATESKIRT_T, BossTab.CLUE_SCROLL_HARD, -1), + RUNE_KITESHIELD_T(ItemID.RUNE_KITESHIELD_T, BossTab.CLUE_SCROLL_HARD, -1), + RUNE_FULL_HELM_G(ItemID.RUNE_FULL_HELM_G, BossTab.CLUE_SCROLL_HARD, 0), + RUNE_PLATEBODY_G(ItemID.RUNE_PLATEBODY_G, BossTab.CLUE_SCROLL_HARD, 0), + RUNE_PLATELEGS_G(ItemID.RUNE_PLATELEGS_G, BossTab.CLUE_SCROLL_HARD, 0), + RUNE_PLATESKIRT_G(ItemID.RUNE_PLATESKIRT_G, BossTab.CLUE_SCROLL_HARD, 0), + RUNE_KITESHIELD_G(ItemID.RUNE_KITESHIELD_G, BossTab.CLUE_SCROLL_HARD, 0), + GUTHIX_FULL_HELM(ItemID.GUTHIX_FULL_HELM, BossTab.CLUE_SCROLL_HARD, 1), + GUTHIX_PLATEBODY(ItemID.GUTHIX_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 1), + GUTHIX_PLATELEGS(ItemID.GUTHIX_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 1), + GUTHIX_PLATESKIRT(ItemID.GUTHIX_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 1), + GUTHIX_KITESHIELD(ItemID.GUTHIX_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 1), + SARADOMIN_FULL_HELM(ItemID.SARADOMIN_FULL_HELM, BossTab.CLUE_SCROLL_HARD, 2), + SARADOMIN_PLATEBODY(ItemID.SARADOMIN_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 2), + SARADOMIN_PLATELEGS(ItemID.SARADOMIN_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 2), + SARADOMIN_PLATESKIRT(ItemID.SARADOMIN_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 2), + SARADOMIN_KITESHIELD(ItemID.SARADOMIN_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 2), + ZAMORAK_FULL_HELM(ItemID.ZAMORAK_FULL_HELM, BossTab.CLUE_SCROLL_HARD, 3), + ZAMORAK_PLATEBODY(ItemID.ZAMORAK_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 3), + ZAMORAK_PLATELEGS(ItemID.ZAMORAK_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 3), + ZAMORAK_PLATESKIRT(ItemID.ZAMORAK_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 3), + ZAMORAK_KITESHIELD(ItemID.ZAMORAK_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 3), + ANCIENT_FULL_HELM(ItemID.ANCIENT_FULL_HELM, BossTab.CLUE_SCROLL_HARD, 4), + ANCIENT_PLATEBODY(ItemID.ANCIENT_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 4), + ANCIENT_PLATELEGS(ItemID.ANCIENT_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 4), + ANCIENT_PLATESKIRT(ItemID.ANCIENT_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 4), + ANCIENT_KITESHIELD(ItemID.ANCIENT_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 4), + BANDOS_FULL_HELM(ItemID.BANDOS_FULL_HELM, BossTab.CLUE_SCROLL_HARD, 5), + BANDOS_PLATEBODY(ItemID.BANDOS_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 5), + BANDOS_PLATELEGS(ItemID.BANDOS_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 5), + BANDOS_PLATESKIRT(ItemID.BANDOS_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 5), + BANDOS_KITESHIELD(ItemID.BANDOS_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 5), + ARMADYL_FULL_HELM(ItemID.ARMADYL_FULL_HELM, BossTab.CLUE_SCROLL_HARD, 6), + ARMADYL_PLATEBODY(ItemID.ARMADYL_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 6), + ARMADYL_PLATELEGS(ItemID.ARMADYL_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 6), + ARMADYL_PLATESKIRT(ItemID.ARMADYL_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 6), + ARMADYL_KITESHIELD(ItemID.ARMADYL_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 6), + GILDED_FULL_HELM(ItemID.GILDED_FULL_HELM, BossTab.CLUE_SCROLL_HARD, 7), + GILDED_PLATEBODY(ItemID.GILDED_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 7), + GILDED_PLATELEGS(ItemID.GILDED_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 7), + GILDED_PLATESKIRT(ItemID.GILDED_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 7), + GILDED_KITESHIELD(ItemID.GILDED_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 7), + GILDED_MED_HELM(ItemID.GILDED_MED_HELM, BossTab.CLUE_SCROLL_HARD, 8), + GILDED_CHAINBODY(ItemID.GILDED_CHAINBODY, BossTab.CLUE_SCROLL_HARD, 8), + GILDED_SQ_SHIELD(ItemID.GILDED_SQ_SHIELD, BossTab.CLUE_SCROLL_HARD, 8), + GILDED_2H_SWORD(ItemID.GILDED_2H_SWORD, BossTab.CLUE_SCROLL_HARD, 8), + GILDED_SPEAR(ItemID.GILDED_SPEAR, BossTab.CLUE_SCROLL_HARD, 8), + GILDED_HASTA(ItemID.GILDED_HASTA, BossTab.CLUE_SCROLL_HARD, 8), + RUNE_HELM_H1(ItemID.RUNE_HELM_H1, BossTab.CLUE_SCROLL_HARD, 9), + RUNE_HELM_H2(ItemID.RUNE_HELM_H2, BossTab.CLUE_SCROLL_HARD, 9), + RUNE_HELM_H3(ItemID.RUNE_HELM_H3, BossTab.CLUE_SCROLL_HARD, 9), + RUNE_HELM_H4(ItemID.RUNE_HELM_H4, BossTab.CLUE_SCROLL_HARD, 9), + RUNE_HELM_H5(ItemID.RUNE_HELM_H5, BossTab.CLUE_SCROLL_HARD, 9), + RUNE_SHIELD_H1(ItemID.RUNE_SHIELD_H1, BossTab.CLUE_SCROLL_HARD, 10), + RUNE_SHIELD_H2(ItemID.RUNE_SHIELD_H2, BossTab.CLUE_SCROLL_HARD, 10), + RUNE_SHIELD_H3(ItemID.RUNE_SHIELD_H3, BossTab.CLUE_SCROLL_HARD, 10), + RUNE_SHIELD_H4(ItemID.RUNE_SHIELD_H4, BossTab.CLUE_SCROLL_HARD, 10), + RUNE_SHIELD_H5(ItemID.RUNE_SHIELD_H5, BossTab.CLUE_SCROLL_HARD, 10), + BLUE_DHIDE_BODY_T(ItemID.BLUE_DHIDE_BODY_T, BossTab.CLUE_SCROLL_HARD, 11), + BLUE_DHIDE_CHAPS_T(ItemID.BLUE_DHIDE_CHAPS_T, BossTab.CLUE_SCROLL_HARD, 11), + BLUE_DHIDE_BODY_G(ItemID.BLUE_DHIDE_BODY_G, BossTab.CLUE_SCROLL_HARD, 11), + BLUE_DHIDE_CHAPS_G(ItemID.BLUE_DHIDE_CHAPS_G, BossTab.CLUE_SCROLL_HARD, 11), + RED_DHIDE_BODY_T(ItemID.RED_DHIDE_BODY_T, BossTab.CLUE_SCROLL_HARD, 12), + RED_DHIDE_CHAPS_T(ItemID.RED_DHIDE_CHAPS_T, BossTab.CLUE_SCROLL_HARD, 12), + RED_DHIDE_BODY_G(ItemID.RED_DHIDE_BODY_G, BossTab.CLUE_SCROLL_HARD, 12), + RED_DHIDE_CHAPS_G(ItemID.RED_DHIDE_CHAPS_G, BossTab.CLUE_SCROLL_HARD, 12), + ENCHANTED_HAT(ItemID.ENCHANTED_HAT, BossTab.CLUE_SCROLL_HARD, 13), + ENCHANTED_TOP(ItemID.ENCHANTED_TOP, BossTab.CLUE_SCROLL_HARD, 13), + ENCHANTED_ROBE(ItemID.ENCHANTED_ROBE, BossTab.CLUE_SCROLL_HARD, 13), + AMULET_OF_GLORY_T(ItemID.AMULET_OF_GLORY_T, BossTab.CLUE_SCROLL_HARD, 13), + ROBIN_HOOD_HAT(ItemID.ROBIN_HOOD_HAT, BossTab.CLUE_SCROLL_HARD, 14), + PIRATE_HAT(ItemID.PIRATE_HAT, BossTab.CLUE_SCROLL_HARD, 14), + PITH_HELMET(ItemID.PITH_HELMET, BossTab.CLUE_SCROLL_HARD, 14), + EXPLORER_BACKPACK(ItemID.EXPLORER_BACKPACK, BossTab.CLUE_SCROLL_HARD, 14), + RED_CAVALIER(ItemID.RED_CAVALIER, BossTab.CLUE_SCROLL_HARD, 15), + TAN_CAVALIER(ItemID.TAN_CAVALIER, BossTab.CLUE_SCROLL_HARD, 15), + DARK_CAVALIER(ItemID.DARK_CAVALIER, BossTab.CLUE_SCROLL_HARD, 15), + BLACK_CAVALIER(ItemID.BLACK_CAVALIER, BossTab.CLUE_SCROLL_HARD, 15), + NAVY_CAVALIER(ItemID.NAVY_CAVALIER, BossTab.CLUE_SCROLL_HARD, 15), + WHITE_CAVALIER(ItemID.WHITE_CAVALIER, BossTab.CLUE_SCROLL_HARD, 15), + _3RD_AGE_FULL_HELMET(ItemID._3RD_AGE_FULL_HELMET, BossTab.CLUE_SCROLL_HARD, 16), + _3RD_AGE_PLATEBODY(ItemID._3RD_AGE_PLATEBODY, BossTab.CLUE_SCROLL_HARD, 16), + _3RD_AGE_PLATELEGS(ItemID._3RD_AGE_PLATELEGS, BossTab.CLUE_SCROLL_HARD, 16), + _3RD_AGE_PLATESKIRT(ItemID._3RD_AGE_PLATESKIRT, BossTab.CLUE_SCROLL_HARD, 16), + _3RD_AGE_KITESHIELD(ItemID._3RD_AGE_KITESHIELD, BossTab.CLUE_SCROLL_HARD, 16), + _3RD_AGE_RANGE_COIF(ItemID._3RD_AGE_RANGE_COIF, BossTab.CLUE_SCROLL_HARD, 17), + _3RD_AGE_RANGE_TOP(ItemID._3RD_AGE_RANGE_TOP, BossTab.CLUE_SCROLL_HARD, 17), + _3RD_AGE_RANGE_LEGS(ItemID._3RD_AGE_RANGE_LEGS, BossTab.CLUE_SCROLL_HARD, 17), + _3RD_AGE_VAMBRACES(ItemID._3RD_AGE_VAMBRACES, BossTab.CLUE_SCROLL_HARD, 17), + _3RD_AGE_MAGE_HAT(ItemID._3RD_AGE_MAGE_HAT, BossTab.CLUE_SCROLL_HARD, 18), + _3RD_AGE_ROBE_TOP(ItemID._3RD_AGE_ROBE_TOP, BossTab.CLUE_SCROLL_HARD, 18), + _3RD_AGE_ROBE(ItemID._3RD_AGE_ROBE, BossTab.CLUE_SCROLL_HARD, 18), + _3RD_AGE_AMULET(ItemID._3RD_AGE_AMULET, BossTab.CLUE_SCROLL_HARD, 18), + GUTHIX_COIF(ItemID.GUTHIX_COIF, BossTab.CLUE_SCROLL_HARD, 19), + GUTHIX_DHIDE(ItemID.GUTHIX_DRAGONHIDE, BossTab.CLUE_SCROLL_HARD, 19), + GUTHIX_CHAPS(ItemID.GUTHIX_CHAPS, BossTab.CLUE_SCROLL_HARD, 19), + GUTHIX_BRACERS(ItemID.GUTHIX_BRACERS, BossTab.CLUE_SCROLL_HARD, 19), + GUTHIX_DHIDE_BOOTS(ItemID.GUTHIX_DHIDE_BOOTS, BossTab.CLUE_SCROLL_HARD, 19), + GUTHIX_DHIDE_SHIELD(ItemID.GUTHIX_DHIDE_SHIELD, BossTab.CLUE_SCROLL_HARD, 19), + SARADOMIN_COIF(ItemID.SARADOMIN_COIF, BossTab.CLUE_SCROLL_HARD, 20), + SARADOMIN_DHIDE(ItemID.SARADOMIN_DHIDE, BossTab.CLUE_SCROLL_HARD, 20), + SARADOMIN_CHAPS(ItemID.SARADOMIN_CHAPS, BossTab.CLUE_SCROLL_HARD, 20), + SARADOMIN_BRACERS(ItemID.SARADOMIN_BRACERS, BossTab.CLUE_SCROLL_HARD, 20), + SARADOMIN_DHIDE_BOOTS(ItemID.SARADOMIN_DHIDE_BOOTS, BossTab.CLUE_SCROLL_HARD, 20), + SARADOMIN_DHIDE_SHIELD(ItemID.SARADOMIN_DHIDE_SHIELD, BossTab.CLUE_SCROLL_HARD, 20), + ZAMORAK_COIF(ItemID.ZAMORAK_COIF, BossTab.CLUE_SCROLL_HARD, 21), + ZAMORAK_DHIDE(ItemID.ZAMORAK_DHIDE, BossTab.CLUE_SCROLL_HARD, 21), + ZAMORAK_CHAPS(ItemID.ZAMORAK_CHAPS, BossTab.CLUE_SCROLL_HARD, 21), + ZAMORAK_BRACERS(ItemID.ZAMORAK_BRACERS, BossTab.CLUE_SCROLL_HARD, 21), + ZAMORAK_DHIDE_BOOTS(ItemID.ZAMORAK_DHIDE_BOOTS, BossTab.CLUE_SCROLL_HARD, 21), + ZAMORAK_DHIDE_SHIELD(ItemID.ZAMORAK_DHIDE_SHIELD, BossTab.CLUE_SCROLL_HARD, 21), + ANCIENT_COIF(ItemID.ANCIENT_COIF, BossTab.CLUE_SCROLL_HARD, 22), + ANCIENT_DHIDE(ItemID.ANCIENT_DHIDE, BossTab.CLUE_SCROLL_HARD, 22), + ANCIENT_CHAPS(ItemID.ANCIENT_CHAPS, BossTab.CLUE_SCROLL_HARD, 22), + ANCIENT_BRACERS(ItemID.ANCIENT_BRACERS, BossTab.CLUE_SCROLL_HARD, 22), + ANCIENT_DHIDE_BOOTS(ItemID.ANCIENT_DHIDE_BOOTS, BossTab.CLUE_SCROLL_HARD, 22), + ANCIENT_DHIDE_SHIELD(ItemID.ANCIENT_DHIDE_SHIELD, BossTab.CLUE_SCROLL_HARD, 22), + BANDOS_COIF(ItemID.BANDOS_COIF, BossTab.CLUE_SCROLL_HARD, 23), + BANDOS_DHIDE(ItemID.BANDOS_DHIDE, BossTab.CLUE_SCROLL_HARD, 23), + BANDOS_CHAPS(ItemID.BANDOS_CHAPS, BossTab.CLUE_SCROLL_HARD, 23), + BANDOS_BRACERS(ItemID.BANDOS_BRACERS, BossTab.CLUE_SCROLL_HARD, 23), + BANDOS_DHIDE_BOOTS(ItemID.BANDOS_DHIDE_BOOTS, BossTab.CLUE_SCROLL_HARD, 23), + BANDOS_DHIDE_SHIELD(ItemID.BANDOS_DHIDE_SHIELD, BossTab.CLUE_SCROLL_HARD, 23), + ARMADYL_COIF(ItemID.ARMADYL_COIF, BossTab.CLUE_SCROLL_HARD, 24), + ARMADYL_DHIDE(ItemID.ARMADYL_DHIDE, BossTab.CLUE_SCROLL_HARD, 24), + ARMADYL_CHAPS(ItemID.ARMADYL_CHAPS, BossTab.CLUE_SCROLL_HARD, 24), + ARMADYL_BRACERS(ItemID.ARMADYL_BRACERS, BossTab.CLUE_SCROLL_HARD, 24), + ARMADYL_DHIDE_BOOTS(ItemID.ARMADYL_DHIDE_BOOTS, BossTab.CLUE_SCROLL_HARD, 24), + ARMADYL_DHIDE_SHIELD(ItemID.ARMADYL_DHIDE_SHIELD, BossTab.CLUE_SCROLL_HARD, 24), + GUTHIX_STOLE(ItemID.GUTHIX_STOLE, BossTab.CLUE_SCROLL_HARD, 25), + GUTHIX_CROZIER(ItemID.GUTHIX_CROZIER, BossTab.CLUE_SCROLL_HARD, 25), + SARADOMIN_STOLE(ItemID.SARADOMIN_STOLE, BossTab.CLUE_SCROLL_HARD, 25), + SARADOMIN_CROZIER(ItemID.SARADOMIN_CROZIER, BossTab.CLUE_SCROLL_HARD, 25), + ZAMORAK_STOLE(ItemID.ZAMORAK_STOLE, BossTab.CLUE_SCROLL_HARD, 25), + ZAMORAK_CROZIER(ItemID.ZAMORAK_CROZIER, BossTab.CLUE_SCROLL_HARD, 25), + GREEN_DRAGON_MASK(ItemID.GREEN_DRAGON_MASK, BossTab.CLUE_SCROLL_HARD, 26), + RED_DRAGON_MASK(ItemID.RED_DRAGON_MASK, BossTab.CLUE_SCROLL_HARD, 26), + BLUE_DRAGON_MASK(ItemID.BLUE_DRAGON_MASK, BossTab.CLUE_SCROLL_HARD, 26), + BLACK_DRAGON_MASK(ItemID.BLACK_DRAGON_MASK, BossTab.CLUE_SCROLL_HARD, 26), + RUNE_CANE(ItemID.RUNE_CANE, BossTab.CLUE_SCROLL_HARD, 27), + ZOMBIE_HEAD(ItemID.ZOMBIE_HEAD, BossTab.CLUE_SCROLL_HARD, 27), + CYCLOPS_HEAD(ItemID.CYCLOPS_HEAD, BossTab.CLUE_SCROLL_HARD, 27), + NUNCHAKU(ItemID.NUNCHAKU, BossTab.CLUE_SCROLL_HARD, 27), + DUAL_SAI(ItemID.DUAL_SAI, BossTab.CLUE_SCROLL_HARD, 27), + THIEVING_BAG(ItemID.THIEVING_BAG, BossTab.CLUE_SCROLL_HARD, 27), + DRAGON_BOOTS_ORNAMENT_KIT(ItemID.DRAGON_BOOTS_ORNAMENT_KIT, BossTab.CLUE_SCROLL_HARD, 28), + RUNE_DEFENDER_ORNAMENT_KIT(ItemID.RUNE_DEFENDER_ORNAMENT_KIT, BossTab.CLUE_SCROLL_HARD, 28), + TZHAARKETOM_ORNAMENT_KIT(ItemID.TZHAARKETOM_ORNAMENT_KIT, BossTab.CLUE_SCROLL_HARD, 28), + BERSERKER_NECKLACE_ORNAMENT_KIT(ItemID.BERSERKER_NECKLACE_ORNAMENT_KIT, BossTab.CLUE_SCROLL_HARD, 28), + RUNE_PLATEBODY_H1(ItemID.RUNE_PLATEBODY_H1, BossTab.CLUE_SCROLL_HARD, 29), + RUNE_PLATEBODY_H2(ItemID.RUNE_PLATEBODY_H2, BossTab.CLUE_SCROLL_HARD, 29), + RUNE_PLATEBODY_H3(ItemID.RUNE_PLATEBODY_H3, BossTab.CLUE_SCROLL_HARD, 29), + RUNE_PLATEBODY_H4(ItemID.RUNE_PLATEBODY_H4, BossTab.CLUE_SCROLL_HARD, 29), + RUNE_PLATEBODY_H5(ItemID.RUNE_PLATEBODY_H5, BossTab.CLUE_SCROLL_HARD, 29), + + // Elite Clue Scrolls + DRAGON_FULL_HELM_ORNAMENT_KIT(ItemID.DRAGON_FULL_HELM_ORNAMENT_KIT, BossTab.CLUE_SCROLL_ELITE, -1), + DRAGON_CHAINBODY_ORNAMENT_KIT(ItemID.DRAGON_CHAINBODY_ORNAMENT_KIT, BossTab.CLUE_SCROLL_ELITE, -1), + DRAGON_LEGSSKIRT_ORNAMENT_KIT(ItemID.DRAGON_LEGSSKIRT_ORNAMENT_KIT, BossTab.CLUE_SCROLL_ELITE, -1), + DRAGON_SQ_SHIELD_ORNAMENT_KIT(ItemID.DRAGON_SQ_SHIELD_ORNAMENT_KIT, BossTab.CLUE_SCROLL_ELITE, -1), + DRAGON_SCIMITAR_ORNAMENT_KIT(ItemID.DRAGON_SCIMITAR_ORNAMENT_KIT, BossTab.CLUE_SCROLL_ELITE, -1), + LIGHT_INFINITY_COLOUR_KIT(ItemID.LIGHT_INFINITY_COLOUR_KIT, BossTab.CLUE_SCROLL_ELITE, 0), + DARK_INFINITY_COLOUR_KIT(ItemID.DARK_INFINITY_COLOUR_KIT, BossTab.CLUE_SCROLL_ELITE, 0), + FURY_ORNAMENT_KIT(ItemID.FURY_ORNAMENT_KIT, BossTab.CLUE_SCROLL_ELITE, 0), + MUSKETEER_HAT(ItemID.MUSKETEER_HAT, BossTab.CLUE_SCROLL_ELITE, 1), + MUSKETEER_TABARD(ItemID.MUSKETEER_TABARD, BossTab.CLUE_SCROLL_ELITE, 1), + MUSKETEER_PANTS(ItemID.MUSKETEER_PANTS, BossTab.CLUE_SCROLL_ELITE, 1), + DRAGON_CANE(ItemID.DRAGON_CANE, BossTab.CLUE_SCROLL_ELITE, 1), + TOP_HAT(ItemID.TOP_HAT, BossTab.CLUE_SCROLL_ELITE, 2), + MONOCLE(ItemID.MONOCLE, BossTab.CLUE_SCROLL_ELITE, 2), + BRIEFCASE(ItemID.BRIEFCASE, BossTab.CLUE_SCROLL_ELITE, 2), + SAGACIOUS_SPECTACLES(ItemID.SAGACIOUS_SPECTACLES, BossTab.CLUE_SCROLL_ELITE, 2), + BIG_PIRATE_HAT(ItemID.BIG_PIRATE_HAT, BossTab.CLUE_SCROLL_ELITE, 3), + DEERSTALKER(ItemID.DEERSTALKER, BossTab.CLUE_SCROLL_ELITE, 3), + BLACKSMITHS_HELM(ItemID.BLACKSMITHS_HELM, BossTab.CLUE_SCROLL_ELITE, 3), + BUCKET_HELM(ItemID.BUCKET_HELM, BossTab.CLUE_SCROLL_ELITE, 3), + AFRO(ItemID.AFRO, BossTab.CLUE_SCROLL_ELITE, 3), + GILDED_COIF(ItemID.GILDED_COIF, BossTab.CLUE_SCROLL_ELITE, 4), + GILDED_DHIDE_BODY(ItemID.GILDED_DHIDE_BODY, BossTab.CLUE_SCROLL_ELITE, 4), + GILDED_DHIDE_CHAPS(ItemID.GILDED_DHIDE_CHAPS, BossTab.CLUE_SCROLL_ELITE, 4), + GILDED_DHIDE_VAMBS(ItemID.GILDED_DHIDE_VAMBS, BossTab.CLUE_SCROLL_ELITE, 4), + GILDED_BOOTS(ItemID.GILDED_BOOTS, BossTab.CLUE_SCROLL_ELITE, 5), + GILDED_SCIMITAR(ItemID.GILDED_SCIMITAR, BossTab.CLUE_SCROLL_ELITE, 5), + GILDED_PICKAXE(ItemID.GILDED_PICKAXE, BossTab.CLUE_SCROLL_ELITE, 5), + GILDED_SPADE(ItemID.GILDED_SPADE, BossTab.CLUE_SCROLL_ELITE, 5), + GILDED_AXE(ItemID.GILDED_AXE, BossTab.CLUE_SCROLL_ELITE, 5), + BRONZE_DRAGON_MASK(ItemID.BRONZE_DRAGON_MASK, BossTab.CLUE_SCROLL_ELITE, 6), + IRON_DRAGON_MASK(ItemID.IRON_DRAGON_MASK, BossTab.CLUE_SCROLL_ELITE, 6), + STEEL_DRAGON_MASK(ItemID.STEEL_DRAGON_MASK, BossTab.CLUE_SCROLL_ELITE, 6), + MITHRIL_DRAGON_MASK(ItemID.MITHRIL_DRAGON_MASK, BossTab.CLUE_SCROLL_ELITE, 6), + ADAMANT_DRAGON_MASK(ItemID.ADAMANT_DRAGON_MASK, BossTab.CLUE_SCROLL_ELITE, 6), + RUNE_DRAGON_MASK(ItemID.RUNE_DRAGON_MASK, BossTab.CLUE_SCROLL_ELITE, 6), + LAVA_DRAGON_MASK(ItemID.LAVA_DRAGON_MASK, BossTab.CLUE_SCROLL_ELITE, 6), + BLACK_DHIDE_BODY_T(ItemID.BLACK_DHIDE_BODY_T, BossTab.CLUE_SCROLL_ELITE, 7), + BLACK_DHIDE_CHAPS_T(ItemID.BLACK_DHIDE_CHAPS_T, BossTab.CLUE_SCROLL_ELITE, 7), + BLACK_DHIDE_BODY_G(ItemID.BLACK_DHIDE_BODY_G, BossTab.CLUE_SCROLL_ELITE, 7), + BLACK_DHIDE_CHAPS_G(ItemID.BLACK_DHIDE_CHAPS_G, BossTab.CLUE_SCROLL_ELITE, 7), + _3RD_AGE_CLOAK(ItemID._3RD_AGE_CLOAK, BossTab.CLUE_SCROLL_ELITE, 8), + _3RD_AGE_WAND(ItemID._3RD_AGE_WAND, BossTab.CLUE_SCROLL_ELITE, 8), + _3RD_AGE_BOW(ItemID._3RD_AGE_BOW, BossTab.CLUE_SCROLL_ELITE, 8), + _3RD_AGE_LONGSWORD(ItemID._3RD_AGE_LONGSWORD, BossTab.CLUE_SCROLL_ELITE, 8), + ROYAL_CROWN(ItemID.ROYAL_CROWN, BossTab.CLUE_SCROLL_ELITE, 9), + ROYAL_GOWN_TOP(ItemID.ROYAL_GOWN_TOP, BossTab.CLUE_SCROLL_ELITE, 9), + ROYAL_GOWN_BOTTOM(ItemID.ROYAL_GOWN_BOTTOM, BossTab.CLUE_SCROLL_ELITE, 9), + ROYAL_SCEPTRE(ItemID.ROYAL_SCEPTRE, BossTab.CLUE_SCROLL_ELITE, 9), + ARCEUUS_SCARF(ItemID.ARCEUUS_SCARF, BossTab.CLUE_SCROLL_ELITE, 10), + HOSIDIUS_SCARF(ItemID.HOSIDIUS_SCARF, BossTab.CLUE_SCROLL_ELITE, 10), + LOVAKENGJ_SCARF(ItemID.LOVAKENGJ_SCARF, BossTab.CLUE_SCROLL_ELITE, 10), + PISCARILIUS_SCARF(ItemID.PISCARILIUS_SCARF, BossTab.CLUE_SCROLL_ELITE, 10), + SHAYZIEN_SCARF(ItemID.SHAYZIEN_SCARF, BossTab.CLUE_SCROLL_ELITE, 10), + DARK_BOW_TIE(ItemID.DARK_BOW_TIE, BossTab.CLUE_SCROLL_ELITE, 11), + DARK_TUXEDO_JACKET(ItemID.DARK_TUXEDO_JACKET, BossTab.CLUE_SCROLL_ELITE, 11), + DARK_TROUSERS(ItemID.DARK_TROUSERS, BossTab.CLUE_SCROLL_ELITE, 11), + DARK_TUXEDO_CUFFS(ItemID.DARK_TUXEDO_CUFFS, BossTab.CLUE_SCROLL_ELITE, 11), + DARK_TUXEDO_SHOES(ItemID.DARK_TUXEDO_SHOES, BossTab.CLUE_SCROLL_ELITE, 11), + LIGHT_BOW_TIE(ItemID.LIGHT_BOW_TIE, BossTab.CLUE_SCROLL_ELITE, 12), + LIGHT_TUXEDO_JACKET(ItemID.LIGHT_TUXEDO_JACKET, BossTab.CLUE_SCROLL_ELITE, 12), + LIGHT_TROUSERS(ItemID.LIGHT_TROUSERS, BossTab.CLUE_SCROLL_ELITE, 12), + LIGHT_TUXEDO_CUFFS(ItemID.LIGHT_TUXEDO_CUFFS, BossTab.CLUE_SCROLL_ELITE, 12), + LIGHT_TUXEDO_SHOES(ItemID.LIGHT_TUXEDO_SHOES, BossTab.CLUE_SCROLL_ELITE, 12), + HOLY_WRAPS(ItemID.HOLY_WRAPS, BossTab.CLUE_SCROLL_ELITE, 13), + RING_OF_NATURE(ItemID.RING_OF_NATURE, BossTab.CLUE_SCROLL_ELITE, 13), + HEAVY_CASKET(ItemID.HEAVY_CASKET, BossTab.CLUE_SCROLL_ELITE, 13), + KATANA(ItemID.KATANA, BossTab.CLUE_SCROLL_ELITE, 13), + URIS_HAT(ItemID.URIS_HAT, BossTab.CLUE_SCROLL_ELITE, 13), + RANGERS_TUNIC(ItemID.RANGERS_TUNIC, BossTab.CLUE_SCROLL_ELITE, 14), + RANGERS_TIGHTS(ItemID.RANGERS_TIGHTS, BossTab.CLUE_SCROLL_ELITE, 14), + RANGER_GLOVES(ItemID.RANGER_GLOVES, BossTab.CLUE_SCROLL_ELITE, 14), + + // Master Clue Scrolls + DRAGON_PLATEBODY_ORNAMENT_KIT(ItemID.DRAGON_PLATEBODY_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, -1), + DRAGON_KITESHIELD_ORNAMENT_KIT(ItemID.DRAGON_KITESHIELD_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, -1), + DRAGON_DEFENDER_ORNAMENT_KIT(ItemID.DRAGON_DEFENDER_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, -1), + ANGUISH_ORNAMENT_KIT(ItemID.ANGUISH_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, -1), + TORTURE_ORNAMENT_KIT(ItemID.TORTURE_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, -1), + TORMENTED_ORNAMENT_KIT(ItemID.TORMENTED_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, -1), + OCCULT_ORNAMENT_KIT(ItemID.OCCULT_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, 0), + ARMADYL_GODSWORD_ORNAMENT_KIT(ItemID.ARMADYL_GODSWORD_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, 0), + BANDOS_GODSWORD_ORNAMENT_KIT(ItemID.BANDOS_GODSWORD_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, 0), + SARADOMIN_GODSWORD_ORNAMENT_KIT(ItemID.SARADOMIN_GODSWORD_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, 0), + ZAMORAK_GODSWORD_ORNAMENT_KIT(ItemID.ZAMORAK_GODSWORD_ORNAMENT_KIT, BossTab.CLUE_SCROLL_MASTER, 0), + _3RD_AGE_DRUIDIC(ItemID._3RD_AGE_DRUIDIC_ROBE_TOP, BossTab.CLUE_SCROLL_MASTER, 1), + _3RD_AGE_DRUIDIC_CLOAK(ItemID._3RD_AGE_DRUIDIC_CLOAK, BossTab.CLUE_SCROLL_MASTER, 1), + _3RD_AGE_DRUIDIC_ROBE_BOTTOMS(ItemID._3RD_AGE_DRUIDIC_ROBE_BOTTOMS, BossTab.CLUE_SCROLL_MASTER, 1), + _3RD_AGE_DRUIDIC_STAFF(ItemID._3RD_AGE_DRUIDIC_STAFF, BossTab.CLUE_SCROLL_MASTER, 1), + _3RD_AGE_AXE(ItemID._3RD_AGE_AXE, BossTab.CLUE_SCROLL_MASTER, 1), + _3RD_AGE_PICKAXE(ItemID._3RD_AGE_PICKAXE, BossTab.CLUE_SCROLL_MASTER, 1), + LESSER_DEMON_MASK(ItemID.LESSER_DEMON_MASK, BossTab.CLUE_SCROLL_MASTER, 2), + GREATER_DEMON_MASK(ItemID.GREATER_DEMON_MASK, BossTab.CLUE_SCROLL_MASTER, 2), + BLACK_DEMON_MASK(ItemID.BLACK_DEMON_MASK, BossTab.CLUE_SCROLL_MASTER, 2), + JUNGLE_DEMON_MASK(ItemID.JUNGLE_DEMON_MASK, BossTab.CLUE_SCROLL_MASTER, 2), + OLD_DEMON_MASK(ItemID.OLD_DEMON_MASK, BossTab.CLUE_SCROLL_MASTER, 2), + ARCEUUS_HOOD(ItemID.ARCEUUS_HOOD, BossTab.CLUE_SCROLL_MASTER, 3), + HOSIDIUS_HOOD(ItemID.HOSIDIUS_HOOD, BossTab.CLUE_SCROLL_MASTER, 3), + LOVAKENGJ_HOOD(ItemID.LOVAKENGJ_HOOD, BossTab.CLUE_SCROLL_MASTER, 3), + PISCARILIUS_HOOD(ItemID.PISCARILIUS_HOOD, BossTab.CLUE_SCROLL_MASTER, 3), + SHAYZIEN_HOUSE_HOOD(ItemID.SHAYZIEN_HOOD, BossTab.CLUE_SCROLL_MASTER, 3), + SAMURAI_KASA(ItemID.SAMURAI_KASA, BossTab.CLUE_SCROLL_MASTER, 4), + SAMURAI_SHIRT(ItemID.SAMURAI_SHIRT, BossTab.CLUE_SCROLL_MASTER, 4), + SAMURAI_GREAVES(ItemID.SAMURAI_GREAVES, BossTab.CLUE_SCROLL_MASTER, 4), + SAMURAI_GLOVES(ItemID.SAMURAI_GLOVES, BossTab.CLUE_SCROLL_MASTER, 4), + SAMURAI_BOOTS(ItemID.SAMURAI_BOOTS, BossTab.CLUE_SCROLL_MASTER, 4), + MUMMYS_HEAD(ItemID.MUMMYS_HEAD, BossTab.CLUE_SCROLL_MASTER, 5), + MUMMYS_BODY(ItemID.MUMMYS_BODY, BossTab.CLUE_SCROLL_MASTER, 5), + MUMMYS_LEGS(ItemID.MUMMYS_LEGS, BossTab.CLUE_SCROLL_MASTER, 5), + MUMMYS_HANDS(ItemID.MUMMYS_HANDS, BossTab.CLUE_SCROLL_MASTER, 5), + MUMMYS_FEET(ItemID.MUMMYS_FEET, BossTab.CLUE_SCROLL_MASTER, 5), + ANKOU_MASK(ItemID.ANKOU_MASK, BossTab.CLUE_SCROLL_MASTER, 6), + ANKOU_TOP(ItemID.ANKOU_TOP, BossTab.CLUE_SCROLL_MASTER, 6), + ANKOUS_LEGGINGS(ItemID.ANKOUS_LEGGINGS, BossTab.CLUE_SCROLL_MASTER, 6), + ANKOU_GLOVES(ItemID.ANKOU_GLOVES, BossTab.CLUE_SCROLL_MASTER, 6), + ANKOU_SOCKS(ItemID.ANKOU_SOCKS, BossTab.CLUE_SCROLL_MASTER, 6), + HOOD_OF_DARKNESS(ItemID.HOOD_OF_DARKNESS, BossTab.CLUE_SCROLL_MASTER, 7), + ROBE_TOP_OF_DARKNESS(ItemID.ROBE_TOP_OF_DARKNESS, BossTab.CLUE_SCROLL_MASTER, 7), + ROBE_BOTTOM_OF_DARKNESS(ItemID.ROBE_BOTTOM_OF_DARKNESS, BossTab.CLUE_SCROLL_MASTER, 7), + BOOTS_OF_DARKNESS(ItemID.BOOTS_OF_DARKNESS, BossTab.CLUE_SCROLL_MASTER, 7), + GLOVES_OF_DARKNESS(ItemID.GLOVES_OF_DARKNESS, BossTab.CLUE_SCROLL_MASTER, 7), + RING_OF_COINS(ItemID.RING_OF_COINS, BossTab.CLUE_SCROLL_MASTER, 8), + LEFT_EYE_PATCH(ItemID.LEFT_EYE_PATCH, BossTab.CLUE_SCROLL_MASTER, 8), + OBSIDIAN_CAPE_R(ItemID.OBSIDIAN_CAPE_R, BossTab.CLUE_SCROLL_MASTER, 8), + FANCY_TIARA(ItemID.FANCY_TIARA, BossTab.CLUE_SCROLL_MASTER, 8), + HALF_MOON_SPECTACLES(ItemID.HALF_MOON_SPECTACLES, BossTab.CLUE_SCROLL_MASTER, 8), + ALE_OF_THE_GODS(ItemID.ALE_OF_THE_GODS, BossTab.CLUE_SCROLL_MASTER, 9), + BUCKET_HELM_G(ItemID.BUCKET_HELM_G, BossTab.CLUE_SCROLL_MASTER, 9), + BOWL_WIG(ItemID.BOWL_WIG, BossTab.CLUE_SCROLL_MASTER, 9), + BLOODHOUND(ItemID.BLOODHOUND, BossTab.CLUE_SCROLL_MASTER, 9); + + private static final ImmutableMultimap BOSS_MAP; + + static + { + final ImmutableMultimap.Builder map = ImmutableMultimap.builder(); + for (UniqueItem item : values()) + { + for (BossTab b : item.getBosses()) + { + map.put(b.getName(), item); + } + } + + BOSS_MAP = map.build(); + } + + private final int itemID; + private final BossTab[] bosses; + private final int position; + private String name; + private int price; + private int linkedID; + @Setter + // Used to store the qty being displayed on the sprite + private int qty; + + // Non-Shared Unique Items + UniqueItem(int id, BossTab boss, int position) + { + this.itemID = id; + this.bosses = new BossTab[]{boss}; + this.position = position; + } + + // Shared Unique Items + UniqueItem(int id, BossTab... bosses) + { + this.itemID = id; + this.bosses = bosses; + this.position = -1; + } + + public static void prepareUniqueItems(final ItemManager itemManager) + { + for (final UniqueItem item : values()) + { + if (item.getName() != null) + { + return; + } + + final ItemDefinition c = itemManager.getItemDefinition(item.getItemID()); + item.name = c.getName(); + item.linkedID = c.getLinkedNoteId(); + item.price = itemManager.getItemPrice(c.getId()); + } + } + + public static Collection getUniquesForBoss(final String bossName) + { + return BOSS_MAP.get(bossName); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/ItemPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/ItemPanel.java similarity index 64% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/ItemPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/ItemPanel.java index aa4947c9e3..a2b41fc8ef 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/ItemPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/ItemPanel.java @@ -22,7 +22,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.stonedloottracker.ui; +package net.runelite.client.plugins.stonedtracker.ui; import java.awt.BorderLayout; import java.awt.Color; @@ -30,24 +30,21 @@ import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; -import javax.inject.Singleton; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; import lombok.Getter; import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry; +import net.runelite.client.plugins.loottracker.localstorage.LTItemEntry; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; import net.runelite.client.util.StackFormatter; -@Singleton -@Getter(AccessLevel.PACKAGE) +@Getter class ItemPanel extends JPanel { private static final GridBagLayout LAYOUT = new GridBagLayout(); @@ -58,75 +55,81 @@ class ItemPanel extends JPanel private static final Border CONTAINER_BORDER = BorderFactory.createMatteBorder(4, 15, 4, 15, PANEL_BACKGROUND_COLOR); - private LootTrackerItemEntry record; + private final LTItemEntry record; + private final long total; - ItemPanel(final LootTrackerItemEntry record, final ItemManager itemManager) + ItemPanel(final LTItemEntry record, final ItemManager itemManager) { + setLayout(LAYOUT); + setBorder(PANEL_BORDER); + setBackground(PANEL_BACKGROUND_COLOR); + setPreferredSize(PANEL_SIZE); + this.record = record; - this.setLayout(LAYOUT); - this.setBorder(PANEL_BORDER); - this.setBackground(PANEL_BACKGROUND_COLOR); - this.setPreferredSize(PANEL_SIZE); + this.total = record.getPrice() * record.getQuantity(); // Item Image Icon - JLabel icon = new JLabel(); - itemManager.getImage(record.getId(), record.getQuantity(), (record.isStackable() || record.getQuantity() > 1)).addTo(icon); + final JLabel icon = new JLabel(); + final boolean stackable = record.getQuantity() > 1; + itemManager.getImage(record.getId(), record.getQuantity(), stackable).addTo(icon); icon.setHorizontalAlignment(JLabel.CENTER); // Container for Info - JPanel uiInfo = new JPanel(new GridLayout(2, 1)); + final JPanel uiInfo = new JPanel(new GridLayout(2, 1)); uiInfo.setBorder(new EmptyBorder(0, 5, 0, 0)); uiInfo.setBackground(PANEL_BACKGROUND_COLOR); - JShadowedLabel labelName = new JShadowedLabel(this.record.getName()); - labelName.setForeground(Color.WHITE); - colorLabel(labelName, this.record.getPrice()); + final JShadowedLabel labelName = new JShadowedLabel(this.record.getName()); + labelName.setFont(FontManager.getRunescapeSmallFont()); + labelName.setForeground(getRSValueColor(this.record.getPrice())); labelName.setVerticalAlignment(SwingUtilities.BOTTOM); - String gpLabel = StackFormatter.quantityToStackSize(this.record.getTotal()) + " gp"; - - if (this.record.getHaTotal() > 0 && this.record.getHaPrice() > 1) - { - gpLabel += " (HA: " + StackFormatter.quantityToStackSize(this.record.getHaTotal()) + " gp)"; - } - - JShadowedLabel labelValue = new JShadowedLabel(gpLabel); - labelValue.setFont(FontManager.getSmallFont(getFont())); - colorLabel(labelValue, this.record.getTotal()); + final JShadowedLabel labelValue = new JShadowedLabel(StackFormatter.quantityToStackSize(total) + " gp"); + labelValue.setFont(FontManager.getRunescapeSmallFont()); + labelValue.setForeground(getRSValueColor(total)); labelValue.setVerticalAlignment(SwingUtilities.TOP); uiInfo.add(labelName); uiInfo.add(labelValue); // Create and append elements to container panel - JPanel panel = createPanel(); + final JPanel panel = createPanel(); panel.add(icon, BorderLayout.LINE_START); panel.add(uiInfo, BorderLayout.CENTER); - GridBagConstraints c = new GridBagConstraints(); + final GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 1; c.gridx = 0; c.gridy = 0; this.add(panel, c); - this.setToolTipText(UniqueItemPanel.tooltipText(this.record.getPrice(), this.record.getHaPrice(), this.record.getQuantity(), this.record.getName())); + this.setToolTipText(buildToolTip(this.record)); } - static JPanel createPanel() + private static String buildToolTip(final LTItemEntry record) { - JPanel panel = new JPanel(); + final String name = record.getName(); + final int quantity = record.getQuantity(); + final long price = record.getPrice(); + + return "" + name + " x " + StackFormatter.formatNumber(quantity) + + "
Price: " + StackFormatter.quantityToStackSize(price) + + "
Total: " + StackFormatter.quantityToStackSize(quantity * price) + ""; + } + + private static Color getRSValueColor(long val) + { + return (val >= 10000000) ? Color.GREEN : (val >= 100000) ? Color.WHITE : Color.YELLOW; + } + + private JPanel createPanel() + { + final JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.setBorder(CONTAINER_BORDER); panel.setBackground(PANEL_BACKGROUND_COLOR); return panel; } - - // Color label to match RuneScape coloring - private void colorLabel(JLabel label, long val) - { - Color labelColor = (val >= 10000000) ? Color.GREEN : (val >= 100000) ? Color.WHITE : Color.YELLOW; - label.setForeground(labelColor); - } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootGrid.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootGrid.java similarity index 75% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootGrid.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootGrid.java index 33927c6ffe..f6c0984f37 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootGrid.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootGrid.java @@ -22,63 +22,41 @@ * (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.stonedloottracker.ui; +package net.runelite.client.plugins.stonedtracker.ui; import java.awt.Dimension; import java.awt.GridLayout; -import java.util.Arrays; -import java.util.List; -import javax.inject.Singleton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry; +import net.runelite.client.plugins.loottracker.localstorage.LTItemEntry; import net.runelite.client.ui.ColorScheme; import net.runelite.client.util.StackFormatter; -@Singleton class LootGrid extends JPanel { private static final int ITEMS_PER_ROW = 5; private static final Dimension ITEM_SIZE = new Dimension(40, 40); - private final LootTrackerItemEntry[] itemsToDisplay; - private final ItemManager itemManager; - LootGrid(final LootTrackerItemEntry[] itemsToDisplay, final ItemManager itemManager) + LootGrid(final LTItemEntry[] itemsToDisplay, final ItemManager itemManager) { - this.itemsToDisplay = itemsToDisplay; - this.itemManager = itemManager; - setBorder(new EmptyBorder(5, 0, 5, 0)); - - buildItems(); - } - - /** - * This method creates stacked items from the item list, calculates total price and then - * displays all the items in the UI. - */ - private void buildItems() - { - List items = LootTrackerBox.dedupeClues(Arrays.asList(itemsToDisplay)); - // Calculates how many rows need to be display to fit all items - final int rowSize = LootTrackerBox.rowSize(items.size()); - - removeAll(); + final int rowSize = ((itemsToDisplay.length % ITEMS_PER_ROW == 0) ? 0 : 1) + itemsToDisplay.length / ITEMS_PER_ROW; setLayout(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1)); + // Create stacked items from the item list, calculates total price and then displays all the items in the UI. for (int i = 0; i < rowSize * ITEMS_PER_ROW; i++) { final JPanel slot = new JPanel(); slot.setLayout(new GridLayout(1, 1, 0, 0)); slot.setBackground(ColorScheme.DARKER_GRAY_COLOR); slot.setPreferredSize(ITEM_SIZE); - if (i < items.size()) + if (i < itemsToDisplay.length) { - final LootTrackerItemEntry item = items.get(i); + final LTItemEntry item = itemsToDisplay[i]; if (item == null) { continue; @@ -97,7 +75,7 @@ class LootGrid extends JPanel repaint(); } - private static String buildToolTip(LootTrackerItemEntry item) + private static String buildToolTip(final LTItemEntry item) { final String name = item.getName(); final int quantity = item.getQuantity(); @@ -105,6 +83,6 @@ class LootGrid extends JPanel return "" + name + " x " + StackFormatter.formatNumber(quantity) + "
Price: " + StackFormatter.quantityToStackSize(price) - + "
Total: " + StackFormatter.quantityToStackSize(quantity * price) + "Total: " + StackFormatter.quantityToStackSize(quantity * price) + ""; } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootPanel.java new file mode 100644 index 0000000000..34132dc304 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootPanel.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2018, TheStonedTurtle + * 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.stonedtracker.ui; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Iterators; +import com.google.common.collect.Multimap; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.game.ItemManager; +import net.runelite.client.plugins.loottracker.localstorage.LTItemEntry; +import net.runelite.client.plugins.loottracker.localstorage.LTRecord; +import net.runelite.client.plugins.stonedtracker.ItemSortTypes; +import net.runelite.client.plugins.stonedtracker.data.UniqueItem; +import net.runelite.client.ui.ColorScheme; + +@Slf4j +class LootPanel extends JPanel +{ + private final Collection records; + private final Collection uniques; + private final boolean hideUniques; + private final ItemSortTypes sortType; + private final boolean itemBreakdown; + private final ItemManager itemManager; + // Consolidate LTItemEntries stored by ItemID + private final Map consolidated = new HashMap<>(); + + private boolean playbackPlaying = false; + private boolean cancelPlayback = false; + + LootPanel( + final Collection records, + final Collection uniques, + final boolean hideUnqiues, + final ItemSortTypes sort, + final boolean itemBreakdown, + final ItemManager itemManager) + { + this.records = records; + this.uniques = uniques; + this.hideUniques = hideUnqiues; + this.sortType = sort; + this.itemBreakdown = itemBreakdown; + this.itemManager = itemManager; + + setLayout(new GridBagLayout()); + setBorder(new EmptyBorder(0, 10, 0, 10)); + setBackground(ColorScheme.DARK_GRAY_COLOR); + + createPanel(this.records, true); + } + + /** + * Sorts the collection of LTItemEntry based on the selected {@link ItemSortTypes} + * + * @param sortType The {@link ItemSortTypes} describing how these entries should be sorted + * @return returns the sorted list + */ + private static Comparator createLTItemEntryComparator(final ItemSortTypes sortType) + { + return (o1, o2) -> + { + switch (sortType) + { + case ITEM_ID: + return o1.getId() - o2.getId(); + case PRICE: + if (o1.getPrice() != o2.getPrice()) + { + return o1.getPrice() > o2.getPrice() ? -1 : 1; + } + break; + case VALUE: + if (o1.getTotal() != o2.getTotal()) + { + return o1.getTotal() > o2.getTotal() ? -1 : 1; + } + break; + case ALPHABETICAL: + // Handled below + break; + default: + log.warn("Sort Type not being handled correctly, defaulting to alphabetical."); + break; + } + + // Default to alphabetical + return o1.getName().compareTo(o2.getName()); + }; + } + + private void createPanel(final Collection records, final boolean reconsolidate) + { + final GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 0; + c.gridy = 0; + + if (reconsolidate) + { + this.consolidated.clear(); + final Collection consolidatedLTItemEntries = LTRecord.consolidateLTItemEntries(records); + final Map itemMap = LTItemEntry.consolidateItemEntires(consolidatedLTItemEntries); + this.consolidated.putAll(itemMap); + } + + // Create necessary helpers for the unique toggles + final Multimap positionMap = ArrayListMultimap.create(); + final Set uniqueIds = new HashSet<>(); + + // Loop over all UniqueItems and check how many the player has received as a drop for each + // Also add all Item IDs for uniques to a Set for easy hiding later on. + for (final UniqueItem item : this.uniques) + { + + final int id = item.getItemID(); + final int linkedId = item.getLinkedID(); + uniqueIds.add(id); + uniqueIds.add(linkedId); + + final LTItemEntry entry = this.consolidated.get(id); + final LTItemEntry notedEntry = this.consolidated.get(linkedId); + final int qty = (entry == null ? 0 : entry.getQuantity()) + (notedEntry == null ? 0 : notedEntry.getQuantity()); + item.setQty(qty); + positionMap.put(item.getPosition(), item); + } + + for (final int position : positionMap.keySet()) + { + final Collection uniques = positionMap.get(position); + + final UniqueItemPanel p = new UniqueItemPanel(uniques, this.itemManager); + this.add(p, c); + c.gridy++; + } + + // Attach Kill Count Panel(s) + if (records.size() > 0) + { + final int amount = records.size(); + final LTRecord entry = Iterators.get(records.iterator(), (amount - 1)); + if (entry.getKillCount() != -1) + { + final TextPanel p = new TextPanel("Current Killcount:", entry.getKillCount()); + this.add(p, c); + c.gridy++; + } + final TextPanel p2 = new TextPanel("Kills Logged:", amount); + this.add(p2, c); + c.gridy++; + } + + // Track total price of all tracked items for this panel + // Also ensure it is placed in correct location by preserving its gridy value + long totalValue = 0; + final int totalValueIndex = c.gridy; + c.gridy++; + + + final Collection itemsToDisplay = consolidated.values().stream() + .filter(e -> !(hideUniques && uniqueIds.contains(e.getId()))) + .sorted(createLTItemEntryComparator(sortType)) + .collect(Collectors.toList()); + + if (itemsToDisplay.size() > 0) + { + totalValue = itemsToDisplay.stream().mapToLong(e -> e.getPrice() * e.getQuantity()).sum(); + if (itemBreakdown) + { + for (final LTItemEntry e : itemsToDisplay) + { + final ItemPanel p = new ItemPanel(e, itemManager); + this.add(p, c); + c.gridy++; + } + } + else + { + final LootGrid grid = new LootGrid(itemsToDisplay.toArray(new LTItemEntry[0]), itemManager); + this.add(grid, c); + c.gridy++; + } + } + + // Only add the total value element if it has something useful to display + if (totalValue > 0) + { + c.gridy = totalValueIndex; + final TextPanel totalPanel = new TextPanel("Total Value:", totalValue); + this.add(totalPanel, c); + } + } + + void addedRecord(final LTRecord record) + { + records.add(record); + for (final LTItemEntry entry : record.getDrops()) + { + final LTItemEntry current = consolidated.get(entry.getId()); + if (current != null) + { + entry.setQuantity(entry.getQuantity() + current.getQuantity()); + } + consolidated.put(entry.getId(), entry); + + } + // TODO: Smarter update system so it only repaints necessary Item and Text Panels + this.removeAll(); + + this.createPanel(this.records, false); + + this.revalidate(); + this.repaint(); + } + + void playback() + { + if (playbackPlaying) + { + cancelPlayback = true; + return; + } + + playbackPlaying = true; + + if (this.records.size() > 0) + { + final Collection recs = new ArrayList<>(); + for (final LTRecord r : this.records) + { + recs.add(r); + + SwingUtilities.invokeLater(() -> refreshPlayback(recs)); + + try + { + if (cancelPlayback) + { + playbackPlaying = false; + cancelPlayback = false; + SwingUtilities.invokeLater(() -> refreshPlayback(this.records)); + break; + } + // TODO: Allow this rate to be configurable? + Thread.sleep(250); + } + catch (InterruptedException e) + { + System.out.println(e.getMessage()); + } + } + } + + playbackPlaying = false; + } + + private void refreshPlayback(final Collection recs) + { + this.removeAll(); + + this.createPanel(recs, true); + + this.revalidate(); + this.repaint(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootTrackerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootTrackerPanel.java similarity index 63% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootTrackerPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootTrackerPanel.java index 6ce3b3cad5..523f9cc07d 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/LootTrackerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/LootTrackerPanel.java @@ -22,7 +22,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.stonedloottracker.ui; +package net.runelite.client.plugins.stonedtracker.ui; import java.awt.BorderLayout; import java.awt.Color; @@ -30,14 +30,13 @@ import java.awt.Dimension; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import javax.imageio.ImageIO; -import javax.inject.Singleton; +import java.util.stream.Collectors; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JOptionPane; @@ -48,16 +47,15 @@ import javax.swing.border.EmptyBorder; import javax.swing.border.MatteBorder; import lombok.extern.slf4j.Slf4j; import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.stonedloottracker.StonedLootTrackerPlugin; -import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom; -import net.runelite.client.plugins.stonedloottracker.data.UniqueItem; -import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared; +import net.runelite.client.plugins.loottracker.localstorage.LTRecord; +import net.runelite.client.plugins.stonedtracker.StonedTrackerPlugin; +import net.runelite.client.plugins.stonedtracker.data.UniqueItem; import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.components.PluginErrorPanel; +import net.runelite.client.util.ImageUtil; @Slf4j -@Singleton public class LootTrackerPanel extends PluginPanel { private static final BufferedImage ICON_DELETE; @@ -70,38 +68,20 @@ public class LootTrackerPanel extends PluginPanel static { - BufferedImage i1; - BufferedImage i2; - BufferedImage i3; - BufferedImage i4; - try - { - synchronized (ImageIO.class) - { - i1 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("delete-white.png")); - i2 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("refresh-white.png")); - i3 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("back-arrow-white.png")); - i4 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("replay-white.png")); - } - } - catch (IOException e) - { - throw new RuntimeException(e); - } - ICON_DELETE = i1; - ICON_REFRESH = i2; - ICON_BACK = i3; - ICON_REPLAY = i4; + ICON_DELETE = ImageUtil.getResourceStreamFromClass(StonedTrackerPlugin.class, "delete-white.png"); + ICON_REFRESH = ImageUtil.getResourceStreamFromClass(StonedTrackerPlugin.class, "refresh-white.png"); + ICON_BACK = ImageUtil.getResourceStreamFromClass(StonedTrackerPlugin.class, "back-arrow-white.png"); + ICON_REPLAY = ImageUtil.getResourceStreamFromClass(StonedTrackerPlugin.class, "replay-white.png"); } + private final ItemManager itemManager; + private final StonedTrackerPlugin plugin; + // NPC name for current view or null if on selection screen private String currentView = null; private LootPanel lootPanel; - private final ItemManager itemManager; - private final StonedLootTrackerPlugin plugin; - - public LootTrackerPanel(final ItemManager itemManager, final StonedLootTrackerPlugin plugin) + public LootTrackerPanel(final ItemManager itemManager, final StonedTrackerPlugin plugin) { super(false); this.itemManager = itemManager; @@ -114,17 +94,17 @@ public class LootTrackerPanel extends PluginPanel } // Loot Selection view - private void showSelectionView() + public void showSelectionView() { this.removeAll(); currentView = null; lootPanel = null; - PluginErrorPanel errorPanel = new PluginErrorPanel(); + final PluginErrorPanel errorPanel = new PluginErrorPanel(); errorPanel.setBorder(new EmptyBorder(10, 25, 10, 25)); - errorPanel.setContent("Stoned Loot Tracker", "Please select the Activity, Player, or NPC you wish to view loot for"); + errorPanel.setContent("Loot Tracker", "Please select the Activity, Player, or NPC you wish to view loot for"); - SelectionPanel selection = new SelectionPanel(plugin.config.bossButtons(), plugin.getNames(), this, itemManager); + final SelectionPanel selection = new SelectionPanel(plugin.config.bossButtons(), plugin.getLootNames(), this, itemManager); this.add(errorPanel, BorderLayout.NORTH); this.add(wrapContainer(selection), BorderLayout.CENTER); @@ -134,22 +114,24 @@ public class LootTrackerPanel extends PluginPanel } // Loot breakdown view - void showLootView(String name) + public void showLootView(final String name) { this.removeAll(); currentView = name; - Collection data = plugin.getDataByName(name); + final Collection data = plugin.getDataByName(name); // Grab all Uniques for this NPC/Activity - Collection uniques = plugin.getUniques(name); + Collection uniques = UniqueItem.getUniquesForBoss(name); if (uniques == null) { uniques = new ArrayList<>(); } - JPanel title = createLootViewTitle(name); - lootPanel = new LootPanel(data, UniqueItem.createPositionSetMap(uniques), plugin.config.hideUniques(), plugin.config.itemSortType(), plugin.config.itemBreakdown(), itemManager); + uniques = uniques.stream().sorted(Comparator.comparingInt(UniqueItem::getPosition)).collect(Collectors.toList()); + + final JPanel title = createLootViewTitle(name); + lootPanel = new LootPanel(data, uniques, plugin.config.hideUniques(), plugin.config.itemSortType(), plugin.config.itemBreakdown(), itemManager); this.add(title, BorderLayout.NORTH); this.add(wrapContainer(lootPanel), BorderLayout.CENTER); @@ -158,16 +140,10 @@ public class LootTrackerPanel extends PluginPanel this.repaint(); } - private LootTrackerBox createLootTrackerBox(LootRecordCustom r) - { - final String subTitle = r.getLevel() > -1 ? "(lvl-" + r.getLevel() + ")" : ""; - return new LootTrackerBox(itemManager, r.getName(), subTitle, r); - } - // Title element for Loot breakdown view - private JPanel createLootViewTitle(String name) + private JPanel createLootViewTitle(final String name) { - JPanel title = new JPanel(); + final JPanel title = new JPanel(); title.setBorder(new CompoundBorder( new EmptyBorder(10, 8, 8, 8), new MatteBorder(0, 0, 1, 0, Color.GRAY) @@ -175,11 +151,11 @@ public class LootTrackerPanel extends PluginPanel title.setLayout(new BorderLayout()); title.setBackground(BACKGROUND_COLOR); - JPanel first = new JPanel(); + final JPanel first = new JPanel(); first.setBackground(BACKGROUND_COLOR); // Back Button - JLabel back = createIconLabel(ICON_BACK); + final JLabel back = createIconLabel(ICON_BACK); back.addMouseListener(new MouseAdapter() { @Override @@ -188,31 +164,31 @@ public class LootTrackerPanel extends PluginPanel showSelectionView(); } }); + back.setToolTipText("Back to selection screen"); - // Plugin Name - JLabel text = new JLabel(name); + final JLabel text = new JLabel(name); text.setForeground(Color.WHITE); first.add(back); first.add(text); - JPanel second = new JPanel(); + final JPanel second = new JPanel(); second.setBackground(BACKGROUND_COLOR); // Refresh Data button - JLabel refresh = createIconLabel(ICON_REFRESH); + final JLabel refresh = createIconLabel(ICON_REFRESH); refresh.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - refreshLootView(name); + showLootView(name); } }); refresh.setToolTipText("Refresh panel"); // Clear data button - JLabel clear = createIconLabel(ICON_DELETE); + final JLabel clear = createIconLabel(ICON_DELETE); clear.addMouseListener(new MouseAdapter() { @Override @@ -224,7 +200,7 @@ public class LootTrackerPanel extends PluginPanel clear.setToolTipText("Clear stored data"); // Clear data button - JLabel replay = createIconLabel(ICON_REPLAY); + final JLabel replay = createIconLabel(ICON_REPLAY); replay.addMouseListener(new MouseAdapter() { @Override @@ -245,9 +221,9 @@ public class LootTrackerPanel extends PluginPanel return title; } - private JLabel createIconLabel(BufferedImage icon) + private JLabel createIconLabel(final BufferedImage icon) { - JLabel label = new JLabel(); + final JLabel label = new JLabel(); label.setIcon(new ImageIcon(icon)); label.setOpaque(true); label.setBackground(BACKGROUND_COLOR); @@ -271,13 +247,13 @@ public class LootTrackerPanel extends PluginPanel } // Wrap the panel inside a scroll pane - private JScrollPane wrapContainer(JPanel container) + private JScrollPane wrapContainer(final JPanel container) { - JPanel wrapped = new JPanel(new BorderLayout()); + final JPanel wrapped = new JPanel(new BorderLayout()); wrapped.add(container, BorderLayout.NORTH); wrapped.setBackground(BACKGROUND_COLOR); - JScrollPane scroller = new JScrollPane(wrapped); + final JScrollPane scroller = new JScrollPane(wrapped); scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scroller.getVerticalScrollBar().setPreferredSize(new Dimension(8, 0)); scroller.setBackground(BACKGROUND_COLOR); @@ -286,42 +262,33 @@ public class LootTrackerPanel extends PluginPanel } // Clear stored data and return to selection screen - private void clearData(String name) + private void clearData(final String name) { // Confirm delete action - int delete = JOptionPane.showConfirmDialog(this.getRootPane(), "Are you sure you want to clear all data for this tab?
There is no way to undo this action.", "Warning", JOptionPane.YES_NO_OPTION); + final int delete = JOptionPane.showConfirmDialog(this.getRootPane(), "Are you sure you want to clear all data for this tab?
There is no way to undo this action.", "Warning", JOptionPane.YES_NO_OPTION); if (delete == JOptionPane.YES_OPTION) { - plugin.clearStoredDataByName(name); + boolean deleted = plugin.clearStoredDataByName(name); + if (!deleted) + { + JOptionPane.showMessageDialog(this.getRootPane(), "Unable to clear stored data, please try again."); + return; + } // Return to selection screen showSelectionView(); } } - public void addLog(LootRecordCustom r) + public void addLog(final LTRecord r) { if (currentView == null) { showLootView(r.getName()); } - else if (currentView.equals(r.getName())) + else if (currentView.equalsIgnoreCase(r.getName())) { - //lootPanel.addedRecord(r); - lootPanel.addedRecord(); - } - } - - // Refresh panel when writer playerFolder is updated - public void updateNames() - { - if (currentView == null) - { - showSelectionView(); - } - else - { - showLootView(currentView); + lootPanel.addedRecord(r); } } @@ -339,12 +306,6 @@ public class LootTrackerPanel extends PluginPanel } } - private void refreshLootView(String name) - { - plugin.refreshDataByName(name); - showLootView(name); // Recreate the entire panel - } - private void playbackLoot() { if (lootPanel == null) @@ -352,13 +313,8 @@ public class LootTrackerPanel extends PluginPanel return; } - if (lootPanel.isPlaybackPlaying()) - { - lootPanel.cancelPlayback(); - return; - } - - ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); + // Create a new thread for this so it doesn't cause swing freezes + final ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); if (currentView != null) { ex.schedule(lootPanel::playback, 0, TimeUnit.SECONDS); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/SelectionPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/SelectionPanel.java similarity index 54% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/SelectionPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/SelectionPanel.java index 510fa4491b..c382504da4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/SelectionPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/SelectionPanel.java @@ -22,8 +22,9 @@ * (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.stonedloottracker.ui; +package net.runelite.client.plugins.stonedtracker.ui; +import com.google.common.base.Strings; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; @@ -33,37 +34,49 @@ import java.awt.Image; import java.awt.Insets; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.List; +import java.util.Arrays; +import java.util.Collection; import java.util.Set; import java.util.TreeSet; -import javax.inject.Singleton; +import java.util.stream.Collectors; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import net.runelite.client.game.AsyncBufferedImage; import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.stonedloottracker.data.BossTab; +import net.runelite.client.plugins.stonedtracker.data.BossTab; import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.IconTextField; import net.runelite.client.ui.components.materialtabs.MaterialTab; import net.runelite.client.ui.components.materialtabs.MaterialTabGroup; +import org.apache.commons.text.similarity.JaroWinklerDistance; -@Singleton class SelectionPanel extends JPanel { + private final static Color BACKGROUND_COLOR = ColorScheme.DARK_GRAY_COLOR; + private final static Color BUTTON_COLOR = ColorScheme.DARKER_GRAY_COLOR; + private final static Color BUTTON_HOVER_COLOR = ColorScheme.DARKER_GRAY_HOVER_COLOR; + private static final JaroWinklerDistance DISTANCE = new JaroWinklerDistance(); + private final Set names; private final LootTrackerPanel parent; private final ItemManager itemManager; - private final static Color BACKGROUND_COLOR = ColorScheme.DARK_GRAY_COLOR; - private final static Color BUTTON_COLOR = ColorScheme.DARKER_GRAY_COLOR; - private final static Color BUTTON_HOVER_COLOR = ColorScheme.DARKER_GRAY_HOVER_COLOR; + private final IconTextField searchBar = new IconTextField(); + private final JPanel namePanel = new JPanel(); private final boolean configToggle; - SelectionPanel(final boolean configToggle, final Set names, final LootTrackerPanel parent, final ItemManager itemManager) + SelectionPanel( + final boolean configToggle, + final Set names, + final LootTrackerPanel parent, + final ItemManager itemManager) { this.names = names == null ? new TreeSet<>() : names; this.parent = parent; @@ -73,46 +86,121 @@ class SelectionPanel extends JPanel this.setLayout(new GridBagLayout()); this.setBackground(BACKGROUND_COLOR); + searchBar.setIcon(IconTextField.Icon.SEARCH); + searchBar.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH - 20, 30)); + searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR); + searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR); + searchBar.getDocument().addDocumentListener(new DocumentListener() + { + @Override + public void insertUpdate(DocumentEvent e) + { + onSearchBarChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) + { + onSearchBarChanged(); + } + + @Override + public void changedUpdate(DocumentEvent e) + { + onSearchBarChanged(); + } + }); + + namePanel.setLayout(new GridBagLayout()); + createPanel(); } + private static boolean matchesSearchTerm(final String name, final String[] terms) + { + for (final String term : terms) + { + if (Arrays.stream(name.toLowerCase().split(" ")).noneMatch((nameTerm -> + nameTerm.contains(term) || DISTANCE.apply(nameTerm, term) > 0.9))) + { + return false; + } + } + + return true; + } + private void createPanel() { - GridBagConstraints c = constrains(); + final GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 0; + c.gridy = 0; c.insets = new Insets(5, 0, 0, 0); // Add the bosses tabs, by category, to tabGroup if (configToggle) { - Set categories = BossTab.categories; - JPanel container = new JPanel(new GridBagLayout()); - container.setBorder(new EmptyBorder(0, 0, 10, 0)); - int oldc = c.gridy; - c.gridy = 0; - for (String categoryName : categories) - { - container.add(createTabCategory(categoryName), c); - c.gridy++; - } - c.gridy = oldc; - this.add(container, c); + this.add(createBossTabPanel(), c); c.gridy++; } - // Add all other names - for (String name : this.names) + this.add(searchBar, c); + c.gridy++; + + addNamesToPanel(this.names); + this.add(namePanel, c); + } + + private JPanel createBossTabPanel() + { + final GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(5, 0, 0, 0); + + final JPanel container = new JPanel(new GridBagLayout()); + container.setBorder(new EmptyBorder(0, 0, 10, 0)); + + for (final String categoryName : BossTab.getCategories()) { + container.add(createTabCategory(categoryName), c); + c.gridy++; + } + + return container; + } + + private void addNamesToPanel(final Collection names) + { + namePanel.removeAll(); + + final GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(5, 0, 0, 0); + + for (final String name : names) + { + // Ignore boss tabs based on config if (!configToggle || BossTab.getByName(name) == null) { - this.add(createNamePanel(name), c); + namePanel.add(createNamePanel(name), c); c.gridy++; } } + + namePanel.revalidate(); } - private JPanel createNamePanel(String name) + private JPanel createNamePanel(final String name) { - JPanel p = new JPanel(); + final JPanel p = new JPanel(); p.add(new JLabel(name)); p.setBackground(BUTTON_COLOR); p.addMouseListener(new MouseAdapter() @@ -132,47 +220,40 @@ class SelectionPanel extends JPanel @Override public void mouseClicked(MouseEvent e) { - SwingUtilities.invokeLater(() -> parent.showLootView(name)); + parent.showLootView(name); } }); return p; } - static GridBagConstraints constrains() + // Creates all tabs for a specific category + private JPanel createTabCategory(final String categoryName) { - GridBagConstraints c = new GridBagConstraints(); + final JPanel container = new JPanel(); + container.setLayout(new GridBagLayout()); + container.setBorder(new EmptyBorder(0, 5, 0, 5)); + + final GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.gridx = 0; c.gridy = 0; - return c; - } - - // Creates all tabs for a specific category - private JPanel createTabCategory(String categoryName) - { - JPanel container = new JPanel(); - container.setLayout(new GridBagLayout()); - container.setBorder(new EmptyBorder(0, 5, 0, 5)); - - GridBagConstraints c = constrains(); - - MaterialTabGroup thisTabGroup = new MaterialTabGroup(); + final MaterialTabGroup thisTabGroup = new MaterialTabGroup(); thisTabGroup.setLayout(new GridLayout(0, 4, 7, 7)); thisTabGroup.setBorder(new EmptyBorder(4, 0, 0, 0)); - JLabel name = new JLabel(categoryName); + final JLabel name = new JLabel(categoryName); name.setBorder(new EmptyBorder(8, 0, 0, 0)); name.setForeground(Color.WHITE); name.setVerticalAlignment(SwingConstants.CENTER); - List categoryTabs = BossTab.getByCategoryName(categoryName); - for (BossTab tab : categoryTabs) + final Collection categoryTabs = BossTab.getByCategoryName(categoryName); + for (final BossTab tab : categoryTabs) { // Create tab (with hover effects/text) - MaterialTab materialTab = new MaterialTab("", thisTabGroup, null); + final MaterialTab materialTab = new MaterialTab("", thisTabGroup, null); materialTab.setName(tab.getName()); materialTab.setToolTipText(tab.getName()); //materialTab.setSelectedBorder(new EmptyBorder(0, 0, 0, 0)); @@ -189,17 +270,17 @@ class SelectionPanel extends JPanel { materialTab.setBackground(BUTTON_COLOR); } + }); - @Override - public void mouseClicked(MouseEvent e) - { - SwingUtilities.invokeLater(() -> parent.showLootView(tab.getName())); - } + materialTab.setOnSelectEvent(() -> + { + parent.showLootView(tab.getName()); + return true; }); // Attach Icon to the Tab - AsyncBufferedImage image = itemManager.getImage(tab.getItemID()); - Runnable resize = () -> + final AsyncBufferedImage image = itemManager.getImage(tab.getItemID()); + final Runnable resize = () -> { materialTab.setIcon(new ImageIcon(image.getScaledInstance(35, 35, Image.SCALE_SMOOTH))); materialTab.setOpaque(true); @@ -220,4 +301,23 @@ class SelectionPanel extends JPanel return container; } + + private void onSearchBarChanged() + { + final String text = searchBar.getText(); + if (Strings.isNullOrEmpty(text)) + { + addNamesToPanel(this.names); + } + else + { + addNamesToPanel(filterNames(this.names, text)); + } + } + + private Collection filterNames(final Collection names, final String searchText) + { + final String[] searchTerms = searchText.toLowerCase().split(" "); + return names.stream().filter(name -> matchesSearchTerm(name, searchTerms)).collect(Collectors.toList()); + } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/TextPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/TextPanel.java similarity index 71% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/TextPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/TextPanel.java index e05caac244..dfef6db86f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/TextPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/TextPanel.java @@ -22,26 +22,22 @@ * (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.stonedloottracker.ui; +package net.runelite.client.plugins.stonedtracker.ui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import javax.inject.Singleton; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; import lombok.Getter; import net.runelite.client.ui.ColorScheme; import net.runelite.client.util.StackFormatter; -@Singleton -@Getter(AccessLevel.PACKAGE) +@Getter class TextPanel extends JPanel { private static final GridBagLayout LAYOUT = new GridBagLayout(); @@ -52,26 +48,26 @@ class TextPanel extends JPanel private static final Border CONTAINER_BORDER = BorderFactory.createMatteBorder(0, 15, 0, 15, PANEL_BACKGROUND_COLOR); // Long value should be for Total Value - TextPanel(String text, long totalValue) + TextPanel(final String text, final long totalValue) { this.setLayout(LAYOUT); this.setBorder(PANEL_BORDER); this.setBackground(PANEL_BACKGROUND_COLOR); - JLabel totalText = new JLabel(text, SwingConstants.LEFT); + final JLabel totalText = new JLabel(text, SwingConstants.LEFT); totalText.setForeground(Color.WHITE); // Item Values (Colored off Total Value of item) - JLabel total = new JLabel(StackFormatter.quantityToStackSize(totalValue) + " gp", SwingConstants.LEFT); - total.setBorder(new EmptyBorder(0, 5, 0, 0)); - colorLabel(total, totalValue); + final JLabel total = new JLabel(StackFormatter.quantityToStackSize(totalValue) + " gp", SwingConstants.LEFT); + total.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + total.setForeground(getRSValueColor(totalValue)); - JPanel panel = ItemPanel.createPanel(); + final JPanel panel = createPanel(); panel.add(totalText, BorderLayout.LINE_START); panel.add(total, BorderLayout.CENTER); - GridBagConstraints c = new GridBagConstraints(); + final GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 1; c.gridx = 0; @@ -83,23 +79,23 @@ class TextPanel extends JPanel this.add(panel, c); } - TextPanel(String text, int value) + TextPanel(final String text, final int value) { this.setLayout(LAYOUT); this.setBorder(PANEL_BORDER); this.setBackground(PANEL_BACKGROUND_COLOR); - JLabel textLabel = new JLabel(text, SwingConstants.LEFT); + final JLabel textLabel = new JLabel(text, SwingConstants.LEFT); textLabel.setForeground(Color.WHITE); - JLabel valueLabel = new JLabel(String.valueOf(value), SwingConstants.LEFT); - valueLabel.setBorder(new EmptyBorder(0, 5, 0, 0)); + final JLabel valueLabel = new JLabel(String.valueOf(value), SwingConstants.LEFT); + valueLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); - JPanel panel = ItemPanel.createPanel(); + final JPanel panel = createPanel(); panel.add(textLabel, BorderLayout.LINE_START); panel.add(valueLabel, BorderLayout.CENTER); - GridBagConstraints c = new GridBagConstraints(); + final GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 1; c.gridx = 0; @@ -109,10 +105,18 @@ class TextPanel extends JPanel this.add(panel, c); } - // Color label to match RuneScape coloring - private void colorLabel(JLabel label, long val) + private static JPanel createPanel() { - Color labelColor = (val >= 10000000) ? Color.GREEN : (val >= 100000) ? Color.WHITE : Color.YELLOW; - label.setForeground(labelColor); + final JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setBorder(CONTAINER_BORDER); + panel.setBackground(PANEL_BACKGROUND_COLOR); + + return panel; + } + + private static Color getRSValueColor(long val) + { + return (val >= 10000000) ? Color.GREEN : (val >= 100000) ? Color.WHITE : Color.YELLOW; } } \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/UniqueItemPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/UniqueItemPanel.java similarity index 58% rename from runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/UniqueItemPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/UniqueItemPanel.java index e4aa3be03b..940ec53c67 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/stonedloottracker/ui/UniqueItemPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/stonedtracker/ui/UniqueItemPanel.java @@ -22,7 +22,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.stonedloottracker.ui; +package net.runelite.client.plugins.stonedtracker.ui; import java.awt.BorderLayout; import java.awt.Color; @@ -31,29 +31,23 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.image.BufferedImage; import java.util.Collection; -import java.util.Map; -import javax.inject.Singleton; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.SwingUtilities; +import javax.swing.SwingConstants; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; -import lombok.AccessLevel; import lombok.Getter; import net.runelite.client.game.AsyncBufferedImage; import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared; +import net.runelite.client.plugins.stonedtracker.data.UniqueItem; import net.runelite.client.ui.ColorScheme; import net.runelite.client.util.ImageUtil; import net.runelite.client.util.StackFormatter; -@Singleton -@Getter(AccessLevel.PACKAGE) +@Getter class UniqueItemPanel extends JPanel { - private ItemManager itemManager; - private final static float alphaMissing = 0.35f; private final static float alphaHas = 1.0f; @@ -61,11 +55,9 @@ class UniqueItemPanel extends JPanel private static final Border panelBorder = new EmptyBorder(3, 0, 3, 0); private static final Color panelBackgroundColor = ColorScheme.DARK_GRAY_COLOR; - UniqueItemPanel(final Collection items, final Map uniqueMap, final ItemManager itemManager) + UniqueItemPanel(final Collection items, final ItemManager itemManager) { - this.itemManager = itemManager; - - JPanel panel = new JPanel(); + final JPanel panel = new JPanel(); panel.setLayout(new GridBagLayout()); panel.setBackground(ColorScheme.DARKER_GRAY_COLOR); panel.setBorder(new EmptyBorder(3, 0, 3, 0)); @@ -83,68 +75,52 @@ class UniqueItemPanel extends JPanel c.ipady = 5; // Add each Unique Item icon to the panel - for (UniqueItemPrepared l : items) + for (final UniqueItem l : items) { - final int id = l.getUniqueItem().getItemID(); - final int quantity = uniqueMap.getOrDefault(l, 0); + final int quantity = l.getQty(); final float alpha = (quantity > 0 ? alphaHas : alphaMissing); - AsyncBufferedImage image = itemManager.getImage(l.getUniqueItem().getItemID(), quantity, quantity > 1); - BufferedImage opaque = ImageUtil.alphaOffset(image, alpha); + final AsyncBufferedImage image = itemManager.getImage(l.getItemID(), quantity, quantity > 1); + final BufferedImage opaque = ImageUtil.alphaOffset(image, alpha); - final long price = itemManager.getItemPrice(id); - final long haPrice = itemManager.getAlchValue(id); - - // Attach Image to Label and append label to Panel - ImageIcon o = new ImageIcon(opaque); - JLabel icon = new JLabel(o); + final JLabel icon = new JLabel(); + icon.setToolTipText(buildToolTip(l, quantity)); + icon.setIcon(new ImageIcon(opaque)); + icon.setVerticalAlignment(SwingConstants.CENTER); + icon.setHorizontalAlignment(SwingConstants.CENTER); panel.add(icon, c); c.gridx++; // in case the image is blank we will refresh it upon load // Should only trigger if image hasn't been added - image.onChanged(() -> SwingUtilities.invokeLater(() -> refreshImage(icon, image, alpha))); - - icon.setToolTipText(tooltipText(price, haPrice, quantity, l.getUniqueItem().getName())); + image.onChanged(() -> + { + icon.setIcon(new ImageIcon(ImageUtil.alphaOffset(image, alpha))); + icon.revalidate(); + icon.repaint(); + }); } this.add(panel, BorderLayout.NORTH); } - static String tooltipText(long price, long haPrice, int quantity, String name) + private static String buildToolTip(final UniqueItem item, final int qty) { - String tooltipText = "" + name; - if (quantity > 1) + String s = "" + item.getName(); + if (qty > 0) { - tooltipText += "
Price: " + StackFormatter.quantityToStackSize(price); - - if (haPrice > 0) + s += " x " + StackFormatter.formatNumber(qty); + } + if (item.getPrice() > 0) + { + s += "
Price: " + StackFormatter.quantityToStackSize(item.getPrice()); + // Check for qty here as well as we should only show Total if the item has a value as well + if (qty > 0) { - tooltipText += " (HA: " + StackFormatter.quantityToStackSize(haPrice) + ")"; + s += "
Total: " + StackFormatter.quantityToStackSize(qty * item.getPrice()) + " 0) - { - tooltipText += "
Total: " + StackFormatter.quantityToStackSize(quantity * price); - - if (haPrice > 0) - { - tooltipText += " (HA: " + StackFormatter.quantityToStackSize(quantity * haPrice) + ")"; - } - } - tooltipText += "sa)Xqoe;nfNzQI*#W z-4V<+5GEA*cZROU`@UOx9JY-f1l(Riz`+BLm5d9CQ7OeH?*`kp8T$3t{yk{FlX2Ll zeHfqt+Zr5xgbUNxi*0SRX0i?9A+IcE|0~(nVY2!rE48F(J;*+-(PTXNH+6 zyRC?g=no%JjL-OtfNvo&K4OCM2udLS(5Q$Sd|?!X_=v`+5nS)=bN05qX(IkHceAf^ z&pqeN{q8wu?w`3mx$MfO#<`6YMKyJG#=GI~+3?di{Y?0s`g!X{_%p-k?6=_fEa%fe zJ@VKbifRa{9UaN!pl<8dpl;Az9UZh`>S;9tC@TNiw!2@xYHxCO+k1CzK9XECb*+)V zuchVn<2UTv$}DYu>EQeWA8&o?D)rn|s}63sb<6cPNP1!TwWC zEej6)+PMpT+;H@6!#Royxjz_278@&*Sa}{&(%vldy z`ofki-c5zGcBgiJqKW3V)%`b~IO*Sh^xeZ>+|xYTH*(p^_HggfFBjhR_?JhI?8{#; zQz;aZ+V9`6yZ0?Wb!_GG6h(sha)=qcdM zXAQ`kqN0oQh9s{6Hk|?ks@CfHX~!-Pttzda6~P3TFgn1X+Bsr^o{?p}^2i!FqIed^ z8l!m;I>-WBqVw5|W{LS$PtmUk|2xC1hb~UB*R*=toq%*-B1w1XCZL1f5F>LTffgcO zJ}3wQ;WFCC@j;gJvwn{8`NaSy27Gk+<%u=Ie^FCOi{0@n%Hg2Y>KU|cLuA=pF6Yhp zy}CKT@{ve{<$SEq$G{nkHLTfEp3$s}N=_<%;=qzk)v#4vqaD9eN*}UYJsu}e^;KS1 z)~E*3tTH=DkL?0;5C%Zsr7>h?ihvcF1sRZqF)e7vkGlq2P1iQ3ZV8TN!f+t3PGII} zN@m4WDD6-b=AYPM0?F3RUR}?`N?BHG6R=A-Sw*+3P&Gx*Sqq{pYEs+pnl})aY!HK% zVTOyqcP}3j1H9-DE#i2Q<6KTkGZ7yNnEQ%kOOx?ZHy8DzD{6XpQeJ8^>wP2=VwYyw zk|u+$cnq%HtE!6V~V*2!t4(2Vo{6M|@0J;RGM>2_WECDuG_M*4B?!6dASHK@7>XfK!;Qo=Rm_TTZp3I5x!s7bV&0Ju%ryUjQl8jn*!!YFRc@ z$8P835S0A8%qNbK8w46I{Y$QjvnF<8>1jJBnV@|DX2@hJv*fkj40Ru6onD<$|AURN zq;>yp8zxs(|BG#?WwAUcX#+rsv6Td_3`}n4O8Z$~S(R!XTZz$HXQ_08cG%gRg0<>1 zqFAs?q=EWT=d#QBQ)wRx2&Mx{n1g-E7iOe%AjO1*aG3Fj(m@}`DZIeR<0oBdv_3|Z zo!k|=7Sf?-bTgqVAm(>l*M@5#T~_e?n=BoF%azrAD;VE*fn7VOT})*N7*rB==?sX`(=iT^99I|<5=GLE}Od5 zsA)gm)U8HMYnIn)svYx{qanjCE9XQZ7BTn0!!L-1fU%A&)lMN-X!OkZ4u_dUz$ z-#kQ8v_Tc)8uq&kA&{D(OHno~<(KQ2TFm9rC_Dti^EX>PfR9P@>Rsb>{;93#bb3X6 zkst^Vyhw22`5;pWjvID*%(O= zoHOH+%$A!vUV7YJL9eH#(DuZ-)8-7xH4NKKodQA3cx2$%HFAyg`*4{BtGcSLuHvKI sFS)HQ`)lH2{EYi25{P>A{1bKa2l6jn4>Jw?FaQ7m07*qoM6N<$f+x_c<^TWy diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/single_loot_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/single_loot_icon.png deleted file mode 100644 index 6c2214da99fd0d2d6699895bb7034261af476177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15393 zcmeI3Yitx%6vwCX5UM3aG$0>zSd|oTcAmT29k)wM7j2CTYg@HoLYSSo+Yao`3^P-9 zTM>)E2O|-U&-h9dd<%*35#tl1X(WEosE86%^ykr<*zaJ{qdy=`xrs9((8?Cacf z|L4y9?zv~~mwQ`c#Z^s>^BXCOYU=8Yb;I9t;HPoMboib8W%pM2Gt=r^<-qni-lu_j z@ZotB)ezJ>IueNi(>0v|)1tdNI%vx_Q+gUuRPNB8J6^c@-NgBAAKw1>(ZrIe8?4;j z&CRczSUb9#Sw8#u0}J+lw)?TG_4C%OIk0)#t{cyun|*uV{%fto>9g`}8%`XVyZ`z9*&;i*mB_muel&C|F+_nC%uU2=E-n?1~P_kph0ADVhs#B}XrelfEBj_F$YL!&P#O;apM-QjQY?j%w?ctD6Sx#Z{8#pxf&6c>`5mrTfZQ zm4OVW#12wqbBe|CevX|$6p!O&nasFK$6dY=UPAU(z;G`a z?;#x`QAu^atIh|xq4WJE!dm?Y1O3*iETwMuRm|~fwQf{eRbFT4Zd53Z zhBVixya%ydVA=!sj362e1jImuMVnDYLeGJ8UrdLO3&$&aJVa8^ppJ2ct7?Q0NL5(l zC<%)hRkOP*l!{_2+&jW;D_hyOj;SJ*V*79Ysov4Q85M~|20?(}O@a&02k{bI2oStU zaN+qNUV;k&f;R~+JRihMa3MhOCc%a0gLnxp1PI4T z@Fu~9=Yx0&E(8ePB)IT=5HG=n0KuCC7oHE|CAbhEc$475^Fh1>7Xk!t5?pvbh?n3( zfZ$Dn3(p7f5?lxnyh(83`5<0`3ju;R2`)Sz#7l4?K=39OS7Y@gC@|ph&n!IWIc4p( zQFum_Ry(`n6g7MqMUB8yx_{*1?{SLioenRz diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/visible_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/visible_icon.png deleted file mode 100644 index 5c4232c808f46b2fee47a5ac1f5045792118165b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 312 zcmV-80muG{P)PbXFR49?Xk)cilQ4mGX+kl~|Xh=}~0+3ZeLIV6k(}WZpztPGP zWQzlVKp+q#grIQz0O1R&Rv@UN2--ae-tHFG_o|u6N#@QSSgOKe;|51GfG=Ko4)Y4_ zp0~~{m3s0Yxlr}nk!{-vNAFlIkahhYMk_*gN%?OfG2*YfLX z-W3sa>^O|Ky;%R7)Um0HO6}( diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/back_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/back-arrow-white.png similarity index 100% rename from runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/back_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/back-arrow-white.png diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/delete-white.png b/runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/delete-white.png new file mode 100644 index 0000000000000000000000000000000000000000..014cf20850376d04ee23397fe43557474ceb7983 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@RheAWs*^kP60R39ASH|NnP$*u&q! z-(WCht?!z&_Wwti*=yJ|848&vMl?=XE#wfV*dW~TF^*aAUY3Mu2ZMyEMmtAyQHNoN la7Xwfud4x;er=BY47?&j`<|}exEW|VgQu&X%Q~loCIEp*D+K@m literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/panel_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/panel-icon.png similarity index 100% rename from runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/panel_icon.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/panel-icon.png diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/refresh-white.png b/runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/refresh-white.png similarity index 100% rename from runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/refresh-white.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/refresh-white.png diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/replay-white.png b/runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/replay-white.png similarity index 100% rename from runelite-client/src/main/resources/net/runelite/client/plugins/stonedloottracker/replay-white.png rename to runelite-client/src/main/resources/net/runelite/client/plugins/stonedtracker/replay-white.png