Merge remote-tracking branch 'runelite/master'
This commit is contained in:
@@ -69,7 +69,7 @@ public class CacheUploader implements Runnable
|
||||
archive.setHash(hash);
|
||||
|
||||
String path = new StringBuilder()
|
||||
.append(hashStr.substring(0, 2))
|
||||
.append(hashStr, 0, 2)
|
||||
.append('/')
|
||||
.append(hashStr.substring(2))
|
||||
.toString();
|
||||
|
||||
@@ -116,7 +116,7 @@ public class FlatStorage implements Storage
|
||||
{
|
||||
int lidx = line.indexOf('=');
|
||||
String key = line.substring(0, lidx);
|
||||
String value = line.substring(lidx + 1, line.length());
|
||||
String value = line.substring(lidx + 1);
|
||||
|
||||
if ("file".equals(key))
|
||||
{
|
||||
@@ -128,7 +128,7 @@ public class FlatStorage implements Storage
|
||||
int vidx = value.indexOf('=');
|
||||
FileData fd = new FileData();
|
||||
fd.setId(Integer.parseInt(value.substring(0, vidx)));
|
||||
fd.setNameHash(Integer.parseInt(value.substring(vidx + 1, value.length())));
|
||||
fd.setNameHash(Integer.parseInt(value.substring(vidx + 1)));
|
||||
fileData.add(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public class CacheService
|
||||
{
|
||||
String hashStr = BaseEncoding.base16().encode(archiveEntry.getHash());
|
||||
String path = new StringBuilder()
|
||||
.append(hashStr.substring(0, 2))
|
||||
.append(hashStr, 0, 2)
|
||||
.append('/')
|
||||
.append(hashStr.substring(2))
|
||||
.toString();
|
||||
|
||||
@@ -151,6 +151,13 @@ public interface Client extends GameEngine
|
||||
*/
|
||||
void setPassword(String password);
|
||||
|
||||
/**
|
||||
* Sets the 6 digit pin used for authenticator on login screen.
|
||||
*
|
||||
* @param otp one time password
|
||||
*/
|
||||
void setOtp(String otp);
|
||||
|
||||
/**
|
||||
* Gets currently selected login field. 0 is username, and 1 is password.
|
||||
*
|
||||
@@ -158,6 +165,13 @@ public interface Client extends GameEngine
|
||||
*/
|
||||
int getCurrentLoginField();
|
||||
|
||||
/**
|
||||
* Gets index of current login state. 2 is username/password form, 4 is authenticator form
|
||||
*
|
||||
* @return current login state index
|
||||
*/
|
||||
int getLoginIndex();
|
||||
|
||||
/**
|
||||
* Gets the account type of the logged in player.
|
||||
*
|
||||
@@ -1352,6 +1366,13 @@ public interface Client extends GameEngine
|
||||
*/
|
||||
boolean isInInstancedRegion();
|
||||
|
||||
/**
|
||||
* Get the number of client ticks an item has been pressed
|
||||
*
|
||||
* @return the number of client ticks an item has been pressed
|
||||
*/
|
||||
int getItemPressedDuration();
|
||||
|
||||
/**
|
||||
* Sets whether the client is hiding entities.
|
||||
* <p>
|
||||
@@ -1598,6 +1619,19 @@ public interface Client extends GameEngine
|
||||
|
||||
void checkClickbox(Model model, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash);
|
||||
|
||||
/**
|
||||
* Get the if1 widget whose item is being dragged
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Widget getIf1DraggedWidget();
|
||||
|
||||
/**
|
||||
* Get the item index of the item being dragged on an if1 widget
|
||||
* @return
|
||||
*/
|
||||
int getIf1DraggedItemIndex();
|
||||
|
||||
/**
|
||||
* Sets if a widget is in target mode
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,10 @@ public enum GameState
|
||||
* The client is at the login screen.
|
||||
*/
|
||||
LOGIN_SCREEN(10),
|
||||
/**
|
||||
* The client is at the login screen entering authenticator code.
|
||||
*/
|
||||
LOGIN_SCREEN_AUTHENTICATOR(11),
|
||||
/**
|
||||
* There is a player logging in.
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,7 @@ package net.runelite.api;
|
||||
|
||||
public class GraphicID
|
||||
{
|
||||
public static final int WINE_MAKE = 47;
|
||||
public static final int SPLASH = 85;
|
||||
public static final int GREY_BUBBLE_TELEPORT = 86;
|
||||
public static final int TELEPORT = 111;
|
||||
|
||||
@@ -79,6 +79,10 @@ public class ArdougneDiaryRequirement extends GenericDiaryRequirement
|
||||
new QuestRequirement(Quest.FAIRYTALE_II__CURE_A_QUEEN, true));
|
||||
|
||||
// HARD
|
||||
// When the task is completed "the Totem" changes to "Totem" - so we add
|
||||
// both variations.
|
||||
add("Recharge some Jewellery at the Totem in the Legends Guild.",
|
||||
new QuestRequirement(Quest.LEGENDS_QUEST));
|
||||
add("Recharge some Jewellery at Totem in the Legends Guild.",
|
||||
new QuestRequirement(Quest.LEGENDS_QUEST));
|
||||
add("Enter the Magic Guild.",
|
||||
|
||||
@@ -46,7 +46,7 @@ class Obstacles
|
||||
// Draynor
|
||||
ROUGH_WALL, TIGHTROPE, TIGHTROPE_11406, NARROW_WALL, WALL_11630, GAP_11631, CRATE_11632, STILE_7527,
|
||||
// Al-Kharid
|
||||
ROUGH_WALL_11633, TIGHTROPE_14398, CABLE, ZIP_LINE, TROPICAL_TREE_14404, ROOF_TOP_BEAMS,
|
||||
ROUGH_WALL_11633, TIGHTROPE_14398, CABLE, ZIP_LINE_14403, TROPICAL_TREE_14404, ROOF_TOP_BEAMS,
|
||||
TIGHTROPE_14409, GAP_14399,
|
||||
// Pyramid
|
||||
STAIRS_10857, LOW_WALL_10865, LEDGE_10860, PLANK_10868, GAP_10882, LEDGE_10886, STAIRS_10857, GAP_10884,
|
||||
|
||||
@@ -188,7 +188,7 @@ public class BarbarianAssaultPlugin extends Plugin
|
||||
Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT);
|
||||
Widget pointsWidget = client.getWidget(WidgetInfo.BA_RUNNERS_PASSED);
|
||||
if (!rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && pointsWidget != null
|
||||
&& !hasAnnounced && client.getVar(Varbits.IN_GAME_BA) == 0)
|
||||
&& !hasAnnounced && client.getVar(Varbits.IN_GAME_BA) == 0)
|
||||
{
|
||||
wave = new Wave(client);
|
||||
wave.setWaveAmounts();
|
||||
@@ -328,7 +328,10 @@ public class BarbarianAssaultPlugin extends Plugin
|
||||
{
|
||||
overlay.setCurrentRound(null);
|
||||
|
||||
if (config.waveTimes() && gameTime != null)
|
||||
// Use an instance check to determine if this is exiting a game or a tutorial
|
||||
// After exiting tutorials there is a small delay before changing IN_GAME_BA back to
|
||||
// 0 whereas when in a real wave it changes while still in the instance.
|
||||
if (config.waveTimes() && gameTime != null && client.isInInstancedRegion())
|
||||
{
|
||||
announceTime("Wave " + currentWave + " duration: ", gameTime.getTime(true));
|
||||
}
|
||||
|
||||
@@ -1,344 +1,344 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Lotto <https://github.com/devLotto>
|
||||
* 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.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.LEGS;
|
||||
import static net.runelite.api.EquipmentInventorySlot.*;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemID;
|
||||
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;
|
||||
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.BULL_ROARER;
|
||||
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 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.*;
|
||||
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;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
|
||||
@Getter
|
||||
public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClueScroll
|
||||
{
|
||||
private static final Set<EmoteClue> CLUES = ImmutableSet.of(
|
||||
new EmoteClue("Beckon on the east coast of the Kharazi Jungle. Beware of double agents! Equip any vestment stole and a heraldic rune shield.", NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE, new WorldPoint(2954, 2933, 0), BECKON, any("Any stole", item(GUTHIX_STOLE), item(SARADOMIN_STOLE), item(ZAMORAK_STOLE), item(ARMADYL_STOLE), item(BANDOS_STOLE), item(ANCIENT_STOLE)), any("Any heraldic rune shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))),
|
||||
new EmoteClue("Cheer in the Barbarian Agility Arena. Headbang before you talk to me. Equip a steel platebody, maple shortbow and a Wilderness cape.", BARBARIAN_OUTPOST_OBSTACLE_COURSE, new WorldPoint(2552, 3556, 0), CHEER, HEADBANG, item(STEEL_PLATEBODY), item(MAPLE_SHORTBOW), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)),
|
||||
new EmoteClue("Bow upstairs in the Edgeville Monastery. Equip a completed prayer book.", SOUTHEAST_CORNER_OF_THE_MONASTERY, new WorldPoint(3056, 3484, 1), BOW, any("Any god book", item(HOLY_BOOK), item(BOOK_OF_BALANCE), item(UNHOLY_BOOK), item(BOOK_OF_LAW), item(BOOK_OF_WAR), item(BOOK_OF_DARKNESS))),
|
||||
new EmoteClue("Cheer in the Shadow dungeon. Equip a rune crossbow, climbing boots and any mitre.", ENTRANCE_OF_THE_CAVE_OF_DAMIS, new WorldPoint(2629, 5071, 0), CHEER, any("Any mitre", item(GUTHIX_MITRE), item(SARADOMIN_MITRE), item(ZAMORAK_MITRE), item(ANCIENT_MITRE), item(BANDOS_MITRE), item(ARMADYL_MITRE)), item(RUNE_CROSSBOW), item(CLIMBING_BOOTS), item(RING_OF_VISIBILITY)),
|
||||
new EmoteClue("Cheer at the top of the agility pyramid. Beware of double agents! Equip a blue mystic robe top, and any rune heraldic shield.", AGILITY_PYRAMID, new WorldPoint(3043, 4697, 3), CHEER, item(MYSTIC_ROBE_TOP), any("Any rune heraldic shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))),
|
||||
new EmoteClue("Dance in Iban's temple. Beware of double agents! Equip Iban's staff, a black mystic top and a black mystic bottom.", WELL_OF_VOYAGE, new WorldPoint(2011, 4712, 0), DANCE, any("Any iban's staff", item(IBANS_STAFF), item(IBANS_STAFF_U)), item(MYSTIC_ROBE_TOP_DARK), item(MYSTIC_ROBE_BOTTOM_DARK)),
|
||||
new EmoteClue("Dance on the Fishing Platform. Equip barrows gloves, an amulet of glory and a dragon med helm.", SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM, new WorldPoint(2782, 3273, 0), DANCE, any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6)), item(BARROWS_GLOVES), item(DRAGON_MED_HELM)),
|
||||
new EmoteClue("Flap at the death altar. Beware of double agents! Equip a death tiara, a legend's cape and any ring of wealth.", DEATH_ALTAR, new WorldPoint(2205, 4838, 0), FLAP, any("Any ring of wealth", item(RING_OF_WEALTH), item(RING_OF_WEALTH_1), item(RING_OF_WEALTH_2), item(RING_OF_WEALTH_3), item(RING_OF_WEALTH_4), item(RING_OF_WEALTH_5), item(RING_OF_WEALTH_I), item(RING_OF_WEALTH_I1), item(RING_OF_WEALTH_I2), item(RING_OF_WEALTH_I3), item(RING_OF_WEALTH_I4), item(RING_OF_WEALTH_I5)), item(DEATH_TIARA), item(CAPE_OF_LEGENDS)),
|
||||
new EmoteClue("Headbang in the Fight Arena pub. Equip a pirate bandana, a dragonstone necklace and and a magic longbow.", OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA, new WorldPoint(2568, 3149, 0), HEADBANG, any("Any pirate bandana", item(PIRATE_BANDANA), item(PIRATE_BANDANA_7124), item(PIRATE_BANDANA_7130), item(PIRATE_BANDANA_7136)), item(DRAGON_NECKLACE), item(MAGIC_LONGBOW)),
|
||||
new EmoteClue("Do a jig at the barrow's chest. Beware of double agents! Equip any full barrows set.", BARROWS_CHEST, new WorldPoint(3551, 9694, 0), JIG, any("Any full barrows set", all(range(AHRIMS_HOOD_100, AHRIMS_HOOD_0), range(AHRIMS_STAFF_100, AHRIMS_STAFF_0), range(AHRIMS_ROBETOP_100, AHRIMS_ROBETOP_0), range(AHRIMS_ROBESKIRT_100, AHRIMS_ROBESKIRT_0)), all(range(DHAROKS_HELM_100, DHAROKS_HELM_0), range(DHAROKS_GREATAXE_100, DHAROKS_GREATAXE_0), range(DHAROKS_PLATEBODY_100, DHAROKS_PLATEBODY_0), range(DHAROKS_PLATELEGS_100, DHAROKS_PLATELEGS_0)), all(range(GUTHANS_HELM_100, GUTHANS_HELM_0), range(GUTHANS_WARSPEAR_100, GUTHANS_WARSPEAR_0), range(GUTHANS_PLATEBODY_100, GUTHANS_PLATEBODY_0), range(GUTHANS_CHAINSKIRT_100, GUTHANS_CHAINSKIRT_0)), all(range(KARILS_COIF_100, KARILS_COIF_0), range(KARILS_CROSSBOW_100, KARILS_CROSSBOW_0), range(KARILS_LEATHERTOP_100, KARILS_LEATHERTOP_0), range(KARILS_LEATHERSKIRT_100, KARILS_LEATHERSKIRT_0)), all(range(TORAGS_HELM_100, TORAGS_HELM_0), range(TORAGS_HAMMERS_100, TORAGS_HAMMERS_0), range(TORAGS_PLATEBODY_100, TORAGS_PLATEBODY_0), range(TORAGS_PLATELEGS_100, TORAGS_PLATELEGS_0)), all(range(VERACS_HELM_100, VERACS_HELM_0), range(VERACS_FLAIL_100, VERACS_FLAIL_0), range(VERACS_BRASSARD_100, VERACS_BRASSARD_0), range(VERACS_PLATESKIRT_100, VERACS_PLATESKIRT_0)))),
|
||||
new EmoteClue("Jig at Jiggig. Beware of double agents! Equip a Rune spear, rune platelegs and any rune heraldic helm.", IN_THE_MIDDLE_OF_JIGGIG, new WorldPoint(2477, 3047, 0), JIG, range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5), item(RUNE_SPEAR), item(RUNE_PLATELEGS)),
|
||||
new EmoteClue("Cheer at the games room. Have nothing equipped at all when you do.", null, new WorldPoint(2207, 4952, 0), CHEER, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Panic on the pier where you catch the Fishing trawler. Have nothing equipped at all when you do.", null, new WorldPoint(2676, 3169, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Panic in the heart of the Haunted Woods. Beware of double agents! Have no items equipped when you do.", null, new WorldPoint(3611, 3492, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Show your anger towards the Statue of Saradomin in Ellamaria's garden. Beware of double agents! Equip a zamorak godsword.", BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS, new WorldPoint(3230, 3478, 0), ANGRY, item(ZAMORAK_GODSWORD)),
|
||||
new EmoteClue("Show your anger at the Wise old man. Beware of double agents! Equip an abyssal whip, a legend's cape and some spined chaps.", BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE, new WorldPoint(3088, 3254, 0), ANGRY, any("Abyssal whip", item(ABYSSAL_WHIP), item(VOLCANIC_ABYSSAL_WHIP), item(FROZEN_ABYSSAL_WHIP)), item(CAPE_OF_LEGENDS), item(SPINED_CHAPS)),
|
||||
new EmoteClue("Beckon in the Digsite, near the eastern winch. Bow before you talk to me. Equip a green gnome hat, snakeskin boots and an iron pickaxe.", DIGSITE, new WorldPoint(3370, 3425, 0), BECKON, BOW, item(GREEN_HAT), item(SNAKESKIN_BOOTS), item(IRON_PICKAXE)),
|
||||
new EmoteClue("Beckon in Tai Bwo Wannai. Clap before you talk to me. Equip green dragonhide chaps, a ring of dueling and a mithril medium helmet.", SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE, new WorldPoint(2803, 3073, 0), BECKON, CLAP, item(GREEN_DHIDE_CHAPS), any("Ring of dueling", item(RING_OF_DUELING1), item(RING_OF_DUELING2), item(RING_OF_DUELING3), item(RING_OF_DUELING4), item(RING_OF_DUELING5), item(RING_OF_DUELING6), item(RING_OF_DUELING7), item(RING_OF_DUELING8)), item(MITHRIL_MED_HELM)),
|
||||
new EmoteClue("Beckon in the combat ring of Shayzien. Show your anger before you talk to me. Equip an adamant platebody, adamant full helm and adamant platelegs.", WEST_OF_THE_SHAYZIEN_COMBAT_RING, new WorldPoint(1545, 3594, 0), BECKON, ANGRY, item(ADAMANT_PLATELEGS), item(ADAMANT_PLATEBODY), item(ADAMANT_FULL_HELM)),
|
||||
new EmoteClue("Bow near Lord Iorwerth. Beware of double agents! Equip a new imbued crystal bow.", TENT_IN_LORD_IORWERTHS_ENCAMPMENT, new WorldPoint(2205, 3252, 0), BOW, any("Imbued crystal bow", item(NEW_CRYSTAL_BOW_I), item(CRYSTAL_BOW_FULL_I), item(CRYSTAL_BOW_910_I), item(CRYSTAL_BOW_810_I), item(CRYSTAL_BOW_710_I), item(CRYSTAL_BOW_610_I), item(CRYSTAL_BOW_510_I), item(CRYSTAL_BOW_410_I), item(CRYSTAL_BOW_310_I), item(CRYSTAL_BOW_210_I), item(CRYSTAL_BOW_110_I))),
|
||||
new EmoteClue("Bow outside the entrance to the Legends' Guild. Equip iron platelegs, an emerald amulet and an oak longbow.", OUTSIDE_THE_LEGENDS_GUILD_GATES, new WorldPoint(2729, 3349, 0), BOW, item(IRON_PLATELEGS), item(OAK_LONGBOW), item(EMERALD_AMULET)),
|
||||
new EmoteClue("Bow on the ground floor of the Legend's guild. Equip Legend's cape, a dragon battleaxe and an amulet of glory.", OUTSIDE_THE_LEGENDS_GUILD_DOOR, new WorldPoint(2728, 3377, 0), BOW, item(CAPE_OF_LEGENDS), item(DRAGON_BATTLEAXE), any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6))),
|
||||
new EmoteClue("Bow in the ticket office of the Duel Arena. Equip an iron chain body, leather chaps and coif.", MUBARIZS_ROOM_AT_THE_DUEL_ARENA, new WorldPoint(3314, 3241, 0), BOW, item(IRON_CHAINBODY), item(LEATHER_CHAPS), item(COIF)),
|
||||
new EmoteClue("Bow at the top of the lighthouse. Beware of double agents! Equip a blue dragonhide body, blue dragonhide vambraces and no jewelry.", TOP_FLOOR_OF_THE_LIGHTHOUSE, new WorldPoint(2511, 3641, 2), BOW, item(BLUE_DHIDE_BODY), item(BLUE_DHIDE_VAMB), emptySlot("No jewelry", AMULET, RING)),
|
||||
new EmoteClue("Blow a kiss between the tables in Shilo Village bank. Beware of double agents! Equip a blue mystic hat, bone spear and rune platebody.", SHILO_VILLAGE_BANK, new WorldPoint(2851, 2954, 0), BLOW_KISS, item(MYSTIC_HAT), item(BONE_SPEAR), item(RUNE_PLATEBODY)),
|
||||
new EmoteClue("Blow a kiss in the heart of the lava maze. Equip black dragonhide chaps, a spotted cape and a rolling pin.", NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE, new WorldPoint(3069, 3861, 0), BLOW_KISS, item(BLACK_DHIDE_CHAPS), any("Spotted cape", item(SPOTTED_CAPE), item(SPOTTED_CAPE_10073)), item(ROLLING_PIN)),
|
||||
new EmoteClue("Blow a kiss outside K'ril Tsutsaroth's chamber. Beware of double agents! Equip a zamorak full helm and the shadow sword.", OUTSIDE_KRIL_TSUTSAROTHS_ROOM, new WorldPoint(2925, 5333, 0), BLOW_KISS, item(ZAMORAK_FULL_HELM), item(SHADOW_SWORD)),
|
||||
new EmoteClue("Cheer at the Druids' Circle. Equip a blue wizard hat, a bronze two-handed sword and HAM boots.", TAVERLEY_STONE_CIRCLE, new WorldPoint(2924, 3478, 0), CHEER, item(BLUE_WIZARD_HAT), item(BRONZE_2H_SWORD), item(HAM_BOOTS)),
|
||||
new EmoteClue("Cheer in the Edgeville general store. Dance before you talk to me. Equip a brown apron, leather boots and leather gloves.", NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE, new WorldPoint(3080, 3509, 0), CHEER, DANCE, item(BROWN_APRON), item(LEATHER_BOOTS), item(LEATHER_GLOVES)),
|
||||
new EmoteClue("Cheer in the Ogre Pen in the Training Camp. Show you are angry before you talk to me. Equip a green dragonhide body and chaps and a steel square shield.", OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP, new WorldPoint(2527, 3375, 0), CHEER, ANGRY, item(GREEN_DHIDE_BODY), item(GREEN_DHIDE_CHAPS), item(STEEL_SQ_SHIELD)),
|
||||
new EmoteClue("Cheer in the Entrana church. Beware of double agents! Equip a full set of black dragonhide armour.", ENTRANA_CHAPEL, new WorldPoint(2852, 3349, 0), CHEER, item(BLACK_DHIDE_VAMB), item(BLACK_DHIDE_CHAPS), item(BLACK_DHIDE_BODY)),
|
||||
new EmoteClue("Cheer for the monks at Port Sarim. Equip a coif, steel plateskirt and a sapphire necklace.", NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM, new WorldPoint(3047, 3237, 0), CHEER, item(COIF), item(STEEL_PLATESKIRT), item(SAPPHIRE_NECKLACE)),
|
||||
new EmoteClue("Clap in the main exam room in the Exam Centre. Equip a white apron, green gnome boots and leather gloves.", INSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3361, 3339, 0), CLAP, item(WHITE_APRON), item(GREEN_BOOTS), item(LEATHER_GLOVES)),
|
||||
new EmoteClue("Clap on the causeway to the Wizards' Tower. Equip an iron medium helmet, emerald ring and a white apron.", ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER, new WorldPoint(3113, 3196, 0), CLAP, item(IRON_MED_HELM), item(EMERALD_RING), item(WHITE_APRON)),
|
||||
new EmoteClue("Clap on the top level of the mill, north of East Ardougne. Equip a blue gnome robe top, HAM robe bottom and an unenchanted tiara.", UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL, new WorldPoint(2635, 3385, 3), CLAP, item(BLUE_ROBE_TOP), item(HAM_ROBE), item(TIARA)),
|
||||
new EmoteClue("Clap in Seers court house. Spin before you talk to me. Equip an adamant halberd, blue mystic robe bottom and a diamond ring.", OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE, new WorldPoint(2735, 3469, 0), CLAP, SPIN, item(ADAMANT_HALBERD), item(MYSTIC_ROBE_BOTTOM), item(DIAMOND_RING)),
|
||||
new EmoteClue("Clap in the magic axe hut. Beware of double agents! Equip only some flared trousers.", OUTSIDE_THE_WILDERNESS_AXE_HUT, new WorldPoint(3191, 3960, 0), CLAP, item(FLARED_TROUSERS), item(LOCKPICK), emptySlot("Nothing else", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Clap your hands north of Mount Karuulm Spin before you talk to me. Equip an adamant warhammer, a ring of life and a pair of mithril boots.", NORTH_OF_MOUNT_KARUULM, new WorldPoint(1306, 3839, 0), CLAP, SPIN, item(ADAMANT_WARHAMMER), item(RING_OF_LIFE), item(MITHRIL_BOOTS)),
|
||||
new EmoteClue("Cry in the Catherby Ranging shop. Bow before you talk to me. Equip blue gnome boots, a hard leather body and an unblessed silver sickle.", HICKTONS_ARCHERY_EMPORIUM, new WorldPoint(2823, 3443, 0), CRY, BOW, item(BLUE_BOOTS), item(HARDLEATHER_BODY), item(SILVER_SICKLE)),
|
||||
new EmoteClue("Cry on the shore of Catherby beach. Laugh before you talk to me, equip an adamant sq shield, a bone dagger and mithril platebody.", OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY, new WorldPoint(2852, 3429, 0), CRY, LAUGH, item(ADAMANT_SQ_SHIELD), item(BONE_DAGGER), item(MITHRIL_PLATEBODY)),
|
||||
new EmoteClue("Cry on top of the western tree in the Gnome Agility Arena. Indicate 'no' before you talk to me. Equip a steel kiteshield, ring of forging and green dragonhide chaps.", GNOME_STRONGHOLD_BALANCING_ROPE, new WorldPoint(2473, 3420, 2), CRY, NO, item(STEEL_KITESHIELD), item(RING_OF_FORGING), item(GREEN_DHIDE_CHAPS)),
|
||||
new EmoteClue("Cry in the TzHaar gem store. Beware of double agents! Equip a fire cape and TokTz-Xil-Ul.", TZHAAR_GEM_STORE, new WorldPoint(2463, 5149, 0), CRY, any("Fire cape", item(FIRE_CAPE), item(FIRE_MAX_CAPE)), item(TOKTZXILUL)),
|
||||
new EmoteClue("Cry in the Draynor Village jail. Jump for joy before you talk to me. Equip an adamant sword, a sapphire amulet and an adamant plateskirt.", OUTSIDE_DRAYNOR_VILLAGE_JAIL, new WorldPoint(3128, 3245, 0), CRY, JUMP_FOR_JOY, item(ADAMANT_SWORD), item(SAPPHIRE_AMULET), item(ADAMANT_PLATESKIRT)),
|
||||
new EmoteClue("Dance at the crossroads north of Draynor. Equip an iron chain body, a sapphire ring and a longbow.", CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE, new WorldPoint(3109, 3294, 0), DANCE, item(IRON_CHAINBODY), item(SAPPHIRE_RING), item(LONGBOW)),
|
||||
new EmoteClue("Dance in the Party Room. Equip a steel full helmet, steel platebody and an iron plateskirt.", OUTSIDE_THE_FALADOR_PARTY_ROOM, new WorldPoint(3045, 3376, 0), DANCE, item(STEEL_FULL_HELM), item(STEEL_PLATEBODY), item(IRON_PLATESKIRT)),
|
||||
new EmoteClue("Dance in the shack in Lumbridge Swamp. Equip a bronze dagger, iron full helmet and a gold ring.", NEAR_A_SHED_IN_LUMBRIDGE_SWAMP, new WorldPoint(3203, 3169, 0), DANCE, item(BRONZE_DAGGER), item(IRON_FULL_HELM), item(GOLD_RING)),
|
||||
new EmoteClue("Dance in the dark caves beneath Lumbridge Swamp. Blow a kiss before you talk to me. Equip an air staff, Bronze full helm and an amulet of power.", LUMBRIDGE_SWAMP_CAVES, new WorldPoint(3168, 9571, 0), DANCE, BLOW_KISS, item(STAFF_OF_AIR), item(BRONZE_FULL_HELM), item(AMULET_OF_POWER)),
|
||||
new EmoteClue("Dance at the cat-doored pyramid in Sophanem. Beware of double agents! Equip a ring of life, an uncharged amulet of glory and an adamant two-handed sword.", OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM, new WorldPoint(3294, 2781, 0), DANCE, item(RING_OF_LIFE), item(AMULET_OF_GLORY), item(ADAMANT_2H_SWORD)),
|
||||
new EmoteClue("Dance in the centre of Canifis. Bow before you talk to me. Equip a green gnome robe top, mithril plate legs and an iron two-handed sword.", CENTRE_OF_CANIFIS, new WorldPoint(3492, 3488, 0), DANCE, BOW, item(GREEN_ROBE_TOP), item(MITHRIL_PLATELEGS), item(IRON_2H_SWORD)),
|
||||
new EmoteClue("Dance in the King Black Dragon's lair. Beware of double agents! Equip a black dragonhide body, black dragonhide vambs and a black dragon mask.", KING_BLACK_DRAGONS_LAIR, new WorldPoint(2271, 4680, 0), DANCE, item(BLACK_DHIDE_BODY), item(BLACK_DHIDE_VAMB), item(BLACK_DRAGON_MASK)),
|
||||
new EmoteClue("Dance at the entrance to the Grand Exchange. Equip a pink skirt, pink robe top and a body tiara.", SOUTH_OF_THE_GRAND_EXCHANGE, new WorldPoint(3165, 3467, 0), DANCE, item(PINK_SKIRT), item(PINK_ROBE_TOP), item(BODY_TIARA)),
|
||||
new EmoteClue("Goblin Salute in the Goblin Village. Beware of double agents! Equip a bandos godsword, a bandos cloak and a bandos platebody.", OUTSIDE_MUDKNUCKLES_HUT, new WorldPoint(2956, 3505, 0), GOBLIN_SALUTE, item(BANDOS_PLATEBODY), item(BANDOS_CLOAK), item(BANDOS_GODSWORD)),
|
||||
new EmoteClue("Headbang in the mine north of Al Kharid. Equip a desert shirt, leather gloves and leather boots.", AL_KHARID_SCORPION_MINE, new WorldPoint(3299, 3289, 0), HEADBANG, item(DESERT_SHIRT), item(LEATHER_GLOVES), item(LEATHER_BOOTS)),
|
||||
new EmoteClue("Headbang at the exam center. Beware of double agents! Equip a mystic fire staff, a diamond bracelet and rune boots.", OUTSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3362, 3340, 0), HEADBANG, item(MYSTIC_FIRE_STAFF), item(DIAMOND_BRACELET), item(RUNE_BOOTS)),
|
||||
new EmoteClue("Headbang at the top of Slayer Tower. Equip a seercull, a combat bracelet and helm of Neitiznot.", OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM, new WorldPoint(3421, 3537, 2), HEADBANG, item(SEERCULL), range("Combat bracelet", COMBAT_BRACELET4, COMBAT_BRACELET), item(HELM_OF_NEITIZNOT)),
|
||||
new EmoteClue("Dance a jig by the entrance to the Fishing Guild. Equip an emerald ring, a sapphire amulet, and a bronze chain body.", OUTSIDE_THE_FISHING_GUILD, new WorldPoint(2610, 3391, 0), JIG, item(EMERALD_RING), item(SAPPHIRE_AMULET), item(BRONZE_CHAINBODY)),
|
||||
new EmoteClue("Dance a jig under Shantay's Awning. Bow before you talk to me. Equip a pointed blue snail helmet, an air staff and a bronze square shield.", SHANTAY_PASS, new WorldPoint(3304, 3124, 0), JIG, BOW, any("Bruise blue snelm (pointed)", item(BRUISE_BLUE_SNELM_3343)), item(STAFF_OF_AIR), item(BRONZE_SQ_SHIELD)),
|
||||
new EmoteClue("Do a jig in Varrock's rune store. Equip an air tiara and a staff of water.", AUBURYS_SHOP_IN_VARROCK, new WorldPoint(3253, 3401, 0), JIG, item(AIR_TIARA), item(STAFF_OF_WATER)),
|
||||
new EmoteClue("Jump for joy at the beehives. Equip a desert shirt, green gnome robe bottoms and a steel axe.", CATHERBY_BEEHIVE_FIELD, new WorldPoint(2759, 3445, 0), JUMP_FOR_JOY, item(DESERT_SHIRT), item(GREEN_ROBE_BOTTOMS), item(STEEL_AXE)),
|
||||
new EmoteClue("Jump for joy in Yanille bank. Dance a jig before you talk to me. Equip a brown apron, adamantite medium helmet and snakeskin chaps.", OUTSIDE_YANILLE_BANK, new WorldPoint(2610, 3092, 0), JUMP_FOR_JOY, JIG, item(BROWN_APRON), item(ADAMANT_MED_HELM), item(SNAKESKIN_CHAPS)),
|
||||
new EmoteClue("Jump for joy in the TzHaar sword shop. Shrug before you talk to me. Equip a Steel longsword, Blue D'hide body and blue mystic gloves.", TZHAAR_WEAPONS_STORE, new WorldPoint(2477, 5146, 0), JUMP_FOR_JOY, SHRUG, item(STEEL_LONGSWORD), item(BLUE_DHIDE_BODY), item(MYSTIC_GLOVES)),
|
||||
new EmoteClue("Jump for joy in the Ancient Cavern. Equip a granite shield, splitbark body and any rune heraldic helm.", ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL, new WorldPoint(1768, 5366, 1), JUMP_FOR_JOY, item(GRANITE_SHIELD), item(SPLITBARK_BODY), range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5)),
|
||||
new EmoteClue("Jump for joy at the Neitiznot rune rock. Equip Rune boots, a proselyte hauberk and a dragonstone ring.", NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES, new WorldPoint(2375, 3850, 0), JUMP_FOR_JOY, item(RUNE_BOOTS), item(PROSELYTE_HAUBERK), item(DRAGONSTONE_RING)),
|
||||
new EmoteClue("Jump for joy in the centre of Zul-Andra. Beware of double agents! Equip a dragon 2h sword, bandos boots and an obsidian cape.", NEAR_THE_PIER_IN_ZULANDRA, new WorldPoint(2199, 3056, 0), JUMP_FOR_JOY, item(DRAGON_2H_SWORD), item(BANDOS_BOOTS), item(OBSIDIAN_CAPE)),
|
||||
new EmoteClue("Laugh by the fountain of heroes. Equip splitbark legs, dragon boots and a Rune longsword.", FOUNTAIN_OF_HEROES, new WorldPoint(2920, 9893, 0), LAUGH, item(SPLITBARK_LEGS), item(DRAGON_BOOTS), item(RUNE_LONGSWORD)),
|
||||
new EmoteClue("Laugh in Jokul's tent in the Mountain Camp. Beware of double agents! Equip a rune full helmet, blue dragonhide chaps and a fire battlestaff.", MOUNTAIN_CAMP_GOAT_ENCLOSURE, new WorldPoint(2812, 3681, 0), LAUGH, item(RUNE_FULL_HELM), item(BLUE_DHIDE_CHAPS), item(FIRE_BATTLESTAFF)),
|
||||
new EmoteClue("Laugh at the crossroads south of the Sinclair Mansion. Equip a cowl, a blue wizard robe top and an iron scimitar.", ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION, new WorldPoint(2741, 3536, 0), LAUGH, item(LEATHER_COWL), item(BLUE_WIZARD_ROBE), item(IRON_SCIMITAR)),
|
||||
new EmoteClue("Laugh in front of the gem store in Ardougne market. Equip a Castlewars bracelet, a dragonstone amulet and a ring of forging.", NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET, new WorldPoint(2666, 3304, 0), LAUGH, any("Castle wars bracelet", range(CASTLE_WARS_BRACELET3, CASTLE_WARS_BRACELET1)), item(DRAGONSTONE_AMULET), item(RING_OF_FORGING)),
|
||||
new EmoteClue("Panic in the Limestone Mine. Equip bronze platelegs, a steel pickaxe and a steel medium helmet.", LIMESTONE_MINE, new WorldPoint(3372, 3498, 0), PANIC, item(BRONZE_PLATELEGS), item(STEEL_PICKAXE), item(STEEL_MED_HELM)),
|
||||
new EmoteClue("Panic by the mausoleum in Morytania. Wave before you speak to me. Equip a mithril plate skirt, a maple longbow and no boots.", MAUSOLEUM_OFF_THE_MORYTANIA_COAST, new WorldPoint(3504, 3576, 0), PANIC, WAVE, item(MITHRIL_PLATESKIRT), item(MAPLE_LONGBOW), emptySlot("No boots", BOOTS)),
|
||||
new EmoteClue("Panic on the Wilderness volcano bridge. Beware of double agents! Equip any headband and crozier.", VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS, new WorldPoint(3368, 3935, 0), PANIC, any("Any headband", range(RED_HEADBAND, BROWN_HEADBAND), range(WHITE_HEADBAND, GREEN_HEADBAND)), any("Any crozier", item(ANCIENT_CROZIER), item(ARMADYL_CROZIER), item(BANDOS_CROZIER), range(SARADOMIN_CROZIER, ZAMORAK_CROZIER))),
|
||||
new EmoteClue("Panic by the pilot on White Wolf Mountain. Beware of double agents! Equip mithril platelegs, a ring of life and a rune axe.", GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN, new WorldPoint(2847, 3499, 0), PANIC, item(MITHRIL_PLATELEGS), item(RING_OF_LIFE), item(RUNE_AXE)),
|
||||
new EmoteClue("Panic by the big egg where no one dare goes and the ground is burnt. Beware of double agents! Equip a dragon med helm, a TokTz-Ket-Xil, a brine sabre, rune platebody and an uncharged amulet of glory.", SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE, new WorldPoint(3227, 3831, 0), PANIC, item(DRAGON_MED_HELM), item(TOKTZKETXIL), item(BRINE_SABRE), item(RUNE_PLATEBODY), item(AMULET_OF_GLORY)),
|
||||
new EmoteClue("Panic at the area flowers meet snow. Equip Blue D'hide vambs, a dragon spear and a rune plateskirt.", HALFWAY_DOWN_TROLLWEISS_MOUNTAIN, new WorldPoint(2776, 3781, 0), PANIC, item(BLUE_DHIDE_VAMB), item(DRAGON_SPEAR), item(RUNE_PLATESKIRT), item(SLED_4084)),
|
||||
new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))),
|
||||
new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))),
|
||||
new EmoteClue("Blow a raspberry at the monkey cage in Ardougne Zoo. Equip a studded leather body, bronze platelegs and a normal staff with no orb.", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)),
|
||||
new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)),
|
||||
new EmoteClue("Blow a raspberry in the Fishing Guild bank. Beware of double agents! Equip an elemental shield, blue dragonhide chaps and a rune warhammer.", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)),
|
||||
new EmoteClue("Salute in the banana plantation. Beware of double agents! Equip a diamond ring, amulet of power, and nothing on your chest and legs.", WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION, new WorldPoint(2914, 3168, 0), SALUTE, item(DIAMOND_RING), item(AMULET_OF_POWER), emptySlot("Nothing on chest & legs", BODY, LEGS)),
|
||||
new EmoteClue("Salute in the Warriors' guild bank. Equip only a black salamander.", WARRIORS_GUILD_BANK, new WorldPoint(2844, 3542, 0), SALUTE, item(BLACK_SALAMANDER), emptySlot("Nothing else", HEAD, CAPE, AMULET, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Salute in the centre of the mess hall. Beware of double agents! Equip a rune halberd rune platebody, and an amulet of strength.", HOSIDIUS_MESS, new WorldPoint(1646, 3632, 0), SALUTE, item(RUNE_HALBERD), item(RUNE_PLATEBODY), item(AMULET_OF_STRENGTH)),
|
||||
new EmoteClue("Shrug in the mine near Rimmington. Equip a gold necklace, a gold ring and a bronze spear.", RIMMINGTON_MINE, new WorldPoint(2976, 3238, 0), SHRUG, item(GOLD_NECKLACE), item(GOLD_RING), item(BRONZE_SPEAR)),
|
||||
new EmoteClue("Shrug in Catherby bank. Yawn before you talk to me. Equip a maple longbow, green d'hide chaps and an iron med helm.", OUTSIDE_CATHERBY_BANK, new WorldPoint(2808, 3440, 0), SHRUG, YAWN, item(MAPLE_LONGBOW), item(GREEN_DHIDE_CHAPS), item(IRON_MED_HELM)),
|
||||
new EmoteClue("Shrug in the Zamorak temple found in the Eastern Wilderness. Beware of double agents! Equip rune platelegs, an iron platebody and blue dragonhide vambraces.", CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS, new WorldPoint(3239, 3611, 0), SHRUG, item(RUNE_PLATELEGS), item(IRON_PLATEBODY), item(BLUE_DHIDE_VAMB)),
|
||||
new EmoteClue("Shrug in the Shayzien command tent. Equip a blue mystic robe bottom, a rune kiteshield and any bob shirt.", SHAYZIEN_WAR_TENT, new WorldPoint(1555, 3537, 0), SHRUG, item(MYSTIC_ROBE_BOTTOM), item(RUNE_KITESHIELD), range("Any bob shirt", BOBS_RED_SHIRT, BOBS_PURPLE_SHIRT)),
|
||||
new EmoteClue("Slap your head in the centre of the Kourend catacombs. Beware of double agents! Equip the arclight and the amulet of the damned.", CENTRE_OF_THE_CATACOMBS_OF_KOUREND, new WorldPoint(1663, 10045, 0), SLAP_HEAD, item(ARCLIGHT), any("Amulet of the damned", item(AMULET_OF_THE_DAMNED), item(AMULET_OF_THE_DAMNED_FULL))),
|
||||
new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", ROAD_JUNCTION_NORTH_OF_RIMMINGTON, new WorldPoint(2981, 3276, 0), SPIN, item(GREEN_HAT), item(CREAM_ROBE_TOP), item(LEATHER_CHAPS)),
|
||||
new EmoteClue("Spin in Draynor Manor by the fountain. Equip an iron platebody, studded leather chaps and a bronze full helmet.", DRAYNOR_MANOR_BY_THE_FOUNTAIN, new WorldPoint(3088, 3336, 0), SPIN, item(IRON_PLATEBODY), item(STUDDED_CHAPS), item(BRONZE_FULL_HELM)),
|
||||
new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)),
|
||||
new EmoteClue("Spin in the Varrock Castle courtyard. Equip a black axe, a coif and a ruby ring.", OUTSIDE_VARROCK_PALACE_COURTYARD, new WorldPoint(3213, 3463, 0), SPIN, item(BLACK_AXE), item(COIF), item(RUBY_RING)),
|
||||
new EmoteClue("Spin in West Ardougne Church. Equip a dragon spear and red dragonhide chaps.", CHAPEL_IN_WEST_ARDOUGNE, new WorldPoint(2530, 3290, 0), SPIN, item(DRAGON_SPEAR), item(RED_DHIDE_CHAPS)),
|
||||
new EmoteClue("Spin on the bridge by the Barbarian Village. Salute before you talk to me. Equip purple gloves, a steel kiteshield and a mithril full helmet.", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)),
|
||||
new EmoteClue("Stamp in the Enchanted valley west of the waterfall. Beware of double agents! Equip a dragon axe.", NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY, new WorldPoint(3030, 4522, 0), STOMP, item(DRAGON_AXE)),
|
||||
new EmoteClue("Think in middle of the wheat field by the Lumbridge mill. Equip a blue gnome robetop, a turquoise gnome robe bottom and an oak shortbow.", WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL, new WorldPoint(3159, 3298, 0), THINK, item(BLUE_ROBE_TOP), item(TURQUOISE_ROBE_BOTTOMS), item(OAK_SHORTBOW)),
|
||||
new EmoteClue("Think in the centre of the Observatory. Spin before you talk to me. Equip a mithril chain body, green dragonhide chaps and a ruby amulet.", OBSERVATORY, new WorldPoint(2439, 3161, 0), THINK, SPIN, item(MITHRIL_CHAINBODY), item(GREEN_DHIDE_CHAPS), item(RUBY_AMULET)),
|
||||
new EmoteClue("Wave along the south fence of the Lumber Yard. Equip a hard leather body, leather chaps and a bronze axe.", NEAR_THE_SAWMILL_OPERATORS_BOOTH, new WorldPoint(3307, 3491, 0), WAVE, item(HARDLEATHER_BODY), item(LEATHER_CHAPS), item(BRONZE_AXE)),
|
||||
new EmoteClue("Wave in the Falador gem store. Equip a Mithril pickaxe, Black platebody and an Iron Kiteshield.", NEAR_HERQUINS_SHOP_IN_FALADOR, new WorldPoint(2945, 3335, 0), WAVE, item(MITHRIL_PICKAXE), item(BLACK_PLATEBODY), item(IRON_KITESHIELD)),
|
||||
new EmoteClue("Wave on Mudskipper Point. Equip a black cape, leather chaps and a steel mace.", MUDSKIPPER_POINT, new WorldPoint(2989, 3110, 0), WAVE, item(BLACK_CAPE), item(LEATHER_CHAPS), item(STEEL_MACE)),
|
||||
new EmoteClue("Wave on the northern wall of Castle Drakan. Beware of double agents! Wear a dragon sq shield, splitbark body and any boater.", NORTHERN_WALL_OF_CASTLE_DRAKAN, new WorldPoint(3560, 3385, 0), WAVE, item(DRAGON_SQ_SHIELD), item(SPLITBARK_BODY), any("Any boater", item(RED_BOATER), item(ORANGE_BOATER), item(GREEN_BOATER), item(BLUE_BOATER), item(BLACK_BOATER), item(PINK_BOATER), item(PURPLE_BOATER), item(WHITE_BOATER))),
|
||||
new EmoteClue("Yawn in the 7th room of Pyramid Plunder. Beware of double agents! Equip a pharaoh sceptre and a full set of menaphite robes.", _7TH_CHAMBER_OF_JALSAVRAH, new WorldPoint(1944, 4427, 0), YAWN, any("Pharaoh's sceptre", item(PHARAOHS_SCEPTRE), item(PHARAOHS_SCEPTRE_1), item(PHARAOHS_SCEPTRE_2), item(PHARAOHS_SCEPTRE_3), item(PHARAOHS_SCEPTRE_4), item(PHARAOHS_SCEPTRE_5), item(PHARAOHS_SCEPTRE_6), item(PHARAOHS_SCEPTRE_7), item(PHARAOHS_SCEPTRE_8)), any("Full set of menaphite robes", all(item(MENAPHITE_PURPLE_HAT), item(MENAPHITE_PURPLE_TOP), range(MENAPHITE_PURPLE_ROBE, MENAPHITE_PURPLE_KILT)), all(item(MENAPHITE_RED_HAT), item(MENAPHITE_RED_TOP), range(MENAPHITE_RED_ROBE, MENAPHITE_RED_KILT)))),
|
||||
new EmoteClue("Yawn in the Varrock library. Equip a green gnome robe top, HAM robe bottom and an iron warhammer.", VARROCK_PALACE_LIBRARY, new WorldPoint(3209, 3492, 0), YAWN, item(GREEN_ROBE_TOP), item(HAM_ROBE), item(IRON_WARHAMMER)),
|
||||
new EmoteClue("Yawn in Draynor Marketplace. Equip studded leather chaps, an iron kiteshield and a steel longsword.", DRAYNOR_VILLAGE_MARKET, new WorldPoint(3083, 3253, 0), YAWN, item(STUDDED_CHAPS), item(IRON_KITESHIELD), item(STEEL_LONGSWORD)),
|
||||
new EmoteClue("Yawn in the Castle Wars lobby. Shrug before you talk to me. Equip a ruby amulet, a mithril scimitar and a Wilderness cape.", CASTLE_WARS_BANK, new WorldPoint(2440, 3092, 0), YAWN, SHRUG, item(RUBY_AMULET), item(MITHRIL_SCIMITAR), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)),
|
||||
new EmoteClue("Yawn in the rogues' general store. Beware of double agents! Equip an adamant square shield, blue dragon vambraces and a rune pickaxe.", NOTERAZZOS_SHOP_IN_THE_WILDERNESS, new WorldPoint(3026, 3701, 0), YAWN, item(ADAMANT_SQ_SHIELD), item(BLUE_DHIDE_VAMB), item(RUNE_PICKAXE)),
|
||||
new EmoteClue("Yawn at the top of Trollheim. Equip a lava battlestaff, black dragonhide vambraces and a mind shield.", ON_TOP_OF_TROLLHEIM_MOUNTAIN, new WorldPoint(2887, 3676, 0), YAWN, item(LAVA_BATTLESTAFF), item(BLACK_DHIDE_VAMB), item(MIND_SHIELD)),
|
||||
new EmoteClue("Yawn in the centre of Arceuus library. Nod your head before you talk to me. Equip blue dragonhide vambraces, adamant boots and an adamant dagger.", ENTRANCE_OF_THE_ARCEUUS_LIBRARY, new WorldPoint(1632, 3807, 0), YAWN, YES, item(BLUE_DHIDE_VAMB), item(ADAMANT_BOOTS), item(ADAMANT_DAGGER)),
|
||||
new EmoteClue("Swing a bullroarer at the top of the watchtower. Beware of double agents! Equip a dragon plateskirt, climbing boots and a dragon chainbody.", TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER, new WorldPoint(2932, 4712, 0), BULL_ROARER, item(DRAGON_PLATESKIRT), item(CLIMBING_BOOTS), item(DRAGON_CHAINBODY_3140), item(ItemID.BULL_ROARER)),
|
||||
new EmoteClue("Blow a raspberry at Gypsy Aris in her tent. Equip a gold ring and a gold necklace.", GYPSY_TENT_ENTRANCE, new WorldPoint(3203, 3424, 0), RASPBERRY, item(GOLD_RING), item(GOLD_NECKLACE)),
|
||||
new EmoteClue("Bow to Brugsen Bursen at the Grand Exchange.", null, new WorldPoint(3164, 3477, 0), BOW),
|
||||
new EmoteClue("Cheer at Iffie Nitter. Equip a chef hat and a red cape.", FINE_CLOTHES_ENTRANCE, new WorldPoint(3205, 3416, 0), CHEER, item(CHEFS_HAT), item(RED_CAPE)),
|
||||
new EmoteClue("Clap at Bob's Brilliant Axes. Equip a bronze axe and leather boots.", BOB_AXES_ENTRANCE, new WorldPoint(3231, 3203, 0), CLAP, item(BRONZE_AXE), item(LEATHER_BOOTS)),
|
||||
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);
|
||||
}
|
||||
|
||||
private static RangeItemRequirement range(int startItemId, int endItemId)
|
||||
{
|
||||
return range(null, startItemId, endItemId);
|
||||
}
|
||||
|
||||
private static RangeItemRequirement range(String name, int startItemId, int endItemId)
|
||||
{
|
||||
return new RangeItemRequirement(name, startItemId, endItemId);
|
||||
}
|
||||
|
||||
private static AnyRequirementCollection any(String name, ItemRequirement... requirements)
|
||||
{
|
||||
return new AnyRequirementCollection(name, requirements);
|
||||
}
|
||||
|
||||
private static AllRequirementsCollection all(ItemRequirement... requirements)
|
||||
{
|
||||
return new AllRequirementsCollection(requirements);
|
||||
}
|
||||
|
||||
private static SlotLimitationRequirement emptySlot(String description, EquipmentInventorySlot... slots)
|
||||
{
|
||||
return new SlotLimitationRequirement(description, slots);
|
||||
}
|
||||
|
||||
private final String text;
|
||||
private final STASHUnit stashUnit;
|
||||
private final WorldPoint location;
|
||||
private final Emote firstEmote;
|
||||
private final Emote secondEmote;
|
||||
private final 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, STASHUnit stashUnit, WorldPoint location, Emote firstEmote, Emote secondEmote, @Nonnull ItemRequirement... itemRequirements)
|
||||
{
|
||||
this.text = text;
|
||||
this.stashUnit = stashUnit;
|
||||
this.location = location;
|
||||
this.firstEmote = firstEmote;
|
||||
this.secondEmote = secondEmote;
|
||||
this.itemRequirements = itemRequirements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin)
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder().text("Emote Clue").build());
|
||||
panelComponent.getChildren().add(LineComponent.builder().left("Emotes:").build());
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(getFirstEmote().getName())
|
||||
.leftColor(TITLED_CONTENT_COLOR)
|
||||
.build());
|
||||
|
||||
if (getSecondEmote() != null)
|
||||
{
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(getSecondEmote().getName())
|
||||
.leftColor(TITLED_CONTENT_COLOR)
|
||||
.build());
|
||||
}
|
||||
|
||||
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();
|
||||
Item[] inventory = plugin.getInventoryItems();
|
||||
|
||||
// If equipment is null, the player is wearing nothing
|
||||
if (equipment == null)
|
||||
{
|
||||
equipment = new Item[0];
|
||||
}
|
||||
|
||||
// If inventory is null, the player has nothing in their inventory
|
||||
if (inventory == null)
|
||||
{
|
||||
inventory = new Item[0];
|
||||
}
|
||||
|
||||
Item[] combined = new Item[equipment.length + inventory.length];
|
||||
System.arraycopy(equipment, 0, combined, 0, equipment.length);
|
||||
System.arraycopy(inventory, 0, combined, equipment.length, inventory.length);
|
||||
|
||||
for (ItemRequirement requirement : itemRequirements)
|
||||
{
|
||||
boolean equipmentFulfilled = requirement.fulfilledBy(equipment);
|
||||
boolean combinedFulfilled = requirement.fulfilledBy(combined);
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(requirement.getCollectiveName(client))
|
||||
.leftColor(TITLED_CONTENT_COLOR)
|
||||
.right(combinedFulfilled ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X)
|
||||
.rightColor(equipmentFulfilled ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin)
|
||||
{
|
||||
LocalPoint localPoint = LocalPoint.fromWorld(plugin.getClient(), getLocation());
|
||||
|
||||
if (localPoint != null)
|
||||
{
|
||||
OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localPoint, 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)
|
||||
{
|
||||
for (EmoteClue clue : CLUES)
|
||||
{
|
||||
if (clue.getText().equalsIgnoreCase(text))
|
||||
{
|
||||
return clue;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2018, Lotto <https://github.com/devLotto>
|
||||
* 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.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.*;
|
||||
import static net.runelite.api.EquipmentInventorySlot.LEGS;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemID;
|
||||
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;
|
||||
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.*;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.Emote.BULL_ROARER;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.ItemRequirement;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.RangeItemRequirement;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.*;
|
||||
import static net.runelite.client.plugins.cluescrolls.clues.emote.STASHUnit.SHANTAY_PASS;
|
||||
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;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
|
||||
@Getter
|
||||
public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClueScroll
|
||||
{
|
||||
private static final Set<EmoteClue> CLUES = ImmutableSet.of(
|
||||
new EmoteClue("Beckon on the east coast of the Kharazi Jungle. Beware of double agents! Equip any vestment stole and a heraldic rune shield.", NORTHEAST_CORNER_OF_THE_KHARAZI_JUNGLE, new WorldPoint(2954, 2933, 0), BECKON, any("Any stole", item(GUTHIX_STOLE), item(SARADOMIN_STOLE), item(ZAMORAK_STOLE), item(ARMADYL_STOLE), item(BANDOS_STOLE), item(ANCIENT_STOLE)), any("Any heraldic rune shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))),
|
||||
new EmoteClue("Cheer in the Barbarian Agility Arena. Headbang before you talk to me. Equip a steel platebody, maple shortbow and a Wilderness cape.", BARBARIAN_OUTPOST_OBSTACLE_COURSE, new WorldPoint(2552, 3556, 0), CHEER, HEADBANG, item(STEEL_PLATEBODY), item(MAPLE_SHORTBOW), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)),
|
||||
new EmoteClue("Bow upstairs in the Edgeville Monastery. Equip a completed prayer book.", SOUTHEAST_CORNER_OF_THE_MONASTERY, new WorldPoint(3056, 3484, 1), BOW, any("Any god book", item(HOLY_BOOK), item(BOOK_OF_BALANCE), item(UNHOLY_BOOK), item(BOOK_OF_LAW), item(BOOK_OF_WAR), item(BOOK_OF_DARKNESS))),
|
||||
new EmoteClue("Cheer in the Shadow dungeon. Equip a rune crossbow, climbing boots and any mitre.", ENTRANCE_OF_THE_CAVE_OF_DAMIS, new WorldPoint(2629, 5071, 0), CHEER, any("Any mitre", item(GUTHIX_MITRE), item(SARADOMIN_MITRE), item(ZAMORAK_MITRE), item(ANCIENT_MITRE), item(BANDOS_MITRE), item(ARMADYL_MITRE)), item(RUNE_CROSSBOW), item(CLIMBING_BOOTS), item(RING_OF_VISIBILITY)),
|
||||
new EmoteClue("Cheer at the top of the agility pyramid. Beware of double agents! Equip a blue mystic robe top, and any rune heraldic shield.", AGILITY_PYRAMID, new WorldPoint(3043, 4697, 3), CHEER, item(MYSTIC_ROBE_TOP), any("Any rune heraldic shield", item(RUNE_SHIELD_H1), item(RUNE_SHIELD_H2), item(RUNE_SHIELD_H3), item(RUNE_SHIELD_H4), item(RUNE_SHIELD_H5))),
|
||||
new EmoteClue("Dance in Iban's temple. Beware of double agents! Equip Iban's staff, a black mystic top and a black mystic bottom.", WELL_OF_VOYAGE, new WorldPoint(2011, 4712, 0), DANCE, any("Any iban's staff", item(IBANS_STAFF), item(IBANS_STAFF_U)), item(MYSTIC_ROBE_TOP_DARK), item(MYSTIC_ROBE_BOTTOM_DARK)),
|
||||
new EmoteClue("Dance on the Fishing Platform. Equip barrows gloves, an amulet of glory and a dragon med helm.", SOUTHEAST_CORNER_OF_THE_FISHING_PLATFORM, new WorldPoint(2782, 3273, 0), DANCE, any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6)), item(BARROWS_GLOVES), item(DRAGON_MED_HELM)),
|
||||
new EmoteClue("Flap at the death altar. Beware of double agents! Equip a death tiara, a legend's cape and any ring of wealth.", DEATH_ALTAR, new WorldPoint(2205, 4838, 0), FLAP, any("Any ring of wealth", item(RING_OF_WEALTH), item(RING_OF_WEALTH_1), item(RING_OF_WEALTH_2), item(RING_OF_WEALTH_3), item(RING_OF_WEALTH_4), item(RING_OF_WEALTH_5), item(RING_OF_WEALTH_I), item(RING_OF_WEALTH_I1), item(RING_OF_WEALTH_I2), item(RING_OF_WEALTH_I3), item(RING_OF_WEALTH_I4), item(RING_OF_WEALTH_I5)), item(DEATH_TIARA), item(CAPE_OF_LEGENDS)),
|
||||
new EmoteClue("Headbang in the Fight Arena pub. Equip a pirate bandana, a dragonstone necklace and and a magic longbow.", OUTSIDE_THE_BAR_BY_THE_FIGHT_ARENA, new WorldPoint(2568, 3149, 0), HEADBANG, any("Any pirate bandana", item(PIRATE_BANDANA), item(PIRATE_BANDANA_7124), item(PIRATE_BANDANA_7130), item(PIRATE_BANDANA_7136)), item(DRAGON_NECKLACE), item(MAGIC_LONGBOW)),
|
||||
new EmoteClue("Do a jig at the barrow's chest. Beware of double agents! Equip any full barrows set.", BARROWS_CHEST, new WorldPoint(3551, 9694, 0), JIG, any("Any full barrows set", all(range(AHRIMS_HOOD_100, AHRIMS_HOOD_0), range(AHRIMS_STAFF_100, AHRIMS_STAFF_0), range(AHRIMS_ROBETOP_100, AHRIMS_ROBETOP_0), range(AHRIMS_ROBESKIRT_100, AHRIMS_ROBESKIRT_0)), all(range(DHAROKS_HELM_100, DHAROKS_HELM_0), range(DHAROKS_GREATAXE_100, DHAROKS_GREATAXE_0), range(DHAROKS_PLATEBODY_100, DHAROKS_PLATEBODY_0), range(DHAROKS_PLATELEGS_100, DHAROKS_PLATELEGS_0)), all(range(GUTHANS_HELM_100, GUTHANS_HELM_0), range(GUTHANS_WARSPEAR_100, GUTHANS_WARSPEAR_0), range(GUTHANS_PLATEBODY_100, GUTHANS_PLATEBODY_0), range(GUTHANS_CHAINSKIRT_100, GUTHANS_CHAINSKIRT_0)), all(range(KARILS_COIF_100, KARILS_COIF_0), range(KARILS_CROSSBOW_100, KARILS_CROSSBOW_0), range(KARILS_LEATHERTOP_100, KARILS_LEATHERTOP_0), range(KARILS_LEATHERSKIRT_100, KARILS_LEATHERSKIRT_0)), all(range(TORAGS_HELM_100, TORAGS_HELM_0), range(TORAGS_HAMMERS_100, TORAGS_HAMMERS_0), range(TORAGS_PLATEBODY_100, TORAGS_PLATEBODY_0), range(TORAGS_PLATELEGS_100, TORAGS_PLATELEGS_0)), all(range(VERACS_HELM_100, VERACS_HELM_0), range(VERACS_FLAIL_100, VERACS_FLAIL_0), range(VERACS_BRASSARD_100, VERACS_BRASSARD_0), range(VERACS_PLATESKIRT_100, VERACS_PLATESKIRT_0)))),
|
||||
new EmoteClue("Jig at Jiggig. Beware of double agents! Equip a Rune spear, rune platelegs and any rune heraldic helm.", IN_THE_MIDDLE_OF_JIGGIG, new WorldPoint(2477, 3047, 0), JIG, range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5), item(RUNE_SPEAR), item(RUNE_PLATELEGS)),
|
||||
new EmoteClue("Cheer at the games room. Have nothing equipped at all when you do.", null, new WorldPoint(2207, 4952, 0), CHEER, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Panic on the pier where you catch the Fishing trawler. Have nothing equipped at all when you do.", null, new WorldPoint(2676, 3169, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Panic in the heart of the Haunted Woods. Beware of double agents! Have no items equipped when you do.", null, new WorldPoint(3611, 3492, 0), PANIC, emptySlot("Nothing at all", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Show your anger towards the Statue of Saradomin in Ellamaria's garden. Beware of double agents! Equip a zamorak godsword.", BY_THE_BEAR_CAGE_IN_VARROCK_PALACE_GARDENS, new WorldPoint(3230, 3478, 0), ANGRY, item(ZAMORAK_GODSWORD)),
|
||||
new EmoteClue("Show your anger at the Wise old man. Beware of double agents! Equip an abyssal whip, a legend's cape and some spined chaps.", BEHIND_MISS_SCHISM_IN_DRAYNOR_VILLAGE, new WorldPoint(3088, 3254, 0), ANGRY, any("Abyssal whip", item(ABYSSAL_WHIP), item(VOLCANIC_ABYSSAL_WHIP), item(FROZEN_ABYSSAL_WHIP)), item(CAPE_OF_LEGENDS), item(SPINED_CHAPS)),
|
||||
new EmoteClue("Beckon in the Digsite, near the eastern winch. Bow before you talk to me. Equip a green gnome hat, snakeskin boots and an iron pickaxe.", DIGSITE, new WorldPoint(3370, 3425, 0), BECKON, BOW, item(GREEN_HAT), item(SNAKESKIN_BOOTS), item(IRON_PICKAXE)),
|
||||
new EmoteClue("Beckon in Tai Bwo Wannai. Clap before you talk to me. Equip green dragonhide chaps, a ring of dueling and a mithril medium helmet.", SOUTH_OF_THE_SHRINE_IN_TAI_BWO_WANNAI_VILLAGE, new WorldPoint(2803, 3073, 0), BECKON, CLAP, item(GREEN_DHIDE_CHAPS), any("Ring of dueling", item(RING_OF_DUELING1), item(RING_OF_DUELING2), item(RING_OF_DUELING3), item(RING_OF_DUELING4), item(RING_OF_DUELING5), item(RING_OF_DUELING6), item(RING_OF_DUELING7), item(RING_OF_DUELING8)), item(MITHRIL_MED_HELM)),
|
||||
new EmoteClue("Beckon in the combat ring of Shayzien. Show your anger before you talk to me. Equip an adamant platebody, adamant full helm and adamant platelegs.", WEST_OF_THE_SHAYZIEN_COMBAT_RING, new WorldPoint(1545, 3594, 0), BECKON, ANGRY, item(ADAMANT_PLATELEGS), item(ADAMANT_PLATEBODY), item(ADAMANT_FULL_HELM)),
|
||||
new EmoteClue("Bow near Lord Iorwerth. Beware of double agents! Equip a new imbued crystal bow.", TENT_IN_LORD_IORWERTHS_ENCAMPMENT, new WorldPoint(2205, 3252, 0), BOW, any("Imbued crystal bow", item(NEW_CRYSTAL_BOW_I), item(CRYSTAL_BOW_FULL_I), item(CRYSTAL_BOW_910_I), item(CRYSTAL_BOW_810_I), item(CRYSTAL_BOW_710_I), item(CRYSTAL_BOW_610_I), item(CRYSTAL_BOW_510_I), item(CRYSTAL_BOW_410_I), item(CRYSTAL_BOW_310_I), item(CRYSTAL_BOW_210_I), item(CRYSTAL_BOW_110_I))),
|
||||
new EmoteClue("Bow outside the entrance to the Legends' Guild. Equip iron platelegs, an emerald amulet and an oak longbow.", OUTSIDE_THE_LEGENDS_GUILD_GATES, new WorldPoint(2729, 3349, 0), BOW, item(IRON_PLATELEGS), item(OAK_LONGBOW), item(EMERALD_AMULET)),
|
||||
new EmoteClue("Bow on the ground floor of the Legend's guild. Equip Legend's cape, a dragon battleaxe and an amulet of glory.", OUTSIDE_THE_LEGENDS_GUILD_DOOR, new WorldPoint(2728, 3377, 0), BOW, item(CAPE_OF_LEGENDS), item(DRAGON_BATTLEAXE), any("Any amulet of glory", item(AMULET_OF_GLORY), item(AMULET_OF_GLORY1), item(AMULET_OF_GLORY2), item(AMULET_OF_GLORY3), item(AMULET_OF_GLORY4), item(AMULET_OF_GLORY5), item(AMULET_OF_GLORY6))),
|
||||
new EmoteClue("Bow in the ticket office of the Duel Arena. Equip an iron chain body, leather chaps and coif.", MUBARIZS_ROOM_AT_THE_DUEL_ARENA, new WorldPoint(3314, 3241, 0), BOW, item(IRON_CHAINBODY), item(LEATHER_CHAPS), item(COIF)),
|
||||
new EmoteClue("Bow at the top of the lighthouse. Beware of double agents! Equip a blue dragonhide body, blue dragonhide vambraces and no jewelry.", TOP_FLOOR_OF_THE_LIGHTHOUSE, new WorldPoint(2511, 3641, 2), BOW, item(BLUE_DHIDE_BODY), item(BLUE_DHIDE_VAMB), emptySlot("No jewelry", AMULET, RING)),
|
||||
new EmoteClue("Blow a kiss between the tables in Shilo Village bank. Beware of double agents! Equip a blue mystic hat, bone spear and rune platebody.", SHILO_VILLAGE_BANK, new WorldPoint(2851, 2954, 0), BLOW_KISS, item(MYSTIC_HAT), item(BONE_SPEAR), item(RUNE_PLATEBODY)),
|
||||
new EmoteClue("Blow a kiss in the heart of the lava maze. Equip black dragonhide chaps, a spotted cape and a rolling pin.", NEAR_A_LADDER_IN_THE_WILDERNESS_LAVA_MAZE, new WorldPoint(3069, 3861, 0), BLOW_KISS, item(BLACK_DHIDE_CHAPS), any("Spotted cape", item(SPOTTED_CAPE), item(SPOTTED_CAPE_10073)), item(ROLLING_PIN)),
|
||||
new EmoteClue("Blow a kiss outside K'ril Tsutsaroth's chamber. Beware of double agents! Equip a zamorak full helm and the shadow sword.", OUTSIDE_KRIL_TSUTSAROTHS_ROOM, new WorldPoint(2925, 5333, 0), BLOW_KISS, item(ZAMORAK_FULL_HELM), item(SHADOW_SWORD)),
|
||||
new EmoteClue("Cheer at the Druids' Circle. Equip a blue wizard hat, a bronze two-handed sword and HAM boots.", TAVERLEY_STONE_CIRCLE, new WorldPoint(2924, 3478, 0), CHEER, item(BLUE_WIZARD_HAT), item(BRONZE_2H_SWORD), item(HAM_BOOTS)),
|
||||
new EmoteClue("Cheer in the Edgeville general store. Dance before you talk to me. Equip a brown apron, leather boots and leather gloves.", NORTH_OF_EVIL_DAVES_HOUSE_IN_EDGEVILLE, new WorldPoint(3080, 3509, 0), CHEER, DANCE, item(BROWN_APRON), item(LEATHER_BOOTS), item(LEATHER_GLOVES)),
|
||||
new EmoteClue("Cheer in the Ogre Pen in the Training Camp. Show you are angry before you talk to me. Equip a green dragonhide body and chaps and a steel square shield.", OGRE_CAGE_IN_KING_LATHAS_TRAINING_CAMP, new WorldPoint(2527, 3375, 0), CHEER, ANGRY, item(GREEN_DHIDE_BODY), item(GREEN_DHIDE_CHAPS), item(STEEL_SQ_SHIELD)),
|
||||
new EmoteClue("Cheer in the Entrana church. Beware of double agents! Equip a full set of black dragonhide armour.", ENTRANA_CHAPEL, new WorldPoint(2852, 3349, 0), CHEER, item(BLACK_DHIDE_VAMB), item(BLACK_DHIDE_CHAPS), item(BLACK_DHIDE_BODY)),
|
||||
new EmoteClue("Cheer for the monks at Port Sarim. Equip a coif, steel plateskirt and a sapphire necklace.", NEAR_THE_ENTRANA_FERRY_IN_PORT_SARIM, new WorldPoint(3047, 3237, 0), CHEER, item(COIF), item(STEEL_PLATESKIRT), item(SAPPHIRE_NECKLACE)),
|
||||
new EmoteClue("Clap in the main exam room in the Exam Centre. Equip a white apron, green gnome boots and leather gloves.", OUTSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3361, 3339, 0), CLAP, item(WHITE_APRON), item(GREEN_BOOTS), item(LEATHER_GLOVES)),
|
||||
new EmoteClue("Clap on the causeway to the Wizards' Tower. Equip an iron medium helmet, emerald ring and a white apron.", ON_THE_BRIDGE_TO_THE_MISTHALIN_WIZARDS_TOWER, new WorldPoint(3113, 3196, 0), CLAP, item(IRON_MED_HELM), item(EMERALD_RING), item(WHITE_APRON)),
|
||||
new EmoteClue("Clap on the top level of the mill, north of East Ardougne. Equip a blue gnome robe top, HAM robe bottom and an unenchanted tiara.", UPSTAIRS_IN_THE_ARDOUGNE_WINDMILL, new WorldPoint(2635, 3385, 3), CLAP, item(BLUE_ROBE_TOP), item(HAM_ROBE), item(TIARA)),
|
||||
new EmoteClue("Clap in Seers court house. Spin before you talk to me. Equip an adamant halberd, blue mystic robe bottom and a diamond ring.", OUTSIDE_THE_SEERS_VILLAGE_COURTHOUSE, new WorldPoint(2735, 3469, 0), CLAP, SPIN, item(ADAMANT_HALBERD), item(MYSTIC_ROBE_BOTTOM), item(DIAMOND_RING)),
|
||||
new EmoteClue("Clap in the magic axe hut. Beware of double agents! Equip only some flared trousers.", OUTSIDE_THE_WILDERNESS_AXE_HUT, new WorldPoint(3191, 3960, 0), CLAP, item(FLARED_TROUSERS), item(LOCKPICK), emptySlot("Nothing else", HEAD, CAPE, AMULET, WEAPON, BODY, SHIELD, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Clap your hands north of Mount Karuulm Spin before you talk to me. Equip an adamant warhammer, a ring of life and a pair of mithril boots.", NORTH_OF_MOUNT_KARUULM, new WorldPoint(1306, 3839, 0), CLAP, SPIN, item(ADAMANT_WARHAMMER), item(RING_OF_LIFE), item(MITHRIL_BOOTS)),
|
||||
new EmoteClue("Cry in the Catherby Ranging shop. Bow before you talk to me. Equip blue gnome boots, a hard leather body and an unblessed silver sickle.", HICKTONS_ARCHERY_EMPORIUM, new WorldPoint(2823, 3443, 0), CRY, BOW, item(BLUE_BOOTS), item(HARDLEATHER_BODY), item(SILVER_SICKLE)),
|
||||
new EmoteClue("Cry on the shore of Catherby beach. Laugh before you talk to me, equip an adamant sq shield, a bone dagger and mithril platebody.", OUTSIDE_HARRYS_FISHING_SHOP_IN_CATHERBY, new WorldPoint(2852, 3429, 0), CRY, LAUGH, item(ADAMANT_SQ_SHIELD), item(BONE_DAGGER), item(MITHRIL_PLATEBODY)),
|
||||
new EmoteClue("Cry on top of the western tree in the Gnome Agility Arena. Indicate 'no' before you talk to me. Equip a steel kiteshield, ring of forging and green dragonhide chaps.", GNOME_STRONGHOLD_BALANCING_ROPE, new WorldPoint(2473, 3420, 2), CRY, NO, item(STEEL_KITESHIELD), item(RING_OF_FORGING), item(GREEN_DHIDE_CHAPS)),
|
||||
new EmoteClue("Cry in the TzHaar gem store. Beware of double agents! Equip a fire cape and TokTz-Xil-Ul.", TZHAAR_GEM_STORE, new WorldPoint(2463, 5149, 0), CRY, any("Fire cape", item(FIRE_CAPE), item(FIRE_MAX_CAPE)), item(TOKTZXILUL)),
|
||||
new EmoteClue("Cry in the Draynor Village jail. Jump for joy before you talk to me. Equip an adamant sword, a sapphire amulet and an adamant plateskirt.", OUTSIDE_DRAYNOR_VILLAGE_JAIL, new WorldPoint(3128, 3245, 0), CRY, JUMP_FOR_JOY, item(ADAMANT_SWORD), item(SAPPHIRE_AMULET), item(ADAMANT_PLATESKIRT)),
|
||||
new EmoteClue("Dance at the crossroads north of Draynor. Equip an iron chain body, a sapphire ring and a longbow.", CROSSROADS_NORTH_OF_DRAYNOR_VILLAGE, new WorldPoint(3109, 3294, 0), DANCE, item(IRON_CHAINBODY), item(SAPPHIRE_RING), item(LONGBOW)),
|
||||
new EmoteClue("Dance in the Party Room. Equip a steel full helmet, steel platebody and an iron plateskirt.", OUTSIDE_THE_FALADOR_PARTY_ROOM, new WorldPoint(3045, 3376, 0), DANCE, item(STEEL_FULL_HELM), item(STEEL_PLATEBODY), item(IRON_PLATESKIRT)),
|
||||
new EmoteClue("Dance in the shack in Lumbridge Swamp. Equip a bronze dagger, iron full helmet and a gold ring.", NEAR_A_SHED_IN_LUMBRIDGE_SWAMP, new WorldPoint(3203, 3169, 0), DANCE, item(BRONZE_DAGGER), item(IRON_FULL_HELM), item(GOLD_RING)),
|
||||
new EmoteClue("Dance in the dark caves beneath Lumbridge Swamp. Blow a kiss before you talk to me. Equip an air staff, Bronze full helm and an amulet of power.", LUMBRIDGE_SWAMP_CAVES, new WorldPoint(3168, 9571, 0), DANCE, BLOW_KISS, item(STAFF_OF_AIR), item(BRONZE_FULL_HELM), item(AMULET_OF_POWER)),
|
||||
new EmoteClue("Dance at the cat-doored pyramid in Sophanem. Beware of double agents! Equip a ring of life, an uncharged amulet of glory and an adamant two-handed sword.", OUTSIDE_THE_GREAT_PYRAMID_OF_SOPHANEM, new WorldPoint(3294, 2781, 0), DANCE, item(RING_OF_LIFE), item(AMULET_OF_GLORY), item(ADAMANT_2H_SWORD)),
|
||||
new EmoteClue("Dance in the centre of Canifis. Bow before you talk to me. Equip a green gnome robe top, mithril plate legs and an iron two-handed sword.", CENTRE_OF_CANIFIS, new WorldPoint(3492, 3488, 0), DANCE, BOW, item(GREEN_ROBE_TOP), item(MITHRIL_PLATELEGS), item(IRON_2H_SWORD)),
|
||||
new EmoteClue("Dance in the King Black Dragon's lair. Beware of double agents! Equip a black dragonhide body, black dragonhide vambs and a black dragon mask.", KING_BLACK_DRAGONS_LAIR, new WorldPoint(2271, 4680, 0), DANCE, item(BLACK_DHIDE_BODY), item(BLACK_DHIDE_VAMB), item(BLACK_DRAGON_MASK)),
|
||||
new EmoteClue("Dance at the entrance to the Grand Exchange. Equip a pink skirt, pink robe top and a body tiara.", SOUTH_OF_THE_GRAND_EXCHANGE, new WorldPoint(3165, 3467, 0), DANCE, item(PINK_SKIRT), item(PINK_ROBE_TOP), item(BODY_TIARA)),
|
||||
new EmoteClue("Goblin Salute in the Goblin Village. Beware of double agents! Equip a bandos godsword, a bandos cloak and a bandos platebody.", OUTSIDE_MUDKNUCKLES_HUT, new WorldPoint(2956, 3505, 0), GOBLIN_SALUTE, item(BANDOS_PLATEBODY), item(BANDOS_CLOAK), item(BANDOS_GODSWORD)),
|
||||
new EmoteClue("Headbang in the mine north of Al Kharid. Equip a desert shirt, leather gloves and leather boots.", AL_KHARID_SCORPION_MINE, new WorldPoint(3299, 3289, 0), HEADBANG, item(DESERT_SHIRT), item(LEATHER_GLOVES), item(LEATHER_BOOTS)),
|
||||
new EmoteClue("Headbang at the exam center. Beware of double agents! Equip a mystic fire staff, a diamond bracelet and rune boots.", INSIDE_THE_DIGSITE_EXAM_CENTRE, new WorldPoint(3362, 3340, 0), HEADBANG, item(MYSTIC_FIRE_STAFF), item(DIAMOND_BRACELET), item(RUNE_BOOTS)),
|
||||
new EmoteClue("Headbang at the top of Slayer Tower. Equip a seercull, a combat bracelet and helm of Neitiznot.", OUTSIDE_THE_SLAYER_TOWER_GARGOYLE_ROOM, new WorldPoint(3421, 3537, 2), HEADBANG, item(SEERCULL), range("Combat bracelet", COMBAT_BRACELET4, COMBAT_BRACELET), item(HELM_OF_NEITIZNOT)),
|
||||
new EmoteClue("Dance a jig by the entrance to the Fishing Guild. Equip an emerald ring, a sapphire amulet, and a bronze chain body.", OUTSIDE_THE_FISHING_GUILD, new WorldPoint(2610, 3391, 0), JIG, item(EMERALD_RING), item(SAPPHIRE_AMULET), item(BRONZE_CHAINBODY)),
|
||||
new EmoteClue("Dance a jig under Shantay's Awning. Bow before you talk to me. Equip a pointed blue snail helmet, an air staff and a bronze square shield.", SHANTAY_PASS, new WorldPoint(3304, 3124, 0), JIG, BOW, any("Bruise blue snelm (pointed)", item(BRUISE_BLUE_SNELM_3343)), item(STAFF_OF_AIR), item(BRONZE_SQ_SHIELD)),
|
||||
new EmoteClue("Do a jig in Varrock's rune store. Equip an air tiara and a staff of water.", AUBURYS_SHOP_IN_VARROCK, new WorldPoint(3253, 3401, 0), JIG, item(AIR_TIARA), item(STAFF_OF_WATER)),
|
||||
new EmoteClue("Jump for joy at the beehives. Equip a desert shirt, green gnome robe bottoms and a steel axe.", CATHERBY_BEEHIVE_FIELD, new WorldPoint(2759, 3445, 0), JUMP_FOR_JOY, item(DESERT_SHIRT), item(GREEN_ROBE_BOTTOMS), item(STEEL_AXE)),
|
||||
new EmoteClue("Jump for joy in Yanille bank. Dance a jig before you talk to me. Equip a brown apron, adamantite medium helmet and snakeskin chaps.", OUTSIDE_YANILLE_BANK, new WorldPoint(2610, 3092, 0), JUMP_FOR_JOY, JIG, item(BROWN_APRON), item(ADAMANT_MED_HELM), item(SNAKESKIN_CHAPS)),
|
||||
new EmoteClue("Jump for joy in the TzHaar sword shop. Shrug before you talk to me. Equip a Steel longsword, Blue D'hide body and blue mystic gloves.", TZHAAR_WEAPONS_STORE, new WorldPoint(2477, 5146, 0), JUMP_FOR_JOY, SHRUG, item(STEEL_LONGSWORD), item(BLUE_DHIDE_BODY), item(MYSTIC_GLOVES)),
|
||||
new EmoteClue("Jump for joy in the Ancient Cavern. Equip a granite shield, splitbark body and any rune heraldic helm.", ENTRANCE_OF_THE_CAVERN_UNDER_THE_WHIRLPOOL, new WorldPoint(1768, 5366, 1), JUMP_FOR_JOY, item(GRANITE_SHIELD), item(SPLITBARK_BODY), range("Any rune heraldic helm", RUNE_HELM_H1, RUNE_HELM_H5)),
|
||||
new EmoteClue("Jump for joy at the Neitiznot rune rock. Equip Rune boots, a proselyte hauberk and a dragonstone ring.", NEAR_A_RUNITE_ROCK_IN_THE_FREMENNIK_ISLES, new WorldPoint(2375, 3850, 0), JUMP_FOR_JOY, item(RUNE_BOOTS), item(PROSELYTE_HAUBERK), item(DRAGONSTONE_RING)),
|
||||
new EmoteClue("Jump for joy in the centre of Zul-Andra. Beware of double agents! Equip a dragon 2h sword, bandos boots and an obsidian cape.", NEAR_THE_PIER_IN_ZULANDRA, new WorldPoint(2199, 3056, 0), JUMP_FOR_JOY, item(DRAGON_2H_SWORD), item(BANDOS_BOOTS), item(OBSIDIAN_CAPE)),
|
||||
new EmoteClue("Laugh by the fountain of heroes. Equip splitbark legs, dragon boots and a Rune longsword.", FOUNTAIN_OF_HEROES, new WorldPoint(2920, 9893, 0), LAUGH, item(SPLITBARK_LEGS), item(DRAGON_BOOTS), item(RUNE_LONGSWORD)),
|
||||
new EmoteClue("Laugh in Jokul's tent in the Mountain Camp. Beware of double agents! Equip a rune full helmet, blue dragonhide chaps and a fire battlestaff.", MOUNTAIN_CAMP_GOAT_ENCLOSURE, new WorldPoint(2812, 3681, 0), LAUGH, item(RUNE_FULL_HELM), item(BLUE_DHIDE_CHAPS), item(FIRE_BATTLESTAFF)),
|
||||
new EmoteClue("Laugh at the crossroads south of the Sinclair Mansion. Equip a cowl, a blue wizard robe top and an iron scimitar.", ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION, new WorldPoint(2741, 3536, 0), LAUGH, item(LEATHER_COWL), item(BLUE_WIZARD_ROBE), item(IRON_SCIMITAR)),
|
||||
new EmoteClue("Laugh in front of the gem store in Ardougne market. Equip a Castlewars bracelet, a dragonstone amulet and a ring of forging.", NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET, new WorldPoint(2666, 3304, 0), LAUGH, any("Castle wars bracelet", range(CASTLE_WARS_BRACELET3, CASTLE_WARS_BRACELET1)), item(DRAGONSTONE_AMULET), item(RING_OF_FORGING)),
|
||||
new EmoteClue("Panic in the Limestone Mine. Equip bronze platelegs, a steel pickaxe and a steel medium helmet.", LIMESTONE_MINE, new WorldPoint(3372, 3498, 0), PANIC, item(BRONZE_PLATELEGS), item(STEEL_PICKAXE), item(STEEL_MED_HELM)),
|
||||
new EmoteClue("Panic by the mausoleum in Morytania. Wave before you speak to me. Equip a mithril plate skirt, a maple longbow and no boots.", MAUSOLEUM_OFF_THE_MORYTANIA_COAST, new WorldPoint(3504, 3576, 0), PANIC, WAVE, item(MITHRIL_PLATESKIRT), item(MAPLE_LONGBOW), emptySlot("No boots", BOOTS)),
|
||||
new EmoteClue("Panic on the Wilderness volcano bridge. Beware of double agents! Equip any headband and crozier.", VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS, new WorldPoint(3368, 3935, 0), PANIC, any("Any headband", range(RED_HEADBAND, BROWN_HEADBAND), range(WHITE_HEADBAND, GREEN_HEADBAND)), any("Any crozier", item(ANCIENT_CROZIER), item(ARMADYL_CROZIER), item(BANDOS_CROZIER), range(SARADOMIN_CROZIER, ZAMORAK_CROZIER))),
|
||||
new EmoteClue("Panic by the pilot on White Wolf Mountain. Beware of double agents! Equip mithril platelegs, a ring of life and a rune axe.", GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN, new WorldPoint(2847, 3499, 0), PANIC, item(MITHRIL_PLATELEGS), item(RING_OF_LIFE), item(RUNE_AXE)),
|
||||
new EmoteClue("Panic by the big egg where no one dare goes and the ground is burnt. Beware of double agents! Equip a dragon med helm, a TokTz-Ket-Xil, a brine sabre, rune platebody and an uncharged amulet of glory.", SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE, new WorldPoint(3227, 3831, 0), PANIC, item(DRAGON_MED_HELM), item(TOKTZKETXIL), item(BRINE_SABRE), item(RUNE_PLATEBODY), item(AMULET_OF_GLORY)),
|
||||
new EmoteClue("Panic at the area flowers meet snow. Equip Blue D'hide vambs, a dragon spear and a rune plateskirt.", HALFWAY_DOWN_TROLLWEISS_MOUNTAIN, new WorldPoint(2776, 3781, 0), PANIC, item(BLUE_DHIDE_VAMB), item(DRAGON_SPEAR), item(RUNE_PLATESKIRT), item(SLED_4084)),
|
||||
new EmoteClue("Do a push up at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), PUSH_UP, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))),
|
||||
new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a dragon defender and a slayer helm of any kind.", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), item(DRAGON_DEFENDER), any("Any slayer helmet", item(SLAYER_HELMET), item(BLACK_SLAYER_HELMET), item(GREEN_SLAYER_HELMET), item(PURPLE_SLAYER_HELMET), item(RED_SLAYER_HELMET), item(TURQUOISE_SLAYER_HELMET), item(SLAYER_HELMET_I), item(BLACK_SLAYER_HELMET_I), item(GREEN_SLAYER_HELMET_I), item(PURPLE_SLAYER_HELMET_I), item(RED_SLAYER_HELMET_I), item(TURQUOISE_SLAYER_HELMET_I), item(HYDRA_SLAYER_HELMET), item(HYDRA_SLAYER_HELMET_I))),
|
||||
new EmoteClue("Blow a raspberry at the monkey cage in Ardougne Zoo. Equip a studded leather body, bronze platelegs and a normal staff with no orb.", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)),
|
||||
new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)),
|
||||
new EmoteClue("Blow a raspberry in the Fishing Guild bank. Beware of double agents! Equip an elemental shield, blue dragonhide chaps and a rune warhammer.", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)),
|
||||
new EmoteClue("Salute in the banana plantation. Beware of double agents! Equip a diamond ring, amulet of power, and nothing on your chest and legs.", WEST_SIDE_OF_THE_KARAMJA_BANANA_PLANTATION, new WorldPoint(2914, 3168, 0), SALUTE, item(DIAMOND_RING), item(AMULET_OF_POWER), emptySlot("Nothing on chest & legs", BODY, LEGS)),
|
||||
new EmoteClue("Salute in the Warriors' guild bank. Equip only a black salamander.", WARRIORS_GUILD_BANK, new WorldPoint(2844, 3542, 0), SALUTE, item(BLACK_SALAMANDER), emptySlot("Nothing else", HEAD, CAPE, AMULET, BODY, SHIELD, LEGS, GLOVES, BOOTS, RING, AMMO)),
|
||||
new EmoteClue("Salute in the centre of the mess hall. Beware of double agents! Equip a rune halberd rune platebody, and an amulet of strength.", HOSIDIUS_MESS, new WorldPoint(1646, 3632, 0), SALUTE, item(RUNE_HALBERD), item(RUNE_PLATEBODY), item(AMULET_OF_STRENGTH)),
|
||||
new EmoteClue("Shrug in the mine near Rimmington. Equip a gold necklace, a gold ring and a bronze spear.", RIMMINGTON_MINE, new WorldPoint(2976, 3238, 0), SHRUG, item(GOLD_NECKLACE), item(GOLD_RING), item(BRONZE_SPEAR)),
|
||||
new EmoteClue("Shrug in Catherby bank. Yawn before you talk to me. Equip a maple longbow, green d'hide chaps and an iron med helm.", OUTSIDE_CATHERBY_BANK, new WorldPoint(2808, 3440, 0), SHRUG, YAWN, item(MAPLE_LONGBOW), item(GREEN_DHIDE_CHAPS), item(IRON_MED_HELM)),
|
||||
new EmoteClue("Shrug in the Zamorak temple found in the Eastern Wilderness. Beware of double agents! Equip rune platelegs, an iron platebody and blue dragonhide vambraces.", CHAOS_TEMPLE_IN_THE_SOUTHEASTERN_WILDERNESS, new WorldPoint(3239, 3611, 0), SHRUG, item(RUNE_PLATELEGS), item(IRON_PLATEBODY), item(BLUE_DHIDE_VAMB)),
|
||||
new EmoteClue("Shrug in the Shayzien command tent. Equip a blue mystic robe bottom, a rune kiteshield and any bob shirt.", SHAYZIEN_WAR_TENT, new WorldPoint(1555, 3537, 0), SHRUG, item(MYSTIC_ROBE_BOTTOM), item(RUNE_KITESHIELD), range("Any bob shirt", BOBS_RED_SHIRT, BOBS_PURPLE_SHIRT)),
|
||||
new EmoteClue("Slap your head in the centre of the Kourend catacombs. Beware of double agents! Equip the arclight and the amulet of the damned.", CENTRE_OF_THE_CATACOMBS_OF_KOUREND, new WorldPoint(1663, 10045, 0), SLAP_HEAD, item(ARCLIGHT), any("Amulet of the damned", item(AMULET_OF_THE_DAMNED), item(AMULET_OF_THE_DAMNED_FULL))),
|
||||
new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", ROAD_JUNCTION_NORTH_OF_RIMMINGTON, new WorldPoint(2981, 3276, 0), SPIN, item(GREEN_HAT), item(CREAM_ROBE_TOP), item(LEATHER_CHAPS)),
|
||||
new EmoteClue("Spin in Draynor Manor by the fountain. Equip an iron platebody, studded leather chaps and a bronze full helmet.", DRAYNOR_MANOR_BY_THE_FOUNTAIN, new WorldPoint(3088, 3336, 0), SPIN, item(IRON_PLATEBODY), item(STUDDED_CHAPS), item(BRONZE_FULL_HELM)),
|
||||
new EmoteClue("Spin in front of the Soul altar. Beware of double agents! Equip a dragon pickaxe, helm of neitiznot and a pair of rune boots.", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)),
|
||||
new EmoteClue("Spin in the Varrock Castle courtyard. Equip a black axe, a coif and a ruby ring.", OUTSIDE_VARROCK_PALACE_COURTYARD, new WorldPoint(3213, 3463, 0), SPIN, item(BLACK_AXE), item(COIF), item(RUBY_RING)),
|
||||
new EmoteClue("Spin in West Ardougne Church. Equip a dragon spear and red dragonhide chaps.", CHAPEL_IN_WEST_ARDOUGNE, new WorldPoint(2530, 3290, 0), SPIN, item(DRAGON_SPEAR), item(RED_DHIDE_CHAPS)),
|
||||
new EmoteClue("Spin on the bridge by the Barbarian Village. Salute before you talk to me. Equip purple gloves, a steel kiteshield and a mithril full helmet.", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)),
|
||||
new EmoteClue("Stamp in the Enchanted valley west of the waterfall. Beware of double agents! Equip a dragon axe.", NORTHWESTERN_CORNER_OF_THE_ENCHANTED_VALLEY, new WorldPoint(3030, 4522, 0), STOMP, item(DRAGON_AXE)),
|
||||
new EmoteClue("Think in middle of the wheat field by the Lumbridge mill. Equip a blue gnome robetop, a turquoise gnome robe bottom and an oak shortbow.", WHEAT_FIELD_NEAR_THE_LUMBRIDGE_WINDMILL, new WorldPoint(3159, 3298, 0), THINK, item(BLUE_ROBE_TOP), item(TURQUOISE_ROBE_BOTTOMS), item(OAK_SHORTBOW)),
|
||||
new EmoteClue("Think in the centre of the Observatory. Spin before you talk to me. Equip a mithril chain body, green dragonhide chaps and a ruby amulet.", OBSERVATORY, new WorldPoint(2439, 3161, 0), THINK, SPIN, item(MITHRIL_CHAINBODY), item(GREEN_DHIDE_CHAPS), item(RUBY_AMULET)),
|
||||
new EmoteClue("Wave along the south fence of the Lumber Yard. Equip a hard leather body, leather chaps and a bronze axe.", NEAR_THE_SAWMILL_OPERATORS_BOOTH, new WorldPoint(3307, 3491, 0), WAVE, item(HARDLEATHER_BODY), item(LEATHER_CHAPS), item(BRONZE_AXE)),
|
||||
new EmoteClue("Wave in the Falador gem store. Equip a Mithril pickaxe, Black platebody and an Iron Kiteshield.", NEAR_HERQUINS_SHOP_IN_FALADOR, new WorldPoint(2945, 3335, 0), WAVE, item(MITHRIL_PICKAXE), item(BLACK_PLATEBODY), item(IRON_KITESHIELD)),
|
||||
new EmoteClue("Wave on Mudskipper Point. Equip a black cape, leather chaps and a steel mace.", MUDSKIPPER_POINT, new WorldPoint(2989, 3110, 0), WAVE, item(BLACK_CAPE), item(LEATHER_CHAPS), item(STEEL_MACE)),
|
||||
new EmoteClue("Wave on the northern wall of Castle Drakan. Beware of double agents! Wear a dragon sq shield, splitbark body and any boater.", NORTHERN_WALL_OF_CASTLE_DRAKAN, new WorldPoint(3560, 3385, 0), WAVE, item(DRAGON_SQ_SHIELD), item(SPLITBARK_BODY), any("Any boater", item(RED_BOATER), item(ORANGE_BOATER), item(GREEN_BOATER), item(BLUE_BOATER), item(BLACK_BOATER), item(PINK_BOATER), item(PURPLE_BOATER), item(WHITE_BOATER))),
|
||||
new EmoteClue("Yawn in the 7th room of Pyramid Plunder. Beware of double agents! Equip a pharaoh sceptre and a full set of menaphite robes.", _7TH_CHAMBER_OF_JALSAVRAH, new WorldPoint(1944, 4427, 0), YAWN, any("Pharaoh's sceptre", item(PHARAOHS_SCEPTRE), item(PHARAOHS_SCEPTRE_1), item(PHARAOHS_SCEPTRE_2), item(PHARAOHS_SCEPTRE_3), item(PHARAOHS_SCEPTRE_4), item(PHARAOHS_SCEPTRE_5), item(PHARAOHS_SCEPTRE_6), item(PHARAOHS_SCEPTRE_7), item(PHARAOHS_SCEPTRE_8)), any("Full set of menaphite robes", all(item(MENAPHITE_PURPLE_HAT), item(MENAPHITE_PURPLE_TOP), range(MENAPHITE_PURPLE_ROBE, MENAPHITE_PURPLE_KILT)), all(item(MENAPHITE_RED_HAT), item(MENAPHITE_RED_TOP), range(MENAPHITE_RED_ROBE, MENAPHITE_RED_KILT)))),
|
||||
new EmoteClue("Yawn in the Varrock library. Equip a green gnome robe top, HAM robe bottom and an iron warhammer.", VARROCK_PALACE_LIBRARY, new WorldPoint(3209, 3492, 0), YAWN, item(GREEN_ROBE_TOP), item(HAM_ROBE), item(IRON_WARHAMMER)),
|
||||
new EmoteClue("Yawn in Draynor Marketplace. Equip studded leather chaps, an iron kiteshield and a steel longsword.", DRAYNOR_VILLAGE_MARKET, new WorldPoint(3083, 3253, 0), YAWN, item(STUDDED_CHAPS), item(IRON_KITESHIELD), item(STEEL_LONGSWORD)),
|
||||
new EmoteClue("Yawn in the Castle Wars lobby. Shrug before you talk to me. Equip a ruby amulet, a mithril scimitar and a Wilderness cape.", CASTLE_WARS_BANK, new WorldPoint(2440, 3092, 0), YAWN, SHRUG, item(RUBY_AMULET), item(MITHRIL_SCIMITAR), range("Any team cape", TEAM1_CAPE, TEAM50_CAPE)),
|
||||
new EmoteClue("Yawn in the rogues' general store. Beware of double agents! Equip an adamant square shield, blue dragon vambraces and a rune pickaxe.", NOTERAZZOS_SHOP_IN_THE_WILDERNESS, new WorldPoint(3026, 3701, 0), YAWN, item(ADAMANT_SQ_SHIELD), item(BLUE_DHIDE_VAMB), item(RUNE_PICKAXE)),
|
||||
new EmoteClue("Yawn at the top of Trollheim. Equip a lava battlestaff, black dragonhide vambraces and a mind shield.", ON_TOP_OF_TROLLHEIM_MOUNTAIN, new WorldPoint(2887, 3676, 0), YAWN, item(LAVA_BATTLESTAFF), item(BLACK_DHIDE_VAMB), item(MIND_SHIELD)),
|
||||
new EmoteClue("Yawn in the centre of Arceuus library. Nod your head before you talk to me. Equip blue dragonhide vambraces, adamant boots and an adamant dagger.", ENTRANCE_OF_THE_ARCEUUS_LIBRARY, new WorldPoint(1632, 3807, 0), YAWN, YES, item(BLUE_DHIDE_VAMB), item(ADAMANT_BOOTS), item(ADAMANT_DAGGER)),
|
||||
new EmoteClue("Swing a bullroarer at the top of the watchtower. Beware of double agents! Equip a dragon plateskirt, climbing boots and a dragon chainbody.", TOP_FLOOR_OF_THE_YANILLE_WATCHTOWER, new WorldPoint(2932, 4712, 0), BULL_ROARER, item(DRAGON_PLATESKIRT), item(CLIMBING_BOOTS), item(DRAGON_CHAINBODY_3140), item(ItemID.BULL_ROARER)),
|
||||
new EmoteClue("Blow a raspberry at Gypsy Aris in her tent. Equip a gold ring and a gold necklace.", GYPSY_TENT_ENTRANCE, new WorldPoint(3203, 3424, 0), RASPBERRY, item(GOLD_RING), item(GOLD_NECKLACE)),
|
||||
new EmoteClue("Bow to Brugsen Bursen at the Grand Exchange.", null, new WorldPoint(3164, 3477, 0), BOW),
|
||||
new EmoteClue("Cheer at Iffie Nitter. Equip a chef hat and a red cape.", FINE_CLOTHES_ENTRANCE, new WorldPoint(3205, 3416, 0), CHEER, item(CHEFS_HAT), item(RED_CAPE)),
|
||||
new EmoteClue("Clap at Bob's Brilliant Axes. Equip a bronze axe and leather boots.", BOB_AXES_ENTRANCE, new WorldPoint(3231, 3203, 0), CLAP, item(BRONZE_AXE), item(LEATHER_BOOTS)),
|
||||
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);
|
||||
}
|
||||
|
||||
private static RangeItemRequirement range(int startItemId, int endItemId)
|
||||
{
|
||||
return range(null, startItemId, endItemId);
|
||||
}
|
||||
|
||||
private static RangeItemRequirement range(String name, int startItemId, int endItemId)
|
||||
{
|
||||
return new RangeItemRequirement(name, startItemId, endItemId);
|
||||
}
|
||||
|
||||
private static AnyRequirementCollection any(String name, ItemRequirement... requirements)
|
||||
{
|
||||
return new AnyRequirementCollection(name, requirements);
|
||||
}
|
||||
|
||||
private static AllRequirementsCollection all(ItemRequirement... requirements)
|
||||
{
|
||||
return new AllRequirementsCollection(requirements);
|
||||
}
|
||||
|
||||
private static SlotLimitationRequirement emptySlot(String description, EquipmentInventorySlot... slots)
|
||||
{
|
||||
return new SlotLimitationRequirement(description, slots);
|
||||
}
|
||||
|
||||
private final String text;
|
||||
private final STASHUnit stashUnit;
|
||||
private final WorldPoint location;
|
||||
private final Emote firstEmote;
|
||||
private final Emote secondEmote;
|
||||
private final 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, STASHUnit stashUnit, WorldPoint location, Emote firstEmote, Emote secondEmote, @Nonnull ItemRequirement... itemRequirements)
|
||||
{
|
||||
this.text = text;
|
||||
this.stashUnit = stashUnit;
|
||||
this.location = location;
|
||||
this.firstEmote = firstEmote;
|
||||
this.secondEmote = secondEmote;
|
||||
this.itemRequirements = itemRequirements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin)
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder().text("Emote Clue").build());
|
||||
panelComponent.getChildren().add(LineComponent.builder().left("Emotes:").build());
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(getFirstEmote().getName())
|
||||
.leftColor(TITLED_CONTENT_COLOR)
|
||||
.build());
|
||||
|
||||
if (getSecondEmote() != null)
|
||||
{
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(getSecondEmote().getName())
|
||||
.leftColor(TITLED_CONTENT_COLOR)
|
||||
.build());
|
||||
}
|
||||
|
||||
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();
|
||||
Item[] inventory = plugin.getInventoryItems();
|
||||
|
||||
// If equipment is null, the player is wearing nothing
|
||||
if (equipment == null)
|
||||
{
|
||||
equipment = new Item[0];
|
||||
}
|
||||
|
||||
// If inventory is null, the player has nothing in their inventory
|
||||
if (inventory == null)
|
||||
{
|
||||
inventory = new Item[0];
|
||||
}
|
||||
|
||||
Item[] combined = new Item[equipment.length + inventory.length];
|
||||
System.arraycopy(equipment, 0, combined, 0, equipment.length);
|
||||
System.arraycopy(inventory, 0, combined, equipment.length, inventory.length);
|
||||
|
||||
for (ItemRequirement requirement : itemRequirements)
|
||||
{
|
||||
boolean equipmentFulfilled = requirement.fulfilledBy(equipment);
|
||||
boolean combinedFulfilled = requirement.fulfilledBy(combined);
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(requirement.getCollectiveName(client))
|
||||
.leftColor(TITLED_CONTENT_COLOR)
|
||||
.right(combinedFulfilled ? UNICODE_CHECK_MARK : UNICODE_BALLOT_X)
|
||||
.rightColor(equipmentFulfilled ? Color.GREEN : (combinedFulfilled ? Color.ORANGE : Color.RED))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin)
|
||||
{
|
||||
LocalPoint localPoint = LocalPoint.fromWorld(plugin.getClient(), getLocation());
|
||||
|
||||
if (localPoint != null)
|
||||
{
|
||||
OverlayUtil.renderTileOverlay(plugin.getClient(), graphics, localPoint, 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)
|
||||
{
|
||||
for (EmoteClue clue : CLUES)
|
||||
{
|
||||
if (clue.getText().equalsIgnoreCase(text))
|
||||
{
|
||||
return clue;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,127 +51,127 @@ import static net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdArea.
|
||||
@Getter
|
||||
public enum HotColdLocation
|
||||
{
|
||||
ASGARNIA_WARRIORS(new WorldPoint(2860, 3562, 0), ASGARNIA, "North of the Warriors' Guild in Burthorpe."),
|
||||
ASGARNIA_JATIX(new WorldPoint(2914, 3429, 0), ASGARNIA, "East of Jatix's Herblore Shop in Taverley."),
|
||||
ASGARNIA_BARB(new WorldPoint(3036, 3439, 0), ASGARNIA, "West of Barbarian Village."),
|
||||
ASGARNIA_MIAZRQA(new WorldPoint(2973, 3489, 0), ASGARNIA, "North of Miazrqa's tower, outside Goblin Village."),
|
||||
ASGARNIA_COW(new WorldPoint(3033, 3308, 0), ASGARNIA, "In the cow pen north of Sarah's Farming Shop."),
|
||||
ASGARNIA_PARTY_ROOM(new WorldPoint(3026, 3363, 0), ASGARNIA, "Outside the Falador Party Room."),
|
||||
ASGARNIA_CRAFT_GUILD(new WorldPoint(2917, 3295, 0), ASGARNIA, "Outside the Crafting Guild cow pen."),
|
||||
ASGARNIA_RIMMINGTON(new WorldPoint(2978, 3241, 0), ASGARNIA, "In the centre of the Rimmington mine."),
|
||||
ASGARNIA_WARRIORS(new WorldPoint(2860, 3562, 0), ASGARNIA, "North of the Warriors' Guild in Burthorpe."),
|
||||
ASGARNIA_JATIX(new WorldPoint(2914, 3429, 0), ASGARNIA, "East of Jatix's Herblore Shop in Taverley."),
|
||||
ASGARNIA_BARB(new WorldPoint(3036, 3439, 0), ASGARNIA, "West of Barbarian Village."),
|
||||
ASGARNIA_MIAZRQA(new WorldPoint(2973, 3489, 0), ASGARNIA, "North of Miazrqa's tower, outside Goblin Village."),
|
||||
ASGARNIA_COW(new WorldPoint(3033, 3308, 0), ASGARNIA, "In the cow pen north of Sarah's Farming Shop."),
|
||||
ASGARNIA_PARTY_ROOM(new WorldPoint(3026, 3363, 0), ASGARNIA, "Outside the Falador Party Room."),
|
||||
ASGARNIA_CRAFT_GUILD(new WorldPoint(2917, 3295, 0), ASGARNIA, "Outside the Crafting Guild cow pen."),
|
||||
ASGARNIA_RIMMINGTON(new WorldPoint(2978, 3241, 0), ASGARNIA, "In the centre of the Rimmington mine."),
|
||||
ASGARNIA_MUDSKIPPER(new WorldPoint(2984, 3109, 0), ASGARNIA, "Mudskipper Point, on the starfish in the south-west corner."),
|
||||
ASGARNIA_TROLL(new WorldPoint(2910, 3616, 0), ASGARNIA, "The Troll arena, where the player fights Dad during the Troll Stronghold quest. Bring climbing boots if travelling from Burthorpe."),
|
||||
DESERT_GENIE(new WorldPoint(3364, 2910, 0), DESERT, "West of Nardah genie cave."),
|
||||
DESERT_ALKHARID_MINE(new WorldPoint(3282, 3270, 0), DESERT, "West of Al Kharid mine."),
|
||||
DESERT_MENAPHOS_GATE(new WorldPoint(3224, 2816, 0), DESERT, "North of Menaphos gate."),
|
||||
ASGARNIA_TROLL(new WorldPoint(2910, 3616, 0), ASGARNIA, "The Troll arena, where the player fights Dad during the Troll Stronghold quest. Bring climbing boots if travelling from Burthorpe."),
|
||||
DESERT_GENIE(new WorldPoint(3364, 2910, 0), DESERT, "West of Nardah genie cave."),
|
||||
DESERT_ALKHARID_MINE(new WorldPoint(3282, 3270, 0), DESERT, "West of Al Kharid mine."),
|
||||
DESERT_MENAPHOS_GATE(new WorldPoint(3224, 2816, 0), DESERT, "North of Menaphos gate."),
|
||||
DESERT_BEDABIN_CAMP(new WorldPoint(3164, 3050, 0), DESERT, "Bedabin Camp, dig around the north tent."),
|
||||
DESERT_UZER(new WorldPoint(3431, 3106, 0), DESERT, "West of Uzer."),
|
||||
DESERT_POLLNIVNEACH(new WorldPoint(3287, 2975, 0), DESERT, "West of Pollnivneach."),
|
||||
DESERT_MTA(new WorldPoint(3350, 3293, 0), DESERT, "Next to Mage Training Arena."),
|
||||
DESERT_SHANTY(new WorldPoint(3294, 3106, 0), DESERT, "South-west of Shantay Pass."),
|
||||
FELDIP_HILLS_JIGGIG(new WorldPoint(2413, 3055, 0), FELDIP_HILLS, "West of Jiggig, east of the fairy ring bkp."),
|
||||
FELDIP_HILLS_SW(new WorldPoint(2582, 2895, 0), FELDIP_HILLS, "West of the southeasternmost lake in Feldip Hills."),
|
||||
FELDIP_HILLS_GNOME_GLITER(new WorldPoint(2553, 2972, 0), FELDIP_HILLS, "East of the gnome glider (Lemantolly Undri)."),
|
||||
FELDIP_HILLS_RANTZ(new WorldPoint(2611, 2946, 0), FELDIP_HILLS, "South of Rantz, six steps west of the empty glass bottles."),
|
||||
FELDIP_HILLS_SOUTH(new WorldPoint(2487, 3005, 0), FELDIP_HILLS, "South of Jiggig."),
|
||||
FELDIP_HILLS_RED_CHIN(new WorldPoint(2532, 2900, 0), FELDIP_HILLS, "Outside the red chinchompa hunting ground entrance, south of the Hunting expert's hut."),
|
||||
FELDIP_HILLS_SE(new WorldPoint(2567, 2916, 0), FELDIP_HILLS, "South-east of the ∩-shaped lake, near the icon."),
|
||||
FELDIP_HILLS_CW_BALLOON(new WorldPoint(2452, 3108, 0), FELDIP_HILLS, "Directly west of the Castle Wars balloon."),
|
||||
FREMENNIK_PROVINCE_MTN_CAMP(new WorldPoint(2804, 3672, 0), FREMENNIK_PROVINCE, "At the Mountain Camp."),
|
||||
FREMENNIK_PROVINCE_RELLEKKA_HUNTER(new WorldPoint(2724, 3783, 0), FREMENNIK_PROVINCE, "At the Rellekka Hunter area, near the icon."),
|
||||
FREMENNIK_PROVINCE_KELGADRIM_ENTRANCE(new WorldPoint(2715, 3689, 0), FREMENNIK_PROVINCE, "West of the Keldagrim entrance mine."),
|
||||
FREMENNIK_PROVINCE_SW(new WorldPoint(2605, 3648, 0), FREMENNIK_PROVINCE, "Outside the fence in the south-western corner of Rellekka."),
|
||||
FREMENNIK_PROVINCE_LIGHTHOUSE(new WorldPoint(2589, 3598, 0), FREMENNIK_PROVINCE, "South-east of the Lighthouse."),
|
||||
FREMENNIK_PROVINCE_ETCETERIA_CASTLE(new WorldPoint(2614, 3867, 0), FREMENNIK_PROVINCE, "Inside Etceteria's castle, in the southern staircase."),
|
||||
FREMENNIK_PROVINCE_MISC_COURTYARD(new WorldPoint(2529, 3867, 0), FREMENNIK_PROVINCE, "Outside Miscellania's courtyard."),
|
||||
DESERT_UZER(new WorldPoint(3431, 3106, 0), DESERT, "West of Uzer."),
|
||||
DESERT_POLLNIVNEACH(new WorldPoint(3287, 2975, 0), DESERT, "West of Pollnivneach."),
|
||||
DESERT_MTA(new WorldPoint(3350, 3293, 0), DESERT, "Next to Mage Training Arena."),
|
||||
DESERT_SHANTY(new WorldPoint(3294, 3106, 0), DESERT, "South-west of Shantay Pass."),
|
||||
FELDIP_HILLS_JIGGIG(new WorldPoint(2413, 3055, 0), FELDIP_HILLS, "West of Jiggig, east of the fairy ring bkp."),
|
||||
FELDIP_HILLS_SW(new WorldPoint(2582, 2895, 0), FELDIP_HILLS, "West of the southeasternmost lake in Feldip Hills."),
|
||||
FELDIP_HILLS_GNOME_GLITER(new WorldPoint(2553, 2972, 0), FELDIP_HILLS, "East of the gnome glider (Lemantolly Undri)."),
|
||||
FELDIP_HILLS_RANTZ(new WorldPoint(2611, 2946, 0), FELDIP_HILLS, "South of Rantz, six steps west of the empty glass bottles."),
|
||||
FELDIP_HILLS_SOUTH(new WorldPoint(2487, 3005, 0), FELDIP_HILLS, "South of Jiggig."),
|
||||
FELDIP_HILLS_RED_CHIN(new WorldPoint(2532, 2900, 0), FELDIP_HILLS, "Outside the red chinchompa hunting ground entrance, south of the Hunting expert's hut."),
|
||||
FELDIP_HILLS_SE(new WorldPoint(2567, 2916, 0), FELDIP_HILLS, "South-east of the ∩-shaped lake, near the icon."),
|
||||
FELDIP_HILLS_CW_BALLOON(new WorldPoint(2452, 3108, 0), FELDIP_HILLS, "Directly west of the Castle Wars balloon."),
|
||||
FREMENNIK_PROVINCE_MTN_CAMP(new WorldPoint(2804, 3672, 0), FREMENNIK_PROVINCE, "At the Mountain Camp."),
|
||||
FREMENNIK_PROVINCE_RELLEKKA_HUNTER(new WorldPoint(2724, 3783, 0), FREMENNIK_PROVINCE, "At the Rellekka Hunter area, near the icon."),
|
||||
FREMENNIK_PROVINCE_KELGADRIM_ENTRANCE(new WorldPoint(2715, 3689, 0), FREMENNIK_PROVINCE, "West of the Keldagrim entrance mine."),
|
||||
FREMENNIK_PROVINCE_SW(new WorldPoint(2605, 3648, 0), FREMENNIK_PROVINCE, "Outside the fence in the south-western corner of Rellekka."),
|
||||
FREMENNIK_PROVINCE_LIGHTHOUSE(new WorldPoint(2589, 3598, 0), FREMENNIK_PROVINCE, "South-east of the Lighthouse."),
|
||||
FREMENNIK_PROVINCE_ETCETERIA_CASTLE(new WorldPoint(2614, 3867, 0), FREMENNIK_PROVINCE, "Inside Etceteria's castle, in the southern staircase."),
|
||||
FREMENNIK_PROVINCE_MISC_COURTYARD(new WorldPoint(2529, 3867, 0), FREMENNIK_PROVINCE, "Outside Miscellania's courtyard."),
|
||||
FREMENNIK_PROVINCE_FREMMY_ISLES_MINE(new WorldPoint(2378, 3849, 0), FREMENNIK_PROVINCE, "Central Fremennik Isles mine."),
|
||||
FREMENNIK_PROVINCE_WEST_ISLES_MINE(new WorldPoint(2313, 3854, 0), FREMENNIK_PROVINCE, "West Fremennik Isles mine."),
|
||||
FREMENNIK_PROVINCE_WEST_JATIZSO_ENTRANCE(new WorldPoint(2391, 3813, 0), FREMENNIK_PROVINCE, "West of the Jatizso mine entrance."),
|
||||
FREMENNIK_PROVINCE_WEST_JATIZSO_ENTRANCE(new WorldPoint(2391, 3813, 0), FREMENNIK_PROVINCE, "West of the Jatizso mine entrance."),
|
||||
FREMENNIK_PROVINCE_PIRATES_COVE(new WorldPoint(2210, 3814, 0), FREMENNIK_PROVINCE, "Pirates' Cove"),
|
||||
FREMENNIK_PROVINCE_ASTRAL_ALTER(new WorldPoint(2147, 3862, 0), FREMENNIK_PROVINCE, "Astral altar"),
|
||||
FREMENNIK_PROVINCE_LUNAR_VILLAGE(new WorldPoint(2087, 3915, 0), FREMENNIK_PROVINCE, "Lunar Isle, inside the village."),
|
||||
FREMENNIK_PROVINCE_LUNAR_NORTH(new WorldPoint(2106, 3949, 0), FREMENNIK_PROVINCE, "Lunar Isle, north of the village."),
|
||||
KANDARIN_SINCLAR_MANSION(new WorldPoint(2726, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut."),
|
||||
KANDARIN_SINCLAR_MANSION(new WorldPoint(2726, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut."),
|
||||
KANDARIN_CATHERBY(new WorldPoint(2774, 3433, 0), KANDARIN, "Catherby, between the bank and the beehives, near small rock formation."),
|
||||
KANDARIN_GRAND_TREE(new WorldPoint(2444, 3503, 0), KANDARIN, "Grand Tree, just east of the terrorchick gnome enclosure."),
|
||||
KANDARIN_SEERS(new WorldPoint(2735, 3486, 0), KANDARIN, "Between the Seers' Village bank and Camelot."),
|
||||
KANDARIN_SEERS(new WorldPoint(2735, 3486, 0), KANDARIN, "Between the Seers' Village bank and Camelot."),
|
||||
KANDARIN_MCGRUBORS_WOOD(new WorldPoint(2653, 3485, 0), KANDARIN, "McGrubor's Wood"),
|
||||
KANDARIN_FISHING_BUILD(new WorldPoint(2586, 3372, 0), KANDARIN, "South of Fishing Guild"),
|
||||
KANDARIN_WITCHHAVEN(new WorldPoint(2708, 3304, 0), KANDARIN, "Outside Witchaven, west of Jeb, Holgart, and Caroline."),
|
||||
KANDARIN_NECRO_TOWER(new WorldPoint(2669, 3242, 0), KANDARIN, "Ground floor inside the Necromancer Tower. Easily accessed by using fairy ring code djp."),
|
||||
KANDARIN_FIGHT_ARENA(new WorldPoint(2587, 3134, 0), KANDARIN, "South of the Fight Arena, north-west of the Nightmare Zone."),
|
||||
KANDARIN_TREE_GNOME_VILLAGE(new WorldPoint(2526, 3160, 0), KANDARIN, "Tree Gnome Village, near the general store icon."),
|
||||
KANDARIN_FISHING_BUILD(new WorldPoint(2586, 3372, 0), KANDARIN, "South of Fishing Guild"),
|
||||
KANDARIN_WITCHHAVEN(new WorldPoint(2708, 3304, 0), KANDARIN, "Outside Witchaven, west of Jeb, Holgart, and Caroline."),
|
||||
KANDARIN_NECRO_TOWER(new WorldPoint(2669, 3242, 0), KANDARIN, "Ground floor inside the Necromancer Tower. Easily accessed by using fairy ring code djp."),
|
||||
KANDARIN_FIGHT_ARENA(new WorldPoint(2587, 3134, 0), KANDARIN, "South of the Fight Arena, north-west of the Nightmare Zone."),
|
||||
KANDARIN_TREE_GNOME_VILLAGE(new WorldPoint(2526, 3160, 0), KANDARIN, "Tree Gnome Village, near the general store icon."),
|
||||
KANDARIN_GRAVE_OF_SCORPIUS(new WorldPoint(2464, 3228, 0), KANDARIN, "Grave of Scorpius"),
|
||||
KANDARIN_KHAZARD_BATTLEFIELD(new WorldPoint(2518, 3249, 0), KANDARIN, "Khazard Battlefield, in the small ruins south of tracker gnome 2."),
|
||||
KANDARIN_KHAZARD_BATTLEFIELD(new WorldPoint(2518, 3249, 0), KANDARIN, "Khazard Battlefield, in the small ruins south of tracker gnome 2."),
|
||||
KANDARIN_WEST_ARDY(new WorldPoint(2533, 3320, 0), KANDARIN, "West Ardougne, near the staircase outside the Civic Office."),
|
||||
KANDARIN_SW_TREE_GNOME_STRONGHOLD(new WorldPoint(2411, 3431, 0), KANDARIN, "South-west Tree Gnome Stronghold"),
|
||||
KANDARIN_OUTPOST(new WorldPoint(2458, 3364, 0), KANDARIN, "South of the Tree Gnome Stronghold, north-east of the Outpost."),
|
||||
KANDARIN_BAXTORIAN_FALLS(new WorldPoint(2534, 3479, 0), KANDARIN, "South-east of Almera's house on Baxtorian Falls."),
|
||||
KANDARIN_BA_AGILITY_COURSE(new WorldPoint(2536, 3546, 0), KANDARIN, "Inside the Barbarian Agility Course. Completion of Alfred Grimhand's Barcrawl is required."),
|
||||
KANDARIN_SW_TREE_GNOME_STRONGHOLD(new WorldPoint(2411, 3431, 0), KANDARIN, "South-west Tree Gnome Stronghold"),
|
||||
KANDARIN_OUTPOST(new WorldPoint(2458, 3364, 0), KANDARIN, "South of the Tree Gnome Stronghold, north-east of the Outpost."),
|
||||
KANDARIN_BAXTORIAN_FALLS(new WorldPoint(2534, 3479, 0), KANDARIN, "South-east of Almera's house on Baxtorian Falls."),
|
||||
KANDARIN_BA_AGILITY_COURSE(new WorldPoint(2536, 3546, 0), KANDARIN, "Inside the Barbarian Agility Course. Completion of Alfred Grimhand's Barcrawl is required."),
|
||||
KARAMJA_MUSA_POINT(new WorldPoint(2914, 3168, 0), KARAMJA, "Musa Point, banana plantation."),
|
||||
KARAMJA_BRIMHAVEN_FRUIT_TREE(new WorldPoint(2783, 3214, 0), KARAMJA, "Brimhaven, east of the fruit tree patch."),
|
||||
KARAMJA_WEST_BRIMHAVEN(new WorldPoint(2721, 3169, 0), KARAMJA, "West of Brimhaven."),
|
||||
KARAMJA_GLIDER(new WorldPoint(2966, 2975, 0), KARAMJA, "West of the gnome glider."),
|
||||
KARAMJA_KHARAZI_NE(new WorldPoint(2908, 2922, 0), KARAMJA, "North-eastern part of Kharazi Jungle."),
|
||||
KARAMJA_KHARAZI_SW(new WorldPoint(2783, 2898, 0), KARAMJA, "South-western part of Kharazi Jungle."),
|
||||
KARAMJA_CRASH_ISLAND(new WorldPoint(2910, 2737, 0), KARAMJA, "Northern part of Crash Island."),
|
||||
MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."),
|
||||
MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."),
|
||||
MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."),
|
||||
MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "North-east of Gertrude's house west of Varrock."),
|
||||
MISTHALIN_DRAYNOR_BANK(new WorldPoint(3096, 3235, 0), MISTHALIN, "South of Draynor Village bank."),
|
||||
MISTHALIN_LUMBER_YARD(new WorldPoint(3303, 3483, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf."),
|
||||
MORYTANIA_BURGH_DE_ROTT(new WorldPoint(3545, 3253, 0), MORYTANIA, "In the north-east area of Burgh de Rott, by the reverse-L-shaped ruins."),
|
||||
MORYTANIA_PORT_PHASMATYS(new WorldPoint(3613, 3485, 0), MORYTANIA, "West of Port Phasmatys, south-east of fairy ring."),
|
||||
MORYTANIA_HOLLOWS(new WorldPoint(3500, 3423, 0), MORYTANIA, "Inside The Hollows, south of the bridge which was repaired in a quest."),
|
||||
MORYTANIA_SWAMP(new WorldPoint(3422, 3374, 0), MORYTANIA, "Inside the Mort Myre Swamp, north-west of the Nature Grotto."),
|
||||
MORYTANIA_HAUNTED_MINE(new WorldPoint(3441, 3259, 0), MORYTANIA, "At Haunted Mine quest start."),
|
||||
MORYTANIA_MAUSOLEUM(new WorldPoint(3499, 3539, 0), MORYTANIA, "South of the Mausoleum."),
|
||||
MORYTANIA_MOS_LES_HARMLESS(new WorldPoint(3744, 3041, 0), MORYTANIA, "Northern area of Mos Le'Harmless, between the lakes."),
|
||||
MORYTANIA_MOS_LES_HARMLESS_BAR(new WorldPoint(3670, 2974, 0), MORYTANIA, "Near Mos Le'Harmless southern bar."),
|
||||
MORYTANIA_DRAGONTOOTH_NORTH(new WorldPoint(3813, 3567, 0), MORYTANIA, "Northern part of Dragontooth Island."),
|
||||
MORYTANIA_DRAGONTOOTH_SOUTH(new WorldPoint(3803, 3532, 0), MORYTANIA, "Southern part of Dragontooth Island."),
|
||||
WESTERN_PROVINCE_EAGLES_PEAK(new WorldPoint(2297, 3530, 0), WESTERN_PROVINCE, "North-west of Eagles' Peak."),
|
||||
KARAMJA_BRIMHAVEN_FRUIT_TREE(new WorldPoint(2783, 3214, 0), KARAMJA, "Brimhaven, east of the fruit tree patch."),
|
||||
KARAMJA_WEST_BRIMHAVEN(new WorldPoint(2721, 3169, 0), KARAMJA, "West of Brimhaven."),
|
||||
KARAMJA_GLIDER(new WorldPoint(2966, 2975, 0), KARAMJA, "West of the gnome glider."),
|
||||
KARAMJA_KHARAZI_NE(new WorldPoint(2908, 2922, 0), KARAMJA, "North-eastern part of Kharazi Jungle."),
|
||||
KARAMJA_KHARAZI_SW(new WorldPoint(2783, 2898, 0), KARAMJA, "South-western part of Kharazi Jungle."),
|
||||
KARAMJA_CRASH_ISLAND(new WorldPoint(2910, 2737, 0), KARAMJA, "Northern part of Crash Island."),
|
||||
MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."),
|
||||
MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."),
|
||||
MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."),
|
||||
MISTHALIN_GERTUDES(new WorldPoint(3158, 3421, 0), MISTHALIN, "North-east of Gertrude's house west of Varrock."),
|
||||
MISTHALIN_DRAYNOR_BANK(new WorldPoint(3096, 3235, 0), MISTHALIN, "South of Draynor Village bank."),
|
||||
MISTHALIN_LUMBER_YARD(new WorldPoint(3303, 3483, 0), MISTHALIN, "South of Lumber Yard, east of Assistant Serf."),
|
||||
MORYTANIA_BURGH_DE_ROTT(new WorldPoint(3545, 3253, 0), MORYTANIA, "In the north-east area of Burgh de Rott, by the reverse-L-shaped ruins."),
|
||||
MORYTANIA_PORT_PHASMATYS(new WorldPoint(3613, 3485, 0), MORYTANIA, "West of Port Phasmatys, south-east of fairy ring."),
|
||||
MORYTANIA_HOLLOWS(new WorldPoint(3500, 3423, 0), MORYTANIA, "Inside The Hollows, south of the bridge which was repaired in a quest."),
|
||||
MORYTANIA_SWAMP(new WorldPoint(3422, 3374, 0), MORYTANIA, "Inside the Mort Myre Swamp, north-west of the Nature Grotto."),
|
||||
MORYTANIA_HAUNTED_MINE(new WorldPoint(3441, 3259, 0), MORYTANIA, "At Haunted Mine quest start."),
|
||||
MORYTANIA_MAUSOLEUM(new WorldPoint(3499, 3539, 0), MORYTANIA, "South of the Mausoleum."),
|
||||
MORYTANIA_MOS_LES_HARMLESS(new WorldPoint(3744, 3041, 0), MORYTANIA, "Northern area of Mos Le'Harmless, between the lakes."),
|
||||
MORYTANIA_MOS_LES_HARMLESS_BAR(new WorldPoint(3670, 2974, 0), MORYTANIA, "Near Mos Le'Harmless southern bar."),
|
||||
MORYTANIA_DRAGONTOOTH_NORTH(new WorldPoint(3813, 3567, 0), MORYTANIA, "Northern part of Dragontooth Island."),
|
||||
MORYTANIA_DRAGONTOOTH_SOUTH(new WorldPoint(3803, 3532, 0), MORYTANIA, "Southern part of Dragontooth Island."),
|
||||
WESTERN_PROVINCE_EAGLES_PEAK(new WorldPoint(2297, 3530, 0), WESTERN_PROVINCE, "North-west of Eagles' Peak."),
|
||||
WESTERN_PROVINCE_PISCATORIS(new WorldPoint(2337, 3689, 0), WESTERN_PROVINCE, "Piscatoris Fishing Colony"),
|
||||
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2361, 3566, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry."),
|
||||
WESTERN_PROVINCE_ARANDAR(new WorldPoint(2366, 3318, 0), WESTERN_PROVINCE, "South-west of the crystal gate to Arandar."),
|
||||
WESTERN_PROVINCE_ELF_CAMP_EAST(new WorldPoint(2270, 3244, 0), WESTERN_PROVINCE, "East of Elf Camp."),
|
||||
WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2174, 3280, 0), WESTERN_PROVINCE, "North-west of Elf Camp."),
|
||||
WESTERN_PROVINCE_LLETYA(new WorldPoint(2335, 3166, 0), WESTERN_PROVINCE, "In Lletya."),
|
||||
WESTERN_PROVINCE_TYRAS(new WorldPoint(2204, 3157, 0), WESTERN_PROVINCE, "Near Tyras Camp."),
|
||||
WESTERN_PROVINCE_ZULANDRA(new WorldPoint(2196, 3057, 0), WESTERN_PROVINCE, "The northern house at Zul-Andra."),
|
||||
WILDERNESS_5(new WorldPoint(3169, 3558, 0), WILDERNESS, "North of the Grand Exchange, level 5 Wilderness."),
|
||||
WILDERNESS_12(new WorldPoint(3038, 3612, 0), WILDERNESS, "South-east of the Dark Warriors' Fortress, level 12 Wilderness."),
|
||||
WILDERNESS_20(new WorldPoint(3225, 3676, 0), WILDERNESS, "East of the Corporeal Beast's lair, level 20 Wilderness."),
|
||||
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2361, 3566, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry."),
|
||||
WESTERN_PROVINCE_ARANDAR(new WorldPoint(2366, 3318, 0), WESTERN_PROVINCE, "South-west of the crystal gate to Arandar."),
|
||||
WESTERN_PROVINCE_ELF_CAMP_EAST(new WorldPoint(2270, 3244, 0), WESTERN_PROVINCE, "East of Elf Camp."),
|
||||
WESTERN_PROVINCE_ELF_CAMP_NW(new WorldPoint(2174, 3280, 0), WESTERN_PROVINCE, "North-west of Elf Camp."),
|
||||
WESTERN_PROVINCE_LLETYA(new WorldPoint(2335, 3166, 0), WESTERN_PROVINCE, "In Lletya."),
|
||||
WESTERN_PROVINCE_TYRAS(new WorldPoint(2204, 3157, 0), WESTERN_PROVINCE, "Near Tyras Camp."),
|
||||
WESTERN_PROVINCE_ZULANDRA(new WorldPoint(2196, 3057, 0), WESTERN_PROVINCE, "The northern house at Zul-Andra."),
|
||||
WILDERNESS_5(new WorldPoint(3169, 3558, 0), WILDERNESS, "North of the Grand Exchange, level 5 Wilderness."),
|
||||
WILDERNESS_12(new WorldPoint(3038, 3612, 0), WILDERNESS, "South-east of the Dark Warriors' Fortress, level 12 Wilderness."),
|
||||
WILDERNESS_20(new WorldPoint(3225, 3676, 0), WILDERNESS, "East of the Corporeal Beast's lair, level 20 Wilderness."),
|
||||
WILDERNESS_27(new WorldPoint(3174, 3735, 0), WILDERNESS, "Inside the Ruins north of the Graveyard of Shadows, level 27 Wilderness."),
|
||||
WILDERNESS_28(new WorldPoint(3374, 3734, 0), WILDERNESS, "East of Venenatis' nest, level 28 Wilderness."),
|
||||
WILDERNESS_28(new WorldPoint(3374, 3734, 0), WILDERNESS, "East of Venenatis' nest, level 28 Wilderness."),
|
||||
WILDERNESS_32(new WorldPoint(3311, 3773, 0), WILDERNESS, "North of Venenatis' nest, level 32 Wilderness."),
|
||||
WILDERNESS_35(new WorldPoint(3153, 3795, 0), WILDERNESS, "East of the Wilderness canoe exit, level 35 Wilderness."),
|
||||
WILDERNESS_37(new WorldPoint(2975, 3811, 0), WILDERNESS, "South-east of the Chaos Temple, level 37 Wilderness."),
|
||||
WILDERNESS_38(new WorldPoint(3294, 3817, 0), WILDERNESS, "South of Callisto, level 38 Wilderness."),
|
||||
WILDERNESS_49(new WorldPoint(3140, 3910, 0), WILDERNESS, "South-west of the Deserted Keep, level 49 Wilderness."),
|
||||
WILDERNESS_54(new WorldPoint(2983, 3946, 0), WILDERNESS, "West of the Wilderness Agility Course, level 54 Wilderness."),
|
||||
ZEAH_BLASTMINE_BANK(new WorldPoint(1507, 3856, 0), ZEAH, "Next to the bank in the Lovakengj blast mine."),
|
||||
ZEAH_BLASTMINE_NORTH(new WorldPoint(1490, 3883, 0), ZEAH, "Northern part of the Lovakengj blast mine."),
|
||||
ZEAH_LOVAKITE_FURNACE(new WorldPoint(1505, 3814, 0), ZEAH, "Next to the lovakite furnace in Lovakengj."),
|
||||
ZEAH_LOVAKENGJ_MINE(new WorldPoint(1477, 3779, 0), ZEAH, "Next to mithril rock in the Lovakengj mine."),
|
||||
ZEAH_SULPHR_MINE(new WorldPoint(1428, 3866, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine."),
|
||||
WILDERNESS_35(new WorldPoint(3153, 3795, 0), WILDERNESS, "East of the Wilderness canoe exit, level 35 Wilderness."),
|
||||
WILDERNESS_37(new WorldPoint(2975, 3811, 0), WILDERNESS, "South-east of the Chaos Temple, level 37 Wilderness."),
|
||||
WILDERNESS_38(new WorldPoint(3294, 3817, 0), WILDERNESS, "South of Callisto, level 38 Wilderness."),
|
||||
WILDERNESS_49(new WorldPoint(3140, 3910, 0), WILDERNESS, "South-west of the Deserted Keep, level 49 Wilderness."),
|
||||
WILDERNESS_54(new WorldPoint(2983, 3946, 0), WILDERNESS, "West of the Wilderness Agility Course, level 54 Wilderness."),
|
||||
ZEAH_BLASTMINE_BANK(new WorldPoint(1507, 3856, 0), ZEAH, "Next to the bank in the Lovakengj blast mine."),
|
||||
ZEAH_BLASTMINE_NORTH(new WorldPoint(1490, 3883, 0), ZEAH, "Northern part of the Lovakengj blast mine."),
|
||||
ZEAH_LOVAKITE_FURNACE(new WorldPoint(1505, 3814, 0), ZEAH, "Next to the lovakite furnace in Lovakengj."),
|
||||
ZEAH_LOVAKENGJ_MINE(new WorldPoint(1477, 3779, 0), ZEAH, "Next to mithril rock in the Lovakengj mine."),
|
||||
ZEAH_SULPHR_MINE(new WorldPoint(1428, 3866, 0), ZEAH, "Western entrance in the Lovakengj sulphur mine."),
|
||||
ZEAH_SHAYZIEN_BANK(new WorldPoint(1517, 3603, 0), ZEAH, "South-east of the bank in Shayzien."),
|
||||
ZEAH_OVERPASS(new WorldPoint(1467, 3714, 0), ZEAH, "Overpass between Lovakengj and Shayzien."),
|
||||
ZEAH_LIZARDMAN(new WorldPoint(1493, 3694, 0), ZEAH, "Within Lizardman Canyon, east of the ladder. Requires 5% favour with Shayzien."),
|
||||
ZEAH_COMBAT_RING(new WorldPoint(1557, 3580, 0), ZEAH, "Shayzien, south-east of the Combat Ring."),
|
||||
ZEAH_SHAYZIEN_BANK_2(new WorldPoint(1494, 3622, 0), ZEAH, "North-west of the bank in Shayzien."),
|
||||
ZEAH_LIBRARY(new WorldPoint(1601, 3842, 0), ZEAH, "North-west of the Arceuus Library."),
|
||||
ZEAH_HOUSECHURCH(new WorldPoint(1682, 3792, 0), ZEAH, "By the entrance to the Arceuus church."),
|
||||
ZEAH_DARK_ALTAR(new WorldPoint(1699, 3879, 0), ZEAH, "West of the Dark Altar."),
|
||||
ZEAH_OVERPASS(new WorldPoint(1467, 3714, 0), ZEAH, "Overpass between Lovakengj and Shayzien."),
|
||||
ZEAH_LIZARDMAN(new WorldPoint(1493, 3694, 0), ZEAH, "Within Lizardman Canyon, east of the ladder. Requires 5% favour with Shayzien."),
|
||||
ZEAH_COMBAT_RING(new WorldPoint(1557, 3580, 0), ZEAH, "Shayzien, south-east of the Combat Ring."),
|
||||
ZEAH_SHAYZIEN_BANK_2(new WorldPoint(1494, 3622, 0), ZEAH, "North-west of the bank in Shayzien."),
|
||||
ZEAH_LIBRARY(new WorldPoint(1601, 3842, 0), ZEAH, "North-west of the Arceuus Library."),
|
||||
ZEAH_HOUSECHURCH(new WorldPoint(1682, 3792, 0), ZEAH, "By the entrance to the Arceuus church."),
|
||||
ZEAH_DARK_ALTAR(new WorldPoint(1699, 3879, 0), ZEAH, "West of the Dark Altar."),
|
||||
ZEAH_ARCEUUS_HOUSE(new WorldPoint(1708, 3701, 0), ZEAH, "By the southern entrance to Arceuus."),
|
||||
ZEAH_ESSENCE_MINE(new WorldPoint(1762, 3852, 0), ZEAH, "By the Arceuus essence mine."),
|
||||
ZEAH_ESSENCE_MINE_NE(new WorldPoint(1772, 3866, 0), ZEAH, "North-east of the Arceuus essence mine."),
|
||||
ZEAH_PISCARILUS_MINE(new WorldPoint(1768, 3705, 0), ZEAH, "South of the Piscarilius mine."),
|
||||
ZEAH_GOLDEN_FIELD_TAVERN(new WorldPoint(1718, 3647, 0), ZEAH, "South of The Golden Field tavern in the northern area of Hosidius."),
|
||||
ZEAH_MESS_HALL(new WorldPoint(1658, 3621, 0), ZEAH, "East of the Mess hall."),
|
||||
ZEAH_WATSONS_HOUSE(new WorldPoint(1653, 3573, 0), ZEAH, "East of Watson's house."),
|
||||
ZEAH_VANNAHS_FARM_STORE(new WorldPoint(1806, 3521, 0), ZEAH, "North of Vannah's Farm Store, between the chicken coop and willow trees."),
|
||||
ZEAH_ESSENCE_MINE(new WorldPoint(1762, 3852, 0), ZEAH, "By the Arceuus essence mine."),
|
||||
ZEAH_ESSENCE_MINE_NE(new WorldPoint(1772, 3866, 0), ZEAH, "North-east of the Arceuus essence mine."),
|
||||
ZEAH_PISCARILUS_MINE(new WorldPoint(1768, 3705, 0), ZEAH, "South of the Piscarilius mine."),
|
||||
ZEAH_GOLDEN_FIELD_TAVERN(new WorldPoint(1718, 3647, 0), ZEAH, "South of The Golden Field tavern in the northern area of Hosidius."),
|
||||
ZEAH_MESS_HALL(new WorldPoint(1658, 3621, 0), ZEAH, "East of the Mess hall."),
|
||||
ZEAH_WATSONS_HOUSE(new WorldPoint(1653, 3573, 0), ZEAH, "East of Watson's house."),
|
||||
ZEAH_VANNAHS_FARM_STORE(new WorldPoint(1806, 3521, 0), ZEAH, "North of Vannah's Farm Store, between the chicken coop and willow trees."),
|
||||
ZEAH_FARMING_GUILD_W(new WorldPoint(1209, 3737, 0), ZEAH, "West of the Farming Guild."),
|
||||
ZEAH_DAIRY_COW(new WorldPoint(1320, 3718, 0), ZEAH, "North-east of the Kebos Lowlands, east of the dairy cow."),
|
||||
ZEAH_CRIMSON_SWIFTS(new WorldPoint(1186, 3583, 0), ZEAH, "South-west of the Kebos Swamp, below the crimson swifts.");
|
||||
|
||||
@@ -46,8 +46,8 @@ public interface CookingConfig extends Config
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "fermentTimer",
|
||||
name = "Show wine fermenting timer",
|
||||
description = "Conifgures if the timer before wines are fermented is shown."
|
||||
name = "Show wine ferment timer",
|
||||
description = "Configures if the timer before wines are fermented is shown"
|
||||
)
|
||||
default boolean fermentTimer()
|
||||
{
|
||||
|
||||
@@ -29,8 +29,8 @@ import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.text.DecimalFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.Duration;
|
||||
import javax.inject.Inject;
|
||||
import static net.runelite.api.AnimationID.COOKING_FIRE;
|
||||
import static net.runelite.api.AnimationID.COOKING_RANGE;
|
||||
@@ -71,7 +71,7 @@ class CookingOverlay extends Overlay
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
CookingSession session = plugin.getCookingSession();
|
||||
CookingSession session = plugin.getSession();
|
||||
if (session == null)
|
||||
{
|
||||
return null;
|
||||
|
||||
@@ -28,23 +28,27 @@ package net.runelite.client.plugins.cooking;
|
||||
import com.google.inject.Provides;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
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.GraphicID;
|
||||
import net.runelite.api.ItemID;
|
||||
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.api.events.GraphicChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDependency;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerPlugin;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Cooking",
|
||||
@@ -61,19 +65,19 @@ public class CookingPlugin extends Plugin
|
||||
private CookingConfig config;
|
||||
|
||||
@Inject
|
||||
private CookingOverlay cookingOverlay;
|
||||
|
||||
@Inject
|
||||
private FermentTimerOverlay fermentTimerOverlay;
|
||||
private CookingOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private CookingSession cookingSession;
|
||||
@Inject
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private FermentTimerSession fermentTimerSession;
|
||||
private CookingSession session;
|
||||
|
||||
@Provides
|
||||
CookingConfig getConfig(ConfigManager configManager)
|
||||
@@ -84,69 +88,62 @@ public class CookingPlugin extends Plugin
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
cookingSession = null;
|
||||
fermentTimerSession = null;
|
||||
overlayManager.add(cookingOverlay);
|
||||
overlayManager.add(fermentTimerOverlay);
|
||||
session = null;
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(fermentTimerOverlay);
|
||||
overlayManager.remove(cookingOverlay);
|
||||
fermentTimerSession = null;
|
||||
cookingSession = null;
|
||||
infoBoxManager.removeIf(FermentTimer.class::isInstance);
|
||||
overlayManager.remove(overlay);
|
||||
session = null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick gameTick)
|
||||
{
|
||||
if (config.statTimeout() == 0)
|
||||
if (session == null || config.statTimeout() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (cookingSession != null)
|
||||
{
|
||||
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
|
||||
Duration sinceCut = Duration.between(cookingSession.getLastCookingAction(), Instant.now());
|
||||
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
|
||||
Duration sinceCut = Duration.between(session.getLastCookingAction(), Instant.now());
|
||||
|
||||
if (sinceCut.compareTo(statTimeout) >= 0)
|
||||
{
|
||||
cookingSession = null;
|
||||
}
|
||||
}
|
||||
if (fermentTimerSession != null)
|
||||
if (sinceCut.compareTo(statTimeout) >= 0)
|
||||
{
|
||||
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
|
||||
Duration sinceCut = Duration.between(fermentTimerSession.getLastWineMakingAction(), Instant.now());
|
||||
|
||||
if (sinceCut.compareTo(statTimeout) >= 0)
|
||||
{
|
||||
fermentTimerSession = null;
|
||||
}
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAnimationChanged(AnimationChanged animationChanged)
|
||||
public void onGraphicChanged(GraphicChanged graphicChanged)
|
||||
{
|
||||
Player localPlayer = client.getLocalPlayer();
|
||||
Player player = client.getLocalPlayer();
|
||||
|
||||
if (localPlayer != animationChanged.getActor())
|
||||
if (graphicChanged.getActor() != player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (localPlayer.getAnimation() == COOKING_WINE && config.fermentTimer())
|
||||
if (player.getGraphic() == GraphicID.WINE_MAKE && config.fermentTimer())
|
||||
{
|
||||
if (fermentTimerSession == null)
|
||||
{
|
||||
fermentTimerSession = new FermentTimerSession();
|
||||
}
|
||||
Optional<FermentTimer> fermentTimerOpt = infoBoxManager.getInfoBoxes().stream()
|
||||
.filter(FermentTimer.class::isInstance)
|
||||
.map(FermentTimer.class::cast)
|
||||
.findAny();
|
||||
|
||||
fermentTimerSession.updateLastWineMakingAction();
|
||||
if (fermentTimerOpt.isPresent())
|
||||
{
|
||||
FermentTimer fermentTimer = fermentTimerOpt.get();
|
||||
fermentTimer.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
FermentTimer fermentTimer = new FermentTimer(itemManager.getImage(ItemID.JUG_OF_WINE), this);
|
||||
infoBoxManager.addInfoBox(fermentTimer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,24 +163,24 @@ public class CookingPlugin extends Plugin
|
||||
|| message.startsWith("You roast a")
|
||||
|| message.startsWith("You cook"))
|
||||
{
|
||||
if (cookingSession == null)
|
||||
if (session == null)
|
||||
{
|
||||
cookingSession = new CookingSession();
|
||||
session = new CookingSession();
|
||||
}
|
||||
|
||||
cookingSession.updateLastCookingAction();
|
||||
cookingSession.increaseCookAmount();
|
||||
session.updateLastCookingAction();
|
||||
session.increaseCookAmount();
|
||||
|
||||
}
|
||||
else if (message.startsWith("You accidentally burn"))
|
||||
{
|
||||
if (cookingSession == null)
|
||||
if (session == null)
|
||||
{
|
||||
cookingSession = new CookingSession();
|
||||
session = new CookingSession();
|
||||
}
|
||||
|
||||
cookingSession.updateLastCookingAction();
|
||||
cookingSession.increaseBurnAmount();
|
||||
session.updateLastCookingAction();
|
||||
session.increaseBurnAmount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* 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.cooking;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Image;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBox;
|
||||
|
||||
final class FermentTimer extends InfoBox
|
||||
{
|
||||
private static final Duration FERMENT_TIME = Duration.ofMillis(13_800);
|
||||
|
||||
private Instant fermentTime;
|
||||
|
||||
FermentTimer(Image image, Plugin plugin)
|
||||
{
|
||||
super(image, plugin);
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
int seconds = timeUntilFerment();
|
||||
return Integer.toString(seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getTextColor()
|
||||
{
|
||||
int seconds = timeUntilFerment();
|
||||
return seconds <= 3 ? Color.RED : Color.WHITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cull()
|
||||
{
|
||||
int seconds = timeUntilFerment();
|
||||
return seconds <= 0;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
fermentTime = Instant.now().plus(FERMENT_TIME);
|
||||
}
|
||||
|
||||
private int timeUntilFerment()
|
||||
{
|
||||
return (int) Duration.between(Instant.now(), fermentTime).getSeconds();
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Lucas C <lucas1757@gmail.com>
|
||||
* 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.cooking;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import static net.runelite.api.AnimationID.COOKING_WINE;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
import net.runelite.client.ui.overlay.components.table.TableAlignment;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
|
||||
@Slf4j
|
||||
class FermentTimerOverlay extends Overlay
|
||||
{
|
||||
private static final int INITIAL_TIME = 12;
|
||||
|
||||
private final Client client;
|
||||
private final CookingPlugin plugin;
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
@Inject
|
||||
private FermentTimerOverlay(final Client client, final CookingPlugin plugin)
|
||||
{
|
||||
super(plugin);
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Fermenting Timer overlay"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
FermentTimerSession session = plugin.getFermentTimerSession();
|
||||
if (session == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
panelComponent.getChildren().clear();
|
||||
|
||||
if (isMakingWine() || Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds() < INITIAL_TIME)
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("Making Wine")
|
||||
.color(Color.GREEN)
|
||||
.build());
|
||||
|
||||
TableComponent tableComponent = new TableComponent();
|
||||
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
|
||||
tableComponent.addRow("Ferments in:", String.valueOf(INITIAL_TIME - Duration.between(session.getLastWineMakingAction(), Instant.now()).getSeconds()));
|
||||
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("Wine Fermented")
|
||||
.color(Color.ORANGE)
|
||||
.build());
|
||||
}
|
||||
|
||||
return panelComponent.render(graphics);
|
||||
}
|
||||
|
||||
private boolean isMakingWine()
|
||||
{
|
||||
return (client.getLocalPlayer().getAnimation() == COOKING_WINE);
|
||||
}
|
||||
}
|
||||
@@ -489,6 +489,7 @@ class DevToolsOverlay extends Overlay
|
||||
|
||||
WidgetItem widgetItem = widget.getWidgetItem(itemIndex);
|
||||
if (widgetItem == null
|
||||
|| widgetItem.getId() < 0
|
||||
|| widgetItem.getId() == ITEM_EMPTY
|
||||
|| widgetItem.getId() == ITEM_FILLED)
|
||||
{
|
||||
|
||||
@@ -123,7 +123,7 @@ public class ExaminePlugin extends Plugin
|
||||
int widgetChild = TO_CHILD(widgetId);
|
||||
Widget widget = client.getWidget(widgetGroup, widgetChild);
|
||||
WidgetItem widgetItem = widget.getWidgetItem(event.getActionParam());
|
||||
quantity = widgetItem != null ? widgetItem.getQuantity() : 1;
|
||||
quantity = widgetItem != null && widgetItem.getId() >= 0 ? widgetItem.getQuantity() : 1;
|
||||
break;
|
||||
}
|
||||
case EXAMINE_ITEM_BANK_EQ:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
|
||||
* Copyright (c) 2018, Lars <lars.oernlo@gmail.com>
|
||||
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -23,53 +22,41 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.mining;
|
||||
package net.runelite.client.plugins.inventorygrid;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("mining")
|
||||
public interface MiningConfig extends Config
|
||||
@ConfigGroup("inventorygrid")
|
||||
public interface InventoryGridConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showMiningRocks",
|
||||
name = "Show rock mining spots",
|
||||
description = "Configures whether or not the mining spots are displayed."
|
||||
keyName = "showItem",
|
||||
name = "Show item",
|
||||
description = "Show a preview of the item in the new slot"
|
||||
)
|
||||
default boolean showMiningRocks()
|
||||
default boolean showItem()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "statTimeout",
|
||||
name = "Reset stats (minutes)",
|
||||
description = "Configures the time until statistics are reset"
|
||||
keyName = "showGrid",
|
||||
name = "Show grid",
|
||||
description = "Show a grid on the inventory while dragging"
|
||||
)
|
||||
default int statTimeout()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMiningStats",
|
||||
name = "Show mining session stats",
|
||||
description = "Configures whether to display mining session stats"
|
||||
)
|
||||
default boolean showMiningStats()
|
||||
default boolean showGrid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMiningState",
|
||||
name = "Show current mining state",
|
||||
description = "Shows current mining state. 'You are currently mining' / 'You are currently NOT mining'"
|
||||
keyName = "showHighlight",
|
||||
name = "Highlight background",
|
||||
description = "Show a green background highlight on the new slot"
|
||||
)
|
||||
default boolean showMiningState()
|
||||
default boolean showHighlight()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -22,7 +23,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.inventoryhighlight;
|
||||
package net.runelite.client.plugins.inventorygrid;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.AlphaComposite;
|
||||
@@ -35,103 +36,78 @@ import java.awt.image.BufferedImage;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
|
||||
public class InventoryHighlightOverlay extends Overlay
|
||||
class InventoryGridOverlay extends Overlay
|
||||
{
|
||||
private final InventoryHighlightPlugin plugin;
|
||||
private final InventoryHighlightConfig config;
|
||||
private final Client client;
|
||||
private final ItemManager itemManager;
|
||||
|
||||
// the inventory widget location is slightly off
|
||||
private static final int FIXED_MARGIN_X = -10;
|
||||
private static final int FIXED_MARGIN_Y = -25;
|
||||
private static final int RESIZEABLE_MARGIN_X = -6;
|
||||
private static final int RESIZEABLE_MARGIN_Y = -21;
|
||||
|
||||
private static final int ITEM_WIDTH = 32;
|
||||
private static final int ITEM_HEIGHT = 32;
|
||||
private static final int ITEM_MARGIN_X = 10;
|
||||
private static final int ITEM_MARGIN_Y = 4;
|
||||
private static final int INVENTORY_SIZE = 28;
|
||||
private static final int DRAG_DELAY = 5;
|
||||
|
||||
private static final Color HIGHLIGHT = new Color(0, 255, 0, 45);
|
||||
private static final Color GRID = new Color(255, 255, 255, 45);
|
||||
|
||||
private final InventoryGridConfig config;
|
||||
private final Client client;
|
||||
private final ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
public InventoryHighlightOverlay(InventoryHighlightPlugin plugin, InventoryHighlightConfig config, Client client, ItemManager itemManager)
|
||||
private InventoryGridOverlay(InventoryGridConfig config, Client client, ItemManager itemManager)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.itemManager = itemManager;
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (plugin.getDraggingItem() == -1 || !plugin.isDragging())
|
||||
final Widget if1DraggingWidget = client.getIf1DraggedWidget();
|
||||
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
|
||||
|
||||
if (if1DraggingWidget == null || if1DraggingWidget != inventoryWidget
|
||||
|| client.getItemPressedDuration() < DRAG_DELAY)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int marginX, marginY;
|
||||
if (client.isResized())
|
||||
{
|
||||
marginX = RESIZEABLE_MARGIN_X;
|
||||
marginY = RESIZEABLE_MARGIN_Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
marginX = FIXED_MARGIN_X;
|
||||
marginY = FIXED_MARGIN_Y;
|
||||
}
|
||||
|
||||
final net.runelite.api.Point mouse = client.getMouseCanvasPosition();
|
||||
final Point updatedMouse = new Point(mouse.getX() + marginX, mouse.getY() + marginY);
|
||||
final Point mousePoint = new Point(mouse.getX(), mouse.getY());
|
||||
|
||||
// null checks for inventory are checked during dragging events
|
||||
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
|
||||
|
||||
final int inventoryX = inventoryWidget.getCanvasLocation().getX() + marginX;
|
||||
final int inventoryY = inventoryWidget.getCanvasLocation().getY() + marginY;
|
||||
|
||||
final BufferedImage draggedItemImage = itemManager.getImage(plugin.getDraggingItem());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int i = 0; i < INVENTORY_SIZE; ++i)
|
||||
{
|
||||
for (int j = 0; j < 7; j++)
|
||||
WidgetItem widgetItem = inventoryWidget.getWidgetItem(i);
|
||||
|
||||
final Rectangle bounds = widgetItem.getCanvasBounds();
|
||||
boolean inBounds = bounds.contains(mousePoint);
|
||||
|
||||
if (config.showItem() && inBounds)
|
||||
{
|
||||
final int x = (ITEM_WIDTH + ITEM_MARGIN_X) * i + inventoryX;
|
||||
final int y = (ITEM_HEIGHT + ITEM_MARGIN_Y) * j + inventoryY;
|
||||
final Rectangle bounds = new Rectangle(x, y, ITEM_WIDTH, ITEM_HEIGHT);
|
||||
final WidgetItem draggedItem = inventoryWidget.getWidgetItem(client.getIf1DraggedItemIndex());
|
||||
final BufferedImage draggedItemImage = itemManager.getImage(draggedItem.getId());
|
||||
final int x = (int) bounds.getX();
|
||||
final int y = (int) bounds.getY();
|
||||
|
||||
if (config.showItem() && bounds.contains(updatedMouse))
|
||||
{
|
||||
graphics.setComposite(AlphaComposite.SrcOver.derive(0.3f));
|
||||
graphics.drawImage(draggedItemImage, x, y, null);
|
||||
graphics.setComposite(AlphaComposite.SrcOver);
|
||||
}
|
||||
graphics.setComposite(AlphaComposite.SrcOver.derive(0.3f));
|
||||
graphics.drawImage(draggedItemImage, x, y, null);
|
||||
graphics.setComposite(AlphaComposite.SrcOver);
|
||||
}
|
||||
|
||||
if (config.showHighlight() && bounds.contains(updatedMouse))
|
||||
{
|
||||
graphics.setColor(HIGHLIGHT);
|
||||
graphics.fill(bounds);
|
||||
}
|
||||
|
||||
if (config.showGrid())
|
||||
{
|
||||
// don't set color on highlighted slot
|
||||
if (!config.showHighlight() || !(config.showHighlight() && bounds.contains(updatedMouse)))
|
||||
{
|
||||
graphics.setColor(GRID);
|
||||
graphics.fill(bounds);
|
||||
}
|
||||
}
|
||||
if (config.showHighlight() && inBounds)
|
||||
{
|
||||
graphics.setColor(HIGHLIGHT);
|
||||
graphics.fill(bounds);
|
||||
}
|
||||
else if (config.showGrid())
|
||||
{
|
||||
graphics.setColor(GRID);
|
||||
graphics.fill(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -22,79 +23,44 @@
|
||||
* (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.inventoryhighlight;
|
||||
package net.runelite.client.plugins.inventorygrid;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.input.MouseManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Inventory Highlight",
|
||||
description = "Shows a preview of where items will be dragged",
|
||||
name = "Inventory Grid",
|
||||
description = "Shows a grid over the inventory and a preview of where items will be dragged",
|
||||
tags = {"items", "overlay"},
|
||||
type = PluginType.UTILITY,
|
||||
enabledByDefault = false
|
||||
)
|
||||
|
||||
public class InventoryHighlightPlugin extends Plugin
|
||||
public class InventoryGridPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private InventoryHighlightOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private InventoryHighlightInputListener inputListener;
|
||||
|
||||
@Inject
|
||||
private MouseManager mouseManager;
|
||||
private InventoryGridOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private int draggingItem = -1;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean dragging = false;
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
mouseManager.registerMouseListener(inputListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
mouseManager.unregisterMouseListener(inputListener);
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
|
||||
@Provides
|
||||
InventoryHighlightConfig getConfig(ConfigManager configManager)
|
||||
InventoryGridConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(InventoryHighlightConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onFocusChanged(FocusChanged focusChanged)
|
||||
{
|
||||
if (!focusChanged.isFocused())
|
||||
{
|
||||
dragging = false;
|
||||
draggingItem = -1;
|
||||
}
|
||||
return configManager.getConfig(InventoryGridConfig.class);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package net.runelite.client.plugins.inventoryhighlight;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Stub;
|
||||
|
||||
@ConfigGroup("inventoryHighlight")
|
||||
public interface InventoryHighlightConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showItem",
|
||||
name = "Show the item",
|
||||
description = "Show a preview of the item in the new slot"
|
||||
)
|
||||
default boolean showItem()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "gridStub",
|
||||
name = "Grid",
|
||||
description = "",
|
||||
position = 1
|
||||
)
|
||||
default Stub gridStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showGrid",
|
||||
name = "Show a grid",
|
||||
description = "Show a grid on the inventory while dragging",
|
||||
parent = "gridStub"
|
||||
)
|
||||
default boolean showGrid()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showHighlight",
|
||||
name = "Show background highlight",
|
||||
description = "Show a green background highlight in the new slot",
|
||||
parent = "gridStub"
|
||||
)
|
||||
default boolean showHighlight()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
|
||||
* 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.inventoryhighlight;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.event.MouseEvent;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.input.MouseListener;
|
||||
|
||||
public class InventoryHighlightInputListener implements MouseListener
|
||||
{
|
||||
private final InventoryHighlightPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public InventoryHighlightInputListener(InventoryHighlightPlugin plugin, Client client)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseDragged(MouseEvent mouseEvent)
|
||||
{
|
||||
plugin.setDragging(true);
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseMoved(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseClicked(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
|
||||
final Widget bankInventoryWidget = client.getWidget(WidgetInfo.BANK_INVENTORY_ITEMS_CONTAINER);
|
||||
|
||||
if ((inventoryWidget == null || inventoryWidget.isSelfHidden()) &&
|
||||
(inventoryWidget == null || bankInventoryWidget == null || bankInventoryWidget.isSelfHidden()))
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Point mouse = client.getMouseCanvasPosition();
|
||||
|
||||
for (WidgetItem item : inventoryWidget.getWidgetItems())
|
||||
{
|
||||
if (item.getCanvasBounds().contains(mouse.getX(), mouse.getY()))
|
||||
{
|
||||
plugin.setDraggingItem(item.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseReleased(MouseEvent mouseEvent)
|
||||
{
|
||||
plugin.setDragging(false);
|
||||
plugin.setDraggingItem(-1);
|
||||
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseEntered(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseExited(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public class InventoryTagsOverlay extends WidgetItemOverlay
|
||||
{
|
||||
Rectangle bounds = itemWidget.getCanvasBounds();
|
||||
final BufferedImage outline = itemManager.getItemOutline(itemId, itemWidget.getQuantity(), color);
|
||||
graphics.drawImage(outline, (int) bounds.getX() + 1, (int) bounds.getY() + 1, null);
|
||||
graphics.drawImage(outline, (int) bounds.getX(), (int) bounds.getY(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,9 +162,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
|
||||
|
||||
final Rectangle bounds = itemWidget.getCanvasBounds();
|
||||
final TextComponent textComponent = new TextComponent();
|
||||
textComponent.setPosition(new
|
||||
|
||||
Point(bounds.x, bounds.y + 16));
|
||||
textComponent.setPosition(new Point(bounds.x - 1, bounds.y + 15));
|
||||
textComponent.setText(charges < 0 ? "?" : String.valueOf(charges));
|
||||
textComponent.setColor(itemChargePlugin.getColor(charges));
|
||||
textComponent.render(graphics);
|
||||
|
||||
@@ -87,7 +87,7 @@ class ItemIdentificationOverlay extends WidgetItemOverlay
|
||||
private void renderText(Graphics2D graphics, Rectangle bounds, ItemIdentification iden)
|
||||
{
|
||||
final TextComponent textComponent = new TextComponent();
|
||||
textComponent.setPosition(new Point(bounds.x, bounds.y + bounds.height));
|
||||
textComponent.setPosition(new Point(bounds.x - 1, bounds.y + bounds.height - 1));
|
||||
textComponent.setColor(config.textColor());
|
||||
switch (config.identificationType())
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.wasdcamera;
|
||||
package net.runelite.client.plugins.keyremapping;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import net.runelite.client.config.Config;
|
||||
@@ -30,13 +30,24 @@ import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.ModifierlessKeybind;
|
||||
|
||||
@ConfigGroup("wasdcamera")
|
||||
public interface WASDCameraConfig extends Config
|
||||
@ConfigGroup("keyremapping")
|
||||
public interface KeyRemappingConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "cameraRemap",
|
||||
name = "Remap Camera",
|
||||
description = "Configures whether the camera movement uses remapped keys"
|
||||
)
|
||||
default boolean cameraRemap()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "up",
|
||||
name = "Up key",
|
||||
name = "Camera Up key",
|
||||
description = "The key which will replace up."
|
||||
)
|
||||
default ModifierlessKeybind up()
|
||||
@@ -45,9 +56,9 @@ public interface WASDCameraConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
position = 3,
|
||||
keyName = "down",
|
||||
name = "Down key",
|
||||
name = "Camera Down key",
|
||||
description = "The key which will replace down."
|
||||
)
|
||||
default ModifierlessKeybind down()
|
||||
@@ -56,9 +67,9 @@ public interface WASDCameraConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
position = 4,
|
||||
keyName = "left",
|
||||
name = "Left key",
|
||||
name = "Camera Left key",
|
||||
description = "The key which will replace left."
|
||||
)
|
||||
default ModifierlessKeybind left()
|
||||
@@ -67,13 +78,24 @@ public interface WASDCameraConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
position = 5,
|
||||
keyName = "right",
|
||||
name = "Right key",
|
||||
name = "Camera Right key",
|
||||
description = "The key which will replace right."
|
||||
)
|
||||
default ModifierlessKeybind right()
|
||||
{
|
||||
return new ModifierlessKeybind(KeyEvent.VK_D, 0);
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
keyName = "fkeyRemap",
|
||||
name = "Remap F Keys",
|
||||
description = "Configures whether F-Keys are Remapped to 1 (F1) through 0 (F10), '-' (F11), and '=' (F12)"
|
||||
)
|
||||
default boolean fkeyRemap()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Abexlry <abexlry@gmail.com>
|
||||
* 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.keyremapping;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.Keybind;
|
||||
import net.runelite.client.config.ModifierlessKeybind;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.MouseAdapter;
|
||||
|
||||
class KeyRemappingListener extends MouseAdapter implements KeyListener
|
||||
{
|
||||
private static final Keybind ONE = new ModifierlessKeybind(KeyEvent.VK_1, 0);
|
||||
private static final Keybind TWO = new ModifierlessKeybind(KeyEvent.VK_2, 0);
|
||||
private static final Keybind THREE = new ModifierlessKeybind(KeyEvent.VK_3, 0);
|
||||
private static final Keybind FOUR = new ModifierlessKeybind(KeyEvent.VK_4, 0);
|
||||
private static final Keybind FIVE = new ModifierlessKeybind(KeyEvent.VK_5, 0);
|
||||
private static final Keybind SIX = new ModifierlessKeybind(KeyEvent.VK_6, 0);
|
||||
private static final Keybind SEVEN = new ModifierlessKeybind(KeyEvent.VK_7, 0);
|
||||
private static final Keybind EIGHT = new ModifierlessKeybind(KeyEvent.VK_8, 0);
|
||||
private static final Keybind NINE = new ModifierlessKeybind(KeyEvent.VK_9, 0);
|
||||
private static final Keybind ZERO = new ModifierlessKeybind(KeyEvent.VK_0, 0);
|
||||
private static final Keybind MINUS = new ModifierlessKeybind(KeyEvent.VK_MINUS, 0);
|
||||
private static final Keybind EQUALS = new ModifierlessKeybind(KeyEvent.VK_EQUALS, 0);
|
||||
|
||||
@Inject
|
||||
private KeyRemappingPlugin plugin;
|
||||
|
||||
@Inject
|
||||
private KeyRemappingConfig config;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
private final Map<Integer, Integer> modified = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGIN_SCREEN || !plugin.chatboxFocused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plugin.isTyping())
|
||||
{
|
||||
if (config.cameraRemap())
|
||||
{
|
||||
if (config.up().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_UP);
|
||||
e.setKeyCode(KeyEvent.VK_UP);
|
||||
}
|
||||
else if (config.down().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_DOWN);
|
||||
e.setKeyCode(KeyEvent.VK_DOWN);
|
||||
}
|
||||
else if (config.left().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_LEFT);
|
||||
e.setKeyCode(KeyEvent.VK_LEFT);
|
||||
}
|
||||
else if (config.right().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_RIGHT);
|
||||
e.setKeyCode(KeyEvent.VK_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.fkeyRemap())
|
||||
{
|
||||
if (ONE.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F1);
|
||||
e.setKeyCode(KeyEvent.VK_F1);
|
||||
}
|
||||
else if (TWO.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F2);
|
||||
e.setKeyCode(KeyEvent.VK_F2);
|
||||
}
|
||||
else if (THREE.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F3);
|
||||
e.setKeyCode(KeyEvent.VK_F3);
|
||||
}
|
||||
else if (FOUR.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F4);
|
||||
e.setKeyCode(KeyEvent.VK_F4);
|
||||
}
|
||||
else if (FIVE.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F5);
|
||||
e.setKeyCode(KeyEvent.VK_F5);
|
||||
}
|
||||
else if (SIX.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F6);
|
||||
e.setKeyCode(KeyEvent.VK_F6);
|
||||
}
|
||||
else if (SEVEN.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F7);
|
||||
e.setKeyCode(KeyEvent.VK_F7);
|
||||
}
|
||||
else if (EIGHT.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F8);
|
||||
e.setKeyCode(KeyEvent.VK_F8);
|
||||
}
|
||||
else if (NINE.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F9);
|
||||
e.setKeyCode(KeyEvent.VK_F9);
|
||||
}
|
||||
else if (ZERO.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F10);
|
||||
e.setKeyCode(KeyEvent.VK_F10);
|
||||
}
|
||||
else if (MINUS.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F11);
|
||||
e.setKeyCode(KeyEvent.VK_F11);
|
||||
}
|
||||
else if (EQUALS.matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_F12);
|
||||
e.setKeyCode(KeyEvent.VK_F12);
|
||||
}
|
||||
}
|
||||
|
||||
switch (e.getKeyCode())
|
||||
{
|
||||
case KeyEvent.VK_ENTER:
|
||||
case KeyEvent.VK_SLASH:
|
||||
case KeyEvent.VK_COLON:
|
||||
// refocus chatbox
|
||||
plugin.setTyping(true);
|
||||
clientThread.invoke(plugin::unlockChat);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (e.getKeyCode())
|
||||
{
|
||||
case KeyEvent.VK_ENTER:
|
||||
plugin.setTyping(false);
|
||||
clientThread.invoke(plugin::lockChat);
|
||||
break;
|
||||
case KeyEvent.VK_ESCAPE:
|
||||
plugin.setTyping(false);
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, "");
|
||||
plugin.lockChat();
|
||||
});
|
||||
break;
|
||||
case KeyEvent.VK_BACK_SPACE:
|
||||
if (Strings.isNullOrEmpty(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT)))
|
||||
{
|
||||
plugin.setTyping(false);
|
||||
clientThread.invoke(plugin::lockChat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.chatboxFocused() && !plugin.isTyping())
|
||||
{
|
||||
modified.remove(e.getKeyCode());
|
||||
|
||||
if (config.cameraRemap())
|
||||
{
|
||||
if (config.up().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_UP);
|
||||
}
|
||||
else if (config.down().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_DOWN);
|
||||
}
|
||||
else if (config.left().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_LEFT);
|
||||
}
|
||||
else if (config.right().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.fkeyRemap())
|
||||
{
|
||||
if (ONE.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F1);
|
||||
}
|
||||
else if (TWO.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F2);
|
||||
}
|
||||
else if (THREE.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F3);
|
||||
}
|
||||
else if (FOUR.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F4);
|
||||
}
|
||||
else if (FIVE.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F5);
|
||||
}
|
||||
else if (SIX.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F6);
|
||||
}
|
||||
else if (SEVEN.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F7);
|
||||
}
|
||||
else if (EIGHT.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F8);
|
||||
}
|
||||
else if (NINE.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F9);
|
||||
}
|
||||
else if (ZERO.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F10);
|
||||
}
|
||||
else if (MINUS.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F11);
|
||||
}
|
||||
else if (EQUALS.matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_F12);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// press d + enter + release d - causes the right arrow to never be released
|
||||
Integer m = modified.get(e.getKeyCode());
|
||||
if (m != null)
|
||||
{
|
||||
modified.remove(e.getKeyCode());
|
||||
e.setKeyCode(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,210 +1,214 @@
|
||||
/*'
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Abexlry <abexlry@gmail.com>
|
||||
* 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.wasdcamera;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.IconID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "WASD Camera",
|
||||
description = "Allows use of WASD keys for camera movement with 'Press Enter to Chat'",
|
||||
tags = {"enter", "chat"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class WASDCameraPlugin extends Plugin
|
||||
{
|
||||
private static final String PRESS_ENTER_TO_CHAT = "Press Enter to Chat...";
|
||||
private static final String SCRIPT_EVENT_SET_CHATBOX_INPUT = "setChatboxInput";
|
||||
private static final String SCRIPT_EVENT_BLOCK_CHAT_INPUT = "blockChatInput";
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
@Inject
|
||||
private WASDCameraListener inputListener;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean typing;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
configManager.setConfiguration("runelite", "entertochatplugin", false);
|
||||
typing = false;
|
||||
keyManager.registerKeyListener(inputListener);
|
||||
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
lockChat();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
unlockChat();
|
||||
}
|
||||
});
|
||||
|
||||
keyManager.unregisterKeyListener(inputListener);
|
||||
}
|
||||
|
||||
@Provides
|
||||
WASDCameraConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(WASDCameraConfig.class);
|
||||
}
|
||||
|
||||
boolean chatboxFocused()
|
||||
{
|
||||
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
|
||||
if (chatboxParent == null || chatboxParent.getOnKeyListener() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// the search box on the world map can be focused, and chat input goes there, even
|
||||
// though the chatbox still has its key listener.
|
||||
Widget worldMapSearch = client.getWidget(WidgetInfo.WORLD_MAP_SEARCH);
|
||||
return worldMapSearch == null || client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) != 1;
|
||||
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
|
||||
{
|
||||
switch (scriptCallbackEvent.getEventName())
|
||||
{
|
||||
case SCRIPT_EVENT_SET_CHATBOX_INPUT:
|
||||
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
|
||||
if (chatboxInput != null)
|
||||
{
|
||||
if (chatboxFocused() && !typing)
|
||||
{
|
||||
chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCRIPT_EVENT_BLOCK_CHAT_INPUT:
|
||||
if (!typing)
|
||||
{
|
||||
int[] intStack = client.getIntStack();
|
||||
int intStackSize = client.getIntStackSize();
|
||||
intStack[intStackSize - 1] = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lockChat()
|
||||
{
|
||||
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
|
||||
if (chatboxParent != null && chatboxParent.getOnKeyListener() != null)
|
||||
{
|
||||
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
|
||||
if (chatboxInput != null)
|
||||
{
|
||||
chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unlockChat()
|
||||
{
|
||||
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
|
||||
if (chatboxParent != null)
|
||||
{
|
||||
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
|
||||
if (chatboxInput != null)
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
final boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1;
|
||||
final Color textColor = isChatboxTransparent ? JagexColors.CHAT_TYPED_TEXT_TRANSPARENT_BACKGROUND : JagexColors.CHAT_TYPED_TEXT_OPAQUE_BACKGROUND;
|
||||
chatboxInput.setText(getPlayerNameWithIcon() + ": " + ColorUtil.wrapWithColorTag(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT) + "*", textColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getPlayerNameWithIcon()
|
||||
{
|
||||
IconID icon;
|
||||
switch (client.getAccountType())
|
||||
{
|
||||
case IRONMAN:
|
||||
icon = IconID.IRONMAN;
|
||||
break;
|
||||
case ULTIMATE_IRONMAN:
|
||||
icon = IconID.ULTIMATE_IRONMAN;
|
||||
break;
|
||||
case HARDCORE_IRONMAN:
|
||||
icon = IconID.HARDCORE_IRONMAN;
|
||||
break;
|
||||
default:
|
||||
return client.getLocalPlayer().getName();
|
||||
}
|
||||
return icon + client.getLocalPlayer().getName();
|
||||
}
|
||||
}
|
||||
/*'
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Abexlry <abexlry@gmail.com>
|
||||
* 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.keyremapping;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.IconID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Key Remapping",
|
||||
description = "Allows use of WASD keys for camera movement with 'Press Enter to Chat', and remapping number keys to F-keys",
|
||||
tags = {"enter", "chat", "wasd", "camera"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class KeyRemappingPlugin extends Plugin
|
||||
{
|
||||
private static final String PRESS_ENTER_TO_CHAT = "Press Enter to Chat...";
|
||||
private static final String SCRIPT_EVENT_SET_CHATBOX_INPUT = "setChatboxInput";
|
||||
private static final String SCRIPT_EVENT_BLOCK_CHAT_INPUT = "blockChatInput";
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
@Inject
|
||||
private KeyRemappingListener inputListener;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean typing;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
configManager.setConfiguration("runelite", "entertochatplugin", false);
|
||||
typing = false;
|
||||
keyManager.registerKeyListener(inputListener);
|
||||
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
lockChat();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
unlockChat();
|
||||
}
|
||||
});
|
||||
|
||||
keyManager.unregisterKeyListener(inputListener);
|
||||
}
|
||||
|
||||
@Provides
|
||||
KeyRemappingConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(KeyRemappingConfig.class);
|
||||
}
|
||||
|
||||
boolean chatboxFocused()
|
||||
{
|
||||
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
|
||||
if (chatboxParent == null || chatboxParent.getOnKeyListener() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// the search box on the world map can be focused, and chat input goes there, even
|
||||
// though the chatbox still has its key listener.
|
||||
Widget worldMapSearch = client.getWidget(WidgetInfo.WORLD_MAP_SEARCH);
|
||||
if (worldMapSearch != null && client.getVar(VarClientInt.WORLD_MAP_SEARCH_FOCUSED) == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
|
||||
{
|
||||
switch (scriptCallbackEvent.getEventName())
|
||||
{
|
||||
case SCRIPT_EVENT_SET_CHATBOX_INPUT:
|
||||
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
|
||||
if (chatboxInput != null)
|
||||
{
|
||||
if (chatboxFocused() && !typing)
|
||||
{
|
||||
chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SCRIPT_EVENT_BLOCK_CHAT_INPUT:
|
||||
if (!typing)
|
||||
{
|
||||
int[] intStack = client.getIntStack();
|
||||
int intStackSize = client.getIntStackSize();
|
||||
intStack[intStackSize - 1] = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lockChat()
|
||||
{
|
||||
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
|
||||
if (chatboxParent != null && chatboxParent.getOnKeyListener() != null)
|
||||
{
|
||||
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
|
||||
if (chatboxInput != null)
|
||||
{
|
||||
chatboxInput.setText(getPlayerNameWithIcon() + ": " + PRESS_ENTER_TO_CHAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unlockChat()
|
||||
{
|
||||
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
|
||||
if (chatboxParent != null)
|
||||
{
|
||||
Widget chatboxInput = client.getWidget(WidgetInfo.CHATBOX_INPUT);
|
||||
if (chatboxInput != null)
|
||||
{
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
final boolean isChatboxTransparent = client.isResized() && client.getVar(Varbits.TRANSPARENT_CHATBOX) == 1;
|
||||
final Color textColor = isChatboxTransparent ? JagexColors.CHAT_TYPED_TEXT_TRANSPARENT_BACKGROUND : JagexColors.CHAT_TYPED_TEXT_OPAQUE_BACKGROUND;
|
||||
chatboxInput.setText(getPlayerNameWithIcon() + ": " + ColorUtil.wrapWithColorTag(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT) + "*", textColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getPlayerNameWithIcon()
|
||||
{
|
||||
IconID icon;
|
||||
switch (client.getAccountType())
|
||||
{
|
||||
case IRONMAN:
|
||||
icon = IconID.IRONMAN;
|
||||
break;
|
||||
case ULTIMATE_IRONMAN:
|
||||
icon = IconID.ULTIMATE_IRONMAN;
|
||||
break;
|
||||
case HARDCORE_IRONMAN:
|
||||
icon = IconID.HARDCORE_IRONMAN;
|
||||
break;
|
||||
default:
|
||||
return client.getLocalPlayer().getName();
|
||||
}
|
||||
return icon + client.getLocalPlayer().getName();
|
||||
}
|
||||
}
|
||||
@@ -1,209 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Seth <Sethtroll3@gmail.com>
|
||||
* 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.loginscreen;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.IOException;
|
||||
import javax.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.SessionOpen;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.OSType;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Login Screen",
|
||||
description = "Provides various enhancements for login screen"
|
||||
)
|
||||
@Slf4j
|
||||
public class LoginScreenPlugin extends Plugin implements KeyListener
|
||||
{
|
||||
private static final int MAX_USERNAME_LENGTH = 254;
|
||||
private static final int MAX_PASSWORD_LENGTH = 20;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private LoginScreenConfig config;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
private String usernameCache;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
applyUsername();
|
||||
keyManager.registerKeyListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
if (config.syncUsername())
|
||||
{
|
||||
client.getPreferences().setRememberedUsername(usernameCache);
|
||||
}
|
||||
|
||||
keyManager.unregisterKeyListener(this);
|
||||
}
|
||||
|
||||
@Provides
|
||||
LoginScreenConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(LoginScreenConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (!config.syncUsername())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
applyUsername();
|
||||
}
|
||||
else if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
String username = "";
|
||||
|
||||
if (client.getPreferences().getRememberedUsername() != null)
|
||||
{
|
||||
username = client.getUsername();
|
||||
}
|
||||
|
||||
if (config.username().equals(username))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Saving username: {}", username);
|
||||
config.username(username);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionOpen(SessionOpen event)
|
||||
{
|
||||
// configuation for the account is available now, so update the username
|
||||
applyUsername();
|
||||
}
|
||||
|
||||
private void applyUsername()
|
||||
{
|
||||
if (!config.syncUsername())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameState gameState = client.getGameState();
|
||||
if (gameState == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
String username = config.username();
|
||||
|
||||
if (Strings.isNullOrEmpty(username))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Save it only once
|
||||
if (usernameCache == null)
|
||||
{
|
||||
usernameCache = client.getPreferences().getRememberedUsername();
|
||||
}
|
||||
|
||||
client.getPreferences().setRememberedUsername(username);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (!config.pasteEnabled() || client.getGameState() != GameState.LOGIN_SCREEN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// enable pasting on macOS with the Command (meta) key
|
||||
boolean isModifierDown = OSType.getOSType() == OSType.MacOS ? e.isMetaDown() : e.isControlDown();
|
||||
|
||||
if (e.getKeyCode() == KeyEvent.VK_V && isModifierDown)
|
||||
{
|
||||
try
|
||||
{
|
||||
final String data = Toolkit
|
||||
.getDefaultToolkit()
|
||||
.getSystemClipboard()
|
||||
.getData(DataFlavor.stringFlavor)
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
// 0 is username, 1 is password
|
||||
if (client.getCurrentLoginField() == 0)
|
||||
{
|
||||
// Truncate data to maximum username length if necessary
|
||||
client.setUsername(data.substring(0, Math.min(data.length(), MAX_USERNAME_LENGTH)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Truncate data to maximum password length if necessary
|
||||
client.setPassword(data.substring(0, Math.min(data.length(), MAX_PASSWORD_LENGTH)));
|
||||
}
|
||||
}
|
||||
catch (UnsupportedFlavorException | IOException ex)
|
||||
{
|
||||
log.warn("failed to fetch clipboard data", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2017, Seth <Sethtroll3@gmail.com>
|
||||
* 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.loginscreen;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.IOException;
|
||||
import javax.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.events.SessionOpen;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.OSType;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Login Screen",
|
||||
description = "Provides various enhancements for login screen"
|
||||
)
|
||||
@Slf4j
|
||||
public class LoginScreenPlugin extends Plugin implements KeyListener
|
||||
{
|
||||
private static final int MAX_USERNAME_LENGTH = 254;
|
||||
private static final int MAX_PASSWORD_LENGTH = 20;
|
||||
private static final int MAX_PIN_LENGTH = 6;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private LoginScreenConfig config;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
private String usernameCache;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
applyUsername();
|
||||
keyManager.registerKeyListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
if (config.syncUsername())
|
||||
{
|
||||
client.getPreferences().setRememberedUsername(usernameCache);
|
||||
}
|
||||
|
||||
keyManager.unregisterKeyListener(this);
|
||||
}
|
||||
|
||||
@Provides
|
||||
LoginScreenConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(LoginScreenConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (!config.syncUsername())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getGameState() == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
applyUsername();
|
||||
}
|
||||
else if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
String username = "";
|
||||
|
||||
if (client.getPreferences().getRememberedUsername() != null)
|
||||
{
|
||||
username = client.getUsername();
|
||||
}
|
||||
|
||||
if (config.username().equals(username))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Saving username: {}", username);
|
||||
config.username(username);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionOpen(SessionOpen event)
|
||||
{
|
||||
// configuation for the account is available now, so update the username
|
||||
applyUsername();
|
||||
}
|
||||
|
||||
private void applyUsername()
|
||||
{
|
||||
if (!config.syncUsername())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameState gameState = client.getGameState();
|
||||
if (gameState == GameState.LOGIN_SCREEN)
|
||||
{
|
||||
String username = config.username();
|
||||
|
||||
if (Strings.isNullOrEmpty(username))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Save it only once
|
||||
if (usernameCache == null)
|
||||
{
|
||||
usernameCache = client.getPreferences().getRememberedUsername();
|
||||
}
|
||||
|
||||
client.getPreferences().setRememberedUsername(username);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (!config.pasteEnabled() || (
|
||||
client.getGameState() != GameState.LOGIN_SCREEN &&
|
||||
client.getGameState() != GameState.LOGIN_SCREEN_AUTHENTICATOR))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// enable pasting on macOS with the Command (meta) key
|
||||
boolean isModifierDown = OSType.getOSType() == OSType.MacOS ? e.isMetaDown() : e.isControlDown();
|
||||
|
||||
if (e.getKeyCode() == KeyEvent.VK_V && isModifierDown)
|
||||
{
|
||||
try
|
||||
{
|
||||
final String data = Toolkit
|
||||
.getDefaultToolkit()
|
||||
.getSystemClipboard()
|
||||
.getData(DataFlavor.stringFlavor)
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
switch (client.getLoginIndex())
|
||||
{
|
||||
// Username/password form
|
||||
case 2:
|
||||
if (client.getCurrentLoginField() == 0)
|
||||
{
|
||||
// Truncate data to maximum username length if necessary
|
||||
client.setUsername(data.substring(0, Math.min(data.length(), MAX_USERNAME_LENGTH)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Truncate data to maximum password length if necessary
|
||||
client.setPassword(data.substring(0, Math.min(data.length(), MAX_PASSWORD_LENGTH)));
|
||||
}
|
||||
|
||||
break;
|
||||
// Authenticator form
|
||||
case 4:
|
||||
// Truncate data to maximum OTP code length if necessary
|
||||
client.setOtp(data.substring(0, Math.min(data.length(), MAX_PIN_LENGTH)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (UnsupportedFlavorException | IOException ex)
|
||||
{
|
||||
log.warn("failed to fetch clipboard data", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
|
||||
* 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.mining;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import static net.runelite.api.AnimationID.*;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
import net.runelite.client.ui.overlay.components.table.TableAlignment;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
|
||||
class MiningOverlay extends Overlay
|
||||
{
|
||||
private static final Set<Integer> MINING_ANIMATION_IDS = ImmutableSet.of(
|
||||
MINING_MOTHERLODE_BRONZE, MINING_MOTHERLODE_IRON, MINING_MOTHERLODE_STEEL,
|
||||
MINING_MOTHERLODE_BLACK, MINING_MOTHERLODE_MITHRIL, MINING_MOTHERLODE_ADAMANT,
|
||||
MINING_MOTHERLODE_RUNE, MINING_MOTHERLODE_DRAGON, MINING_MOTHERLODE_DRAGON_ORN,
|
||||
MINING_MOTHERLODE_INFERNAL
|
||||
);
|
||||
|
||||
private final Client client;
|
||||
private final MiningPlugin plugin;
|
||||
private final MiningConfig config;
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
@Inject
|
||||
MiningOverlay(Client client, MiningPlugin plugin, MiningConfig config)
|
||||
{
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isInMlm() || !config.showMiningStats())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
MiningSession session = plugin.getSession();
|
||||
|
||||
if (session.getLastPayDirtMined() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Duration statTimeout = Duration.ofMinutes(config.statTimeout());
|
||||
Duration sinceCut = Duration.between(session.getLastPayDirtMined(), Instant.now());
|
||||
|
||||
if (sinceCut.compareTo(statTimeout) >= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
panelComponent.getChildren().clear();
|
||||
|
||||
if (config.showMiningState())
|
||||
{
|
||||
if (MINING_ANIMATION_IDS.contains(client.getLocalPlayer().getAnimation()))
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("Mining")
|
||||
.color(Color.GREEN)
|
||||
.build());
|
||||
}
|
||||
else
|
||||
{
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("NOT mining")
|
||||
.color(Color.RED)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
TableComponent tableComponent = new TableComponent();
|
||||
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
|
||||
|
||||
tableComponent.addRow("Pay-dirt mined:", Integer.toString(session.getTotalMined()));
|
||||
tableComponent.addRow("Pay-dirt/hr:", session.getRecentMined() > 2 ? Integer.toString(session.getPerHour()) : "");
|
||||
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
|
||||
return panelComponent.render(graphics);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* 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.mining;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.time.Instant;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.ProgressPieComponent;
|
||||
|
||||
class MiningOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final MiningPlugin plugin;
|
||||
|
||||
@Inject
|
||||
private MiningOverlay(Client client, MiningPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
List<RockRespawn> respawns = plugin.getRespawns();
|
||||
if (respawns.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Instant now = Instant.now();
|
||||
for (Iterator<RockRespawn> it = respawns.iterator(); it.hasNext();)
|
||||
{
|
||||
RockRespawn rockRespawn = it.next();
|
||||
float percent = (now.toEpochMilli() - rockRespawn.getStartTime().toEpochMilli()) / (float) rockRespawn.getRespawnTime();
|
||||
WorldPoint worldPoint = rockRespawn.getWorldPoint();
|
||||
LocalPoint loc = LocalPoint.fromWorld(client, worldPoint);
|
||||
if (loc == null || percent > 1.0f)
|
||||
{
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
Point point = Perspective.localToCanvas(client, loc, client.getPlane());
|
||||
if (point == null)
|
||||
{
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
ProgressPieComponent ppc = new ProgressPieComponent();
|
||||
ppc.setBorderColor(Color.ORANGE);
|
||||
ppc.setFill(Color.YELLOW);
|
||||
ppc.setPosition(point);
|
||||
ppc.setProgress(percent);
|
||||
ppc.render(graphics);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Lars <lars.oernlo@gmail.com>
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,63 +24,45 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.mining;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Provides;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ItemID;
|
||||
import static net.runelite.api.ObjectID.ORE_VEIN_26661;
|
||||
import static net.runelite.api.ObjectID.ORE_VEIN_26662;
|
||||
import static net.runelite.api.ObjectID.ORE_VEIN_26663;
|
||||
import static net.runelite.api.ObjectID.ORE_VEIN_26664;
|
||||
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26665;
|
||||
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26666;
|
||||
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26667;
|
||||
import static net.runelite.api.ObjectID.DEPLETED_VEIN_26668;
|
||||
import static net.runelite.api.ObjectID.EMPTY_WALL;
|
||||
import net.runelite.api.WallObject;
|
||||
import net.runelite.api.events.GameObjectChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.WallObjectSpawned;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.task.Schedule;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Mining",
|
||||
description = "Show helpful information about Mining",
|
||||
tags = {"mining", "skilling", "overlay"},
|
||||
type = PluginType.SKILLING,
|
||||
description = "Show ore respawn timers",
|
||||
tags = {"overlay", "skilling", "timers"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
|
||||
public class MiningPlugin extends Plugin
|
||||
{
|
||||
private static final Set<Integer> MOTHERLODE_MAP_REGIONS = ImmutableSet.of(14679, 14680, 14681, 14935, 14936, 14937, 15191, 15192, 15193);
|
||||
private static final Set<Integer> MINE_SPOTS = ImmutableSet.of(ORE_VEIN_26661, ORE_VEIN_26662, ORE_VEIN_26663, ORE_VEIN_26664);
|
||||
private static final Set<Integer> MLM_ORE_TYPES = ImmutableSet.of(ItemID.RUNITE_ORE, ItemID.ADAMANTITE_ORE,
|
||||
ItemID.MITHRIL_ORE, ItemID.GOLD_ORE, ItemID.COAL, ItemID.GOLDEN_NUGGET);
|
||||
private static final Set<Integer> MINING_ROCKS = ImmutableSet.of(
|
||||
// another website says depleted rocks are 7468, 7469
|
||||
// website says stoney 2902, 2962, 2963, 2964,
|
||||
2231, 2257, 2584, 2704, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 3805, 3806, 3807, 3808, 4437, 4438, 4676, 6669, 6670, 6671, 6672, 6673, 7453, 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, 7464, 7467, 7470, 7484, 7485, 7486, 7487, 7488, 7489, 7490, 7491, 7492, 7493, 7494, 7495, 8727, 8828, 8829, 8830, 10079, 10080, 10081, 11441, 11924, 12590, 15127, 15128, 15213, 16464, 16514, 16515, 16521, 16522, 16523, 16524, 16534, 16535, 16545, 16549, 16550, 16998, 16999, 17042, 17043, 17064, 17065, 18817, 18840, 18952, 18953, 18954, 18961, 19849, 19969, 19970, 19971, 19972, 19973, 22665, 22667, 23280, 23281, 23640, 24146, 24147, 24148, 24557, 26873, 26874, 27984, 27985, 27987, 27988, 28596, 28597, 28752, 28753, 28890
|
||||
//2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2231, 2257, 2328, 3042, 3043, 3722, 3723, 3748, 3790, 3791, 3803, 3804, 4676, 6943, 6944, 6945, 6946, 6947, 6948, 9296, 9297, 9303, 9304, 9305, 9306, 9316, 9317, 9331, 9332, 9335, 9336, 9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, 9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, 9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, 9732, 9733, 9734, 9735, 9736, 9737, 10583, 10584, 10585, 10586, 10587, 10944, 10945, 10946, 10947, 10948, 10949, 11165, 11166, 11167, 11168, 11169, 11170, 11171, 11172, 11173, 11174, 11175, 11176, 11177, 11178, 11179, 11180, 11181, 11182, 11183, 11184, 11185, 11186, 11187, 11188, 11189, 11190, 11191, 11192, 11193, 11194, 11195, 11424, 11425, 11426, 11427, 11428, 11429, 11430, 11431, 11432, 11433, 11434, 11435, 11436, 11437, 11438, 11439, 11440, 11441, 11442, 11443, 11444, 11552, 11553, 11554, 11555, 11556, 11557, 11915, 11916, 11917, 11918, 11919, 11920, 11921, 11922, 11923, 11924, 11925, 11926, 11927, 11928, 11929, 11930, 11931, 11932, 11933, 11934, 11935, 11936, 11937, 11938, 11939, 11940, 11941, 11942, 11943, 11944, 11945, 11946, 11947, 11948, 11949, 11950, 11951, 11952, 11953, 11954, 11955, 11956, 11957, 11958, 11959, 11960, 11961, 11962, 11963, 11964, 11965
|
||||
//968, 1480, 1855, 4043, 4487, 7533, 9716, 21250, 1997, 2581, 2582, 2694, 2695, 2696, 2697, 2835, 2836, 2837, 2901, 2965, 3339, 3364, 4526, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4887, 5604, 5605, 5606, 5844, 5845, 5896, 5985, 5987, 6622, 6623, 6707, 6708, 6709, 7466, 8725, 8726, 8950, 8951, 8952, 9031, 9032, 10036, 10782, 10783, 10784, 10785, 10786, 10787, 10788, 11097, 11098, 11182, 11183, 11424, 11425, 12564, 12565, 12566, 12567, 12588, 12589, 12774, 14814, 14815, 14816, 14817, 15198, 15199, 15217, 15218, 15219, 15410, 15536, 15537, 16077, 16078, 16079, 16080, 16115, 16136, 16284, 16303, 17350, 17351, 17352, 17353, 17354, 17355, 17356, 17357, 17358, 17364, 17365, 17366, 17679, 17958, 17959, 17960, 17970, 17971, 17972, 18871, 18872, 18873, 19131, 21571, 21572, 21573, 22549, 22550, 22551, 23124, 23125, 23126, 23127, 23165, 23976, 23977, 23978, 23979, 23980, 23981, 24693, 24694, 24695, 24696, 24697, 24698, 24699, 24700, 24701, 24781, 25158, 25159, 25160, 25422, 25423, 26372, 26373, 26376, 26377, 26850, 26856, 28580, 29102, 29883, 29884, 29885, 30344, 30519, 30521, 30522, 30857, 30858, 31045, 31781, 31782, 31783, 31784, 31785, 31786, 31787, 31788, 31789
|
||||
);
|
||||
private static final int MAX_INVENTORY_SIZE = 28;
|
||||
private static final int ROCK_DISTANCE = 14;
|
||||
private static final int MINING_GUILD_REGION = 12183;
|
||||
|
||||
// private static final int SACK_LARGE_SIZE = 162;
|
||||
// private static final int SACK_SIZE = 81;
|
||||
//
|
||||
// private static final int UPPER_FLOOR_HEIGHT = -500;
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
@@ -90,278 +70,99 @@ public class MiningPlugin extends Plugin
|
||||
@Inject
|
||||
private MiningOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private MiningRocksOverlay rocksOverlay;
|
||||
|
||||
@Inject
|
||||
private MiningConfig config;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private boolean inMlm;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int curSackSize;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int maxSackSize;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Integer depositsLeft;
|
||||
|
||||
private MiningSession session;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Set<WallObject> veins = new HashSet<>();
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Set<GameObject> rocks = new HashSet<>();
|
||||
|
||||
@Provides
|
||||
MiningConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(MiningConfig.class);
|
||||
}
|
||||
private final List<RockRespawn> respawns = new ArrayList<>();
|
||||
private boolean recentlyLoggedIn;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(rocksOverlay);
|
||||
// overlayManager.add(motherlodeGemOverlay);
|
||||
// overlayManager.add(motherlodeSackOverlay);
|
||||
|
||||
session = new MiningSession();
|
||||
//inMlm = checkInMlm();
|
||||
|
||||
// if (inMlm)
|
||||
// {
|
||||
// clientThread.invokeLater(this::refreshSackValues);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(rocksOverlay);
|
||||
// overlayManager.remove(motherlodeGemOverlay);
|
||||
// overlayManager.remove(motherlodeSackOverlay);
|
||||
session = null;
|
||||
// veins.clear();
|
||||
rocks.clear();
|
||||
|
||||
// Widget sack = client.getWidget(WidgetInfo.MOTHERLODE_MINE);
|
||||
|
||||
// clientThread.invokeLater(() ->
|
||||
// {
|
||||
// if (sack != null && sack.isHidden())
|
||||
// {
|
||||
// sack.setHidden(false);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public MiningSession getSession()
|
||||
{
|
||||
return session;
|
||||
}
|
||||
|
||||
// @Subscribe
|
||||
// public void onVarbitChanged(VarbitChanged event)
|
||||
// {
|
||||
// if (inMlm)
|
||||
// {
|
||||
// refreshSackValues();
|
||||
// }
|
||||
// }
|
||||
|
||||
// @Subscribe
|
||||
// public void onChatMessage(ChatMessage event)
|
||||
// {
|
||||
// if (!inMlm || event.getType() != ChatMessageType.FILTERED)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// String chatMessage = event.getMessage();
|
||||
//
|
||||
// switch (chatMessage)
|
||||
// {
|
||||
// case "You manage to mine some pay-dirt.":
|
||||
// session.incrementPayDirtMined();
|
||||
// break;
|
||||
//
|
||||
// case "You just found a Diamond!":
|
||||
// session.incrementGemFound(ItemID.UNCUT_DIAMOND);
|
||||
// break;
|
||||
//
|
||||
// case "You just found a Ruby!":
|
||||
// session.incrementGemFound(ItemID.UNCUT_RUBY);
|
||||
// break;
|
||||
//
|
||||
// case "You just found an Emerald!":
|
||||
// session.incrementGemFound(ItemID.UNCUT_EMERALD);
|
||||
// break;
|
||||
//
|
||||
// case "You just found a Sapphire!":
|
||||
// session.incrementGemFound(ItemID.UNCUT_SAPPHIRE);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
@Schedule(
|
||||
period = 1,
|
||||
unit = ChronoUnit.SECONDS
|
||||
)
|
||||
// public void checkMining()
|
||||
// {
|
||||
// if (!inMlm)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// depositsLeft = calculateDepositsLeft();
|
||||
//
|
||||
// Instant lastPayDirtMined = session.getLastPayDirtMined();
|
||||
// if (lastPayDirtMined == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // reset recentPayDirtMined if you haven't mined anything recently
|
||||
// Duration statTimeout = Duration.ofMinutes(config.statTimeout());
|
||||
// Duration sinceMined = Duration.between(lastPayDirtMined, Instant.now());
|
||||
//
|
||||
// if (sinceMined.compareTo(statTimeout) >= 0)
|
||||
// {
|
||||
// session.resetRecent();
|
||||
// }
|
||||
// }
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectSpawned(GameObjectSpawned event)
|
||||
{
|
||||
GameObject gameObject = event.getGameObject();
|
||||
if (MINING_ROCKS.contains(gameObject.getId()))
|
||||
{
|
||||
rocks.add(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectChanged(GameObjectChanged event)
|
||||
{
|
||||
GameObject previous = event.getPrevious();
|
||||
GameObject gameObject = event.getGameObject();
|
||||
rocks.remove(previous);
|
||||
if (MINING_ROCKS.contains(gameObject.getId()))
|
||||
{
|
||||
rocks.add(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectDespawned(GameObjectDespawned event)
|
||||
{
|
||||
GameObject gameObject = event.getGameObject();
|
||||
rocks.remove(gameObject);
|
||||
respawns.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.LOADING)
|
||||
switch (event.getGameState())
|
||||
{
|
||||
// on region changes the tiles get set to null
|
||||
rocks.clear();
|
||||
case LOADING:
|
||||
case HOPPING:
|
||||
respawns.clear();
|
||||
break;
|
||||
case LOGGED_IN:
|
||||
// After login rocks that are depleted will be changed,
|
||||
// so wait for the next game tick before watching for
|
||||
// rocks to deplete
|
||||
recentlyLoggedIn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// private Integer calculateDepositsLeft()
|
||||
// {
|
||||
// if (maxSackSize == 0) // check if maxSackSize has been initialized
|
||||
// {
|
||||
// refreshSackValues();
|
||||
// }
|
||||
//
|
||||
// double depositsLeft = 0;
|
||||
// int nonPayDirtItems = 0;
|
||||
//
|
||||
// ItemContainer inventory = client.getItemContainer(InventoryID.INVENTORY);
|
||||
// if (inventory == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// Item[] result = inventory.getItems();
|
||||
// assert result != null;
|
||||
//
|
||||
// for (Item item : result)
|
||||
// {
|
||||
// // Assume that MLM ores are being banked and exclude them from the check,
|
||||
// // so the user doesn't see the Overlay switch between deposits left and N/A.
|
||||
// //
|
||||
// // Count other items at nonPayDirtItems so depositsLeft is calculated accordingly.
|
||||
// if (item.getId() != ItemID.PAYDIRT && item.getId() != -1 && !MLM_ORE_TYPES.contains(item.getId()))
|
||||
// {
|
||||
// nonPayDirtItems += 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// double inventorySpace = MAX_INVENTORY_SIZE - nonPayDirtItems;
|
||||
// double sackSizeRemaining = maxSackSize - curSackSize;
|
||||
//
|
||||
// if (inventorySpace > 0 && sackSizeRemaining > 0)
|
||||
// {
|
||||
// depositsLeft = Math.ceil(sackSizeRemaining / inventorySpace);
|
||||
// }
|
||||
// else if (inventorySpace == 0)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// return (int) depositsLeft;
|
||||
// }
|
||||
//
|
||||
// private boolean checkInMlm()
|
||||
// {
|
||||
// if (client.getGameState() != GameState.LOGGED_IN)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// int[] currentMapRegions = client.getMapRegions();
|
||||
//
|
||||
// // Verify that all regions exist in MOTHERLODE_MAP_REGIONS
|
||||
// for (int region : currentMapRegions)
|
||||
// {
|
||||
// if (!MOTHERLODE_MAP_REGIONS.contains(region))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private void refreshSackValues()
|
||||
// {
|
||||
// curSackSize = client.getVar(Varbits.SACK_NUMBER);
|
||||
// boolean sackUpgraded = client.getVar(Varbits.SACK_UPGRADED) == 1;
|
||||
// maxSackSize = sackUpgraded ? SACK_LARGE_SIZE : SACK_SIZE;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Checks if the given point is "upstairs" in the mlm.
|
||||
// * The upper floor is actually on z=0.
|
||||
// * @param localPoint
|
||||
// * @return
|
||||
// */
|
||||
// boolean isUpstairs(LocalPoint localPoint)
|
||||
// {
|
||||
// return Perspective.getTileHeight(client, localPoint, 0) < UPPER_FLOOR_HEIGHT;
|
||||
// }
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick gameTick)
|
||||
{
|
||||
recentlyLoggedIn = false;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectDespawned(GameObjectDespawned event)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN || recentlyLoggedIn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final GameObject object = event.getGameObject();
|
||||
|
||||
Rock rock = Rock.getRock(object.getId());
|
||||
if (rock != null)
|
||||
{
|
||||
RockRespawn rockRespawn = new RockRespawn(rock, object.getWorldLocation(), Instant.now(), (int) rock.getRespawnTime(inMiningGuild()).toMillis());
|
||||
respawns.add(rockRespawn);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWallObjectSpawned(WallObjectSpawned event)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final WallObject object = event.getWallObject();
|
||||
|
||||
switch (object.getId())
|
||||
{
|
||||
case EMPTY_WALL:
|
||||
{
|
||||
Rock rock = Rock.AMETHYST;
|
||||
RockRespawn rockRespawn = new RockRespawn(rock, object.getWorldLocation(), Instant.now(), (int) rock.getRespawnTime(inMiningGuild()).toMillis());
|
||||
respawns.add(rockRespawn);
|
||||
break;
|
||||
}
|
||||
case DEPLETED_VEIN_26665: // Depleted motherlode vein
|
||||
case DEPLETED_VEIN_26666: // Depleted motherlode vein
|
||||
case DEPLETED_VEIN_26667: // Depleted motherlode vein
|
||||
case DEPLETED_VEIN_26668: // Depleted motherlode vein
|
||||
{
|
||||
Rock rock = Rock.ORE_VEIN;
|
||||
RockRespawn rockRespawn = new RockRespawn(rock, object.getWorldLocation(), Instant.now(), (int) rock.getRespawnTime(inMiningGuild()).toMillis());
|
||||
respawns.add(rockRespawn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean inMiningGuild()
|
||||
{
|
||||
return client.getLocalPlayer().getWorldLocation().getRegionID() == MINING_GUILD_REGION;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Lars <lars.oernlo@gmail.com>
|
||||
* 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.mining;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.client.game.SkillIconManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
|
||||
class MiningRocksOverlay extends Overlay
|
||||
{
|
||||
private static final int MAX_DISTANCE = 2350;
|
||||
|
||||
private final Client client;
|
||||
private final MiningPlugin plugin;
|
||||
private final MiningConfig config;
|
||||
|
||||
private final BufferedImage miningIcon;
|
||||
|
||||
@Inject
|
||||
MiningRocksOverlay(Client client, MiningPlugin plugin, MiningConfig config, SkillIconManager iconManager)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
|
||||
miningIcon = iconManager.getSkillImage(Skill.MINING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
Player local = client.getLocalPlayer();
|
||||
|
||||
renderTiles(graphics, local);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderTiles(Graphics2D graphics, Player local)
|
||||
{
|
||||
LocalPoint localLocation = local.getLocalLocation();
|
||||
|
||||
if (config.showMiningRocks())
|
||||
{
|
||||
for (GameObject rock : plugin.getRocks())
|
||||
{
|
||||
|
||||
LocalPoint location = rock.getLocalLocation();
|
||||
if (localLocation.distanceTo(location) <= MAX_DISTANCE)
|
||||
{
|
||||
renderMiningRock(graphics, rock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void renderMiningRock(Graphics2D graphics, GameObject rock)
|
||||
{
|
||||
Point canvasLoc = Perspective.getCanvasImageLocation(client, rock.getLocalLocation(), miningIcon, 0);
|
||||
if (canvasLoc != null)
|
||||
{
|
||||
graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null);
|
||||
}
|
||||
}
|
||||
|
||||
// private void renderMiningRockSquare(Graphics2D graphics, GameObject rock)
|
||||
// {
|
||||
// Polygon poly = Perspective.getCanvasTilePoly(client, rock.getLocalLocation());
|
||||
//
|
||||
// if (poly != null)
|
||||
// {
|
||||
// OverlayUtil.renderPolygon(graphics, poly, Color.red);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Seth <Sethtroll3@gmail.com>
|
||||
* 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.mining;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
@Slf4j
|
||||
public class MiningSession
|
||||
{
|
||||
private static final Duration HOUR = Duration.ofHours(1);
|
||||
|
||||
private int perHour;
|
||||
|
||||
private Instant lastPayDirtMined;
|
||||
private int totalMined;
|
||||
|
||||
private Instant recentPayDirtMined;
|
||||
private int recentMined;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Instant lastGemFound;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int diamondsFound;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int rubiesFound;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int emeraldsFound;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int sapphiresFound;
|
||||
|
||||
public void incrementGemFound(int gemID)
|
||||
{
|
||||
lastGemFound = Instant.now();
|
||||
|
||||
switch (gemID)
|
||||
{
|
||||
case ItemID.UNCUT_DIAMOND:
|
||||
diamondsFound++;
|
||||
break;
|
||||
|
||||
case ItemID.UNCUT_RUBY:
|
||||
rubiesFound++;
|
||||
break;
|
||||
|
||||
case ItemID.UNCUT_EMERALD:
|
||||
emeraldsFound++;
|
||||
break;
|
||||
|
||||
case ItemID.UNCUT_SAPPHIRE:
|
||||
sapphiresFound++;
|
||||
break;
|
||||
|
||||
default:
|
||||
log.error("Invalid gem type specified. The gem count will not be incremented.");
|
||||
}
|
||||
}
|
||||
|
||||
public void incrementPayDirtMined()
|
||||
{
|
||||
Instant now = Instant.now();
|
||||
|
||||
lastPayDirtMined = now;
|
||||
++totalMined;
|
||||
|
||||
if (recentMined == 0)
|
||||
{
|
||||
recentPayDirtMined = now;
|
||||
}
|
||||
++recentMined;
|
||||
|
||||
Duration timeSinceStart = Duration.between(recentPayDirtMined, now);
|
||||
if (!timeSinceStart.isZero())
|
||||
{
|
||||
perHour = (int) ((double) recentMined * (double) HOUR.toMillis() / (double) timeSinceStart.toMillis());
|
||||
}
|
||||
}
|
||||
|
||||
public void resetRecent()
|
||||
{
|
||||
recentPayDirtMined = null;
|
||||
recentMined = 0;
|
||||
}
|
||||
|
||||
public int getPerHour()
|
||||
{
|
||||
return perHour;
|
||||
}
|
||||
|
||||
public Instant getLastPayDirtMined()
|
||||
{
|
||||
return lastPayDirtMined;
|
||||
}
|
||||
|
||||
public int getTotalMined()
|
||||
{
|
||||
return totalMined;
|
||||
}
|
||||
|
||||
public Instant getRecentPayDirtMined()
|
||||
{
|
||||
return recentPayDirtMined;
|
||||
}
|
||||
|
||||
public int getRecentMined()
|
||||
{
|
||||
return recentMined;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* 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.mining;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11161;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11360;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11361;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11364;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11365;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11366;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11367;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11369;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11370;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11371;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11372;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11373;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11374;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11375;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11376;
|
||||
import static net.runelite.api.ObjectID.ROCKS_11377;
|
||||
|
||||
enum Rock
|
||||
{
|
||||
TIN(Duration.ofMillis(2300), ROCKS_11360, ROCKS_11361),
|
||||
COPPER(Duration.ofMillis(2200), ROCKS_11161),
|
||||
IRON(Duration.ofMillis(5300), ROCKS_11364, ROCKS_11365)
|
||||
{
|
||||
@Override
|
||||
Duration getRespawnTime(boolean inMiningGuild)
|
||||
{
|
||||
return inMiningGuild ? Duration.ofMillis(2200) : super.respawnTime;
|
||||
}
|
||||
},
|
||||
COAL(Duration.ofSeconds(40), ROCKS_11366, ROCKS_11367)
|
||||
{
|
||||
@Override
|
||||
Duration getRespawnTime(boolean inMiningGuild)
|
||||
{
|
||||
return inMiningGuild ? Duration.ofMillis(14_500) : super.respawnTime;
|
||||
}
|
||||
},
|
||||
SILVER(Duration.ofMinutes(1), ROCKS_11369),
|
||||
GOLD(Duration.ofMinutes(1), ROCKS_11370, ROCKS_11371),
|
||||
MITHRIL(Duration.ofMinutes(2), ROCKS_11372, ROCKS_11373)
|
||||
{
|
||||
@Override
|
||||
Duration getRespawnTime(boolean inMiningGuild)
|
||||
{
|
||||
return inMiningGuild ? Duration.ofMinutes(1) : super.respawnTime;
|
||||
}
|
||||
},
|
||||
ADAMANTITE(Duration.ofMinutes(4), ROCKS_11374, ROCKS_11375)
|
||||
{
|
||||
@Override
|
||||
Duration getRespawnTime(boolean inMiningGuild)
|
||||
{
|
||||
return inMiningGuild ? Duration.ofMinutes(2) : super.respawnTime;
|
||||
}
|
||||
},
|
||||
RUNITE(Duration.ofMinutes(12), ROCKS_11376, ROCKS_11377)
|
||||
{
|
||||
@Override
|
||||
Duration getRespawnTime(boolean inMiningGuild)
|
||||
{
|
||||
return inMiningGuild ? Duration.ofMinutes(6) : super.respawnTime;
|
||||
}
|
||||
},
|
||||
ORE_VEIN(Duration.ofSeconds(108)),
|
||||
AMETHYST(Duration.ofSeconds(75));
|
||||
|
||||
private static final Map<Integer, Rock> ROCKS;
|
||||
|
||||
static
|
||||
{
|
||||
ImmutableMap.Builder<Integer, Rock> builder = new ImmutableMap.Builder<>();
|
||||
for (Rock rock : values())
|
||||
{
|
||||
for (int id : rock.ids)
|
||||
{
|
||||
builder.put(id, rock);
|
||||
}
|
||||
}
|
||||
ROCKS = builder.build();
|
||||
}
|
||||
|
||||
private final Duration respawnTime;
|
||||
private final int[] ids;
|
||||
|
||||
Rock(Duration respawnTime, int... ids)
|
||||
{
|
||||
this.respawnTime = respawnTime;
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
Duration getRespawnTime(boolean inMiningGuild)
|
||||
{
|
||||
return respawnTime;
|
||||
}
|
||||
|
||||
static Rock getRock(int id)
|
||||
{
|
||||
return ROCKS.get(id);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Lucas C <lucas1757@gmail.com>
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -22,19 +22,19 @@
|
||||
* (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.cooking;
|
||||
package net.runelite.client.plugins.mining;
|
||||
|
||||
import java.time.Instant;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
class FermentTimerSession
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
class RockRespawn
|
||||
{
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Instant lastWineMakingAction;
|
||||
|
||||
void updateLastWineMakingAction()
|
||||
{
|
||||
this.lastWineMakingAction = Instant.now();
|
||||
}
|
||||
private final Rock rock;
|
||||
private final WorldPoint worldPoint;
|
||||
private final Instant startTime;
|
||||
private final int respawnTime;
|
||||
}
|
||||
@@ -123,6 +123,8 @@ public class MusicListPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
header.deleteAllChildren();
|
||||
|
||||
//Creation of the search and toggle status buttons
|
||||
musicSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
musicSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||
|
||||
@@ -134,6 +134,8 @@ public class QuestListPlugin extends Plugin
|
||||
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
|
||||
if (header != null)
|
||||
{
|
||||
header.deleteAllChildren();
|
||||
|
||||
questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
|
||||
questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
|
||||
questSearchButton.setOriginalWidth(18);
|
||||
|
||||
@@ -1,179 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Tyler <http://github.com/tylerthardy>
|
||||
* 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.runepouch;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.BOTH;
|
||||
import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.MOUSE_HOVER;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
import net.runelite.client.ui.overlay.WidgetItemOverlay;
|
||||
import net.runelite.client.ui.overlay.tooltip.Tooltip;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
public class RunepouchOverlay extends WidgetItemOverlay
|
||||
{
|
||||
private static final Varbits[] AMOUNT_VARBITS =
|
||||
{
|
||||
Varbits.RUNE_POUCH_AMOUNT1, Varbits.RUNE_POUCH_AMOUNT2, Varbits.RUNE_POUCH_AMOUNT3
|
||||
};
|
||||
private static final Varbits[] RUNE_VARBITS =
|
||||
{
|
||||
Varbits.RUNE_POUCH_RUNE1, Varbits.RUNE_POUCH_RUNE2, Varbits.RUNE_POUCH_RUNE3
|
||||
};
|
||||
private static final Dimension IMAGE_SIZE = new Dimension(11, 11);
|
||||
|
||||
private final Client client;
|
||||
private final RunepouchConfig config;
|
||||
private final TooltipManager tooltipManager;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
RunepouchOverlay(Client client, RunepouchConfig config, TooltipManager tooltipManager)
|
||||
{
|
||||
this.tooltipManager = tooltipManager;
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
showOnInventory();
|
||||
showOnBank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem itemWidget)
|
||||
{
|
||||
if (itemId != ItemID.RUNE_POUCH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assert AMOUNT_VARBITS.length == RUNE_VARBITS.length;
|
||||
|
||||
graphics.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
Point location = itemWidget.getCanvasLocation();
|
||||
StringBuilder tooltipBuilder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < AMOUNT_VARBITS.length; i++)
|
||||
{
|
||||
Varbits amountVarbit = AMOUNT_VARBITS[i];
|
||||
|
||||
int amount = client.getVar(amountVarbit);
|
||||
if (amount <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Varbits runeVarbit = RUNE_VARBITS[i];
|
||||
int runeId = client.getVar(runeVarbit);
|
||||
Runes rune = Runes.getRune(runeId);
|
||||
if (rune == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tooltipBuilder
|
||||
.append(amount)
|
||||
.append(" ")
|
||||
.append(ColorUtil.wrapWithColorTag(rune.getName(), Color.YELLOW))
|
||||
.append("</br>");
|
||||
|
||||
if (config.runePouchOverlayMode() == MOUSE_HOVER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
graphics.setColor(Color.black);
|
||||
graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 13 : 6),
|
||||
location.getY() + 14 + (graphics.getFontMetrics().getHeight() - 1) * i);
|
||||
|
||||
graphics.setColor(config.fontColor());
|
||||
graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 12 : 5),
|
||||
location.getY() + 13 + (graphics.getFontMetrics().getHeight() - 1) * i);
|
||||
|
||||
if (!config.showIcons())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferedImage image = getRuneImage(rune);
|
||||
if (image != null)
|
||||
{
|
||||
OverlayUtil.renderImageLocation(graphics,
|
||||
new Point(location.getX(), location.getY() + graphics.getFontMetrics().getHeight() * i),
|
||||
image);
|
||||
}
|
||||
}
|
||||
|
||||
String tooltip = tooltipBuilder.toString();
|
||||
|
||||
if (!tooltip.isEmpty()
|
||||
&& itemWidget.getCanvasBounds().contains(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY())
|
||||
&& (config.runePouchOverlayMode() == MOUSE_HOVER || config.runePouchOverlayMode() == BOTH))
|
||||
{
|
||||
tooltipManager.add(new Tooltip(tooltip));
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage getRuneImage(Runes rune)
|
||||
{
|
||||
BufferedImage runeImg = rune.getImage();
|
||||
if (runeImg != null)
|
||||
{
|
||||
return runeImg;
|
||||
}
|
||||
|
||||
runeImg = itemManager.getImage(rune.getItemId());
|
||||
if (runeImg == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedImage resizedImg = new BufferedImage(IMAGE_SIZE.width, IMAGE_SIZE.height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = resizedImg.createGraphics();
|
||||
g.drawImage(runeImg, 0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height, null);
|
||||
g.dispose();
|
||||
|
||||
rune.setImage(resizedImg);
|
||||
return resizedImg;
|
||||
}
|
||||
|
||||
private static String formatNumber(int amount)
|
||||
{
|
||||
return amount < 1000 ? String.valueOf(amount) : amount / 1000 + "K";
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2017, Tyler <http://github.com/tylerthardy>
|
||||
* 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.runepouch;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.BOTH;
|
||||
import static net.runelite.client.plugins.runepouch.config.RunePouchOverlayMode.MOUSE_HOVER;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
import net.runelite.client.ui.overlay.WidgetItemOverlay;
|
||||
import net.runelite.client.ui.overlay.tooltip.Tooltip;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
public class RunepouchOverlay extends WidgetItemOverlay
|
||||
{
|
||||
private static final Varbits[] AMOUNT_VARBITS =
|
||||
{
|
||||
Varbits.RUNE_POUCH_AMOUNT1, Varbits.RUNE_POUCH_AMOUNT2, Varbits.RUNE_POUCH_AMOUNT3
|
||||
};
|
||||
private static final Varbits[] RUNE_VARBITS =
|
||||
{
|
||||
Varbits.RUNE_POUCH_RUNE1, Varbits.RUNE_POUCH_RUNE2, Varbits.RUNE_POUCH_RUNE3
|
||||
};
|
||||
private static final Dimension IMAGE_SIZE = new Dimension(11, 11);
|
||||
|
||||
private final Client client;
|
||||
private final RunepouchConfig config;
|
||||
private final TooltipManager tooltipManager;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
RunepouchOverlay(Client client, RunepouchConfig config, TooltipManager tooltipManager)
|
||||
{
|
||||
this.tooltipManager = tooltipManager;
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
showOnInventory();
|
||||
showOnBank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem itemWidget)
|
||||
{
|
||||
if (itemId != ItemID.RUNE_POUCH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assert AMOUNT_VARBITS.length == RUNE_VARBITS.length;
|
||||
|
||||
graphics.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
Point location = itemWidget.getCanvasLocation();
|
||||
StringBuilder tooltipBuilder = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < AMOUNT_VARBITS.length; i++)
|
||||
{
|
||||
Varbits amountVarbit = AMOUNT_VARBITS[i];
|
||||
|
||||
int amount = client.getVar(amountVarbit);
|
||||
if (amount <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Varbits runeVarbit = RUNE_VARBITS[i];
|
||||
int runeId = client.getVar(runeVarbit);
|
||||
Runes rune = Runes.getRune(runeId);
|
||||
if (rune == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tooltipBuilder
|
||||
.append(amount)
|
||||
.append(" ")
|
||||
.append(ColorUtil.wrapWithColorTag(rune.getName(), Color.YELLOW))
|
||||
.append("</br>");
|
||||
|
||||
if (config.runePouchOverlayMode() == MOUSE_HOVER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
graphics.setColor(Color.black);
|
||||
graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 12 : 5),
|
||||
location.getY() + 13 + (graphics.getFontMetrics().getHeight() - 1) * i);
|
||||
|
||||
graphics.setColor(config.fontColor());
|
||||
graphics.drawString("" + formatNumber(amount), location.getX() + (config.showIcons() ? 11 : 4),
|
||||
location.getY() + 12 + (graphics.getFontMetrics().getHeight() - 1) * i);
|
||||
|
||||
if (!config.showIcons())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferedImage image = getRuneImage(rune);
|
||||
if (image != null)
|
||||
{
|
||||
OverlayUtil.renderImageLocation(graphics,
|
||||
new Point(location.getX() - 1, location.getY() + graphics.getFontMetrics().getHeight() * i - 1),
|
||||
image);
|
||||
}
|
||||
}
|
||||
|
||||
String tooltip = tooltipBuilder.toString();
|
||||
|
||||
if (!tooltip.isEmpty()
|
||||
&& itemWidget.getCanvasBounds().contains(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY())
|
||||
&& (config.runePouchOverlayMode() == MOUSE_HOVER || config.runePouchOverlayMode() == BOTH))
|
||||
{
|
||||
tooltipManager.add(new Tooltip(tooltip));
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage getRuneImage(Runes rune)
|
||||
{
|
||||
BufferedImage runeImg = rune.getImage();
|
||||
if (runeImg != null)
|
||||
{
|
||||
return runeImg;
|
||||
}
|
||||
|
||||
runeImg = itemManager.getImage(rune.getItemId());
|
||||
if (runeImg == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
BufferedImage resizedImg = new BufferedImage(IMAGE_SIZE.width, IMAGE_SIZE.height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = resizedImg.createGraphics();
|
||||
g.drawImage(runeImg, 0, 0, IMAGE_SIZE.width, IMAGE_SIZE.height, null);
|
||||
g.dispose();
|
||||
|
||||
rune.setImage(resizedImg);
|
||||
return resizedImg;
|
||||
}
|
||||
|
||||
private static String formatNumber(int amount)
|
||||
{
|
||||
return amount < 1000 ? String.valueOf(amount) : amount / 1000 + "K";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +124,8 @@ class SlayerOverlay extends WidgetItemOverlay
|
||||
|
||||
textComponent.setText(String.valueOf(amount));
|
||||
|
||||
// Draw the counter in the top left for equipment, and bottom left for jewelry
|
||||
textComponent.setPosition(new Point(bounds.x, bounds.y + (SLAYER_JEWELRY.contains(itemId)
|
||||
// Draw the counter in the bottom left for equipment, and top left for jewelry
|
||||
textComponent.setPosition(new Point(bounds.x - 1, bounds.y - 1 + (SLAYER_JEWELRY.contains(itemId)
|
||||
? bounds.height
|
||||
: graphics.getFontMetrics().getHeight())));
|
||||
textComponent.render(graphics);
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Abexlry <abexlry@gmail.com>
|
||||
* 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.wasdcamera;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.MouseAdapter;
|
||||
|
||||
class WASDCameraListener extends MouseAdapter implements KeyListener
|
||||
{
|
||||
@Inject
|
||||
private WASDCameraPlugin plugin;
|
||||
|
||||
@Inject
|
||||
private WASDCameraConfig config;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
private final Map<Integer, Integer> modified = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN || !plugin.chatboxFocused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plugin.isTyping())
|
||||
{
|
||||
if (config.up().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_UP);
|
||||
e.setKeyCode(KeyEvent.VK_UP);
|
||||
}
|
||||
else if (config.down().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_DOWN);
|
||||
e.setKeyCode(KeyEvent.VK_DOWN);
|
||||
}
|
||||
else if (config.left().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_LEFT);
|
||||
e.setKeyCode(KeyEvent.VK_LEFT);
|
||||
}
|
||||
else if (config.right().matches(e))
|
||||
{
|
||||
modified.put(e.getKeyCode(), KeyEvent.VK_RIGHT);
|
||||
e.setKeyCode(KeyEvent.VK_RIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (e.getKeyCode())
|
||||
{
|
||||
case KeyEvent.VK_ENTER:
|
||||
case KeyEvent.VK_SLASH:
|
||||
case KeyEvent.VK_COLON:
|
||||
// refocus chatbox
|
||||
plugin.setTyping(true);
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
plugin.unlockChat();
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (e.getKeyCode())
|
||||
{
|
||||
case KeyEvent.VK_ENTER:
|
||||
plugin.setTyping(false);
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
plugin.lockChat();
|
||||
});
|
||||
break;
|
||||
case KeyEvent.VK_ESCAPE:
|
||||
plugin.setTyping(false);
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, "");
|
||||
plugin.lockChat();
|
||||
});
|
||||
break;
|
||||
case KeyEvent.VK_BACK_SPACE:
|
||||
if (Strings.isNullOrEmpty(client.getVar(VarClientStr.CHATBOX_TYPED_TEXT)))
|
||||
{
|
||||
plugin.setTyping(false);
|
||||
clientThread.invoke(() -> plugin.lockChat());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.chatboxFocused() && !plugin.isTyping())
|
||||
{
|
||||
modified.remove(e.getKeyCode());
|
||||
|
||||
if (config.up().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_UP);
|
||||
}
|
||||
else if (config.down().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_DOWN);
|
||||
}
|
||||
else if (config.left().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_LEFT);
|
||||
}
|
||||
else if (config.right().matches(e))
|
||||
{
|
||||
e.setKeyCode(KeyEvent.VK_RIGHT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// press d + enter + release d - causes the right arrow to never be released
|
||||
Integer m = modified.get(e.getKeyCode());
|
||||
if (m != null)
|
||||
{
|
||||
modified.remove(e.getKeyCode());
|
||||
e.setKeyCode(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,220 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* 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.ui.overlay.components;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.IndexedSprite;
|
||||
import net.runelite.client.ui.overlay.RenderableEntity;
|
||||
|
||||
@Setter
|
||||
public class TooltipComponent implements RenderableEntity
|
||||
{
|
||||
private static final Pattern BR = Pattern.compile("</br>");
|
||||
private static final int OFFSET = 4;
|
||||
private static final int MOD_ICON_WIDTH = 13; // they are generally 13px wide
|
||||
|
||||
private String text;
|
||||
private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR;
|
||||
private Point position = new Point();
|
||||
private IndexedSprite[] modIcons;
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
// Tooltip size
|
||||
final FontMetrics metrics = graphics.getFontMetrics();
|
||||
final int textDescent = metrics.getDescent();
|
||||
final int textHeight = metrics.getHeight();
|
||||
int tooltipWidth = 0;
|
||||
int tooltipHeight = 0;
|
||||
String[] lines = BR.split(text);
|
||||
|
||||
// Calculate tooltip size
|
||||
for (String line : lines)
|
||||
{
|
||||
int textWidth = calculateTextWidth(metrics, line);
|
||||
|
||||
if (textWidth > tooltipWidth)
|
||||
{
|
||||
tooltipWidth = textWidth;
|
||||
}
|
||||
|
||||
tooltipHeight += textHeight;
|
||||
}
|
||||
|
||||
// Tooltip position
|
||||
int x = position.x;
|
||||
int y = position.y;
|
||||
|
||||
// Render tooltip - background
|
||||
final Rectangle tooltipBackground = new Rectangle(x, y,
|
||||
tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2);
|
||||
final BackgroundComponent backgroundComponent = new BackgroundComponent();
|
||||
backgroundComponent.setBackgroundColor(backgroundColor);
|
||||
backgroundComponent.setRectangle(tooltipBackground);
|
||||
backgroundComponent.render(graphics);
|
||||
graphics.setColor(Color.WHITE);
|
||||
|
||||
// Render tooltip - text - line by line
|
||||
int textX = x + OFFSET;
|
||||
int textY = y + OFFSET;
|
||||
int lineX;
|
||||
Color nextColor = Color.WHITE;
|
||||
for (int i = 0; i < lines.length; i++)
|
||||
{
|
||||
lineX = textX;
|
||||
final String line = lines[i];
|
||||
char[] chars = line.toCharArray();
|
||||
|
||||
int begin = 0;
|
||||
for (int j = 0; j < chars.length; j++)
|
||||
{
|
||||
if (chars[j] == '<')
|
||||
{
|
||||
TextComponent textComponent = new TextComponent();
|
||||
textComponent.setColor(nextColor);
|
||||
String text = line.substring(begin, j);
|
||||
textComponent.setText(text);
|
||||
textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent));
|
||||
textComponent.render(graphics);
|
||||
|
||||
lineX += metrics.stringWidth(text);
|
||||
|
||||
begin = j;
|
||||
}
|
||||
else if (chars[j] == '>')
|
||||
{
|
||||
String subLine = line.substring(begin + 1, j);
|
||||
|
||||
if (subLine.startsWith("col="))
|
||||
{
|
||||
String argument = subLine.substring(4);
|
||||
nextColor = Color.decode("#" + argument);
|
||||
}
|
||||
else if (subLine.equals("/col"))
|
||||
{
|
||||
nextColor = Color.WHITE;
|
||||
}
|
||||
else if (subLine.startsWith("img="))
|
||||
{
|
||||
if (modIcons != null)
|
||||
{
|
||||
String argument = subLine.substring(4);
|
||||
int iconId = Integer.parseInt(argument);
|
||||
IndexedSprite modIcon = modIcons[iconId];
|
||||
renderModIcon(graphics, lineX, textY + i * textHeight - textDescent, modIcon);
|
||||
lineX += modIcon.getWidth();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TextComponent textComponent = new TextComponent();
|
||||
textComponent.setColor(nextColor);
|
||||
String text = line.substring(begin, j + 1);
|
||||
textComponent.setText(text);
|
||||
textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent));
|
||||
textComponent.render(graphics);
|
||||
|
||||
lineX += metrics.stringWidth(text);
|
||||
}
|
||||
|
||||
begin = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw trailing text (after last tag)
|
||||
final TextComponent textComponent = new TextComponent();
|
||||
textComponent.setColor(nextColor);
|
||||
textComponent.setText(line.substring(begin));
|
||||
textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent));
|
||||
textComponent.render(graphics);
|
||||
}
|
||||
|
||||
return new Dimension(tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2);
|
||||
}
|
||||
|
||||
private static int calculateTextWidth(FontMetrics metrics, String line)
|
||||
{
|
||||
char[] chars = line.toCharArray();
|
||||
int textWidth = 0;
|
||||
|
||||
int begin = 0;
|
||||
for (int j = 0; j < chars.length; j++)
|
||||
{
|
||||
if (chars[j] == '<')
|
||||
{
|
||||
textWidth += metrics.stringWidth(line.substring(begin, j));
|
||||
|
||||
begin = j;
|
||||
}
|
||||
else if (chars[j] == '>')
|
||||
{
|
||||
String subLine = line.substring(begin + 1, j);
|
||||
|
||||
if (subLine.startsWith("img="))
|
||||
{
|
||||
textWidth += MOD_ICON_WIDTH;
|
||||
}
|
||||
else if (!subLine.startsWith("col=") && !subLine.startsWith("/col"))
|
||||
{
|
||||
textWidth += metrics.stringWidth(line.substring(begin, j + 1));
|
||||
}
|
||||
|
||||
begin = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Include trailing text (after last tag)
|
||||
textWidth += metrics.stringWidth(line.substring(begin));
|
||||
|
||||
return textWidth;
|
||||
}
|
||||
|
||||
private void renderModIcon(Graphics2D graphics, int x, int y, IndexedSprite modIcon)
|
||||
{
|
||||
int sourceOffset = 0;
|
||||
|
||||
for (int y2 = 0; y2 < modIcon.getHeight(); y2++)
|
||||
{
|
||||
for (int x2 = 0; x2 < modIcon.getWidth(); x2++)
|
||||
{
|
||||
int index = modIcon.getPixels()[sourceOffset++] & 0xff;
|
||||
|
||||
if (index != 0)
|
||||
{
|
||||
graphics.setColor(new Color(modIcon.getPalette()[index]));
|
||||
graphics.drawLine(x + x2, y + y2, x + x2, y + y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
|
||||
* 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.ui.overlay.components;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.IndexedSprite;
|
||||
import net.runelite.client.ui.overlay.RenderableEntity;
|
||||
|
||||
@Setter
|
||||
public class TooltipComponent implements RenderableEntity
|
||||
{
|
||||
private static final Pattern BR = Pattern.compile("</br>");
|
||||
private static final int OFFSET = 4;
|
||||
private static final int MOD_ICON_WIDTH = 13; // they are generally 13px wide
|
||||
|
||||
private String text;
|
||||
private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR;
|
||||
private Point position = new Point();
|
||||
private IndexedSprite[] modIcons;
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
// Tooltip size
|
||||
final FontMetrics metrics = graphics.getFontMetrics();
|
||||
final int textDescent = metrics.getDescent();
|
||||
final int textHeight = metrics.getHeight();
|
||||
int tooltipWidth = 0;
|
||||
int tooltipHeight = 0;
|
||||
String[] lines = BR.split(text);
|
||||
|
||||
// Calculate tooltip size
|
||||
for (String line : lines)
|
||||
{
|
||||
int textWidth = calculateTextWidth(metrics, line);
|
||||
|
||||
if (textWidth > tooltipWidth)
|
||||
{
|
||||
tooltipWidth = textWidth;
|
||||
}
|
||||
|
||||
tooltipHeight += textHeight;
|
||||
}
|
||||
|
||||
// Tooltip position
|
||||
int x = position.x;
|
||||
int y = position.y;
|
||||
|
||||
// Render tooltip - background
|
||||
final Rectangle tooltipBackground = new Rectangle(x, y,
|
||||
tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2);
|
||||
final BackgroundComponent backgroundComponent = new BackgroundComponent();
|
||||
backgroundComponent.setBackgroundColor(backgroundColor);
|
||||
backgroundComponent.setRectangle(tooltipBackground);
|
||||
backgroundComponent.render(graphics);
|
||||
graphics.setColor(Color.WHITE);
|
||||
|
||||
// Render tooltip - text - line by line
|
||||
int textX = x + OFFSET;
|
||||
int textY = y + OFFSET;
|
||||
int lineX;
|
||||
Color nextColor = Color.WHITE;
|
||||
for (int i = 0; i < lines.length; i++)
|
||||
{
|
||||
lineX = textX;
|
||||
final String line = lines[i];
|
||||
char[] chars = line.toCharArray();
|
||||
|
||||
int begin = 0;
|
||||
for (int j = 0; j < chars.length; j++)
|
||||
{
|
||||
if (chars[j] == '<')
|
||||
{
|
||||
TextComponent textComponent = new TextComponent();
|
||||
textComponent.setColor(nextColor);
|
||||
String text = line.substring(begin, j);
|
||||
textComponent.setText(text);
|
||||
textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent));
|
||||
textComponent.render(graphics);
|
||||
|
||||
lineX += metrics.stringWidth(text);
|
||||
|
||||
begin = j;
|
||||
}
|
||||
else if (chars[j] == '>')
|
||||
{
|
||||
String subLine = line.substring(begin + 1, j);
|
||||
|
||||
if (subLine.startsWith("col="))
|
||||
{
|
||||
String argument = subLine.substring(4);
|
||||
nextColor = Color.decode("#" + argument);
|
||||
}
|
||||
else if (subLine.equals("/col"))
|
||||
{
|
||||
nextColor = Color.WHITE;
|
||||
}
|
||||
else if (subLine.startsWith("img="))
|
||||
{
|
||||
if (modIcons != null)
|
||||
{
|
||||
String argument = subLine.substring(4);
|
||||
int iconId = Integer.parseInt(argument);
|
||||
IndexedSprite modIcon = modIcons[iconId];
|
||||
renderModIcon(graphics, lineX, textY + i * textHeight - textDescent, modIcon);
|
||||
lineX += modIcon.getWidth();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TextComponent textComponent = new TextComponent();
|
||||
textComponent.setColor(nextColor);
|
||||
String text = line.substring(begin, j + 1);
|
||||
textComponent.setText(text);
|
||||
textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent));
|
||||
textComponent.render(graphics);
|
||||
|
||||
lineX += metrics.stringWidth(text);
|
||||
}
|
||||
|
||||
begin = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw trailing text (after last tag)
|
||||
final TextComponent textComponent = new TextComponent();
|
||||
textComponent.setColor(nextColor);
|
||||
textComponent.setText(line.substring(begin));
|
||||
textComponent.setPosition(new Point(lineX, textY + (i + 1) * textHeight - textDescent));
|
||||
textComponent.render(graphics);
|
||||
}
|
||||
|
||||
return new Dimension(tooltipWidth + OFFSET * 2, tooltipHeight + OFFSET * 2);
|
||||
}
|
||||
|
||||
private static int calculateTextWidth(FontMetrics metrics, String line)
|
||||
{
|
||||
char[] chars = line.toCharArray();
|
||||
int textWidth = 0;
|
||||
|
||||
int begin = 0;
|
||||
for (int j = 0; j < chars.length; j++)
|
||||
{
|
||||
if (chars[j] == '<')
|
||||
{
|
||||
textWidth += metrics.stringWidth(line.substring(begin, j));
|
||||
|
||||
begin = j;
|
||||
}
|
||||
else if (chars[j] == '>')
|
||||
{
|
||||
String subLine = line.substring(begin + 1, j);
|
||||
|
||||
if (subLine.startsWith("img="))
|
||||
{
|
||||
textWidth += MOD_ICON_WIDTH;
|
||||
}
|
||||
else if (!subLine.startsWith("col=") && !subLine.startsWith("/col"))
|
||||
{
|
||||
textWidth += metrics.stringWidth(line.substring(begin, j + 1));
|
||||
}
|
||||
|
||||
begin = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Include trailing text (after last tag)
|
||||
textWidth += metrics.stringWidth(line.substring(begin));
|
||||
|
||||
return textWidth;
|
||||
}
|
||||
|
||||
private void renderModIcon(Graphics2D graphics, int x, int y, IndexedSprite modIcon)
|
||||
{
|
||||
int sourceOffset = 0;
|
||||
|
||||
for (int y2 = 0; y2 < modIcon.getHeight(); y2++)
|
||||
{
|
||||
for (int x2 = 0; x2 < modIcon.getWidth(); x2++)
|
||||
{
|
||||
int index = modIcon.getPixels()[sourceOffset++] & 0xff;
|
||||
|
||||
if (index != 0)
|
||||
{
|
||||
graphics.setColor(new Color(modIcon.getPalette()[index]));
|
||||
graphics.drawLine(x + x2, y + y2, x + x2, y + y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3314,7 +3314,7 @@
|
||||
"21521": 250,
|
||||
"21543": 13000,
|
||||
"21545": 13000,
|
||||
"21555": 18000,
|
||||
"21555": 30000,
|
||||
"21622": 13000,
|
||||
"21634": 8,
|
||||
"21637": 5,
|
||||
|
||||
@@ -30,14 +30,23 @@ import com.google.inject.testing.fieldbinder.BoundFieldModule;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GraphicChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import static org.mockito.Matchers.any;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@@ -60,6 +69,14 @@ public class CookingPluginTest
|
||||
@Bind
|
||||
Client client;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
InfoBoxManager infoBoxManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
ItemManager itemManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
CookingConfig config;
|
||||
@@ -68,10 +85,6 @@ public class CookingPluginTest
|
||||
@Bind
|
||||
CookingOverlay cookingOverlay;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
FermentTimerOverlay fermentTimerOverlay;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
OverlayManager overlayManager;
|
||||
@@ -91,8 +104,24 @@ public class CookingPluginTest
|
||||
cookingPlugin.onChatMessage(chatMessage);
|
||||
}
|
||||
|
||||
CookingSession cookingSession = cookingPlugin.getCookingSession();
|
||||
CookingSession cookingSession = cookingPlugin.getSession();
|
||||
assertNotNull(cookingSession);
|
||||
assertEquals(COOKING_MESSAGES.length, cookingSession.getCookAmount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnGraphicChanged()
|
||||
{
|
||||
Player player = mock(Player.class);
|
||||
when(player.getGraphic()).thenReturn(GraphicID.WINE_MAKE);
|
||||
|
||||
when(config.fermentTimer()).thenReturn(true);
|
||||
when(client.getLocalPlayer()).thenReturn(player);
|
||||
|
||||
GraphicChanged graphicChanged = new GraphicChanged();
|
||||
graphicChanged.setActor(player);
|
||||
cookingPlugin.onGraphicChanged(graphicChanged);
|
||||
|
||||
verify(infoBoxManager).addInfoBox(any(FermentTimer.class));
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,10 @@ package net.runelite.mixins;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.CollisionData;
|
||||
import net.runelite.api.CollisionDataFlag;
|
||||
import net.runelite.api.Constants;
|
||||
import net.runelite.api.DecorativeObject;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GroundObject;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemLayer;
|
||||
@@ -59,13 +57,18 @@ import net.runelite.api.mixins.FieldHook;
|
||||
import net.runelite.api.mixins.Inject;
|
||||
import net.runelite.api.mixins.Mixin;
|
||||
import net.runelite.api.mixins.Shadow;
|
||||
import net.runelite.rs.api.RSActor;
|
||||
import net.runelite.rs.api.RSClient;
|
||||
import net.runelite.rs.api.RSDeque;
|
||||
import net.runelite.rs.api.RSGameObject;
|
||||
import net.runelite.rs.api.RSGraphicsObject;
|
||||
import net.runelite.rs.api.RSItem;
|
||||
import net.runelite.rs.api.RSItemLayer;
|
||||
import net.runelite.rs.api.RSNode;
|
||||
import net.runelite.rs.api.RSProjectile;
|
||||
import net.runelite.rs.api.RSRenderable;
|
||||
import net.runelite.rs.api.RSTile;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@Mixin(RSTile.class)
|
||||
public abstract class RSTileMixin implements RSTile
|
||||
@@ -73,9 +76,6 @@ public abstract class RSTileMixin implements RSTile
|
||||
@Shadow("clientInstance")
|
||||
private static RSClient client;
|
||||
|
||||
@Inject
|
||||
private static GameObject lastGameObject;
|
||||
|
||||
@Inject
|
||||
private static RSDeque[][][] lastGroundItems = new RSDeque[Constants.MAX_Z][Constants.SCENE_SIZE][Constants.SCENE_SIZE];
|
||||
|
||||
@@ -89,7 +89,7 @@ public abstract class RSTileMixin implements RSTile
|
||||
private GroundObject previousGroundObject;
|
||||
|
||||
@Inject
|
||||
private GameObject[] previousGameObjects;
|
||||
private RSGameObject[] previousGameObjects;
|
||||
|
||||
@Inject
|
||||
@Override
|
||||
@@ -222,55 +222,82 @@ public abstract class RSTileMixin implements RSTile
|
||||
|
||||
if (previousGameObjects == null)
|
||||
{
|
||||
previousGameObjects = new GameObject[5];
|
||||
previousGameObjects = new RSGameObject[5];
|
||||
}
|
||||
|
||||
// Previous game object
|
||||
GameObject previous = previousGameObjects[idx];
|
||||
RSGameObject previous = previousGameObjects[idx];
|
||||
|
||||
// GameObject that was changed.
|
||||
RSGameObject current = (RSGameObject) getGameObjects()[idx];
|
||||
|
||||
// Last game object
|
||||
GameObject last = lastGameObject;
|
||||
|
||||
// Update last game object
|
||||
lastGameObject = current;
|
||||
|
||||
// Update previous object to current
|
||||
previousGameObjects[idx] = current;
|
||||
|
||||
// Duplicate event, return
|
||||
if (current != null && current.equals(last))
|
||||
if (current == previous)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Characters seem to generate a constant stream of new GameObjects
|
||||
if (current == null || !(current.getRenderable() instanceof Actor))
|
||||
// actors, projectiles, and graphics objects are added and removed from the scene each frame as GameObjects,
|
||||
// so ignore them.
|
||||
boolean currentInvalid = false, prevInvalid = false;
|
||||
if (current != null)
|
||||
{
|
||||
if (current == null && previous != null)
|
||||
RSRenderable renderable = current.getRenderable();
|
||||
currentInvalid = renderable instanceof RSActor || renderable instanceof RSProjectile || renderable instanceof RSGraphicsObject;
|
||||
}
|
||||
|
||||
if (previous != null)
|
||||
{
|
||||
RSRenderable renderable = previous.getRenderable();
|
||||
prevInvalid = renderable instanceof RSActor || renderable instanceof RSProjectile || renderable instanceof RSGraphicsObject;
|
||||
}
|
||||
|
||||
Logger logger = client.getLogger();
|
||||
if (current == null)
|
||||
{
|
||||
if (prevInvalid)
|
||||
{
|
||||
GameObjectDespawned gameObjectDespawned = new GameObjectDespawned();
|
||||
gameObjectDespawned.setTile(this);
|
||||
gameObjectDespawned.setGameObject(previous);
|
||||
client.getCallbacks().post(gameObjectDespawned);
|
||||
return;
|
||||
}
|
||||
else if (current != null && previous == null)
|
||||
|
||||
logger.trace("Game object despawn: {}", previous.getId());
|
||||
|
||||
GameObjectDespawned gameObjectDespawned = new GameObjectDespawned();
|
||||
gameObjectDespawned.setTile(this);
|
||||
gameObjectDespawned.setGameObject(previous);
|
||||
client.getCallbacks().post(gameObjectDespawned);
|
||||
}
|
||||
else if (previous == null)
|
||||
{
|
||||
if (currentInvalid)
|
||||
{
|
||||
GameObjectSpawned gameObjectSpawned = new GameObjectSpawned();
|
||||
gameObjectSpawned.setTile(this);
|
||||
gameObjectSpawned.setGameObject(current);
|
||||
client.getCallbacks().post(gameObjectSpawned);
|
||||
return;
|
||||
}
|
||||
else if (current != null && previous != null)
|
||||
|
||||
logger.trace("Game object spawn: {}", current.getId());
|
||||
|
||||
GameObjectSpawned gameObjectSpawned = new GameObjectSpawned();
|
||||
gameObjectSpawned.setTile(this);
|
||||
gameObjectSpawned.setGameObject(current);
|
||||
client.getCallbacks().post(gameObjectSpawned);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentInvalid && prevInvalid)
|
||||
{
|
||||
GameObjectChanged gameObjectsChanged = new GameObjectChanged();
|
||||
gameObjectsChanged.setTile(this);
|
||||
gameObjectsChanged.setPrevious(previous);
|
||||
gameObjectsChanged.setGameObject(current);
|
||||
client.getCallbacks().post(gameObjectsChanged);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.trace("Game object change: {} -> {}", previous.getId(), current.getId());
|
||||
|
||||
GameObjectChanged gameObjectsChanged = new GameObjectChanged();
|
||||
gameObjectsChanged.setTile(this);
|
||||
gameObjectsChanged.setPrevious(previous);
|
||||
gameObjectsChanged.setGameObject(current);
|
||||
client.getCallbacks().post(gameObjectsChanged);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +258,11 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
|
||||
for (int i = 0; i < itemIds.length; ++i)
|
||||
{
|
||||
if (itemIds[i] <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
WidgetItem item = getWidgetItem(i);
|
||||
|
||||
if (item != null)
|
||||
@@ -287,19 +292,17 @@ public abstract class RSWidgetMixin implements RSWidget
|
||||
int itemId = itemIds[index];
|
||||
int itemQuantity = itemQuantities[index];
|
||||
|
||||
Point widgetCanvasLocation = getCanvasLocation();
|
||||
|
||||
if (itemId <= 0 || itemQuantity <= 0 || columns <= 0)
|
||||
if (columns <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int row = index / columns;
|
||||
int col = index % columns;
|
||||
int itemX = widgetCanvasLocation.getX() + ((ITEM_SLOT_SIZE + xPitch) * col);
|
||||
int itemY = widgetCanvasLocation.getY() + ((ITEM_SLOT_SIZE + yPitch) * row);
|
||||
int itemX = rl$x + ((ITEM_SLOT_SIZE + xPitch) * col);
|
||||
int itemY = rl$y + ((ITEM_SLOT_SIZE + yPitch) * row);
|
||||
|
||||
Rectangle bounds = new Rectangle(itemX - 1, itemY - 1, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
|
||||
Rectangle bounds = new Rectangle(itemX, itemY, ITEM_SLOT_SIZE, ITEM_SLOT_SIZE);
|
||||
return new WidgetItem(itemId - 1, itemQuantity, index, bounds, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -248,10 +248,18 @@ public interface RSClient extends RSGameEngine, Client
|
||||
@Override
|
||||
void setPassword(String password);
|
||||
|
||||
@Import("otp")
|
||||
@Override
|
||||
void setOtp(String otp);
|
||||
|
||||
@Import("currentLoginField")
|
||||
@Override
|
||||
int getCurrentLoginField();
|
||||
|
||||
@Import("loginIndex")
|
||||
@Override
|
||||
int getLoginIndex();
|
||||
|
||||
@Import("playerOptions")
|
||||
@Override
|
||||
String[] getPlayerOptions();
|
||||
@@ -772,6 +780,7 @@ public interface RSClient extends RSGameEngine, Client
|
||||
boolean isInInstancedRegion();
|
||||
|
||||
@Import("itemPressedDuration")
|
||||
@Override
|
||||
int getItemPressedDuration();
|
||||
|
||||
@Import("itemPressedDuration")
|
||||
@@ -927,6 +936,14 @@ public interface RSClient extends RSGameEngine, Client
|
||||
@Import("endY")
|
||||
int getEndY();
|
||||
|
||||
@Import("if1DraggedWidget")
|
||||
@Override
|
||||
RSWidget getIf1DraggedWidget();
|
||||
|
||||
@Import("if1DraggedItemIndex")
|
||||
@Override
|
||||
int getIf1DraggedItemIndex();
|
||||
|
||||
@Import("spellSelected")
|
||||
@Override
|
||||
void setSpellSelected(boolean selected);
|
||||
|
||||
Reference in New Issue
Block a user