From db684d8d1bf4b1362b92e41b219f63f9a3cf9707 Mon Sep 17 00:00:00 2001 From: Dustin Date: Sun, 28 Oct 2018 02:44:06 -0500 Subject: [PATCH] Stop slayer kills desync for Grotesque Guardians with Double Trouble reward active (#5983) Correctly reduce task amount by 2 if killing Grotesque Guardians with the Double Trouble slayer reward enabled Fixes #4336 --- .../java/net/runelite/api/SlayerUnlock.java | 117 ++++++++++++++++++ .../main/java/net/runelite/api/VarPlayer.java | 8 +- .../main/java/net/runelite/api/Varbits.java | 6 + .../client/plugins/slayer/SlayerPlugin.java | 15 +++ .../plugins/slayer/SlayerPluginTest.java | 2 +- 5 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/SlayerUnlock.java diff --git a/runelite-api/src/main/java/net/runelite/api/SlayerUnlock.java b/runelite-api/src/main/java/net/runelite/api/SlayerUnlock.java new file mode 100644 index 0000000000..1575650453 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/SlayerUnlock.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api; + +/** + * Unlockables in the slayer interface + */ +public enum SlayerUnlock +{ + // Copied from enum 834 in the cache + // enum 854 contains if you can disable the unlock + GARGOYLE_SMASHER(0), + SLUG_SALTER(1), + REPTILE_FREEZER(2), + SHROOM_SPRAYER(3), + DARK_BEAST_EXTEND(4), + SLAYER_HELMET(5), + SLAYER_RINGS(6), + BROADER_FLETCHING(7), + ANKOU_EXTEND(8), + SUQAH_EXTEND(9), + BLACK_DRAGON_EXTEND(10), + METAL_DRAGON_EXTEND(11), + SPIRITUAL_MAGE_EXTEND(12), + ABYSSAL_DEMON_EXTEND(13), + BLACK_DEMON_EXTEND(14), + GREATER_DEMON_EXTEND(15), + MITHRIL_DRAGON_UNLOCK(16), + AVIANSIES_ENABLE(17), + TZHARR_ENABLE(18), + BOSS_ENABLE(19), + BLOODVELD_EXTEND(20), + ABBERANT_SPECTRE_EXTEND(21), + AVIANSIES_EXTEND(22), + MITHRIL_DRAGON_EXTEND(23), + CAVE_HORROR_EXTEND(24), + DUST_DEVIL_EXTEND(25), + SKELETAL_WYVERN_EXTEND(26), + GARGOYLE_EXTEND(27), + NECHRYAEL_EXTEND(28), + CAVE_KRAKEN_EXTEND(29), + LIZARDMEN_ENABLE(30), + KBD_SLAYER_HELM(31), + KALPHITE_QUEEN_SLAYER_HELM(32), + ABYSSAL_DEMON_SAYER_HELM(33), + RED_DRAGON_ENABLE(34), + SUPERIOR_ENABLE(35, Varbits.SUPERIOR_ENABLED), + SCABARITE_EXTEND(36), + MITHRIL_DRAGON_NOTES(37), + SKOTIZO_SLAYER_HELM(38), + FOSSIL_ISLAND_WYVERN_EXTEND(39), + ADAMANT_DRAGON_EXTEND(40), + RUNE_DRAGON_EXTEND(41), + VORKATH_SLAYER_HELM(42), + FOSSIL_ISLAND_WYVERN_DISABLE(43, Varbits.FOSSIL_ISLAND_WYVERN_DISABLE), + GROTESQUE_GARDIAN_DOUBLE_COUNT(44); + + private Varbits toggleVarbit; + + SlayerUnlock(int index) + { + this(index, null); + } + + SlayerUnlock(int index, Varbits toggleVarbit) + { + assert index == ordinal(); + this.toggleVarbit = toggleVarbit; + } + + /** + * @return true if this unlock is bought + */ + public boolean isOwned(Client client) + { + VarPlayer varp = ordinal() > 32 ? VarPlayer.SLAYER_UNLOCK_2 : VarPlayer.SLAYER_UNLOCK_1; + return (client.getVar(varp) & (1 << (ordinal() % 32))) != 0; + } + + /** + * @return true if this unlock is bought and enabled + */ + public boolean isEnabled(Client client) + { + if (isOwned(client)) + { + if (toggleVarbit == null) + { + return true; + } + return client.getVar(toggleVarbit) == 0; + } + return false; + } +} 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 af559e0f2b..79cd10ff1a 100644 --- a/runelite-api/src/main/java/net/runelite/api/VarPlayer.java +++ b/runelite-api/src/main/java/net/runelite/api/VarPlayer.java @@ -114,7 +114,13 @@ public enum VarPlayer BIRD_HOUSE_MEADOW_NORTH(1626), BIRD_HOUSE_MEADOW_SOUTH(1627), BIRD_HOUSE_VALLEY_NORTH(1628), - BIRD_HOUSE_VALLEY_SOUTH(1629); + BIRD_HOUSE_VALLEY_SOUTH(1629), + + /** + * Slayer unlock bitfields + */ + SLAYER_UNLOCK_1(1076), + SLAYER_UNLOCK_2(1344); private final int id; } diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index c1b051040c..bc850fb4a1 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -409,6 +409,12 @@ public enum Varbits */ CORP_DAMAGE(999), + /** + * Toggleable slayer unlocks + */ + SUPERIOR_ENABLED(5362), + FOSSIL_ISLAND_WYVERN_DISABLE(6251), + CURRENT_BANK_TAB(4150), WORLDHOPPER_FAVROITE_1(4597), diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java index 6d375102c6..41080747e7 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/slayer/SlayerPlugin.java @@ -49,6 +49,8 @@ import net.runelite.api.ItemID; import net.runelite.api.NPC; import net.runelite.api.NPCComposition; import static net.runelite.api.Skill.SLAYER; +import net.runelite.api.SlayerUnlock; +import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.ChatMessage; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.ExperienceChanged; @@ -102,6 +104,8 @@ public class SlayerPlugin extends Plugin //Reward UI private static final Pattern REWARD_POINTS = Pattern.compile("Reward points: ((?:\\d+,)*\\d+)"); + private static final int GROTESQUE_GUARDIANS_REGION = 6727; + private static final int EXPEDITIOUS_CHARGE = 30; private static final int SLAUGHTER_CHARGE = 30; @@ -490,6 +494,11 @@ public class SlayerPlugin extends Plugin } amount--; + if (doubleTroubleExtraKill()) + { + amount--; + } + config.amount(amount); // save changed value if (!config.showInfobox()) @@ -503,6 +512,12 @@ public class SlayerPlugin extends Plugin infoTimer = Instant.now(); } + private boolean doubleTroubleExtraKill() + { + return WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID() == GROTESQUE_GUARDIANS_REGION && + SlayerUnlock.GROTESQUE_GARDIAN_DOUBLE_COUNT.isEnabled(client); + } + private boolean isTarget(NPC npc) { if (targetNames.isEmpty()) diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java index a5bc5abc01..4728f9507b 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java @@ -324,7 +324,7 @@ public class SlayerPluginTest } @Test - public void testBracletSlaughter() + public void testBraceletSlaughter() { ChatMessage chatMessageEvent = new ChatMessage(SERVER, "", BRACLET_SLAUGHTER, null);