diff --git a/runelite-api/src/main/java/net/runelite/api/SpriteID.java b/runelite-api/src/main/java/net/runelite/api/SpriteID.java index 41af3559c4..d2667b2e85 100644 --- a/runelite-api/src/main/java/net/runelite/api/SpriteID.java +++ b/runelite-api/src/main/java/net/runelite/api/SpriteID.java @@ -1564,6 +1564,7 @@ public final class SpriteID public static final int MOBILE_FUNCTION_MODE_DISABLED = 1624; public static final int MOBILE_YELLOW_TOUCH_ANIMATION_1 = 1625; public static final int MOBILE_YELLOW_TOUCH_ANIMATION_2 = 1626; + public static final int MOBILE_FINGER_ON_INTERFACE = 1653; /* Unmapped: 1627~1701 */ public static final int BUTTON_FRIENDS = 1702; public static final int BUTTON_IGNORES = 1703; diff --git a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java index ba78672da5..f544845e8c 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java +++ b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java @@ -167,6 +167,10 @@ public enum VarPlayer MUSIC_TRACKS_UNLOCKED_18(1681), MUSIC_TRACKS_UNLOCKED_19(2065), + MUSIC_VOLUME(168), + SOUND_EFFECT_VOLUME(169), + AREA_EFFECT_VOLUME(872), + /** * f2p Quest varbits, these don't hold the completion value. */ diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 38f37f4e7e..511b00f1a2 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -46,11 +46,14 @@ import joptsimple.util.EnumConverter; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.api.events.GameStateChanged; import net.runelite.client.account.SessionManager; +import net.runelite.client.callback.Hooks; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.chat.CommandManager; import net.runelite.client.config.ConfigManager; import net.runelite.client.discord.DiscordService; +import net.runelite.client.eventbus.EventBus; import net.runelite.client.game.ClanManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.LootManager; @@ -148,6 +151,12 @@ public class RuneLite @Inject private Provider chatboxPanelManager; + @Inject + private Hooks hooks; + + @Inject + private EventBus eventBus; + @Inject @Nullable private Client client; @@ -348,6 +357,8 @@ public class RuneLite lootManager.get(); chatboxPanelManager.get(); + eventBus.subscribe(GameStateChanged.class, this, hooks::onGameStateChanged); + // Add core overlays WidgetOverlay.createOverlays(client).forEach(overlayManager::add); overlayManager.add(infoBoxOverlay.get()); diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index 1a97b5ea6c..94648a1f68 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -51,6 +51,7 @@ import net.runelite.api.WorldMapManager; import net.runelite.api.events.BeforeMenuRender; import net.runelite.api.events.BeforeRender; import net.runelite.api.events.Event; +import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.hooks.Callbacks; import net.runelite.api.hooks.DrawCallbacks; @@ -126,6 +127,7 @@ public class Hooks implements Callbacks private Graphics2D stretchedGraphics; private long lastCheck; + private boolean ignoreNextNpcUpdate; private boolean shouldProcessGameTick; private static MainBufferProvider lastMainBufferProvider; @@ -459,15 +461,36 @@ public class Hooks implements Callbacks overlayManager.getItemWidgets().clear(); } + public void onGameStateChanged(GameStateChanged gameStateChanged) + { + switch (gameStateChanged.getGameState()) + { + case LOGGING_IN: + case HOPPING: + ignoreNextNpcUpdate = true; + } + } + @Override public void updateNpcs() { - // The NPC update event seem to run every server tick, - // but having the game tick event after all packets - // have been processed is typically more useful. - shouldProcessGameTick = true; + if (ignoreNextNpcUpdate) + { + // After logging in an NPC update happens outside of the normal game tick, which + // is sent prior to skills and vars being bursted, so ignore it. + ignoreNextNpcUpdate = false; + log.debug("Skipping login updateNpc"); + } + else + { + // The NPC update event seem to run every server tick, + // but having the game tick event after all packets + // have been processed is typically more useful. + shouldProcessGameTick = true; + } + // Replay deferred events, otherwise if two npc - // update packets get processed in one frame, a + // update packets get processed in one client tick, a // despawn event could be published prior to the // spawn event, which is deferred deferredEventBus.replay(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java index 55735a3767..039e70770c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/CoordinateClue.java @@ -94,13 +94,13 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati .put(new WorldPoint(3544, 3256, 0), "North-east of Burgh de Rott.") .put(new WorldPoint(2841, 3267, 0), "Crandor island.") .put(new WorldPoint(3168, 3041, 0), "Bedabin Camp.") - .put(new WorldPoint(2542, 3031, 0), "Gu'Tanoth.") + .put(new WorldPoint(2542, 3031, 0), "Gu'Tanoth, may require 20gp.") .put(new WorldPoint(2581, 3030, 0), "Gu'Tanoth island, enter cave north-west of Feldip Hills (AKS).") .put(new WorldPoint(2961, 3024, 0), "Ship yard (DKP).") .put(new WorldPoint(2339, 3311, 0), "East of Prifddinas on Arandar mountain pass.") .put(new WorldPoint(3440, 3341, 0), "Nature Spirit's grotto.") .put(new WorldPoint(2763, 2974, 0), "Cairn Isle, west of Shilo Village.") - .put(new WorldPoint(3138, 2969, 0), "West of Bandit Camp.") + .put(new WorldPoint(3138, 2969, 0), "West of Bandit Camp in Kharidian Desert.") .put(new WorldPoint(2924, 2963, 0), "On the southern part of eastern Karamja.") .put(new WorldPoint(2838, 2914, 0), "Kharazi Jungle, near water pool.") .put(new WorldPoint(3441, 3419, 0), "Mort Myre Swamp.") diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java index ceb8df6df2..87deb91231 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/EmoteClue.java @@ -142,8 +142,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Panic on the pier where you catch the Fishing trawler. Have nothing equipped at all when you do.", "Fishing trawler", 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 on the Wilderness volcano bridge. Beware of double agents! Equip any headband and crozier.", "Wilderness volcano", 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("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", 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 Gypsy Aris in her tent. Equip a gold ring and a gold necklace.", "Varrock", GYPSY_TENT_ENTRANCE, new WorldPoint(3203, 3424, 0), RASPBERRY, item(GOLD_RING), item(GOLD_NECKLACE)), - new EmoteClue("Blow a raspberry at the bank of the Warrior's guild. Beware of double agents! Equip a dragon battleaxe, a slayer helm of any kind and a dragon defender or avernic defender.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), any("Dragon defender or Avernic defender", item(DRAGON_DEFENDER), item(AVERNIC_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 in the bank of the Warriors' Guild. Beware of double agents! Equip a dragon battleaxe, a slayer helm of any kind and a dragon defender or avernic defender.", "Warriors' guild", WARRIORS_GUILD_BANK_29047, new WorldPoint(2843, 3543, 0), RASPBERRY, item(DRAGON_BATTLEAXE), any("Dragon defender or Avernic defender", item(DRAGON_DEFENDER), item(AVERNIC_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.", "Ardougne Zoo", NEAR_THE_PARROTS_IN_ARDOUGNE_ZOO, new WorldPoint(2607, 3282, 0), RASPBERRY, item(STUDDED_BODY), item(BRONZE_PLATELEGS), item(STAFF)), 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", FISHING_GUILD_BANK, new WorldPoint(2588, 3419, 0), RASPBERRY, item(ELEMENTAL_SHIELD), item(BLUE_DHIDE_CHAPS), item(RUNE_WARHAMMER)), new EmoteClue("Blow raspberries outside the entrance to Keep Le Faye. Equip a coif, an iron platebody and leather gloves.", "Keep Le Faye", OUTSIDE_KEEP_LE_FAYE, new WorldPoint(2757, 3401, 0), RASPBERRY, item(COIF), item(IRON_PLATEBODY), item(LEATHER_GLOVES)), @@ -158,7 +157,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu new EmoteClue("Spin at Flynn's Mace Shop.", "Falador", null, new WorldPoint(2950, 3387, 0), SPIN), new EmoteClue("Spin at the crossroads north of Rimmington. Equip a green gnome hat, cream gnome top and leather chaps.", "Rimmington", 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", 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", 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(DRAGON_PICKAXEOR)), item(HELM_OF_NEITIZNOT), item(RUNE_BOOTS)), + 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", SOUL_ALTAR, new WorldPoint(1815, 3856, 0), SPIN, any("Dragon or Crystal pickaxe", item(DRAGON_PICKAXE), item(DRAGON_PICKAXE_12797), item(INFERNAL_PICKAXE), item(INFERNAL_PICKAXE_UNCHARGED), item(DRAGON_PICKAXEOR), item(CRYSTAL_PICKAXE), item(CRYSTAL_PICKAXE_INACTIVE)), 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.", "Varrock Castle", 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.", "Ardougne", 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.", "Barbarian Village", EAST_OF_THE_BARBARIAN_VILLAGE_BRIDGE, new WorldPoint(3105, 3420, 0), SPIN, SALUTE, item(PURPLE_GLOVES), item(STEEL_KITESHIELD), item(MITHRIL_FULL_HELM)), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java index df10aa06cc..2c75d1a49e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/cluescrolls/clues/SkillChallengeClue.java @@ -140,7 +140,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll new SkillChallengeClue("Chop a yew tree.", ANY_AXE), new SkillChallengeClue("Fix a magical lamp in Dorgesh-Kaan.", item(ItemID.LIGHT_ORB)), new SkillChallengeClue("Burn a yew log.", item(ItemID.YEW_LOGS), item(ItemID.TINDERBOX)), - new SkillChallengeClue("Catch and cook a swordfish.", "cook a swordfish.", ANY_HARPOON), + new SkillChallengeClue("Cook a swordfish", "cook a swordfish", item(ItemID.RAW_SWORDFISH)), new SkillChallengeClue("Craft multiple cosmic runes from a single essence.", item(ItemID.PURE_ESSENCE)), new SkillChallengeClue("Plant a watermelon seed.", item(ItemID.RAKE), item(ItemID.SEED_DIBBER), xOfItem(ItemID.WATERMELON_SEED, 3)), new SkillChallengeClue("Activate the Chivalry prayer."), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java index 07a84629c8..9f08e128af 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoConfig.java @@ -63,4 +63,15 @@ public interface OpponentInfoConfig extends Config { return true; } + + @ConfigItem( + keyName = "showOpponentsInMenu", + name = "Show opponents in menu", + description = "Marks opponents names in the menu which you are attacking or are attacking you (NPC only)", + position = 3 + ) + default boolean showOpponentsInMenu() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java index 4b1a5a223f..8c79904a96 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/opponentinfo/OpponentInfoPlugin.java @@ -36,11 +36,15 @@ import lombok.Getter; import net.runelite.api.Actor; import net.runelite.api.Client; import net.runelite.api.GameState; +import net.runelite.api.MenuEntry; +import net.runelite.api.MenuOpcode; +import net.runelite.api.NPC; import net.runelite.api.WorldType; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.InteractingChanged; +import net.runelite.api.events.MenuEntryAdded; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.EventBus; import net.runelite.client.plugins.Plugin; @@ -124,6 +128,7 @@ public class OpponentInfoPlugin extends Plugin eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged); eventBus.subscribe(InteractingChanged.class, this, this::onInteractingChanged); eventBus.subscribe(GameTick.class, this, this::onGameTick); + eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded); } private void onGameStateChanged(GameStateChanged gameStateChanged) @@ -198,4 +203,28 @@ public class OpponentInfoPlugin extends Plugin this.hitpointsDisplayStyle = config.hitpointsDisplayStyle(); this.showOpponentsOpponent = config.showOpponentsOpponent(); } + + private void onMenuEntryAdded(MenuEntryAdded menuEntryAdded) + { + if (menuEntryAdded.getType() != MenuOpcode.NPC_SECOND_OPTION.getId() + || !menuEntryAdded.getOption().equals("Attack") + || !config.showOpponentsInMenu()) + { + return; + } + + int npcIndex = menuEntryAdded.getIdentifier(); + NPC npc = client.getCachedNPCs()[npcIndex]; + if (npc == null) + { + return; + } + + if (npc.getInteracting() == client.getLocalPlayer() || lastOpponent == npc) + { + MenuEntry[] menuEntries = client.getMenuEntries(); + menuEntries[menuEntries.length - 1].setTarget("*" + menuEntryAdded.getTarget()); + client.setMenuEntries(menuEntries); + } + } }