Merge branch 'master' of https://github.com/runelite/runelite
# Conflicts: # runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java # runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java # runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java # runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/MapClue.java # runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java # runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java # runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperConfig.java # runelite-client/src/main/java/net/runelite/client/plugins/menuentryswapper/MenuEntrySwapperPlugin.java # runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/HitpointsDisplayStyle.java # runelite-client/src/main/java/net/runelite/client/plugins/questlist/QuestListPlugin.java # runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingTracker.java # runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Magic fTail
|
||||
* Copyright (c) 2019, osrs-music-map <osrs-music-map@users.noreply.github.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -63,4 +64,26 @@ public interface ChatFilterConfig extends Config
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "filterFriends",
|
||||
name = "Filter Friends",
|
||||
description = "Filter your friends' messages",
|
||||
position = 4
|
||||
)
|
||||
default boolean filterFriends()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "filterClan",
|
||||
name = "Filter Clan Chat Members",
|
||||
description = "Filter your clan chat members' messages",
|
||||
position = 5
|
||||
)
|
||||
default boolean filterClan()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Magic fTail
|
||||
* Copyright (c) 2019, osrs-music-map <osrs-music-map@users.noreply.github.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -35,6 +36,7 @@ import java.util.regex.PatternSyntaxException;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MessageNode;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.OverheadTextChanged;
|
||||
@@ -97,7 +99,10 @@ public class ChatFilterPlugin extends Plugin
|
||||
|
||||
int[] intStack = client.getIntStack();
|
||||
int intStackSize = client.getIntStackSize();
|
||||
ChatMessageType chatMessageType = ChatMessageType.of(intStack[intStackSize - 1]);
|
||||
int messageType = intStack[intStackSize - 2];
|
||||
int messageId = intStack[intStackSize - 1];
|
||||
|
||||
ChatMessageType chatMessageType = ChatMessageType.of(messageType);
|
||||
|
||||
// Only filter public chat and private messages
|
||||
switch (chatMessageType)
|
||||
@@ -114,6 +119,13 @@ public class ChatFilterPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
MessageNode messageNode = (MessageNode) client.getMessages().get(messageId);
|
||||
String name = messageNode.getName();
|
||||
if (!shouldFilterPlayerMessage(name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String[] stringStack = client.getStringStack();
|
||||
int stringStackSize = client.getStringStackSize();
|
||||
|
||||
@@ -123,7 +135,7 @@ public class ChatFilterPlugin extends Plugin
|
||||
if (censoredMessage == null)
|
||||
{
|
||||
// Block the message
|
||||
intStack[intStackSize - 2] = 0;
|
||||
intStack[intStackSize - 3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -135,7 +147,7 @@ public class ChatFilterPlugin extends Plugin
|
||||
@Subscribe
|
||||
public void onOverheadTextChanged(OverheadTextChanged event)
|
||||
{
|
||||
if (!(event.getActor() instanceof Player))
|
||||
if (!(event.getActor() instanceof Player) || !shouldFilterPlayerMessage(event.getActor().getName()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -150,6 +162,14 @@ public class ChatFilterPlugin extends Plugin
|
||||
event.getActor().setOverheadText(message);
|
||||
}
|
||||
|
||||
boolean shouldFilterPlayerMessage(String playerName)
|
||||
{
|
||||
boolean isMessageFromSelf = playerName.equals(client.getLocalPlayer().getName());
|
||||
return !isMessageFromSelf &&
|
||||
(config.filterFriends() || !client.isFriended(playerName, false)) &&
|
||||
(config.filterClan() || !client.isClanMember(playerName));
|
||||
}
|
||||
|
||||
String censorMessage(final String message)
|
||||
{
|
||||
String strippedMessage = jagexPrintableCharMatcher.retainFrom(message)
|
||||
|
||||
@@ -126,4 +126,15 @@ public interface ClanChatConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "clanTabChat",
|
||||
name = "Clan Tab Chat",
|
||||
description = "Allows clan chat without prepending '/' to messages when on clan tab",
|
||||
position = 8
|
||||
)
|
||||
default boolean clanTabChat()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.PlayerDespawned;
|
||||
import net.runelite.api.events.PlayerSpawned;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.VarClientStrChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
@@ -498,6 +499,19 @@ public class ClanChatPlugin extends Plugin
|
||||
activityBuffer.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
|
||||
{
|
||||
if (!scriptCallbackEvent.getEventName().equalsIgnoreCase("clanchatInput"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final int[] intStack = client.getIntStack();
|
||||
final int size = client.getIntStackSize();
|
||||
intStack[size - 1] = config.clanTabChat() ? 1 : 0;
|
||||
}
|
||||
|
||||
int getClanAmount()
|
||||
{
|
||||
return clanMembers.size();
|
||||
|
||||
@@ -66,7 +66,9 @@ import net.runelite.api.events.ItemContainerChanged;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
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.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
@@ -74,6 +76,7 @@ import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.AnagramClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.BeginnerMapClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.CipherClue;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.ClueScroll;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.CoordinateClue;
|
||||
@@ -386,6 +389,18 @@ public class ClueScrollPlugin extends Plugin
|
||||
updateClue(findClueScroll());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded event)
|
||||
{
|
||||
if (event.getGroupId() < WidgetID.BEGINNER_CLUE_MAP_CHAMPIONS_GUILD
|
||||
|| event.getGroupId() > WidgetID.BEGINNER_CLUE_MAP_WIZARDS_TOWER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
updateClue(BeginnerMapClue.forWidgetID(event.getGroupId()));
|
||||
}
|
||||
|
||||
public BufferedImage getClueScrollImage()
|
||||
{
|
||||
return itemManager.getImage(ItemID.CLUE_SCROLL_MASTER);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.cluescrolls.clues;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
|
||||
@Getter
|
||||
public class BeginnerMapClue extends MapClue implements LocationClueScroll
|
||||
{
|
||||
private static final ImmutableList<BeginnerMapClue> CLUES = ImmutableList.of(
|
||||
new BeginnerMapClue(WidgetID.BEGINNER_CLUE_MAP_CHAMPIONS_GUILD, new WorldPoint(3166, 3361, 0), "South West of the Champion's Guild"),
|
||||
new BeginnerMapClue(WidgetID.BEGINNER_CLUE_MAP_VARROCK_EAST_MINE, new WorldPoint(3290, 3374, 0), "Outside Varrock East Mine"),
|
||||
new BeginnerMapClue(WidgetID.BEGINNER_CLUE_MAP_DRAYNOR, new WorldPoint(3093, 3226, 0), "South of Draynor Village Bank"),
|
||||
new BeginnerMapClue(WidgetID.BEGINNER_CLUE_MAP_NORTH_OF_FALADOR, new WorldPoint(3043, 3398, 0), "In the standing stones north of Falador"),
|
||||
new BeginnerMapClue(WidgetID.BEGINNER_CLUE_MAP_WIZARDS_TOWER, new WorldPoint(3110, 3152, 0), "On the south side of the Wizard's Tower")
|
||||
);
|
||||
|
||||
private final int widgetGroupID;
|
||||
|
||||
private BeginnerMapClue(int widgetGroupID, WorldPoint location, String description)
|
||||
{
|
||||
super(-1, location, description);
|
||||
this.widgetGroupID = widgetGroupID;
|
||||
setRequiresSpade(true);
|
||||
}
|
||||
|
||||
// Beginner Map Clues all use the same ItemID, but the WidgetID used to display them is unique
|
||||
public static BeginnerMapClue forWidgetID(int widgetGroupID)
|
||||
{
|
||||
for (BeginnerMapClue clue : CLUES)
|
||||
{
|
||||
if (clue.widgetGroupID == widgetGroupID)
|
||||
{
|
||||
return clue;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
|
||||
.put(new WorldPoint(3573, 3425, 0), "North of Dessous's tomb from Desert Treasure.")
|
||||
.put(new WorldPoint(3828, 2848, 0), "East of Harmony Island.")
|
||||
.put(new WorldPoint(3225, 2838, 0), "South of Desert Treasure pyramid.")
|
||||
.put(new WorldPoint(1773, 3510, 0), "Between magic trees South of Tithe Farm.")
|
||||
.put(new WorldPoint(1773, 3510, 0), "Ruins north of the Hosidius mine.")
|
||||
.put(new WorldPoint(3822, 3562, 0), "North-east of Dragontooth Island.")
|
||||
.put(new WorldPoint(3603, 3564, 0), "North of the wrecked ship, outside of Port Phasmatys.")
|
||||
.put(new WorldPoint(2936, 2721, 0), "Eastern shore of Crash Island.")
|
||||
|
||||
@@ -32,56 +32,7 @@ import lombok.Getter;
|
||||
import net.runelite.api.NPC;
|
||||
import static net.runelite.api.NullObjectID.NULL_1293;
|
||||
import net.runelite.api.ObjectComposition;
|
||||
import static net.runelite.api.ObjectID.BOOKCASE_12539;
|
||||
import static net.runelite.api.ObjectID.BOOKCASE_380;
|
||||
import static net.runelite.api.ObjectID.BOOKCASE_394;
|
||||
import static net.runelite.api.ObjectID.BOOKCASE_9523;
|
||||
import static net.runelite.api.ObjectID.BOXES;
|
||||
import static net.runelite.api.ObjectID.BOXES_360;
|
||||
import static net.runelite.api.ObjectID.BOXES_361;
|
||||
import static net.runelite.api.ObjectID.BOXES_3686;
|
||||
import static net.runelite.api.ObjectID.BOXES_5111;
|
||||
import static net.runelite.api.ObjectID.BOXES_6176;
|
||||
import static net.runelite.api.ObjectID.BUCKET_9568;
|
||||
import static net.runelite.api.ObjectID.BUSH_2357;
|
||||
import static net.runelite.api.ObjectID.CLOSED_CHEST_25592;
|
||||
import static net.runelite.api.ObjectID.CLOSED_CHEST_375;
|
||||
import static net.runelite.api.ObjectID.CLOSED_CHEST_5108;
|
||||
import static net.runelite.api.ObjectID.COFFIN;
|
||||
import static net.runelite.api.ObjectID.CRATES_11600;
|
||||
import static net.runelite.api.ObjectID.CRATES_24088;
|
||||
import static net.runelite.api.ObjectID.CRATE_11485;
|
||||
import static net.runelite.api.ObjectID.CRATE_12963;
|
||||
import static net.runelite.api.ObjectID.CRATE_14934;
|
||||
import static net.runelite.api.ObjectID.CRATE_18204;
|
||||
import static net.runelite.api.ObjectID.CRATE_18506;
|
||||
import static net.runelite.api.ObjectID.CRATE_18889;
|
||||
import static net.runelite.api.ObjectID.CRATE_24344;
|
||||
import static net.runelite.api.ObjectID.CRATE_25775;
|
||||
import static net.runelite.api.ObjectID.CRATE_27532;
|
||||
import static net.runelite.api.ObjectID.CRATE_27533;
|
||||
import static net.runelite.api.ObjectID.CRATE_354;
|
||||
import static net.runelite.api.ObjectID.CRATE_355;
|
||||
import static net.runelite.api.ObjectID.CRATE_356;
|
||||
import static net.runelite.api.ObjectID.CRATE_357;
|
||||
import static net.runelite.api.ObjectID.CRATE_358;
|
||||
import static net.runelite.api.ObjectID.CRATE_366;
|
||||
import static net.runelite.api.ObjectID.CRATE_5106;
|
||||
import static net.runelite.api.ObjectID.CRATE_5107;
|
||||
import static net.runelite.api.ObjectID.CRATE_5113;
|
||||
import static net.runelite.api.ObjectID.CRATE_9534;
|
||||
import static net.runelite.api.ObjectID.DRAWERS;
|
||||
import static net.runelite.api.ObjectID.DRAWERS_25766;
|
||||
import static net.runelite.api.ObjectID.DRAWERS_350;
|
||||
import static net.runelite.api.ObjectID.DRAWERS_352;
|
||||
import static net.runelite.api.ObjectID.DRAWERS_5618;
|
||||
import static net.runelite.api.ObjectID.DRAWERS_7194;
|
||||
import static net.runelite.api.ObjectID.HAYSTACK;
|
||||
import static net.runelite.api.ObjectID.JUNA;
|
||||
import static net.runelite.api.ObjectID.MINE_CART_6045;
|
||||
import static net.runelite.api.ObjectID.STONES_26633;
|
||||
import static net.runelite.api.ObjectID.WARDROBE_5622;
|
||||
import static net.runelite.api.ObjectID.WHEELBARROW_9625;
|
||||
import static net.runelite.api.ObjectID.*;
|
||||
import net.runelite.api.TileObject;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
@@ -347,7 +298,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("I would make a chemistry joke, but I'm afraid I wouldn't get a reaction.", "Chemist", new WorldPoint(2932, 3212, 0), "Talk to the Chemist in Rimmington"),
|
||||
new CrypticClue("Show this to Hazelmere.", "Hazelmere", new WorldPoint(2677, 3088, 1), "Hazelmere is found upstairs on the island located just east of Yanille."),
|
||||
new CrypticClue("Does one really need a fire to stay warm here?", new WorldPoint(3816, 3810, 0), "Dig next to the fire near the Volcanic Mine entrance."),
|
||||
new CrypticClue("Search the open crate found in a small farmhouse in Hosidius. Cabbages grow outside.", CRATE_27533, new WorldPoint(1687, 3628, 0), "The house is north-east of the general store in Hosidius."),
|
||||
new CrypticClue("Search the open crate found in the Hosidius kitchens.", CRATE_27533, new WorldPoint(1683, 3616, 0), "The kitchens are north-west of the town in Hosidius."),
|
||||
new CrypticClue("Dig under Ithoi's cabin.", new WorldPoint(2529, 2838, 0), "Dig under Ithoi's cabin in the Corsair Cove."),
|
||||
new CrypticClue("Search the drawers, upstairs in the bank to the East of Varrock.", DRAWERS_7194, new WorldPoint(3250, 3420, 1), "Search the drawers upstairs in Varrock east bank."),
|
||||
new CrypticClue("Speak to Hazelmere.", "Hazelmere", new WorldPoint(2677, 3088, 1), "Located upstairs in the house to the north of fairy ring CLS. Answer: 6859"),
|
||||
|
||||
@@ -27,399 +27,19 @@ package net.runelite.client.plugins.cluescrolls.clues;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.EquipmentInventorySlot;
|
||||
import static net.runelite.api.EquipmentInventorySlot.AMMO;
|
||||
import static net.runelite.api.EquipmentInventorySlot.AMULET;
|
||||
import static net.runelite.api.EquipmentInventorySlot.BODY;
|
||||
import static net.runelite.api.EquipmentInventorySlot.BOOTS;
|
||||
import static net.runelite.api.EquipmentInventorySlot.CAPE;
|
||||
import static net.runelite.api.EquipmentInventorySlot.GLOVES;
|
||||
import static net.runelite.api.EquipmentInventorySlot.HEAD;
|
||||
import static net.runelite.api.EquipmentInventorySlot.LEGS;
|
||||
import static net.runelite.api.EquipmentInventorySlot.RING;
|
||||
import static net.runelite.api.EquipmentInventorySlot.SHIELD;
|
||||
import static net.runelite.api.EquipmentInventorySlot.WEAPON;
|
||||
import static net.runelite.api.EquipmentInventorySlot.*;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemID;
|
||||
import static net.runelite.api.ItemID.ABYSSAL_WHIP;
|
||||
import static net.runelite.api.ItemID.ADAMANT_2H_SWORD;
|
||||
import static net.runelite.api.ItemID.ADAMANT_BOOTS;
|
||||
import static net.runelite.api.ItemID.ADAMANT_DAGGER;
|
||||
import static net.runelite.api.ItemID.ADAMANT_FULL_HELM;
|
||||
import static net.runelite.api.ItemID.ADAMANT_HALBERD;
|
||||
import static net.runelite.api.ItemID.ADAMANT_MED_HELM;
|
||||
import static net.runelite.api.ItemID.ADAMANT_PLATEBODY;
|
||||
import static net.runelite.api.ItemID.ADAMANT_PLATELEGS;
|
||||
import static net.runelite.api.ItemID.ADAMANT_PLATESKIRT;
|
||||
import static net.runelite.api.ItemID.ADAMANT_SQ_SHIELD;
|
||||
import static net.runelite.api.ItemID.ADAMANT_SWORD;
|
||||
import static net.runelite.api.ItemID.ADAMANT_WARHAMMER;
|
||||
import static net.runelite.api.ItemID.AHRIMS_HOOD_0;
|
||||
import static net.runelite.api.ItemID.AHRIMS_HOOD_100;
|
||||
import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_0;
|
||||
import static net.runelite.api.ItemID.AHRIMS_ROBESKIRT_100;
|
||||
import static net.runelite.api.ItemID.AHRIMS_ROBETOP_0;
|
||||
import static net.runelite.api.ItemID.AHRIMS_ROBETOP_100;
|
||||
import static net.runelite.api.ItemID.AHRIMS_STAFF_0;
|
||||
import static net.runelite.api.ItemID.AHRIMS_STAFF_100;
|
||||
import static net.runelite.api.ItemID.AIR_TIARA;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY1;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY2;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY3;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY4;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY5;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY6;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_POWER;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_STRENGTH;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_THE_DAMNED;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_THE_DAMNED_FULL;
|
||||
import static net.runelite.api.ItemID.ANCIENT_CROZIER;
|
||||
import static net.runelite.api.ItemID.ANCIENT_MITRE;
|
||||
import static net.runelite.api.ItemID.ANCIENT_STOLE;
|
||||
import static net.runelite.api.ItemID.ARCLIGHT;
|
||||
import static net.runelite.api.ItemID.ARMADYL_CROZIER;
|
||||
import static net.runelite.api.ItemID.ARMADYL_MITRE;
|
||||
import static net.runelite.api.ItemID.ARMADYL_STOLE;
|
||||
import static net.runelite.api.ItemID.BANDOS_BOOTS;
|
||||
import static net.runelite.api.ItemID.BANDOS_CLOAK;
|
||||
import static net.runelite.api.ItemID.BANDOS_CROZIER;
|
||||
import static net.runelite.api.ItemID.BANDOS_GODSWORD;
|
||||
import static net.runelite.api.ItemID.BANDOS_MITRE;
|
||||
import static net.runelite.api.ItemID.BANDOS_PLATEBODY;
|
||||
import static net.runelite.api.ItemID.BANDOS_STOLE;
|
||||
import static net.runelite.api.ItemID.BARROWS_GLOVES;
|
||||
import static net.runelite.api.ItemID.BLACK_AXE;
|
||||
import static net.runelite.api.ItemID.BLACK_BOATER;
|
||||
import static net.runelite.api.ItemID.BLACK_CAPE;
|
||||
import static net.runelite.api.ItemID.BLACK_DHIDE_BODY;
|
||||
import static net.runelite.api.ItemID.BLACK_DHIDE_CHAPS;
|
||||
import static net.runelite.api.ItemID.BLACK_DHIDE_VAMB;
|
||||
import static net.runelite.api.ItemID.BLACK_DRAGON_MASK;
|
||||
import static net.runelite.api.ItemID.BLACK_PLATEBODY;
|
||||
import static net.runelite.api.ItemID.BLACK_SALAMANDER;
|
||||
import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET;
|
||||
import static net.runelite.api.ItemID.BLACK_SLAYER_HELMET_I;
|
||||
import static net.runelite.api.ItemID.BLUE_BOATER;
|
||||
import static net.runelite.api.ItemID.BLUE_BOOTS;
|
||||
import static net.runelite.api.ItemID.BLUE_DHIDE_BODY;
|
||||
import static net.runelite.api.ItemID.BLUE_DHIDE_CHAPS;
|
||||
import static net.runelite.api.ItemID.BLUE_DHIDE_VAMB;
|
||||
import static net.runelite.api.ItemID.BLUE_ROBE_TOP;
|
||||
import static net.runelite.api.ItemID.BLUE_WIZARD_HAT;
|
||||
import static net.runelite.api.ItemID.BLUE_WIZARD_ROBE;
|
||||
import static net.runelite.api.ItemID.BOBS_PURPLE_SHIRT;
|
||||
import static net.runelite.api.ItemID.BOBS_RED_SHIRT;
|
||||
import static net.runelite.api.ItemID.BODY_TIARA;
|
||||
import static net.runelite.api.ItemID.BONE_DAGGER;
|
||||
import static net.runelite.api.ItemID.BONE_SPEAR;
|
||||
import static net.runelite.api.ItemID.BOOK_OF_BALANCE;
|
||||
import static net.runelite.api.ItemID.BOOK_OF_DARKNESS;
|
||||
import static net.runelite.api.ItemID.BOOK_OF_LAW;
|
||||
import static net.runelite.api.ItemID.BOOK_OF_WAR;
|
||||
import static net.runelite.api.ItemID.BRINE_SABRE;
|
||||
import static net.runelite.api.ItemID.BRONZE_2H_SWORD;
|
||||
import static net.runelite.api.ItemID.BRONZE_AXE;
|
||||
import static net.runelite.api.ItemID.BRONZE_CHAINBODY;
|
||||
import static net.runelite.api.ItemID.BRONZE_DAGGER;
|
||||
import static net.runelite.api.ItemID.BRONZE_FULL_HELM;
|
||||
import static net.runelite.api.ItemID.BRONZE_PLATELEGS;
|
||||
import static net.runelite.api.ItemID.BRONZE_SPEAR;
|
||||
import static net.runelite.api.ItemID.BRONZE_SQ_SHIELD;
|
||||
import static net.runelite.api.ItemID.BROWN_APRON;
|
||||
import static net.runelite.api.ItemID.BROWN_HEADBAND;
|
||||
import static net.runelite.api.ItemID.BRUISE_BLUE_SNELM_3343;
|
||||
import static net.runelite.api.ItemID.CAPE_OF_LEGENDS;
|
||||
import static net.runelite.api.ItemID.CASTLE_WARS_BRACELET1;
|
||||
import static net.runelite.api.ItemID.CASTLE_WARS_BRACELET3;
|
||||
import static net.runelite.api.ItemID.CHEFS_HAT;
|
||||
import static net.runelite.api.ItemID.CLIMBING_BOOTS;
|
||||
import static net.runelite.api.ItemID.COIF;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET4;
|
||||
import static net.runelite.api.ItemID.CREAM_ROBE_TOP;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_110_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_210_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_310_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_410_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_510_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_610_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_710_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_810_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_910_I;
|
||||
import static net.runelite.api.ItemID.CRYSTAL_BOW_FULL_I;
|
||||
import static net.runelite.api.ItemID.DEATH_TIARA;
|
||||
import static net.runelite.api.ItemID.DESERT_SHIRT;
|
||||
import static net.runelite.api.ItemID.DHAROKS_GREATAXE_0;
|
||||
import static net.runelite.api.ItemID.DHAROKS_GREATAXE_100;
|
||||
import static net.runelite.api.ItemID.DHAROKS_HELM_0;
|
||||
import static net.runelite.api.ItemID.DHAROKS_HELM_100;
|
||||
import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_0;
|
||||
import static net.runelite.api.ItemID.DHAROKS_PLATEBODY_100;
|
||||
import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_0;
|
||||
import static net.runelite.api.ItemID.DHAROKS_PLATELEGS_100;
|
||||
import static net.runelite.api.ItemID.DIAMOND_BRACELET;
|
||||
import static net.runelite.api.ItemID.DIAMOND_RING;
|
||||
import static net.runelite.api.ItemID.DRAGONSTONE_AMULET;
|
||||
import static net.runelite.api.ItemID.DRAGONSTONE_RING;
|
||||
import static net.runelite.api.ItemID.DRAGON_2H_SWORD;
|
||||
import static net.runelite.api.ItemID.DRAGON_AXE;
|
||||
import static net.runelite.api.ItemID.DRAGON_BATTLEAXE;
|
||||
import static net.runelite.api.ItemID.DRAGON_BOOTS;
|
||||
import static net.runelite.api.ItemID.DRAGON_CHAINBODY_3140;
|
||||
import static net.runelite.api.ItemID.DRAGON_DEFENDER;
|
||||
import static net.runelite.api.ItemID.DRAGON_MED_HELM;
|
||||
import static net.runelite.api.ItemID.DRAGON_NECKLACE;
|
||||
import static net.runelite.api.ItemID.DRAGON_PICKAXE;
|
||||
import static net.runelite.api.ItemID.DRAGON_PICKAXE_12797;
|
||||
import static net.runelite.api.ItemID.DRAGON_PLATESKIRT;
|
||||
import static net.runelite.api.ItemID.DRAGON_SPEAR;
|
||||
import static net.runelite.api.ItemID.DRAGON_SQ_SHIELD;
|
||||
import static net.runelite.api.ItemID.ELEMENTAL_SHIELD;
|
||||
import static net.runelite.api.ItemID.EMERALD_AMULET;
|
||||
import static net.runelite.api.ItemID.EMERALD_RING;
|
||||
import static net.runelite.api.ItemID.FIRE_BATTLESTAFF;
|
||||
import static net.runelite.api.ItemID.FIRE_CAPE;
|
||||
import static net.runelite.api.ItemID.FIRE_MAX_CAPE;
|
||||
import static net.runelite.api.ItemID.FLARED_TROUSERS;
|
||||
import static net.runelite.api.ItemID.FROZEN_ABYSSAL_WHIP;
|
||||
import static net.runelite.api.ItemID.GOLD_NECKLACE;
|
||||
import static net.runelite.api.ItemID.GOLD_RING;
|
||||
import static net.runelite.api.ItemID.GRANITE_SHIELD;
|
||||
import static net.runelite.api.ItemID.GREEN_BOATER;
|
||||
import static net.runelite.api.ItemID.GREEN_BOOTS;
|
||||
import static net.runelite.api.ItemID.GREEN_DHIDE_BODY;
|
||||
import static net.runelite.api.ItemID.GREEN_DHIDE_CHAPS;
|
||||
import static net.runelite.api.ItemID.GREEN_HAT;
|
||||
import static net.runelite.api.ItemID.GREEN_HEADBAND;
|
||||
import static net.runelite.api.ItemID.GREEN_ROBE_BOTTOMS;
|
||||
import static net.runelite.api.ItemID.GREEN_ROBE_TOP;
|
||||
import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET;
|
||||
import static net.runelite.api.ItemID.GREEN_SLAYER_HELMET_I;
|
||||
import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_0;
|
||||
import static net.runelite.api.ItemID.GUTHANS_CHAINSKIRT_100;
|
||||
import static net.runelite.api.ItemID.GUTHANS_HELM_0;
|
||||
import static net.runelite.api.ItemID.GUTHANS_HELM_100;
|
||||
import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_0;
|
||||
import static net.runelite.api.ItemID.GUTHANS_PLATEBODY_100;
|
||||
import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_0;
|
||||
import static net.runelite.api.ItemID.GUTHANS_WARSPEAR_100;
|
||||
import static net.runelite.api.ItemID.GUTHIX_MITRE;
|
||||
import static net.runelite.api.ItemID.GUTHIX_STOLE;
|
||||
import static net.runelite.api.ItemID.HAM_BOOTS;
|
||||
import static net.runelite.api.ItemID.HAM_ROBE;
|
||||
import static net.runelite.api.ItemID.HARDLEATHER_BODY;
|
||||
import static net.runelite.api.ItemID.HELM_OF_NEITIZNOT;
|
||||
import static net.runelite.api.ItemID.HOLY_BOOK;
|
||||
import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET;
|
||||
import static net.runelite.api.ItemID.HYDRA_SLAYER_HELMET_I;
|
||||
import static net.runelite.api.ItemID.IBANS_STAFF;
|
||||
import static net.runelite.api.ItemID.IBANS_STAFF_U;
|
||||
import static net.runelite.api.ItemID.INFERNAL_PICKAXE;
|
||||
import static net.runelite.api.ItemID.INFERNAL_PICKAXE_UNCHARGED;
|
||||
import static net.runelite.api.ItemID.IRON_2H_SWORD;
|
||||
import static net.runelite.api.ItemID.IRON_CHAINBODY;
|
||||
import static net.runelite.api.ItemID.IRON_FULL_HELM;
|
||||
import static net.runelite.api.ItemID.IRON_KITESHIELD;
|
||||
import static net.runelite.api.ItemID.IRON_MED_HELM;
|
||||
import static net.runelite.api.ItemID.IRON_PICKAXE;
|
||||
import static net.runelite.api.ItemID.IRON_PLATEBODY;
|
||||
import static net.runelite.api.ItemID.IRON_PLATELEGS;
|
||||
import static net.runelite.api.ItemID.IRON_PLATESKIRT;
|
||||
import static net.runelite.api.ItemID.IRON_SCIMITAR;
|
||||
import static net.runelite.api.ItemID.IRON_WARHAMMER;
|
||||
import static net.runelite.api.ItemID.KARILS_COIF_0;
|
||||
import static net.runelite.api.ItemID.KARILS_COIF_100;
|
||||
import static net.runelite.api.ItemID.KARILS_CROSSBOW_0;
|
||||
import static net.runelite.api.ItemID.KARILS_CROSSBOW_100;
|
||||
import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_0;
|
||||
import static net.runelite.api.ItemID.KARILS_LEATHERSKIRT_100;
|
||||
import static net.runelite.api.ItemID.KARILS_LEATHERTOP_0;
|
||||
import static net.runelite.api.ItemID.KARILS_LEATHERTOP_100;
|
||||
import static net.runelite.api.ItemID.LAVA_BATTLESTAFF;
|
||||
import static net.runelite.api.ItemID.LEATHER_BOOTS;
|
||||
import static net.runelite.api.ItemID.LEATHER_CHAPS;
|
||||
import static net.runelite.api.ItemID.LEATHER_COWL;
|
||||
import static net.runelite.api.ItemID.LEATHER_GLOVES;
|
||||
import static net.runelite.api.ItemID.LOCKPICK;
|
||||
import static net.runelite.api.ItemID.LONGBOW;
|
||||
import static net.runelite.api.ItemID.MAGIC_LONGBOW;
|
||||
import static net.runelite.api.ItemID.MAPLE_LONGBOW;
|
||||
import static net.runelite.api.ItemID.MAPLE_SHORTBOW;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_PURPLE_HAT;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_PURPLE_KILT;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_PURPLE_ROBE;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_PURPLE_TOP;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_RED_HAT;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_RED_KILT;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_RED_ROBE;
|
||||
import static net.runelite.api.ItemID.MENAPHITE_RED_TOP;
|
||||
import static net.runelite.api.ItemID.MIND_SHIELD;
|
||||
import static net.runelite.api.ItemID.MITHRIL_BOOTS;
|
||||
import static net.runelite.api.ItemID.MITHRIL_CHAINBODY;
|
||||
import static net.runelite.api.ItemID.MITHRIL_FULL_HELM;
|
||||
import static net.runelite.api.ItemID.MITHRIL_MED_HELM;
|
||||
import static net.runelite.api.ItemID.MITHRIL_PICKAXE;
|
||||
import static net.runelite.api.ItemID.MITHRIL_PLATEBODY;
|
||||
import static net.runelite.api.ItemID.MITHRIL_PLATELEGS;
|
||||
import static net.runelite.api.ItemID.MITHRIL_PLATESKIRT;
|
||||
import static net.runelite.api.ItemID.MITHRIL_SCIMITAR;
|
||||
import static net.runelite.api.ItemID.MYSTIC_FIRE_STAFF;
|
||||
import static net.runelite.api.ItemID.MYSTIC_GLOVES;
|
||||
import static net.runelite.api.ItemID.MYSTIC_HAT;
|
||||
import static net.runelite.api.ItemID.MYSTIC_ROBE_BOTTOM;
|
||||
import static net.runelite.api.ItemID.MYSTIC_ROBE_BOTTOM_DARK;
|
||||
import static net.runelite.api.ItemID.MYSTIC_ROBE_TOP;
|
||||
import static net.runelite.api.ItemID.MYSTIC_ROBE_TOP_DARK;
|
||||
import static net.runelite.api.ItemID.NEW_CRYSTAL_BOW_I;
|
||||
import static net.runelite.api.ItemID.OAK_LONGBOW;
|
||||
import static net.runelite.api.ItemID.OAK_SHORTBOW;
|
||||
import static net.runelite.api.ItemID.OBSIDIAN_CAPE;
|
||||
import static net.runelite.api.ItemID.ORANGE_BOATER;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_1;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_2;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_3;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_4;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_5;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_6;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_7;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_8;
|
||||
import static net.runelite.api.ItemID.PINK_BOATER;
|
||||
import static net.runelite.api.ItemID.PINK_ROBE_TOP;
|
||||
import static net.runelite.api.ItemID.PINK_SKIRT;
|
||||
import static net.runelite.api.ItemID.PIRATE_BANDANA;
|
||||
import static net.runelite.api.ItemID.PIRATE_BANDANA_7124;
|
||||
import static net.runelite.api.ItemID.PIRATE_BANDANA_7130;
|
||||
import static net.runelite.api.ItemID.PIRATE_BANDANA_7136;
|
||||
import static net.runelite.api.ItemID.PROSELYTE_HAUBERK;
|
||||
import static net.runelite.api.ItemID.PURPLE_BOATER;
|
||||
import static net.runelite.api.ItemID.PURPLE_GLOVES;
|
||||
import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET;
|
||||
import static net.runelite.api.ItemID.PURPLE_SLAYER_HELMET_I;
|
||||
import static net.runelite.api.ItemID.RED_BOATER;
|
||||
import static net.runelite.api.ItemID.RED_CAPE;
|
||||
import static net.runelite.api.ItemID.RED_DHIDE_CHAPS;
|
||||
import static net.runelite.api.ItemID.RED_HEADBAND;
|
||||
import static net.runelite.api.ItemID.RED_SLAYER_HELMET;
|
||||
import static net.runelite.api.ItemID.RED_SLAYER_HELMET_I;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING1;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING2;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING3;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING4;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING5;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING6;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING7;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING8;
|
||||
import static net.runelite.api.ItemID.RING_OF_FORGING;
|
||||
import static net.runelite.api.ItemID.RING_OF_LIFE;
|
||||
import static net.runelite.api.ItemID.RING_OF_VISIBILITY;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_1;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_2;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_3;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_4;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_5;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_I;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_I1;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_I2;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_I3;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_I4;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_I5;
|
||||
import static net.runelite.api.ItemID.ROLLING_PIN;
|
||||
import static net.runelite.api.ItemID.RUBY_AMULET;
|
||||
import static net.runelite.api.ItemID.RUBY_RING;
|
||||
import static net.runelite.api.ItemID.RUNE_AXE;
|
||||
import static net.runelite.api.ItemID.RUNE_BOOTS;
|
||||
import static net.runelite.api.ItemID.RUNE_CROSSBOW;
|
||||
import static net.runelite.api.ItemID.RUNE_FULL_HELM;
|
||||
import static net.runelite.api.ItemID.RUNE_HALBERD;
|
||||
import static net.runelite.api.ItemID.RUNE_HELM_H1;
|
||||
import static net.runelite.api.ItemID.RUNE_HELM_H5;
|
||||
import static net.runelite.api.ItemID.RUNE_KITESHIELD;
|
||||
import static net.runelite.api.ItemID.RUNE_LONGSWORD;
|
||||
import static net.runelite.api.ItemID.RUNE_PICKAXE;
|
||||
import static net.runelite.api.ItemID.RUNE_PLATEBODY;
|
||||
import static net.runelite.api.ItemID.RUNE_PLATELEGS;
|
||||
import static net.runelite.api.ItemID.RUNE_PLATESKIRT;
|
||||
import static net.runelite.api.ItemID.RUNE_SHIELD_H1;
|
||||
import static net.runelite.api.ItemID.RUNE_SHIELD_H2;
|
||||
import static net.runelite.api.ItemID.RUNE_SHIELD_H3;
|
||||
import static net.runelite.api.ItemID.RUNE_SHIELD_H4;
|
||||
import static net.runelite.api.ItemID.RUNE_SHIELD_H5;
|
||||
import static net.runelite.api.ItemID.RUNE_SPEAR;
|
||||
import static net.runelite.api.ItemID.RUNE_WARHAMMER;
|
||||
import static net.runelite.api.ItemID.SAPPHIRE_AMULET;
|
||||
import static net.runelite.api.ItemID.SAPPHIRE_NECKLACE;
|
||||
import static net.runelite.api.ItemID.SAPPHIRE_RING;
|
||||
import static net.runelite.api.ItemID.SARADOMIN_CROZIER;
|
||||
import static net.runelite.api.ItemID.SARADOMIN_MITRE;
|
||||
import static net.runelite.api.ItemID.SARADOMIN_STOLE;
|
||||
import static net.runelite.api.ItemID.SEERCULL;
|
||||
import static net.runelite.api.ItemID.SHADOW_SWORD;
|
||||
import static net.runelite.api.ItemID.SILVER_SICKLE;
|
||||
import static net.runelite.api.ItemID.SLAYER_HELMET;
|
||||
import static net.runelite.api.ItemID.SLAYER_HELMET_I;
|
||||
import static net.runelite.api.ItemID.SLED_4084;
|
||||
import static net.runelite.api.ItemID.SNAKESKIN_BOOTS;
|
||||
import static net.runelite.api.ItemID.SNAKESKIN_CHAPS;
|
||||
import static net.runelite.api.ItemID.SPINED_CHAPS;
|
||||
import static net.runelite.api.ItemID.SPLITBARK_BODY;
|
||||
import static net.runelite.api.ItemID.SPLITBARK_LEGS;
|
||||
import static net.runelite.api.ItemID.SPOTTED_CAPE;
|
||||
import static net.runelite.api.ItemID.SPOTTED_CAPE_10073;
|
||||
import static net.runelite.api.ItemID.STAFF;
|
||||
import static net.runelite.api.ItemID.STAFF_OF_AIR;
|
||||
import static net.runelite.api.ItemID.STAFF_OF_WATER;
|
||||
import static net.runelite.api.ItemID.STEEL_AXE;
|
||||
import static net.runelite.api.ItemID.STEEL_FULL_HELM;
|
||||
import static net.runelite.api.ItemID.STEEL_KITESHIELD;
|
||||
import static net.runelite.api.ItemID.STEEL_LONGSWORD;
|
||||
import static net.runelite.api.ItemID.STEEL_MACE;
|
||||
import static net.runelite.api.ItemID.STEEL_MED_HELM;
|
||||
import static net.runelite.api.ItemID.STEEL_PICKAXE;
|
||||
import static net.runelite.api.ItemID.STEEL_PLATEBODY;
|
||||
import static net.runelite.api.ItemID.STEEL_PLATESKIRT;
|
||||
import static net.runelite.api.ItemID.STEEL_SQ_SHIELD;
|
||||
import static net.runelite.api.ItemID.STUDDED_BODY;
|
||||
import static net.runelite.api.ItemID.STUDDED_CHAPS;
|
||||
import static net.runelite.api.ItemID.TEAM1_CAPE;
|
||||
import static net.runelite.api.ItemID.TEAM50_CAPE;
|
||||
import static net.runelite.api.ItemID.TIARA;
|
||||
import static net.runelite.api.ItemID.TOKTZKETXIL;
|
||||
import static net.runelite.api.ItemID.TOKTZXILUL;
|
||||
import static net.runelite.api.ItemID.TORAGS_HAMMERS_0;
|
||||
import static net.runelite.api.ItemID.TORAGS_HAMMERS_100;
|
||||
import static net.runelite.api.ItemID.TORAGS_HELM_0;
|
||||
import static net.runelite.api.ItemID.TORAGS_HELM_100;
|
||||
import static net.runelite.api.ItemID.TORAGS_PLATEBODY_0;
|
||||
import static net.runelite.api.ItemID.TORAGS_PLATEBODY_100;
|
||||
import static net.runelite.api.ItemID.TORAGS_PLATELEGS_0;
|
||||
import static net.runelite.api.ItemID.TORAGS_PLATELEGS_100;
|
||||
import static net.runelite.api.ItemID.TURQUOISE_ROBE_BOTTOMS;
|
||||
import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET;
|
||||
import static net.runelite.api.ItemID.TURQUOISE_SLAYER_HELMET_I;
|
||||
import static net.runelite.api.ItemID.UNHOLY_BOOK;
|
||||
import static net.runelite.api.ItemID.VERACS_BRASSARD_0;
|
||||
import static net.runelite.api.ItemID.VERACS_BRASSARD_100;
|
||||
import static net.runelite.api.ItemID.VERACS_FLAIL_0;
|
||||
import static net.runelite.api.ItemID.VERACS_FLAIL_100;
|
||||
import static net.runelite.api.ItemID.VERACS_HELM_0;
|
||||
import static net.runelite.api.ItemID.VERACS_HELM_100;
|
||||
import static net.runelite.api.ItemID.VERACS_PLATESKIRT_0;
|
||||
import static net.runelite.api.ItemID.VERACS_PLATESKIRT_100;
|
||||
import static net.runelite.api.ItemID.VOLCANIC_ABYSSAL_WHIP;
|
||||
import static net.runelite.api.ItemID.WHITE_APRON;
|
||||
import static net.runelite.api.ItemID.WHITE_BOATER;
|
||||
import static net.runelite.api.ItemID.WHITE_HEADBAND;
|
||||
import static net.runelite.api.ItemID.ZAMORAK_CROZIER;
|
||||
import static net.runelite.api.ItemID.ZAMORAK_FULL_HELM;
|
||||
import static net.runelite.api.ItemID.ZAMORAK_GODSWORD;
|
||||
import static net.runelite.api.ItemID.ZAMORAK_MITRE;
|
||||
import static net.runelite.api.ItemID.ZAMORAK_STOLE;
|
||||
import static net.runelite.api.ItemID.*;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR;
|
||||
@@ -427,143 +47,13 @@ import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.AllRequirementsCollection;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.AnyRequirementCollection;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.Emote;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.ANGRY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BECKON;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BLOW_KISS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BOW;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.CHEER;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.CLAP;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.CRY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.DANCE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.FLAP;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.GOBLIN_SALUTE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.HEADBANG;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.JIG;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.JUMP_FOR_JOY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.LAUGH;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.NO;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.PANIC;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.PUSH_UP;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.RASPBERRY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SALUTE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SHRUG;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SLAP_HEAD;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.SPIN;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.STOMP;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.THINK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.WAVE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.YAWN;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.YES;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.*;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.ItemRequirement;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.RangeItemRequirement;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.AGILITY_PYRAMID;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.AL_KHARID_SCORPION_MINE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.AUBURYS_SHOP_IN_VARROCK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BARBARIAN_OUTPOST_OBSTACLE_COURSE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BARROWS_CHEST;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BOB_AXES_ENTRANCE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CASTLE_WARS_BANK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CATHERBY_BEEHIVE_FIELD;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CENTRE_OF_CANIFIS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CENTRE_OF_THE_CATACOMBS_OF_KOUREND;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CHAPEL_IN_WEST_ARDOUGNE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DEATH_ALTAR;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DIGSITE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DRAYNOR_MANOR_BY_THE_FOUNTAIN;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.DRAYNOR_VILLAGE_MARKET;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANA_CHAPEL;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANCE_OF_THE_ARCEUUS_LIBRARY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ENTRANCE_OF_THE_CAVE_OF_DAMIS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.FINE_CLOTHES_ENTRANCE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.FISHING_GUILD_BANK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.FOUNTAIN_OF_HEROES;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.GNOME_STRONGHOLD_BALANCING_ROPE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.GYPSY_TENT_ENTRANCE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.HALFWAY_DOWN_TROLLWEISS_MOUNTAIN;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.HICKTONS_ARCHERY_EMPORIUM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.HOSIDIUS_MESS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.INSIDE_THE_DIGSITE_EXAM_CENTRE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.IN_THE_MIDDLE_OF_JIGGIG;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.KING_BLACK_DRAGONS_LAIR;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.LIMESTONE_MINE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.LUMBRIDGE_SWAMP_CAVES;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MAUSOLEUM_OFF_THE_MORYTANIA_COAST;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MOUNTAIN_CAMP_GOAT_ENCLOSURE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MUBARIZS_ROOM_AT_THE_DUEL_ARENA;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.MUDSKIPPER_POINT;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_A_SHED_IN_LUMBRIDGE_SWAMP;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_HERQUINS_SHOP_IN_FALADOR;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_PIER_IN_ZULANDRA;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NEAR_THE_SAWMILL_OPERATORS_BOOTH;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTHERN_WALL_OF_CASTLE_DRAKAN;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NORTH_OF_MOUNT_KARUULM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.NOTERAZZOS_SHOP_IN_THE_WILDERNESS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OBSERVATORY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ON_TOP_OF_TROLLHEIM_MOUNTAIN;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_CATHERBY_BANK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_DRAYNOR_VILLAGE_JAIL;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_KEEP_LE_FAYE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_KRIL_TSUTSAROTHS_ROOM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_MUDKNUCKLES_HUT;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_DIGSITE_EXAM_CENTRE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_FALADOR_PARTY_ROOM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_FISHING_GUILD;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_LEGENDS_GUILD_DOOR;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_LEGENDS_GUILD_GATES;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_THE_WILDERNESS_AXE_HUT;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_VARROCK_PALACE_COURTYARD;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.OUTSIDE_YANILLE_BANK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.RIMMINGTON_MINE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ROAD_JUNCTION_NORTH_OF_RIMMINGTON;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHAYZIEN_WAR_TENT;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHILO_VILLAGE_BANK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUL_ALTAR;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTHEAST_CORNER_OF_THE_MONASTERY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTH_OF_THE_GRAND_EXCHANGE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TAVERLEY_STONE_CIRCLE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TENT_IN_LORD_IORWERTHS_ENCAMPMENT;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TOP_FLOOR_OF_THE_LIGHTHOUSE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TZHAAR_GEM_STORE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.TZHAAR_WEAPONS_STORE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.VARROCK_PALACE_LIBRARY;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WARRIORS_GUILD_BANK;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WARRIORS_GUILD_BANK_29047;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WELL_OF_VOYAGE;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WEST_OF_THE_SHAYZIEN_COMBAT_RING;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit._7TH_CHAMBER_OF_JALSAVRAH;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.*;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.SingleItemRequirement;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.SlotLimitationRequirement;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
@@ -690,6 +180,9 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
|
||||
new EmoteClue("Panic at Al Kharid mine.", null, new WorldPoint(3300, 3314, 0), PANIC),
|
||||
new EmoteClue("Spin at Flynn's Mace Shop.", null, new WorldPoint(2950, 3387, 0), SPIN));
|
||||
|
||||
private static final String UNICODE_CHECK_MARK = "\u2713";
|
||||
private static final String UNICODE_BALLOT_X = "\u2717";
|
||||
|
||||
private static SingleItemRequirement item(int itemId)
|
||||
{
|
||||
return new SingleItemRequirement(itemId);
|
||||
@@ -721,19 +214,18 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
|
||||
}
|
||||
|
||||
private final String text;
|
||||
private final Integer stashUnit;
|
||||
private final STASHUnit stashUnit;
|
||||
private final WorldPoint location;
|
||||
private final Emote firstEmote;
|
||||
private final Emote secondEmote;
|
||||
@Nonnull
|
||||
private final ItemRequirement[] itemRequirements;
|
||||
|
||||
private EmoteClue(String text, Integer stashUnit, WorldPoint location, Emote firstEmote, @Nonnull ItemRequirement... itemRequirements)
|
||||
private EmoteClue(String text, STASHUnit stashUnit, WorldPoint location, Emote firstEmote, @Nonnull ItemRequirement... itemRequirements)
|
||||
{
|
||||
this(text, stashUnit, location, firstEmote, null, itemRequirements);
|
||||
}
|
||||
|
||||
private EmoteClue(String text, Integer stashUnit, WorldPoint location, Emote firstEmote, Emote secondEmote, @Nonnull ItemRequirement... itemRequirements)
|
||||
private EmoteClue(String text, STASHUnit stashUnit, WorldPoint location, Emote firstEmote, Emote secondEmote, @Nonnull ItemRequirement... itemRequirements)
|
||||
{
|
||||
this.text = text;
|
||||
this.stashUnit = stashUnit;
|
||||
@@ -763,6 +255,17 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
|
||||
|
||||
if (itemRequirements.length > 0)
|
||||
{
|
||||
Client client = plugin.getClient();
|
||||
client.runScript(ScriptID.WATSON_STASH_UNIT_CHECK, stashUnit.getObjectId(), 0, 0, 0);
|
||||
int[] intStack = client.getIntStack();
|
||||
boolean stashUnitBuilt = intStack[0] == 1;
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("STASH Unit:")
|
||||
.right(stashUnitBuilt ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X)
|
||||
.rightColor(stashUnitBuilt ? Color.GREEN : Color.RED)
|
||||
.build());
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder().left("Equip:").build());
|
||||
|
||||
Item[] equipment = plugin.getEquippedItems();
|
||||
@@ -790,9 +293,9 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
|
||||
boolean combinedFulfilled = requirement.fulfilledBy(combined);
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(requirement.getCollectiveName(plugin.getClient()))
|
||||
.left(requirement.getCollectiveName(client))
|
||||
.leftColor(TITLED_CONTENT_COLOR)
|
||||
.right(combinedFulfilled ? "\u2713" : "\u2717")
|
||||
.right(combinedFulfilled ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X)
|
||||
.rightColor(equipmentFulfilled ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED))
|
||||
.build());
|
||||
}
|
||||
@@ -802,14 +305,28 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
|
||||
@Override
|
||||
public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin)
|
||||
{
|
||||
LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation());
|
||||
LocalPoint localPoint = LocalPoint.fromWorld(plugin.getClient(), getLocation());
|
||||
|
||||
if (localLocation == null)
|
||||
if (localPoint != null)
|
||||
{
|
||||
return;
|
||||
OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localPoint, plugin.getEmoteImage(), Color.ORANGE);
|
||||
}
|
||||
|
||||
OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localLocation, plugin.getEmoteImage(), Color.ORANGE);
|
||||
final WorldPoint[] worldPoints = stashUnit.getWorldPoints();
|
||||
|
||||
for (final WorldPoint worldPoint : worldPoints)
|
||||
{
|
||||
final LocalPoint stashUnitLocalPoint = LocalPoint.fromWorld(plugin.getClient(), worldPoint);
|
||||
|
||||
if (stashUnitLocalPoint != null)
|
||||
{
|
||||
final Polygon poly = Perspective.getCanvasTilePoly(plugin.getClient(), stashUnitLocalPoint);
|
||||
if (poly != null)
|
||||
{
|
||||
OverlayUtil.renderPolygon(graphics, poly, Color.RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static EmoteClue forText(String text)
|
||||
|
||||
@@ -29,38 +29,7 @@ import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_12179;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_2713;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_2716;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_2719;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_3516;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_3518;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_EASY_7236;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_12130;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19782;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19783;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19784;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19785;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_ELITE_19786;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_2729;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3520;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3522;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3524;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_3525;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_7239;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_HARD_7241;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_2827;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3596;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3598;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3599;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3601;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_3602;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7286;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7288;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7290;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7292;
|
||||
import static net.runelite.api.ItemID.CLUE_SCROLL_MEDIUM_7294;
|
||||
import static net.runelite.api.ItemID.*;
|
||||
import net.runelite.api.ObjectComposition;
|
||||
import static net.runelite.api.ObjectID.CRATE_18506;
|
||||
import static net.runelite.api.ObjectID.CRATE_2620;
|
||||
@@ -133,7 +102,7 @@ public class MapClue extends ClueScroll implements ObjectClueScroll
|
||||
this(itemId, location, objectId, null);
|
||||
}
|
||||
|
||||
private MapClue(int itemId, WorldPoint location, String description)
|
||||
MapClue(int itemId, WorldPoint location, String description)
|
||||
{
|
||||
this(itemId, location, -1, description);
|
||||
}
|
||||
|
||||
@@ -24,115 +24,127 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.cluescrolls.clues.emote;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.NullObjectID;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
public final class STASHUnit
|
||||
@Getter
|
||||
public enum STASHUnit
|
||||
{
|
||||
public static final int NEAR_A_SHED_IN_LUMBRIDGE_SWAMP = NullObjectID.NULL_28958;
|
||||
public static final int ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER = NullObjectID.NULL_28959;
|
||||
public static final int DRAYNOR_VILLAGE_MARKET = NullObjectID.NULL_28960;
|
||||
public static final int LIMESTONE_MINE = NullObjectID.NULL_28961;
|
||||
public static final int OUTSIDE_THE_LEGENDS_GUILD_GATES = NullObjectID.NULL_28962;
|
||||
public static final int MUDSKIPPER_POINT = NullObjectID.NULL_28963;
|
||||
public static final int NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM = NullObjectID.NULL_28964;
|
||||
public static final int AL_KHARID_SCORPION_MINE = NullObjectID.NULL_28965;
|
||||
public static final int DRAYNOR_MANOR_BY_THE_FOUNTAIN = NullObjectID.NULL_28966;
|
||||
public static final int WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL = NullObjectID.NULL_28967;
|
||||
public static final int CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE = NullObjectID.NULL_28968;
|
||||
public static final int RIMMINGTON_MINE = NullObjectID.NULL_28969;
|
||||
public static final int VARROCK_PALACE_LIBRARY = NullObjectID.NULL_28970;
|
||||
public static final int UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL = NullObjectID.NULL_28971;
|
||||
public static final int OUTSIDE_THE_FALADOR_PARTY_ROOM = NullObjectID.NULL_28972;
|
||||
public static final int TAVERLEY_STONE_CIRCLE = NullObjectID.NULL_28973;
|
||||
public static final int CATHERBY_BEEHIVE_FIELD = NullObjectID.NULL_28974;
|
||||
public static final int NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO = NullObjectID.NULL_28975;
|
||||
public static final int ROAD_JUNCTION_NORTH_OF_RIMMINGTON = NullObjectID.NULL_28976;
|
||||
public static final int OUTSIDE_THE_FISHING_GUILD = NullObjectID.NULL_28977;
|
||||
public static final int OUTSIDE_KEEP_LE_FAYE = NullObjectID.NULL_28978;
|
||||
public static final int ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION = NullObjectID.NULL_28979;
|
||||
public static final int OUTSIDE_THE_DIGSITE_EXAM_CENTRE = NullObjectID.NULL_28980;
|
||||
public static final int NEAR_THE_SAWMILL_OPERATORS_BOOTH = NullObjectID.NULL_28981;
|
||||
public static final int MUBARIZS_ROOM_AT_THE_DUEL_ARENA = NullObjectID.NULL_28982;
|
||||
public static final int OUTSIDE_VARROCK_PALACE_COURTYARD = NullObjectID.NULL_28983;
|
||||
public static final int NEAR_HERQUINS_SHOP_IN_FALADOR = NullObjectID.NULL_28984;
|
||||
public static final int SOUTH_OF_THE_GRAND_EXCHANGE = NullObjectID.NULL_28985;
|
||||
public static final int AUBURYS_SHOP_IN_VARROCK = NullObjectID.NULL_28986;
|
||||
public static final int CENTRE_OF_CANIFIS = NullObjectID.NULL_28987;
|
||||
public static final int MAUSOLEUM_OFF_THE_MORYTANIA_COAST = NullObjectID.NULL_28988;
|
||||
public static final int EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE = NullObjectID.NULL_28989;
|
||||
public static final int SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE = NullObjectID.NULL_28990;
|
||||
public static final int CASTLE_WARS_BANK = NullObjectID.NULL_28991;
|
||||
public static final int BARBARIAN_OUTPOST_OBSTACLE_COURSE = NullObjectID.NULL_28992;
|
||||
public static final int GNOME_STRONGHOLD_BALANCING_ROPE = NullObjectID.NULL_28993;
|
||||
public static final int OUTSIDE_YANILLE_BANK = NullObjectID.NULL_28994;
|
||||
public static final int OBSERVATORY = NullObjectID.NULL_28995;
|
||||
public static final int OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP = NullObjectID.NULL_28996;
|
||||
public static final int DIGSITE = NullObjectID.NULL_28997;
|
||||
public static final int HICKTONS_ARCHERY_EMPORIUM = NullObjectID.NULL_28998;
|
||||
public static final int SHANTAY_PASS = NullObjectID.NULL_28999;
|
||||
public static final int LUMBRIDGE_SWAMP_CAVES = NullObjectID.NULL_29000;
|
||||
public static final int OUTSIDE_CATHERBY_BANK = NullObjectID.NULL_29001;
|
||||
public static final int OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE = NullObjectID.NULL_29002;
|
||||
public static final int OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY = NullObjectID.NULL_29003;
|
||||
public static final int TZHAAR_WEAPONS_STORE = NullObjectID.NULL_29004;
|
||||
public static final int NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE = NullObjectID.NULL_29005;
|
||||
public static final int WEST_OF_THE_SHAYZIEN_COMBAT_RING = NullObjectID.NULL_29006;
|
||||
public static final int ENTRANCE_OF_THE_ARCEUUS_LIBRARY = NullObjectID.NULL_29007;
|
||||
public static final int OUTSIDE_DRAYNOR_VILLAGE_JAIL = NullObjectID.NULL_29008;
|
||||
public static final int CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS = NullObjectID.NULL_29009;
|
||||
public static final int FISHING_GUILD_BANK = NullObjectID.NULL_29010;
|
||||
public static final int TOP_FLOOR_OF_THE_LIGHTHOUSE = NullObjectID.NULL_29011;
|
||||
public static final int OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM = NullObjectID.NULL_29012;
|
||||
public static final int NOTERAZZOS_SHOP_IN_THE_WILDERNESS = NullObjectID.NULL_29013;
|
||||
public static final int WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION = NullObjectID.NULL_29014;
|
||||
public static final int MOUNTAIN_CAMP_GOAT_ENCLOSURE = NullObjectID.NULL_29015;
|
||||
public static final int GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN = NullObjectID.NULL_29016;
|
||||
public static final int SHILO_VILLAGE_BANK = NullObjectID.NULL_29017;
|
||||
public static final int INSIDE_THE_DIGSITE_EXAM_CENTRE = NullObjectID.NULL_29018;
|
||||
public static final int NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE = NullObjectID.NULL_29019;
|
||||
public static final int VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS = NullObjectID.NULL_29020;
|
||||
public static final int IN_THE_MIDDLE_OF_JIGGIG = NullObjectID.NULL_29021;
|
||||
public static final int AGILITY_PYRAMID = NullObjectID.NULL_29022;
|
||||
public static final int HOSIDIUS_MESS = NullObjectID.NULL_29023;
|
||||
public static final int CHAPEL_IN_WEST_ARDOUGNE = NullObjectID.NULL_29024;
|
||||
public static final int NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES = NullObjectID.NULL_29025;
|
||||
public static final int NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE = NullObjectID.NULL_29026;
|
||||
public static final int ENTRANCE_OF_THE_CAVE_OF_DAMIS = NullObjectID.NULL_29027;
|
||||
public static final int WARRIORS_GUILD_BANK = NullObjectID.NULL_29028;
|
||||
public static final int SOUTHEAST_CORNER_OF_THE_MONASTERY = NullObjectID.NULL_29029;
|
||||
public static final int SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM = NullObjectID.NULL_29030;
|
||||
public static final int OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM = NullObjectID.NULL_29031;
|
||||
public static final int ON_TOP_OF_TROLLHEIM_MOUNTAIN = NullObjectID.NULL_29032;
|
||||
public static final int FOUNTAIN_OF_HEROES = NullObjectID.NULL_29033;
|
||||
public static final int ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL = NullObjectID.NULL_29034;
|
||||
public static final int HALFWAY_DOWN_TROLLWEISS_MOUNTAIN = NullObjectID.NULL_29035;
|
||||
public static final int SHAYZIEN_WAR_TENT = NullObjectID.NULL_29036;
|
||||
public static final int OUTSIDE_THE_LEGENDS_GUILD_DOOR = NullObjectID.NULL_29037;
|
||||
public static final int NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET = NullObjectID.NULL_29038;
|
||||
public static final int OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA = NullObjectID.NULL_29039;
|
||||
public static final int SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE = NullObjectID.NULL_29040;
|
||||
public static final int NEAR_THE_PIER_IN_ZULANDRA = NullObjectID.NULL_29041;
|
||||
public static final int BARROWS_CHEST = NullObjectID.NULL_29042;
|
||||
public static final int WELL_OF_VOYAGE = NullObjectID.NULL_29043;
|
||||
public static final int NORTHERN_WALL_OF_CASTLE_DRAKAN = NullObjectID.NULL_29044;
|
||||
public static final int _7TH_CHAMBER_OF_JALSAVRAH = NullObjectID.NULL_29045;
|
||||
public static final int SOUL_ALTAR = NullObjectID.NULL_29046;
|
||||
public static final int WARRIORS_GUILD_BANK_29047 = NullObjectID.NULL_29047;
|
||||
public static final int ENTRANA_CHAPEL = NullObjectID.NULL_29048;
|
||||
public static final int TZHAAR_GEM_STORE = NullObjectID.NULL_29049;
|
||||
public static final int TENT_IN_LORD_IORWERTHS_ENCAMPMENT = NullObjectID.NULL_29050;
|
||||
public static final int OUTSIDE_MUDKNUCKLES_HUT = NullObjectID.NULL_29051;
|
||||
public static final int CENTRE_OF_THE_CATACOMBS_OF_KOUREND = NullObjectID.NULL_29052;
|
||||
public static final int KING_BLACK_DRAGONS_LAIR = NullObjectID.NULL_29053;
|
||||
public static final int OUTSIDE_KRIL_TSUTSAROTHS_ROOM = NullObjectID.NULL_29054;
|
||||
public static final int BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS = NullObjectID.NULL_29055;
|
||||
public static final int OUTSIDE_THE_WILDERNESS_AXE_HUT = NullObjectID.NULL_29056;
|
||||
public static final int TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER = NullObjectID.NULL_29057;
|
||||
public static final int DEATH_ALTAR = NullObjectID.NULL_29058;
|
||||
public static final int BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE = NullObjectID.NULL_29059;
|
||||
public static final int NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY = NullObjectID.NULL_29060;
|
||||
public static final int NORTH_OF_MOUNT_KARUULM = NullObjectID.NULL_34647;
|
||||
public static final int GYPSY_TENT_ENTRANCE = NullObjectID.NULL_34736;
|
||||
public static final int FINE_CLOTHES_ENTRANCE = NullObjectID.NULL_34737;
|
||||
public static final int BOB_AXES_ENTRANCE = NullObjectID.NULL_34738;
|
||||
NEAR_A_SHED_IN_LUMBRIDGE_SWAMP(NullObjectID.NULL_28958, new WorldPoint(3201, 3171, 0)),
|
||||
ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER(NullObjectID.NULL_28959, new WorldPoint(3115, 3194, 1)),
|
||||
DRAYNOR_VILLAGE_MARKET(NullObjectID.NULL_28960, new WorldPoint(3083, 3254, 0)),
|
||||
LIMESTONE_MINE(NullObjectID.NULL_28961, new WorldPoint(3373, 3498, 0)),
|
||||
OUTSIDE_THE_LEGENDS_GUILD_GATES(NullObjectID.NULL_28962, new WorldPoint(2735, 3350, 0)),
|
||||
MUDSKIPPER_POINT(NullObjectID.NULL_28963, new WorldPoint(2988, 3111, 0)),
|
||||
NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM(NullObjectID.NULL_28964, new WorldPoint(3050, 3237, 1)),
|
||||
AL_KHARID_SCORPION_MINE(NullObjectID.NULL_28965, new WorldPoint(3303, 3289, 0)),
|
||||
DRAYNOR_MANOR_BY_THE_FOUNTAIN(NullObjectID.NULL_28966, new WorldPoint(3089, 3331, 0)),
|
||||
WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL(NullObjectID.NULL_28967, new WorldPoint(3163, 3297, 0)),
|
||||
CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE(NullObjectID.NULL_28968, new WorldPoint(3111, 3289, 0)),
|
||||
RIMMINGTON_MINE(NullObjectID.NULL_28969, new WorldPoint(2976, 3239, 0)),
|
||||
VARROCK_PALACE_LIBRARY(NullObjectID.NULL_28970, new WorldPoint(3214, 3490, 0)),
|
||||
UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL(NullObjectID.NULL_28971, new WorldPoint(2635, 3386, 2)),
|
||||
OUTSIDE_THE_FALADOR_PARTY_ROOM(NullObjectID.NULL_28972, new WorldPoint(3043, 3371, 0)),
|
||||
TAVERLEY_STONE_CIRCLE(NullObjectID.NULL_28973, new WorldPoint(2924, 3477, 0)),
|
||||
CATHERBY_BEEHIVE_FIELD(NullObjectID.NULL_28974, new WorldPoint(2764, 3438, 0)),
|
||||
NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO(NullObjectID.NULL_28975, new WorldPoint(2608, 3284, 0)),
|
||||
ROAD_JUNCTION_NORTH_OF_RIMMINGTON(NullObjectID.NULL_28976, new WorldPoint(2981, 3278, 0)),
|
||||
OUTSIDE_THE_FISHING_GUILD(NullObjectID.NULL_28977, new WorldPoint(2608, 3393, 0)),
|
||||
OUTSIDE_KEEP_LE_FAYE(NullObjectID.NULL_28978, new WorldPoint(2756, 3399, 0)),
|
||||
ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION(NullObjectID.NULL_28979, new WorldPoint(2735, 3534, 0)),
|
||||
OUTSIDE_THE_DIGSITE_EXAM_CENTRE(NullObjectID.NULL_28980, new WorldPoint(3353, 3343, 0)),
|
||||
NEAR_THE_SAWMILL_OPERATORS_BOOTH(NullObjectID.NULL_28981, new WorldPoint(3298, 3490, 0)),
|
||||
MUBARIZS_ROOM_AT_THE_DUEL_ARENA(NullObjectID.NULL_28982, new WorldPoint(3316, 3242, 0)),
|
||||
OUTSIDE_VARROCK_PALACE_COURTYARD(NullObjectID.NULL_28983, new WorldPoint(3211, 3456, 0)),
|
||||
NEAR_HERQUINS_SHOP_IN_FALADOR(NullObjectID.NULL_28984, new WorldPoint(2941, 3339, 0)),
|
||||
SOUTH_OF_THE_GRAND_EXCHANGE(NullObjectID.NULL_28985, new WorldPoint(3159, 3464, 0)),
|
||||
AUBURYS_SHOP_IN_VARROCK(NullObjectID.NULL_28986, new WorldPoint(3252, 3404, 0)),
|
||||
CENTRE_OF_CANIFIS(NullObjectID.NULL_28987, new WorldPoint(3491, 3489, 0)),
|
||||
MAUSOLEUM_OFF_THE_MORYTANIA_COAST(NullObjectID.NULL_28988, new WorldPoint(3500, 3575, 0)),
|
||||
EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE(NullObjectID.NULL_28989, new WorldPoint(3110, 3422, 0)),
|
||||
SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE(NullObjectID.NULL_28990, new WorldPoint(2802, 3081, 0)),
|
||||
CASTLE_WARS_BANK(NullObjectID.NULL_28991, new WorldPoint(2444, 3093, 0)),
|
||||
BARBARIAN_OUTPOST_OBSTACLE_COURSE(NullObjectID.NULL_28992, new WorldPoint(2541, 3550, 0)),
|
||||
GNOME_STRONGHOLD_BALANCING_ROPE(NullObjectID.NULL_28993, new WorldPoint(2473, 3418, 2)),
|
||||
OUTSIDE_YANILLE_BANK(NullObjectID.NULL_28994, new WorldPoint(2603, 3091, 0)),
|
||||
OBSERVATORY(NullObjectID.NULL_28995, new WorldPoint(2439, 3166, 0)),
|
||||
OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP(NullObjectID.NULL_28996, new WorldPoint(2533, 3377, 0)),
|
||||
DIGSITE(NullObjectID.NULL_28997, new WorldPoint(3370, 3420, 0)),
|
||||
HICKTONS_ARCHERY_EMPORIUM(NullObjectID.NULL_28998, new WorldPoint(2825, 3441, 0)),
|
||||
SHANTAY_PASS(NullObjectID.NULL_28999, new WorldPoint(3308, 3125, 0)),
|
||||
LUMBRIDGE_SWAMP_CAVES(NullObjectID.NULL_29000, new WorldPoint(3222, 9584, 0), new WorldPoint(3167, 9570, 0)),
|
||||
OUTSIDE_CATHERBY_BANK(NullObjectID.NULL_29001, new WorldPoint(2807, 3437, 0)),
|
||||
OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE(NullObjectID.NULL_29002, new WorldPoint(2731, 3475, 0)),
|
||||
OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY(NullObjectID.NULL_29003, new WorldPoint(2837, 3436, 0)),
|
||||
TZHAAR_WEAPONS_STORE(NullObjectID.NULL_29004, new WorldPoint(2479, 5146, 0)),
|
||||
NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE(NullObjectID.NULL_29005, new WorldPoint(3077, 3503, 0)),
|
||||
WEST_OF_THE_SHAYZIEN_COMBAT_RING(NullObjectID.NULL_29006, new WorldPoint(1534, 3591, 0)),
|
||||
ENTRANCE_OF_THE_ARCEUUS_LIBRARY(NullObjectID.NULL_29007, new WorldPoint(1642, 3809, 0)),
|
||||
OUTSIDE_DRAYNOR_VILLAGE_JAIL(NullObjectID.NULL_29008, new WorldPoint(3130, 3250, 0)),
|
||||
CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS(NullObjectID.NULL_29009, new WorldPoint(3245, 3609, 0)),
|
||||
FISHING_GUILD_BANK(NullObjectID.NULL_29010, new WorldPoint(2593, 3409, 0)),
|
||||
TOP_FLOOR_OF_THE_LIGHTHOUSE(NullObjectID.NULL_29011, new WorldPoint(2512, 3640, 2)),
|
||||
OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM(NullObjectID.NULL_29012, new WorldPoint(3291, 2780, 0)),
|
||||
NOTERAZZOS_SHOP_IN_THE_WILDERNESS(NullObjectID.NULL_29013, new WorldPoint(3027, 3699, 0)),
|
||||
WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION(NullObjectID.NULL_29014, new WorldPoint(2909, 3169, 0)),
|
||||
MOUNTAIN_CAMP_GOAT_ENCLOSURE(NullObjectID.NULL_29015, new WorldPoint(2810, 3677, 0)),
|
||||
GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN(NullObjectID.NULL_29016, new WorldPoint(2849, 3496, 0)),
|
||||
SHILO_VILLAGE_BANK(NullObjectID.NULL_29017, new WorldPoint(2853, 2952, 0)),
|
||||
INSIDE_THE_DIGSITE_EXAM_CENTRE(NullObjectID.NULL_29018, new WorldPoint(3356, 3333, 0)),
|
||||
NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE(NullObjectID.NULL_29019, new WorldPoint(2952, 2932, 0)),
|
||||
VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS(NullObjectID.NULL_29020, new WorldPoint(3368, 3930, 0)),
|
||||
IN_THE_MIDDLE_OF_JIGGIG(NullObjectID.NULL_29021, new WorldPoint(2478, 3048, 0)),
|
||||
AGILITY_PYRAMID(NullObjectID.NULL_29022, new WorldPoint(3357, 2830, 0)),
|
||||
HOSIDIUS_MESS(NullObjectID.NULL_29023, new WorldPoint(1648, 3631, 0)),
|
||||
CHAPEL_IN_WEST_ARDOUGNE(NullObjectID.NULL_29024, new WorldPoint(2527, 3294, 0)),
|
||||
NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES(NullObjectID.NULL_29025, new WorldPoint(2374, 3847, 0)),
|
||||
NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE(NullObjectID.NULL_29026, new WorldPoint(3069, 3862, 0)),
|
||||
ENTRANCE_OF_THE_CAVE_OF_DAMIS(NullObjectID.NULL_29027, new WorldPoint(2629, 5070, 0)),
|
||||
WARRIORS_GUILD_BANK(NullObjectID.NULL_29028, new WorldPoint(2844, 3537, 0)),
|
||||
SOUTHEAST_CORNER_OF_THE_MONASTERY(NullObjectID.NULL_29029, new WorldPoint(3056, 3482, 0)),
|
||||
SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM(NullObjectID.NULL_29030, new WorldPoint(2787, 3277, 1)),
|
||||
OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM(NullObjectID.NULL_29031, new WorldPoint(3423, 3534, 2)),
|
||||
ON_TOP_OF_TROLLHEIM_MOUNTAIN(NullObjectID.NULL_29032, new WorldPoint(2886, 3676, 0)),
|
||||
FOUNTAIN_OF_HEROES(NullObjectID.NULL_29033, new WorldPoint(2916, 9891, 0)),
|
||||
ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL(NullObjectID.NULL_29034, new WorldPoint(1764, 5367, 1), new WorldPoint(1636, 5367, 1)),
|
||||
HALFWAY_DOWN_TROLLWEISS_MOUNTAIN(NullObjectID.NULL_29035, new WorldPoint(2782, 3787, 0)),
|
||||
SHAYZIEN_WAR_TENT(NullObjectID.NULL_29036, new WorldPoint(1550, 3541, 0)),
|
||||
OUTSIDE_THE_LEGENDS_GUILD_DOOR(NullObjectID.NULL_29037, new WorldPoint(2727, 3371, 0)),
|
||||
NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET(NullObjectID.NULL_29038, new WorldPoint(2672, 3302, 0)),
|
||||
OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA(NullObjectID.NULL_29039, new WorldPoint(2571, 3150, 0)),
|
||||
SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE(NullObjectID.NULL_29040, new WorldPoint(3228, 3830, 0)),
|
||||
NEAR_THE_PIER_IN_ZULANDRA(NullObjectID.NULL_29041, new WorldPoint(2203, 3059, 0)),
|
||||
BARROWS_CHEST(NullObjectID.NULL_29042, new WorldPoint(3547, 9690, 0)),
|
||||
WELL_OF_VOYAGE(NullObjectID.NULL_29043, new WorldPoint(2006, 4709, 1)),
|
||||
NORTHERN_WALL_OF_CASTLE_DRAKAN(NullObjectID.NULL_29044, new WorldPoint(3559, 3385, 1)),
|
||||
_7TH_CHAMBER_OF_JALSAVRAH(NullObjectID.NULL_29045, new WorldPoint(1951, 4431, 0)),
|
||||
SOUL_ALTAR(NullObjectID.NULL_29046, new WorldPoint(1810, 3855, 0)),
|
||||
WARRIORS_GUILD_BANK_29047(NullObjectID.NULL_29047, new WorldPoint(2845, 3545, 0)),
|
||||
ENTRANA_CHAPEL(NullObjectID.NULL_29048, new WorldPoint(2851, 3355, 0)),
|
||||
TZHAAR_GEM_STORE(NullObjectID.NULL_29049, new WorldPoint(2466, 5150, 0)),
|
||||
TENT_IN_LORD_IORWERTHS_ENCAMPMENT(NullObjectID.NULL_29050, new WorldPoint(2198, 3257, 0)),
|
||||
OUTSIDE_MUDKNUCKLES_HUT(NullObjectID.NULL_29051, new WorldPoint(2959, 3502, 0)),
|
||||
CENTRE_OF_THE_CATACOMBS_OF_KOUREND(NullObjectID.NULL_29052, new WorldPoint(1661, 10045, 0)),
|
||||
KING_BLACK_DRAGONS_LAIR(NullObjectID.NULL_29053, new WorldPoint(2286, 4680, 0)),
|
||||
OUTSIDE_KRIL_TSUTSAROTHS_ROOM(NullObjectID.NULL_29054, new WorldPoint(2931, 5337, 2)),
|
||||
BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS(NullObjectID.NULL_29055, new WorldPoint(3232, 3494, 0)),
|
||||
OUTSIDE_THE_WILDERNESS_AXE_HUT(NullObjectID.NULL_29056, new WorldPoint(3186, 3958, 0)),
|
||||
TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER(NullObjectID.NULL_29057, new WorldPoint(2930, 4718, 2)),
|
||||
DEATH_ALTAR(NullObjectID.NULL_29058, new WorldPoint(2210, 4842, 0)),
|
||||
BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE(NullObjectID.NULL_29059, new WorldPoint(3095, 3254, 0)),
|
||||
NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY(NullObjectID.NULL_29060, new WorldPoint(3022, 4517, 0)),
|
||||
NORTH_OF_MOUNT_KARUULM(NullObjectID.NULL_34647, new WorldPoint(1308, 3840, 0)),
|
||||
GYPSY_TENT_ENTRANCE(NullObjectID.NULL_34736, new WorldPoint(3206, 3422, 0)),
|
||||
FINE_CLOTHES_ENTRANCE(NullObjectID.NULL_34737, new WorldPoint(3209, 3416, 0)),
|
||||
BOB_AXES_ENTRANCE(NullObjectID.NULL_34738, new WorldPoint(3233, 3200, 0));
|
||||
|
||||
private final int objectId;
|
||||
private final WorldPoint[] worldPoints;
|
||||
|
||||
STASHUnit(int objectId, WorldPoint... worldPoints)
|
||||
{
|
||||
this.objectId = objectId;
|
||||
this.worldPoints = worldPoints;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,11 @@ import java.time.Instant;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import static net.runelite.api.AnimationID.COOKING_WINE;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
@@ -50,7 +54,8 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
@PluginDependency(XpTrackerPlugin.class)
|
||||
public class CookingPlugin extends Plugin
|
||||
{
|
||||
private static final String WINE_MESSAGE = "You squeeze the grapes into the jug";
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private CookingConfig config;
|
||||
@@ -124,6 +129,27 @@ public class CookingPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAnimationChanged(AnimationChanged animationChanged)
|
||||
{
|
||||
Player localPlayer = client.getLocalPlayer();
|
||||
|
||||
if (localPlayer != animationChanged.getActor())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (localPlayer.getAnimation() == COOKING_WINE && config.fermentTimer())
|
||||
{
|
||||
if (fermentTimerSession == null)
|
||||
{
|
||||
fermentTimerSession = new FermentTimerSession();
|
||||
}
|
||||
|
||||
fermentTimerSession.updateLastWineMakingAction();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
@@ -134,22 +160,11 @@ public class CookingPlugin extends Plugin
|
||||
|
||||
final String message = event.getMessage();
|
||||
|
||||
if (message.startsWith(WINE_MESSAGE) && config.fermentTimer())
|
||||
{
|
||||
if (fermentTimerSession == null)
|
||||
{
|
||||
fermentTimerSession = new FermentTimerSession();
|
||||
}
|
||||
|
||||
fermentTimerSession.updateLastWineMakingAction();
|
||||
}
|
||||
|
||||
if (message.startsWith("You successfully cook")
|
||||
|| message.startsWith("You successfully bake")
|
||||
|| message.startsWith("You manage to cook")
|
||||
|| message.startsWith("You roast a")
|
||||
|| message.startsWith("You cook")
|
||||
|| message.startsWith(WINE_MESSAGE))
|
||||
|| message.startsWith("You cook"))
|
||||
{
|
||||
if (cookingSession == null)
|
||||
{
|
||||
|
||||
@@ -1008,7 +1008,10 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
{
|
||||
swap(client, "pay-toll(10gp)", option, target, true);
|
||||
}
|
||||
|
||||
else if (config.swapHardWoodGrove() && option.equals("open") && target.equals("hardwood grove doors"))
|
||||
{
|
||||
swap(client, "quick-pay(100)", option, target, true);
|
||||
}
|
||||
else if (config.swapTravel() && option.equals("inspect") && target.equals("trapdoor"))
|
||||
{
|
||||
swap(client, "travel", option, target, true);
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Anthony Chen <https://github.com/achencoms>
|
||||
* 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.musiclist;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.SoundEffectID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.VarClientIntChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetPositionMode;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Music List",
|
||||
description = "Adds search and filter for the music list"
|
||||
)
|
||||
public class MusicListPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
private ChatboxTextInput searchInput;
|
||||
|
||||
private Widget musicSearchButton;
|
||||
private Widget musicFilterButton;
|
||||
|
||||
private Collection<Widget> tracks;
|
||||
|
||||
private MusicState currentMusicFilter;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
clientThread.invoke(this::addMusicButtons);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
Widget header = client.getWidget(WidgetInfo.MUSIC_WINDOW);
|
||||
if (header != null)
|
||||
{
|
||||
header.deleteAllChildren();
|
||||
}
|
||||
|
||||
tracks = null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
currentMusicFilter = MusicState.ALL;
|
||||
tracks = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded widgetLoaded)
|
||||
{
|
||||
if (widgetLoaded.getGroupId() == WidgetID.MUSIC_GROUP_ID)
|
||||
{
|
||||
addMusicButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private void addMusicButtons()
|
||||
{
|
||||
Widget header = client.getWidget(WidgetInfo.MUSIC_WINDOW);
|
||||
|
||||
if (header == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Creation of the search and toggle status buttons
|
||||
musicSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
musicSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||
musicSearchButton.setOriginalWidth(18);
|
||||
musicSearchButton.setOriginalHeight(17);
|
||||
musicSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
musicSearchButton.setOriginalX(5);
|
||||
musicSearchButton.setOriginalY(32);
|
||||
musicSearchButton.setHasListener(true);
|
||||
musicSearchButton.setAction(1, "Open");
|
||||
musicSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
musicSearchButton.setName("Search");
|
||||
musicSearchButton.revalidate();
|
||||
|
||||
musicFilterButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
musicFilterButton.setSpriteId(SpriteID.MINIMAP_ORB_HITPOINTS);
|
||||
musicFilterButton.setOriginalWidth(15);
|
||||
musicFilterButton.setOriginalHeight(15);
|
||||
musicFilterButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
musicFilterButton.setOriginalX(25);
|
||||
musicFilterButton.setOriginalY(34);
|
||||
musicFilterButton.setHasListener(true);
|
||||
musicFilterButton.setAction(1, "Toggle");
|
||||
musicFilterButton.setOnOpListener((JavaScriptCallback) e -> toggleStatus());
|
||||
musicFilterButton.setName("All");
|
||||
musicFilterButton.revalidate();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
|
||||
{
|
||||
if (isChatboxOpen() && !isOnMusicTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOnMusicTab()
|
||||
{
|
||||
return client.getVar(VarClientInt.INVENTORY_TAB) == 13;
|
||||
}
|
||||
|
||||
private boolean isChatboxOpen()
|
||||
{
|
||||
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
|
||||
}
|
||||
|
||||
private String getChatboxInput()
|
||||
{
|
||||
return isChatboxOpen() ? searchInput.getValue() : "";
|
||||
}
|
||||
|
||||
private void toggleStatus()
|
||||
{
|
||||
MusicState[] states = MusicState.values();
|
||||
currentMusicFilter = states[(currentMusicFilter.ordinal() + 1) % states.length];
|
||||
musicFilterButton.setSpriteId(currentMusicFilter.getSpriteID());
|
||||
musicFilterButton.setName(currentMusicFilter.getName());
|
||||
updateFilter(getChatboxInput());
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void openSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
musicSearchButton.setAction(1, "Close");
|
||||
musicSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
|
||||
searchInput = chatboxPanelManager.openTextInput("Search music list")
|
||||
.onChanged(s -> clientThread.invokeLater(() -> updateFilter(s.trim())))
|
||||
.onClose(() ->
|
||||
{
|
||||
clientThread.invokeLater(() -> updateFilter(""));
|
||||
musicSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
musicSearchButton.setAction(1, "Open");
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private void closeSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
chatboxPanelManager.close();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void updateFilter(String input)
|
||||
{
|
||||
final Widget container = client.getWidget(WidgetInfo.MUSIC_WINDOW);
|
||||
final Widget musicList = client.getWidget(WidgetInfo.MUSIC_TRACK_LIST);
|
||||
|
||||
if (container == null || musicList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String filter = input.toLowerCase();
|
||||
updateList(musicList, filter);
|
||||
}
|
||||
|
||||
private void updateList(Widget musicList, String filter)
|
||||
{
|
||||
if (tracks == null)
|
||||
{
|
||||
tracks = Arrays.stream(musicList.getDynamicChildren())
|
||||
.sorted(Comparator.comparing(Widget::getRelativeY))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
tracks.forEach(w -> w.setHidden(true));
|
||||
|
||||
Collection<Widget> relevantTracks = tracks.stream()
|
||||
.filter(w -> w.getText().toLowerCase().contains(filter))
|
||||
.filter(w -> currentMusicFilter == MusicState.ALL || w.getTextColor() == currentMusicFilter.getColor())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Original music track list has a little offset
|
||||
int y = 3;
|
||||
|
||||
for (Widget track : relevantTracks)
|
||||
{
|
||||
track.setHidden(false);
|
||||
track.setOriginalY(y);
|
||||
track.revalidate();
|
||||
|
||||
y += track.getHeight();
|
||||
}
|
||||
|
||||
y += 3;
|
||||
|
||||
int newHeight = 0;
|
||||
|
||||
if (musicList.getScrollHeight() > 0)
|
||||
{
|
||||
newHeight = (musicList.getScrollY() * y) / musicList.getScrollHeight();
|
||||
}
|
||||
|
||||
musicList.setScrollHeight(y);
|
||||
musicList.revalidateScroll();
|
||||
|
||||
client.runScript(
|
||||
ScriptID.UPDATE_SCROLLBAR,
|
||||
WidgetInfo.MUSIC_TRACK_SCROLLBAR.getId(),
|
||||
WidgetInfo.MUSIC_TRACK_LIST.getId(),
|
||||
newHeight
|
||||
);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum MusicState
|
||||
{
|
||||
NOT_FOUND(0xff0000, "Locked", SpriteID.MINIMAP_ORB_HITPOINTS),
|
||||
FOUND(0xdc10d, "Unlocked", SpriteID.MINIMAP_ORB_HITPOINTS_POISON),
|
||||
ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER);
|
||||
|
||||
private final int color;
|
||||
private final String name;
|
||||
private final int spriteID;
|
||||
}
|
||||
}
|
||||
@@ -1,398 +1,419 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Spudjb <https://github.com/spudjb>
|
||||
* 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.questlist;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.SoundEffectID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.VarClientIntChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetPositionMode;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Quest List",
|
||||
description = "Adds searching and filtering to the quest list"
|
||||
)
|
||||
public class QuestListPlugin extends Plugin
|
||||
{
|
||||
private static final int ENTRY_PADDING = 8;
|
||||
private static final List<String> QUEST_HEADERS = ImmutableList.of("Free Quests", "Members' Quests", "Miniquests");
|
||||
|
||||
private static final String MENU_OPEN = "Open";
|
||||
private static final String MENU_CLOSE = "Close";
|
||||
|
||||
private static final String MENU_TOGGLE = "Toggle";
|
||||
|
||||
private static final String MENU_SEARCH = "Search";
|
||||
private static final String MENU_SHOW = "Show";
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
private ChatboxTextInput searchInput;
|
||||
private Widget questSearchButton;
|
||||
private Widget questHideButton;
|
||||
|
||||
private EnumMap<QuestContainer, Collection<QuestWidget>> questSet;
|
||||
|
||||
private QuestState currentFilterState;
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged e)
|
||||
{
|
||||
if (e.getGameState() == GameState.LOGGING_IN)
|
||||
{
|
||||
currentFilterState = QuestState.ALL;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||
{
|
||||
if (!event.getEventName().equals("questProgressUpdated"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||
if (header != null)
|
||||
{
|
||||
questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||
questSearchButton.setOriginalWidth(18);
|
||||
questSearchButton.setOriginalHeight(17);
|
||||
questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
questSearchButton.setOriginalX(5);
|
||||
questSearchButton.setOriginalY(0);
|
||||
questSearchButton.setHasListener(true);
|
||||
questSearchButton.setAction(1, MENU_OPEN);
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
questSearchButton.setName(MENU_SEARCH);
|
||||
questSearchButton.revalidate();
|
||||
|
||||
questHideButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
redrawHideButton();
|
||||
|
||||
questHideButton.setOriginalWidth(13);
|
||||
questHideButton.setOriginalHeight(13);
|
||||
questHideButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
questHideButton.setOriginalX(24);
|
||||
questHideButton.setOriginalY(2);
|
||||
questHideButton.setHasListener(true);
|
||||
questHideButton.setOnOpListener((JavaScriptCallback) e -> toggleHidden());
|
||||
questHideButton.setAction(1, MENU_TOGGLE);
|
||||
questHideButton.revalidate();
|
||||
|
||||
questSet = new EnumMap<>(QuestContainer.class);
|
||||
|
||||
updateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged varbitChanged)
|
||||
{
|
||||
if (isChatboxOpen() && !isOnQuestTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
|
||||
{
|
||||
if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex())
|
||||
{
|
||||
if (isChatboxOpen() && !isOnQuestTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleHidden()
|
||||
{
|
||||
QuestState[] questStates = QuestState.values();
|
||||
int nextState = (currentFilterState.ordinal() + 1) % questStates.length;
|
||||
currentFilterState = questStates[nextState];
|
||||
|
||||
redrawHideButton();
|
||||
|
||||
updateFilter();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void redrawHideButton()
|
||||
{
|
||||
questHideButton.setSpriteId(currentFilterState.getSpriteId());
|
||||
questHideButton.setName(MENU_SHOW + " " + currentFilterState.getName());
|
||||
}
|
||||
|
||||
private boolean isOnQuestTab()
|
||||
{
|
||||
return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2;
|
||||
}
|
||||
|
||||
private boolean isChatboxOpen()
|
||||
{
|
||||
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
|
||||
}
|
||||
|
||||
private void closeSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
chatboxPanelManager.close();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void openSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
questSearchButton.setAction(1, MENU_CLOSE);
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
|
||||
searchInput = chatboxPanelManager.openTextInput("Search quest list")
|
||||
.onChanged(s -> clientThread.invokeLater(() -> updateFilter(s)))
|
||||
.onClose(() ->
|
||||
{
|
||||
clientThread.invokeLater(() -> updateFilter(""));
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
questSearchButton.setAction(1, MENU_OPEN);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private void updateFilter()
|
||||
{
|
||||
String filter = "";
|
||||
if (isChatboxOpen())
|
||||
{
|
||||
filter = searchInput.getValue();
|
||||
}
|
||||
|
||||
updateFilter(filter);
|
||||
}
|
||||
|
||||
private void updateFilter(String filter)
|
||||
{
|
||||
filter = filter.toLowerCase();
|
||||
final Widget container = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER);
|
||||
|
||||
final Widget freeList = client.getWidget(QuestContainer.FREE_QUESTS.widgetInfo);
|
||||
final Widget memberList = client.getWidget(QuestContainer.MEMBER_QUESTS.widgetInfo);
|
||||
final Widget miniList = client.getWidget(QuestContainer.MINI_QUESTS.widgetInfo);
|
||||
|
||||
if (container == null || freeList == null || memberList == null || miniList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
updateList(QuestContainer.FREE_QUESTS, filter);
|
||||
updateList(QuestContainer.MEMBER_QUESTS, filter);
|
||||
updateList(QuestContainer.MINI_QUESTS, filter);
|
||||
|
||||
memberList.setOriginalY(freeList.getOriginalY() + freeList.getOriginalHeight() + ENTRY_PADDING);
|
||||
miniList.setOriginalY(memberList.getOriginalY() + memberList.getOriginalHeight() + ENTRY_PADDING);
|
||||
|
||||
// originalHeight is changed within updateList so revalidate all lists
|
||||
freeList.revalidate();
|
||||
memberList.revalidate();
|
||||
miniList.revalidate();
|
||||
|
||||
int y = miniList.getRelativeY() + miniList.getHeight() + 10;
|
||||
|
||||
int newHeight;
|
||||
if (container.getScrollHeight() > 0)
|
||||
{
|
||||
newHeight = (container.getScrollY() * y) / container.getScrollHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
newHeight = 0;
|
||||
}
|
||||
|
||||
container.setScrollHeight(y);
|
||||
container.revalidateScroll();
|
||||
|
||||
clientThread.invokeLater(() ->
|
||||
client.runScript(
|
||||
ScriptID.UPDATE_SCROLLBAR,
|
||||
WidgetInfo.QUESTLIST_SCROLLBAR.getId(),
|
||||
WidgetInfo.QUESTLIST_CONTAINER.getId(),
|
||||
newHeight
|
||||
));
|
||||
}
|
||||
|
||||
private void updateList(QuestContainer questContainer, String filter)
|
||||
{
|
||||
Widget list = client.getWidget(questContainer.widgetInfo);
|
||||
if (list == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<QuestWidget> quests = questSet.get(questContainer);
|
||||
|
||||
if (quests != null)
|
||||
{
|
||||
// Check to make sure the list hasn't been rebuild since we were last her
|
||||
// Do this by making sure the list's dynamic children are the same as when we last saw them
|
||||
if (quests.stream().noneMatch(w ->
|
||||
{
|
||||
Widget codeWidget = w.getQuest();
|
||||
if (codeWidget == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return list.getChild(codeWidget.getIndex()) == codeWidget;
|
||||
}))
|
||||
{
|
||||
quests = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (quests == null)
|
||||
{
|
||||
// Find all of the widgets that we care about, sorting by their Y value
|
||||
quests = Arrays.stream(list.getDynamicChildren())
|
||||
.sorted(Comparator.comparing(Widget::getRelativeY))
|
||||
.filter(w -> !QUEST_HEADERS.contains(w.getText()))
|
||||
.map(w -> new QuestWidget(w, Text.removeTags(w.getText()).toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
questSet.put(questContainer, quests);
|
||||
}
|
||||
|
||||
// offset because of header
|
||||
int y = 20;
|
||||
for (QuestWidget questInfo : quests)
|
||||
{
|
||||
Widget quest = questInfo.getQuest();
|
||||
QuestState questState = QuestState.getByColor(quest.getTextColor());
|
||||
|
||||
boolean hidden;
|
||||
if (!filter.isEmpty())
|
||||
{
|
||||
// If searching, show result regardless of filtered state
|
||||
hidden = !questInfo.getTitle().contains(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise hide if it doesn't match the filter state
|
||||
hidden = currentFilterState != QuestState.ALL && questState != currentFilterState;
|
||||
}
|
||||
|
||||
quest.setHidden(hidden);
|
||||
quest.setOriginalY(y);
|
||||
quest.revalidate();
|
||||
|
||||
if (!hidden)
|
||||
{
|
||||
y += quest.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
list.setOriginalHeight(y);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum QuestContainer
|
||||
{
|
||||
FREE_QUESTS(WidgetInfo.QUESTLIST_FREE_CONTAINER),
|
||||
MEMBER_QUESTS(WidgetInfo.QUESTLIST_MEMBERS_CONTAINER),
|
||||
MINI_QUESTS(WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER);
|
||||
|
||||
private final WidgetInfo widgetInfo;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum QuestState
|
||||
{
|
||||
NOT_STARTED(0xff0000, "Not started", SpriteID.MINIMAP_ORB_HITPOINTS),
|
||||
IN_PROGRESS(0xffff00, "In progress", SpriteID.MINIMAP_ORB_HITPOINTS_DISEASE),
|
||||
COMPLETE(0xdc10d, "Completed", SpriteID.MINIMAP_ORB_HITPOINTS_POISON),
|
||||
ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER);
|
||||
|
||||
private final int color;
|
||||
private final String name;
|
||||
private final int spriteId;
|
||||
|
||||
static QuestState getByColor(int color)
|
||||
{
|
||||
for (QuestState value : values())
|
||||
{
|
||||
if (value.getColor() == color)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
private static class QuestWidget
|
||||
{
|
||||
private Widget quest;
|
||||
private String title;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2019 Spudjb <https://github.com/spudjb>
|
||||
* 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.questlist;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.SoundEffectID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.VarClientIntChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetPositionMode;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Quest List",
|
||||
description = "Adds searching and filtering to the quest list"
|
||||
)
|
||||
public class QuestListPlugin extends Plugin
|
||||
{
|
||||
private static final int ENTRY_PADDING = 8;
|
||||
private static final List<String> QUEST_HEADERS = ImmutableList.of("Free Quests", "Members' Quests", "Miniquests");
|
||||
|
||||
private static final String MENU_OPEN = "Open";
|
||||
private static final String MENU_CLOSE = "Close";
|
||||
|
||||
private static final String MENU_TOGGLE = "Toggle";
|
||||
|
||||
private static final String MENU_SEARCH = "Search";
|
||||
private static final String MENU_SHOW = "Show";
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
private ChatboxTextInput searchInput;
|
||||
private Widget questSearchButton;
|
||||
private Widget questHideButton;
|
||||
|
||||
private EnumMap<QuestContainer, Collection<QuestWidget>> questSet;
|
||||
|
||||
private QuestState currentFilterState;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
clientThread.invoke(this::addQuestButtons);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||
if (header != null)
|
||||
{
|
||||
header.deleteAllChildren();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged e)
|
||||
{
|
||||
if (e.getGameState() == GameState.LOGGING_IN)
|
||||
{
|
||||
currentFilterState = QuestState.ALL;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||
{
|
||||
if (!event.getEventName().equals("questProgressUpdated"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
addQuestButtons();
|
||||
}
|
||||
|
||||
private void addQuestButtons()
|
||||
{
|
||||
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||
if (header != null)
|
||||
{
|
||||
questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||
questSearchButton.setOriginalWidth(18);
|
||||
questSearchButton.setOriginalHeight(17);
|
||||
questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
questSearchButton.setOriginalX(5);
|
||||
questSearchButton.setOriginalY(0);
|
||||
questSearchButton.setHasListener(true);
|
||||
questSearchButton.setAction(1, MENU_OPEN);
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
questSearchButton.setName(MENU_SEARCH);
|
||||
questSearchButton.revalidate();
|
||||
|
||||
questHideButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
redrawHideButton();
|
||||
|
||||
questHideButton.setOriginalWidth(13);
|
||||
questHideButton.setOriginalHeight(13);
|
||||
questHideButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
questHideButton.setOriginalX(24);
|
||||
questHideButton.setOriginalY(2);
|
||||
questHideButton.setHasListener(true);
|
||||
questHideButton.setOnOpListener((JavaScriptCallback) e -> toggleHidden());
|
||||
questHideButton.setAction(1, MENU_TOGGLE);
|
||||
questHideButton.revalidate();
|
||||
|
||||
questSet = new EnumMap<>(QuestContainer.class);
|
||||
|
||||
updateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged varbitChanged)
|
||||
{
|
||||
if (isChatboxOpen() && !isOnQuestTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
|
||||
{
|
||||
if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex())
|
||||
{
|
||||
if (isChatboxOpen() && !isOnQuestTab())
|
||||
{
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleHidden()
|
||||
{
|
||||
QuestState[] questStates = QuestState.values();
|
||||
int nextState = (currentFilterState.ordinal() + 1) % questStates.length;
|
||||
currentFilterState = questStates[nextState];
|
||||
|
||||
redrawHideButton();
|
||||
|
||||
updateFilter();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void redrawHideButton()
|
||||
{
|
||||
questHideButton.setSpriteId(currentFilterState.getSpriteId());
|
||||
questHideButton.setName(MENU_SHOW + " " + currentFilterState.getName());
|
||||
}
|
||||
|
||||
private boolean isOnQuestTab()
|
||||
{
|
||||
return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2;
|
||||
}
|
||||
|
||||
private boolean isChatboxOpen()
|
||||
{
|
||||
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
|
||||
}
|
||||
|
||||
private void closeSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
chatboxPanelManager.close();
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
}
|
||||
|
||||
private void openSearch()
|
||||
{
|
||||
updateFilter("");
|
||||
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||
questSearchButton.setAction(1, MENU_CLOSE);
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
|
||||
searchInput = chatboxPanelManager.openTextInput("Search quest list")
|
||||
.onChanged(s -> clientThread.invokeLater(() -> updateFilter(s)))
|
||||
.onClose(() ->
|
||||
{
|
||||
clientThread.invokeLater(() -> updateFilter(""));
|
||||
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
|
||||
questSearchButton.setAction(1, MENU_OPEN);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private void updateFilter()
|
||||
{
|
||||
String filter = "";
|
||||
if (isChatboxOpen())
|
||||
{
|
||||
filter = searchInput.getValue();
|
||||
}
|
||||
|
||||
updateFilter(filter);
|
||||
}
|
||||
|
||||
private void updateFilter(String filter)
|
||||
{
|
||||
filter = filter.toLowerCase();
|
||||
final Widget container = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER);
|
||||
|
||||
final Widget freeList = client.getWidget(QuestContainer.FREE_QUESTS.widgetInfo);
|
||||
final Widget memberList = client.getWidget(QuestContainer.MEMBER_QUESTS.widgetInfo);
|
||||
final Widget miniList = client.getWidget(QuestContainer.MINI_QUESTS.widgetInfo);
|
||||
|
||||
if (container == null || freeList == null || memberList == null || miniList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
updateList(QuestContainer.FREE_QUESTS, filter);
|
||||
updateList(QuestContainer.MEMBER_QUESTS, filter);
|
||||
updateList(QuestContainer.MINI_QUESTS, filter);
|
||||
|
||||
memberList.setOriginalY(freeList.getOriginalY() + freeList.getOriginalHeight() + ENTRY_PADDING);
|
||||
miniList.setOriginalY(memberList.getOriginalY() + memberList.getOriginalHeight() + ENTRY_PADDING);
|
||||
|
||||
// originalHeight is changed within updateList so revalidate all lists
|
||||
freeList.revalidate();
|
||||
memberList.revalidate();
|
||||
miniList.revalidate();
|
||||
|
||||
int y = miniList.getRelativeY() + miniList.getHeight() + 10;
|
||||
|
||||
int newHeight;
|
||||
if (container.getScrollHeight() > 0)
|
||||
{
|
||||
newHeight = (container.getScrollY() * y) / container.getScrollHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
newHeight = 0;
|
||||
}
|
||||
|
||||
container.setScrollHeight(y);
|
||||
container.revalidateScroll();
|
||||
|
||||
clientThread.invokeLater(() ->
|
||||
client.runScript(
|
||||
ScriptID.UPDATE_SCROLLBAR,
|
||||
WidgetInfo.QUESTLIST_SCROLLBAR.getId(),
|
||||
WidgetInfo.QUESTLIST_CONTAINER.getId(),
|
||||
newHeight
|
||||
));
|
||||
}
|
||||
|
||||
private void updateList(QuestContainer questContainer, String filter)
|
||||
{
|
||||
Widget list = client.getWidget(questContainer.widgetInfo);
|
||||
if (list == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<QuestWidget> quests = questSet.get(questContainer);
|
||||
|
||||
if (quests != null)
|
||||
{
|
||||
// Check to make sure the list hasn't been rebuild since we were last her
|
||||
// Do this by making sure the list's dynamic children are the same as when we last saw them
|
||||
if (quests.stream().noneMatch(w ->
|
||||
{
|
||||
Widget codeWidget = w.getQuest();
|
||||
if (codeWidget == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return list.getChild(codeWidget.getIndex()) == codeWidget;
|
||||
}))
|
||||
{
|
||||
quests = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (quests == null)
|
||||
{
|
||||
// Find all of the widgets that we care about, sorting by their Y value
|
||||
quests = Arrays.stream(list.getDynamicChildren())
|
||||
.sorted(Comparator.comparing(Widget::getRelativeY))
|
||||
.filter(w -> !QUEST_HEADERS.contains(w.getText()))
|
||||
.map(w -> new QuestWidget(w, Text.removeTags(w.getText()).toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
questSet.put(questContainer, quests);
|
||||
}
|
||||
|
||||
// offset because of header
|
||||
int y = 20;
|
||||
for (QuestWidget questInfo : quests)
|
||||
{
|
||||
Widget quest = questInfo.getQuest();
|
||||
QuestState questState = QuestState.getByColor(quest.getTextColor());
|
||||
|
||||
boolean hidden;
|
||||
if (!filter.isEmpty())
|
||||
{
|
||||
// If searching, show result regardless of filtered state
|
||||
hidden = !questInfo.getTitle().contains(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise hide if it doesn't match the filter state
|
||||
hidden = currentFilterState != QuestState.ALL && questState != currentFilterState;
|
||||
}
|
||||
|
||||
quest.setHidden(hidden);
|
||||
quest.setOriginalY(y);
|
||||
quest.revalidate();
|
||||
|
||||
if (!hidden)
|
||||
{
|
||||
y += quest.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
list.setOriginalHeight(y);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum QuestContainer
|
||||
{
|
||||
FREE_QUESTS(WidgetInfo.QUESTLIST_FREE_CONTAINER),
|
||||
MEMBER_QUESTS(WidgetInfo.QUESTLIST_MEMBERS_CONTAINER),
|
||||
MINI_QUESTS(WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER);
|
||||
|
||||
private final WidgetInfo widgetInfo;
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private enum QuestState
|
||||
{
|
||||
NOT_STARTED(0xff0000, "Not started", SpriteID.MINIMAP_ORB_HITPOINTS),
|
||||
IN_PROGRESS(0xffff00, "In progress", SpriteID.MINIMAP_ORB_HITPOINTS_DISEASE),
|
||||
COMPLETE(0xdc10d, "Completed", SpriteID.MINIMAP_ORB_HITPOINTS_POISON),
|
||||
ALL(0, "All", SpriteID.MINIMAP_ORB_PRAYER);
|
||||
|
||||
private final int color;
|
||||
private final String name;
|
||||
private final int spriteId;
|
||||
|
||||
static QuestState getByColor(int color)
|
||||
{
|
||||
for (QuestState value : values())
|
||||
{
|
||||
if (value.getColor() == color)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
private static class QuestWidget
|
||||
{
|
||||
private Widget quest;
|
||||
private String title;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCComposition;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.VarPlayer;
|
||||
@@ -51,6 +52,7 @@ import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.ws.PartyService;
|
||||
import net.runelite.client.ws.WSClient;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Special Attack Counter",
|
||||
@@ -181,7 +183,16 @@ public class SpecialCounterPlugin extends Plugin
|
||||
|
||||
if (interacting instanceof NPC)
|
||||
{
|
||||
int interactingId = ((NPC) interacting).getId();
|
||||
NPC npc = (NPC) interacting;
|
||||
NPCComposition composition = npc.getComposition();
|
||||
int interactingId = npc.getId();
|
||||
|
||||
if (!ArrayUtils.contains(composition.getActions(), "Attack"))
|
||||
{
|
||||
// Skip over non attackable npcs so that eg. talking to bankers doesn't reset
|
||||
// the counters.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!interactedNpcIds.contains(interactingId))
|
||||
{
|
||||
|
||||
@@ -1,309 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.timetracking.farming;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.time.Instant;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.vars.Autoweed;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.timetracking.SummaryState;
|
||||
import net.runelite.client.plugins.timetracking.Tab;
|
||||
import net.runelite.client.plugins.timetracking.TimeTrackingConfig;
|
||||
|
||||
@Singleton
|
||||
public class FarmingTracker
|
||||
{
|
||||
private final Client client;
|
||||
private final ItemManager itemManager;
|
||||
private final ConfigManager configManager;
|
||||
private final TimeTrackingConfig config;
|
||||
private final FarmingWorld farmingWorld;
|
||||
|
||||
private final Map<Tab, SummaryState> summaries = new EnumMap<>(Tab.class);
|
||||
|
||||
/**
|
||||
* The time at which all patches of a particular type will be ready to be harvested,
|
||||
* or {@code -1} if we have no data about any patch of the given type.
|
||||
*/
|
||||
private final Map<Tab, Long> completionTimes = new EnumMap<>(Tab.class);
|
||||
|
||||
@Inject
|
||||
private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager,
|
||||
TimeTrackingConfig config, FarmingWorld farmingWorld)
|
||||
{
|
||||
this.client = client;
|
||||
this.itemManager = itemManager;
|
||||
this.configManager = configManager;
|
||||
this.config = config;
|
||||
this.farmingWorld = farmingWorld;
|
||||
}
|
||||
|
||||
|
||||
public FarmingTabPanel createTabPanel(Tab tab)
|
||||
{
|
||||
return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates tracker data for the current region. Returns true if any data was changed.
|
||||
*/
|
||||
public boolean updateData(WorldPoint location)
|
||||
{
|
||||
boolean changed = false;
|
||||
|
||||
{
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername();
|
||||
String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED));
|
||||
if (!autoweed.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED)))
|
||||
{
|
||||
configManager.setConfiguration(group, TimeTrackingConfig.AUTOWEED, autoweed);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
FarmingRegion region = farmingWorld.getRegions().get(location.getRegionID());
|
||||
if (region != null && region.isInBounds(location))
|
||||
{
|
||||
// Write config with new varbits
|
||||
// timetracking.<login-username>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + region.getRegionID();
|
||||
long unixNow = Instant.now().getEpochSecond();
|
||||
for (FarmingPatch patch : region.getPatches())
|
||||
{
|
||||
// Write the config value if it doesn't match what is current, or it is more than 5 minutes old
|
||||
Varbits varbit = patch.getVarbit();
|
||||
String key = Integer.toString(varbit.getId());
|
||||
String strVarbit = Integer.toString(client.getVar(varbit));
|
||||
String storedValue = configManager.getConfiguration(group, key);
|
||||
|
||||
if (storedValue != null)
|
||||
{
|
||||
String[] parts = storedValue.split(":");
|
||||
if (parts.length == 2 && parts[0].equals(strVarbit))
|
||||
{
|
||||
long unixTime = 0;
|
||||
try
|
||||
{
|
||||
unixTime = Long.parseLong(parts[1]);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String value = strVarbit + ":" + unixNow;
|
||||
configManager.setConfiguration(group, key, value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
updateCompletionTime();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PatchPrediction predictPatch(FarmingPatch patch)
|
||||
{
|
||||
long unixNow = Instant.now().getEpochSecond();
|
||||
|
||||
boolean autoweed;
|
||||
{
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername();
|
||||
autoweed = Integer.toString(Autoweed.ON.ordinal())
|
||||
.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED));
|
||||
}
|
||||
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + patch.getRegion().getRegionID();
|
||||
String key = Integer.toString(patch.getVarbit().getId());
|
||||
String storedValue = configManager.getConfiguration(group, key);
|
||||
|
||||
if (storedValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
long unixTime = 0;
|
||||
int value = 0;
|
||||
{
|
||||
String[] parts = storedValue.split(":");
|
||||
if (parts.length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Integer.parseInt(parts[0]);
|
||||
unixTime = Long.parseLong(parts[1]);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unixTime <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
PatchState state = patch.getImplementation().forVarbitValue(value);
|
||||
|
||||
int stage = state.getStage();
|
||||
int stages = state.getStages();
|
||||
int tickrate = state.getTickRate() * 60;
|
||||
|
||||
if (autoweed && state.getProduce() == Produce.WEEDS)
|
||||
{
|
||||
stage = 0;
|
||||
stages = 1;
|
||||
tickrate = 0;
|
||||
}
|
||||
|
||||
long doneEstimate = 0;
|
||||
if (tickrate > 0)
|
||||
{
|
||||
long tickNow = (unixNow + (5 * 60)) / tickrate;
|
||||
long tickTime = (unixTime + (5 * 60)) / tickrate;
|
||||
int delta = (int) (tickNow - tickTime);
|
||||
|
||||
doneEstimate = ((stages - 1 - stage) + tickTime) * tickrate + (5 * 60);
|
||||
|
||||
stage += delta;
|
||||
if (stage >= stages)
|
||||
{
|
||||
stage = stages - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return new PatchPrediction(
|
||||
state.getProduce(),
|
||||
state.getCropState(),
|
||||
doneEstimate,
|
||||
stage,
|
||||
stages
|
||||
);
|
||||
}
|
||||
|
||||
public void loadCompletionTimes()
|
||||
{
|
||||
summaries.clear();
|
||||
completionTimes.clear();
|
||||
updateCompletionTime();
|
||||
}
|
||||
|
||||
public SummaryState getSummary(Tab patchType)
|
||||
{
|
||||
SummaryState summary = summaries.get(patchType);
|
||||
return summary == null ? SummaryState.UNKNOWN : summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall completion time for the given patch type.
|
||||
*
|
||||
* @see #completionTimes
|
||||
*/
|
||||
public long getCompletionTime(Tab patchType)
|
||||
{
|
||||
Long completionTime = completionTimes.get(patchType);
|
||||
return completionTime == null ? -1 : completionTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the overall completion time for the given patch type.
|
||||
*
|
||||
* @see #completionTimes
|
||||
*/
|
||||
private void updateCompletionTime()
|
||||
{
|
||||
for (Map.Entry<Tab, Set<FarmingPatch>> tab : farmingWorld.getTabs().entrySet())
|
||||
{
|
||||
long maxCompletionTime = 0;
|
||||
boolean allUnknown = true;
|
||||
boolean allEmpty = true;
|
||||
|
||||
for (FarmingPatch patch : tab.getValue())
|
||||
{
|
||||
PatchPrediction prediction = predictPatch(patch);
|
||||
if (prediction == null || prediction.getProduce().getItemID() < 0)
|
||||
{
|
||||
continue; // unknown state
|
||||
}
|
||||
|
||||
allUnknown = false;
|
||||
|
||||
if (prediction.getProduce() != Produce.WEEDS && prediction.getProduce() != Produce.SCARECROW)
|
||||
{
|
||||
allEmpty = false;
|
||||
|
||||
// update max duration if this patch takes longer to grow
|
||||
maxCompletionTime = Math.max(maxCompletionTime, prediction.getDoneEstimate());
|
||||
}
|
||||
}
|
||||
|
||||
final SummaryState state;
|
||||
final long completionTime;
|
||||
|
||||
if (allUnknown)
|
||||
{
|
||||
state = SummaryState.UNKNOWN;
|
||||
completionTime = -1L;
|
||||
}
|
||||
else if (allEmpty)
|
||||
{
|
||||
state = SummaryState.EMPTY;
|
||||
completionTime = -1L;
|
||||
}
|
||||
else if (maxCompletionTime <= Instant.now().getEpochSecond())
|
||||
{
|
||||
state = SummaryState.COMPLETED;
|
||||
completionTime = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = SummaryState.IN_PROGRESS;
|
||||
completionTime = maxCompletionTime;
|
||||
}
|
||||
summaries.put(tab.getKey(), state);
|
||||
completionTimes.put(tab.getKey(), completionTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.timetracking.farming;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.time.Instant;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.vars.Autoweed;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.timetracking.SummaryState;
|
||||
import net.runelite.client.plugins.timetracking.Tab;
|
||||
import net.runelite.client.plugins.timetracking.TimeTrackingConfig;
|
||||
|
||||
@Singleton
|
||||
public class FarmingTracker
|
||||
{
|
||||
private final Client client;
|
||||
private final ItemManager itemManager;
|
||||
private final ConfigManager configManager;
|
||||
private final TimeTrackingConfig config;
|
||||
private final FarmingWorld farmingWorld;
|
||||
|
||||
private final Map<Tab, SummaryState> summaries = new EnumMap<>(Tab.class);
|
||||
|
||||
/**
|
||||
* The time at which all patches of a particular type will be ready to be harvested,
|
||||
* or {@code -1} if we have no data about any patch of the given type.
|
||||
*/
|
||||
private final Map<Tab, Long> completionTimes = new EnumMap<>(Tab.class);
|
||||
|
||||
@Inject
|
||||
private FarmingTracker(Client client, ItemManager itemManager, ConfigManager configManager,
|
||||
TimeTrackingConfig config, FarmingWorld farmingWorld)
|
||||
{
|
||||
this.client = client;
|
||||
this.itemManager = itemManager;
|
||||
this.configManager = configManager;
|
||||
this.config = config;
|
||||
this.farmingWorld = farmingWorld;
|
||||
}
|
||||
|
||||
|
||||
public FarmingTabPanel createTabPanel(Tab tab)
|
||||
{
|
||||
return new FarmingTabPanel(this, itemManager, config, farmingWorld.getTabs().get(tab));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates tracker data for the current region. Returns true if any data was changed.
|
||||
*/
|
||||
public boolean updateData(WorldPoint location)
|
||||
{
|
||||
boolean changed = false;
|
||||
|
||||
{
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername();
|
||||
String autoweed = Integer.toString(client.getVar(Varbits.AUTOWEED));
|
||||
if (!autoweed.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED)))
|
||||
{
|
||||
configManager.setConfiguration(group, TimeTrackingConfig.AUTOWEED, autoweed);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
FarmingRegion region = farmingWorld.getRegions().get(location.getRegionID());
|
||||
if (region != null && region.isInBounds(location))
|
||||
{
|
||||
// Write config with new varbits
|
||||
// timetracking.<login-username>.<regionID>.<VarbitID>=<varbitValue>:<unix time>
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + region.getRegionID();
|
||||
long unixNow = Instant.now().getEpochSecond();
|
||||
for (FarmingPatch patch : region.getPatches())
|
||||
{
|
||||
// Write the config value if it doesn't match what is current, or it is more than 5 minutes old
|
||||
Varbits varbit = patch.getVarbit();
|
||||
String key = Integer.toString(varbit.getId());
|
||||
String strVarbit = Integer.toString(client.getVar(varbit));
|
||||
String storedValue = configManager.getConfiguration(group, key);
|
||||
|
||||
if (storedValue != null)
|
||||
{
|
||||
String[] parts = storedValue.split(":");
|
||||
if (parts.length == 2 && parts[0].equals(strVarbit))
|
||||
{
|
||||
long unixTime = 0;
|
||||
try
|
||||
{
|
||||
unixTime = Long.parseLong(parts[1]);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
if (unixTime + (5 * 60) > unixNow && unixNow + 30 > unixTime)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String value = strVarbit + ":" + unixNow;
|
||||
configManager.setConfiguration(group, key, value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
updateCompletionTime();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PatchPrediction predictPatch(FarmingPatch patch)
|
||||
{
|
||||
long unixNow = Instant.now().getEpochSecond();
|
||||
|
||||
boolean autoweed;
|
||||
{
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername();
|
||||
autoweed = Integer.toString(Autoweed.ON.ordinal())
|
||||
.equals(configManager.getConfiguration(group, TimeTrackingConfig.AUTOWEED));
|
||||
}
|
||||
|
||||
String group = TimeTrackingConfig.CONFIG_GROUP + "." + client.getUsername() + "." + patch.getRegion().getRegionID();
|
||||
String key = Integer.toString(patch.getVarbit().getId());
|
||||
String storedValue = configManager.getConfiguration(group, key);
|
||||
|
||||
if (storedValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
long unixTime = 0;
|
||||
int value = 0;
|
||||
{
|
||||
String[] parts = storedValue.split(":");
|
||||
if (parts.length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Integer.parseInt(parts[0]);
|
||||
unixTime = Long.parseLong(parts[1]);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unixTime <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
PatchState state = patch.getImplementation().forVarbitValue(value);
|
||||
|
||||
if (state == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int stage = state.getStage();
|
||||
int stages = state.getStages();
|
||||
int tickrate = state.getTickRate() * 60;
|
||||
|
||||
if (autoweed && state.getProduce() == Produce.WEEDS)
|
||||
{
|
||||
stage = 0;
|
||||
stages = 1;
|
||||
tickrate = 0;
|
||||
}
|
||||
|
||||
long doneEstimate = 0;
|
||||
if (tickrate > 0)
|
||||
{
|
||||
long tickNow = (unixNow + (5 * 60)) / tickrate;
|
||||
long tickTime = (unixTime + (5 * 60)) / tickrate;
|
||||
int delta = (int) (tickNow - tickTime);
|
||||
|
||||
doneEstimate = ((stages - 1 - stage) + tickTime) * tickrate + (5 * 60);
|
||||
|
||||
stage += delta;
|
||||
if (stage >= stages)
|
||||
{
|
||||
stage = stages - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return new PatchPrediction(
|
||||
state.getProduce(),
|
||||
state.getCropState(),
|
||||
doneEstimate,
|
||||
stage,
|
||||
stages
|
||||
);
|
||||
}
|
||||
|
||||
public void loadCompletionTimes()
|
||||
{
|
||||
summaries.clear();
|
||||
completionTimes.clear();
|
||||
updateCompletionTime();
|
||||
}
|
||||
|
||||
public SummaryState getSummary(Tab patchType)
|
||||
{
|
||||
SummaryState summary = summaries.get(patchType);
|
||||
return summary == null ? SummaryState.UNKNOWN : summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall completion time for the given patch type.
|
||||
*
|
||||
* @see #completionTimes
|
||||
*/
|
||||
public long getCompletionTime(Tab patchType)
|
||||
{
|
||||
Long completionTime = completionTimes.get(patchType);
|
||||
return completionTime == null ? -1 : completionTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the overall completion time for the given patch type.
|
||||
*
|
||||
* @see #completionTimes
|
||||
*/
|
||||
private void updateCompletionTime()
|
||||
{
|
||||
for (Map.Entry<Tab, Set<FarmingPatch>> tab : farmingWorld.getTabs().entrySet())
|
||||
{
|
||||
long maxCompletionTime = 0;
|
||||
boolean allUnknown = true;
|
||||
boolean allEmpty = true;
|
||||
|
||||
for (FarmingPatch patch : tab.getValue())
|
||||
{
|
||||
PatchPrediction prediction = predictPatch(patch);
|
||||
if (prediction == null || prediction.getProduce().getItemID() < 0)
|
||||
{
|
||||
continue; // unknown state
|
||||
}
|
||||
|
||||
allUnknown = false;
|
||||
|
||||
if (prediction.getProduce() != Produce.WEEDS && prediction.getProduce() != Produce.SCARECROW)
|
||||
{
|
||||
allEmpty = false;
|
||||
|
||||
// update max duration if this patch takes longer to grow
|
||||
maxCompletionTime = Math.max(maxCompletionTime, prediction.getDoneEstimate());
|
||||
}
|
||||
}
|
||||
|
||||
final SummaryState state;
|
||||
final long completionTime;
|
||||
|
||||
if (allUnknown)
|
||||
{
|
||||
state = SummaryState.UNKNOWN;
|
||||
completionTime = -1L;
|
||||
}
|
||||
else if (allEmpty)
|
||||
{
|
||||
state = SummaryState.EMPTY;
|
||||
completionTime = -1L;
|
||||
}
|
||||
else if (maxCompletionTime <= Instant.now().getEpochSecond())
|
||||
{
|
||||
state = SummaryState.COMPLETED;
|
||||
completionTime = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = SummaryState.IN_PROGRESS;
|
||||
completionTime = maxCompletionTime;
|
||||
}
|
||||
summaries.put(tab.getKey(), state);
|
||||
completionTimes.put(tab.getKey(), completionTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,28 +139,28 @@ class FarmingWorld
|
||||
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.HERB)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Kourend", 7222,
|
||||
add(new FarmingRegion("Kourend", 6967,
|
||||
new FarmingPatch("North East", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||
));
|
||||
add(new FarmingRegion("Kourend", 6711,
|
||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
||||
new FarmingPatch("", Varbits.FARMING_7904, PatchImplementation.SPIRIT_TREE)
|
||||
));
|
||||
add(new FarmingRegion("Kourend", 7223,
|
||||
new FarmingPatch("West 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 2", Varbits.GRAPES_4954, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 3", Varbits.GRAPES_4955, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 4", Varbits.GRAPES_4956, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 5", Varbits.GRAPES_4957, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 6", Varbits.GRAPES_4958, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 1", Varbits.GRAPES_4959, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 2", Varbits.GRAPES_4960, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 3", Varbits.GRAPES_4961, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 4", Varbits.GRAPES_4962, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 5", Varbits.GRAPES_4963, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 6", Varbits.GRAPES_4964, PatchImplementation.GRAPES)
|
||||
new FarmingPatch("East 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 2", Varbits.GRAPES_4954, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 3", Varbits.GRAPES_4955, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 4", Varbits.GRAPES_4956, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 5", Varbits.GRAPES_4957, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("East 6", Varbits.GRAPES_4958, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 1", Varbits.GRAPES_4959, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 2", Varbits.GRAPES_4960, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 3", Varbits.GRAPES_4961, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 4", Varbits.GRAPES_4962, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 5", Varbits.GRAPES_4963, PatchImplementation.GRAPES),
|
||||
new FarmingPatch("West 6", Varbits.GRAPES_4964, PatchImplementation.GRAPES)
|
||||
));
|
||||
|
||||
add(new FarmingRegion("Lletya", 9265,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.timetracking.farming;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.runelite.client.plugins.timetracking.Tab;
|
||||
@@ -2576,6 +2577,7 @@ public enum PatchImplementation
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
abstract PatchState forVarbitValue(int value);
|
||||
|
||||
private final Tab tab;
|
||||
|
||||
@@ -115,7 +115,7 @@ enum TeleportLocationData
|
||||
|
||||
// Misc
|
||||
XERICS_LOOKOUT(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Lookout", new WorldPoint(1576, 3528, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_GLADE(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Glade", new WorldPoint(1773, 3502, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_GLADE(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Glade", new WorldPoint(1754, 3564, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_INFERNO(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Inferno", new WorldPoint(1504, 3819, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_HEART(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Heart", new WorldPoint(1641, 3670, 0), "xerics_talisman_teleport_icon.png"),
|
||||
XERICS_HONOUR(TeleportType.OTHER, "Xeric's Talisman", "Xeric's Honour", new WorldPoint(1254, 3559, 0), "xerics_talisman_teleport_icon.png"),
|
||||
@@ -138,6 +138,7 @@ enum TeleportLocationData
|
||||
PHARAOHS_SCEPTRE_JALSAVRAH(TeleportType.OTHER, "Pharaoh's Sceptre", "Jalsavrah (Pyramid Plunder)", new WorldPoint(3288, 2795, 0), "pharaohs_sceptre_teleport_icon.png"),
|
||||
PHARAOHS_SCEPTRE_JALEUSTROPHOS(TeleportType.OTHER, "Pharaoh's Sceptre", "Jaleustrophos (Agility Pyramid)", new WorldPoint(3341, 2827, 0), "pharaohs_sceptre_teleport_icon.png"),
|
||||
PHARAOHS_SCEPTRE_JALDRAOCHT(TeleportType.OTHER, "Pharaoh's Sceptre", "Jaldraocht (Desert Treasure Pyramid)", new WorldPoint(3232, 2897, 0), "pharaohs_sceptre_teleport_icon.png"),
|
||||
CAMULET_TEMPLE(TeleportType.OTHER, "Camulet", "Enakhra's Temple", new WorldPoint(3190, 2923, 0), "camulet_teleport_icon.png"),
|
||||
|
||||
// Wilderness
|
||||
OBELISK_13(TeleportType.OTHER, "Obelisk", "13", new WorldPoint(3156, 3620, 0), "obelisk_icon.png"),
|
||||
|
||||
Reference in New Issue
Block a user