From 83f31b87b79f0ca178c2e74035e57d52294bdafb Mon Sep 17 00:00:00 2001 From: Ganom Date: Wed, 23 Oct 2019 21:24:39 -0400 Subject: [PATCH] itemskeptondeath: add true risk handling. (#1807) * itemskeptondeath: add true risk handling. * itemmanager: ensure itemManager is grabbing true break value. * itemskeptondeath: update test. * itemskeptondeath: fix test this time. * itemskeptondeath: i hate tests. * itemskeptondeath: kms. * itemreclaimcost: refactor. --- .../net/runelite/client/game/ItemManager.java | 13 +- ...ueBrokenItem.java => ItemReclaimCost.java} | 28 +++-- .../itemskeptondeath/BrokenOnDeathItem.java | 113 ------------------ .../ItemsKeptOnDeathPlugin.java | 53 ++++++-- .../itemskeptondeath/TrueItemValue.java | 45 +++++++ .../plugins/playerscouter/PlayerScouter.java | 8 +- .../ItemsKeptOnDeathPluginTest.java | 5 +- 7 files changed, 126 insertions(+), 139 deletions(-) rename runelite-client/src/main/java/net/runelite/client/game/{PvPValueBrokenItem.java => ItemReclaimCost.java} (81%) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/BrokenOnDeathItem.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/TrueItemValue.java diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java index ff22e90cf9..0415a40518 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemManager.java @@ -326,12 +326,21 @@ public class ItemManager return (int) Math.max(1, getItemDefinition(itemID).getPrice() * HIGH_ALCHEMY_MULTIPLIER); } - public int getBrokenValue(int itemId) + public int getRepairValue(int itemId) { - PvPValueBrokenItem b = PvPValueBrokenItem.of(itemId); + return getRepairValue(itemId, false); + } + + public int getRepairValue(int itemId, boolean fullValue) + { + final ItemReclaimCost b = ItemReclaimCost.of(itemId); if (b != null) { + if (fullValue || b.getItemID() == GRANITE_MAUL_24225 || b.getItemID() == GRANITE_MAUL_24227) + { + return b.getValue(); + } return (int) (b.getValue() * (75.0f / 100.0f)); } diff --git a/runelite-client/src/main/java/net/runelite/client/game/PvPValueBrokenItem.java b/runelite-client/src/main/java/net/runelite/client/game/ItemReclaimCost.java similarity index 81% rename from runelite-client/src/main/java/net/runelite/client/game/PvPValueBrokenItem.java rename to runelite-client/src/main/java/net/runelite/client/game/ItemReclaimCost.java index e84354f4fc..9b6a1b4cbc 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/PvPValueBrokenItem.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ItemReclaimCost.java @@ -37,15 +37,21 @@ import net.runelite.api.ItemID; */ @AllArgsConstructor @Getter -public enum PvPValueBrokenItem +public enum ItemReclaimCost { // Capes FIRE_CAPE(ItemID.FIRE_CAPE, 50000), - FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE, 50000), + FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE, 99000), INFERNAL_CAPE(ItemID.INFERNAL_CAPE, 50000), - INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE, 50000), + INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE, 99000), AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER, 75000), - ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE, 75000), + ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE, 99000), + IMBUED_GUTHIX_CAPE(ItemID.IMBUED_GUTHIX_CAPE, 75000), + IMBUED_GUTHIX_MAX_CAPE(ItemID.GUTHIX_MAX_CAPE, 99000), + IMBUED_SARADOMIN_CAPE(ItemID.IMBUED_SARADOMIN_CAPE, 75000), + IMBUED_SARADOMIN_MAX_CAPE(ItemID.SARADOMIN_MAX_CAPE, 99000), + IMBUED_ZAMORAK_CAPE(ItemID.IMBUED_ZAMORAK_CAPE, 75000), + IMBUED_ZAMORAK_MAX_CAPE(ItemID.ZAMORAK_MAX_CAPE, 99000), // Defenders BRONZE_DEFENDER(ItemID.BRONZE_DEFENDER, 1000), @@ -90,15 +96,19 @@ public enum PvPValueBrokenItem GOLD_DECORATIVE_LEGS(ItemID.DECORATIVE_ARMOUR_4510, 5000), GOLD_DECORATIVE_SKIRT(ItemID.DECORATIVE_ARMOUR_11895, 5000), GOLD_DECORATIVE_SHIELD(ItemID.DECORATIVE_SHIELD_4512, 5000), - GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508, 5000); + GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508, 5000), - private static final ImmutableMap idMap; + // Granite Maul + GRANITE_MAUL(ItemID.GRANITE_MAUL_24225, 375000), + GRANITE_MAUL_OR(ItemID.GRANITE_MAUL_24227, 375000); + + private static final ImmutableMap idMap; static { - ImmutableMap.Builder builder = ImmutableMap.builder(); + ImmutableMap.Builder builder = ImmutableMap.builder(); - for (PvPValueBrokenItem items : values()) + for (ItemReclaimCost items : values()) { builder.put(items.itemID, items); } @@ -110,7 +120,7 @@ public enum PvPValueBrokenItem private final int value; @Nullable - public static PvPValueBrokenItem of(int itemId) + public static ItemReclaimCost of(int itemId) { return idMap.get(itemId); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/BrokenOnDeathItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/BrokenOnDeathItem.java deleted file mode 100644 index 8512a05541..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/BrokenOnDeathItem.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2018, TheStonedTurtle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.plugins.itemskeptondeath; - -import com.google.common.collect.ImmutableMap; -import javax.annotation.Nullable; -import lombok.AllArgsConstructor; -import net.runelite.api.ItemID; - -/** - * Some non tradeable items are kept on death inside low level wilderness (1-20) but are turned into a broken variant. - * - * The non-broken variant will be shown inside the interface. - */ -@AllArgsConstructor -enum BrokenOnDeathItem -{ - // Capes - FIRE_CAPE(ItemID.FIRE_CAPE, 50000), - FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE, 50000), - INFERNAL_CAPE(ItemID.INFERNAL_CAPE, 50000), - INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE, 50000), - AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER, 75000), - ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE, 75000), - - // Defenders - BRONZE_DEFENDER(ItemID.BRONZE_DEFENDER, 1000), - IRON_DEFENDER(ItemID.IRON_DEFENDER, 2000), - STEEL_DEFENDER(ItemID.STEEL_DEFENDER, 2500), - BLACK_DEFENDER(ItemID.BLACK_DEFENDER, 5000), - MITHRIL_DEFENDER(ItemID.MITHRIL_DEFENDER, 15000), - ADAMANT_DEFENDER(ItemID.ADAMANT_DEFENDER, 25000), - RUNE_DEFENDER(ItemID.RUNE_DEFENDER, 35000), - DRAGON_DEFENDER(ItemID.DRAGON_DEFENDER, 40000), - AVERNIC_DEFENDER(ItemID.AVERNIC_DEFENDER, 1000000), - - // Void - VOID_MAGE_HELM(ItemID.VOID_MAGE_HELM, 40000), - VOID_RANGER_HELM(ItemID.VOID_RANGER_HELM, 40000), - VOID_MELEE_HELM(ItemID.VOID_MELEE_HELM, 40000), - VOID_KNIGHT_TOP(ItemID.VOID_KNIGHT_TOP, 45000), - VOID_KNIGHT_ROBE(ItemID.VOID_KNIGHT_ROBE, 45000), - VOID_KNIGHT_GLOVES(ItemID.VOID_KNIGHT_GLOVES, 30000), - ELITE_VOID_TOP(ItemID.ELITE_VOID_TOP, 50000), - ELITE_VOID_ROBE(ItemID.ELITE_VOID_ROBE, 50000), - - // Barb Assault - FIGHTER_HAT(ItemID.FIGHTER_HAT, 45000), - RANGER_HAT(ItemID.RANGER_HAT, 45000), - HEALER_HAT(ItemID.HEALER_HAT, 45000), - FIGHTER_TORSO(ItemID.FIGHTER_TORSO, 50000), - PENANCE_SKIRT(ItemID.PENANCE_SKIRT, 20000), - - // Castle Wars - SARADOMIN_HALO(ItemID.SARADOMIN_HALO, 25000), - ZAMORAK_HALO(ItemID.ZAMORAK_HALO, 25000), - GUTHIX_HALO(ItemID.GUTHIX_HALO, 25000), - DECORATIVE_MAGIC_HAT(ItemID.DECORATIVE_ARMOUR_11898, 5000), - DECORATIVE_MAGIC_ROBE_TOP(ItemID.DECORATIVE_ARMOUR_11896, 5000), - DECORATIVE_MAGIC_ROBE_LEGS(ItemID.DECORATIVE_ARMOUR_11897, 5000), - DECORATIVE_RANGE_TOP(ItemID.DECORATIVE_ARMOUR_11899, 5000), - DECORATIVE_RANGE_BOTTOM(ItemID.DECORATIVE_ARMOUR_11900, 5000), - DECORATIVE_RANGE_QUIVER(ItemID.DECORATIVE_ARMOUR_11901, 5000), - GOLD_DECORATIVE_HELM(ItemID.DECORATIVE_HELM_4511, 5000), - GOLD_DECORATIVE_BODY(ItemID.DECORATIVE_ARMOUR_4509, 5000), - GOLD_DECORATIVE_LEGS(ItemID.DECORATIVE_ARMOUR_4510, 5000), - GOLD_DECORATIVE_SKIRT(ItemID.DECORATIVE_ARMOUR_11895, 5000), - GOLD_DECORATIVE_SHIELD(ItemID.DECORATIVE_SHIELD_4512, 5000), - GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508, 5000); - - private final int itemID; - private final int repairPrice; - - private static final ImmutableMap REPAIR_MAP; - - static - { - final ImmutableMap.Builder map = new ImmutableMap.Builder<>(); - for (final BrokenOnDeathItem p : values()) - { - map.put(p.itemID, p.repairPrice); - } - REPAIR_MAP = map.build(); - } - - @Nullable - static Integer getRepairPrice(int itemId) - { - return REPAIR_MAP.get(itemId); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPlugin.java index 8d80b5cf13..6cbee4b19e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPlugin.java @@ -26,7 +26,9 @@ package net.runelite.client.plugins.itemskeptondeath; import com.google.common.annotations.VisibleForTesting; +import java.awt.Color; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; @@ -44,8 +46,8 @@ import net.runelite.api.Constants; import net.runelite.api.FontID; import net.runelite.api.InventoryID; import net.runelite.api.Item; -import net.runelite.api.ItemDefinition; import net.runelite.api.ItemContainer; +import net.runelite.api.ItemDefinition; import net.runelite.api.ItemID; import net.runelite.api.ScriptID; import net.runelite.api.SkullIcon; @@ -60,8 +62,10 @@ import net.runelite.api.widgets.WidgetType; import net.runelite.client.eventbus.EventBus; import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemMapping; +import net.runelite.client.game.ItemReclaimCost; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.util.ColorUtil; import net.runelite.client.util.QuantityFormatter; @PluginDescriptor( @@ -354,7 +358,7 @@ public class ItemsKeptOnDeathPlugin extends Plugin if (!Pets.isPet(id) && !LostIfNotProtected.isLostIfNotProtected(id) && !isTradeable(itemManager.getItemDefinition(id)) && wildyLevel <= DEEP_WILDY - && (wildyLevel <= 0 || BrokenOnDeathItem.getRepairPrice(i.getId()) != null)) + && (wildyLevel <= 0 || ItemReclaimCost.of(id) != null)) { keptItems.add(new ItemStack(id, qty)); } @@ -460,10 +464,10 @@ public class ItemsKeptOnDeathPlugin extends Plugin } // Jagex uses the repair price when determining which items are kept on death. - final Integer repairPrice = BrokenOnDeathItem.getRepairPrice(canonicalizedItemId); + final ItemReclaimCost repairPrice = ItemReclaimCost.of(canonicalizedItemId); if (repairPrice != null) { - exchangePrice = repairPrice; + exchangePrice = repairPrice.getValue(); } if (exchangePrice == 0) @@ -573,20 +577,51 @@ public class ItemsKeptOnDeathPlugin extends Plugin textWidget.revalidate(); // Update Items lost total value - long total = 0; + long theyGet = 0; + long youLose = 0; + for (final Widget w : lostItems) { - int cid = itemManager.canonicalize(w.getItemId()); + final int cid = itemManager.canonicalize(w.getItemId()); + final TrueItemValue trueItemValue = TrueItemValue.map(cid); + final Collection mapping = ItemMapping.map(cid); + final int breakValue = itemManager.getRepairValue(cid); + + if (breakValue != 0) + { + youLose -= breakValue; + theyGet += breakValue; + } + + if (trueItemValue != null) + { + int truePrice = 0; + + for (int id : trueItemValue.getDeconstructedItem()) + { + if (mapping.contains(id)) + { + continue; + } + truePrice += itemManager.getItemPrice(id); + } + + youLose += truePrice; + } + int price = itemManager.getItemPrice(cid); - if (price == 0) + + if (price == 0 && breakValue == 0) { // Default to alch price price = (int) (itemManager.getItemDefinition(cid).getPrice() * Constants.HIGH_ALCHEMY_MULTIPLIER); } - total += (long) price * w.getItemQuantity(); + + theyGet += (long) price * w.getItemQuantity(); } final Widget lostValue = client.getWidget(WidgetInfo.ITEMS_LOST_VALUE); - lostValue.setText(QuantityFormatter.quantityToStackSize(total) + " gp"); + lostValue.setText("They get: " + QuantityFormatter.quantityToStackSize(theyGet) + + "
You lose: " + ColorUtil.prependColorTag("(" + QuantityFormatter.quantityToStackSize(theyGet + youLose) + ")", Color.red)); // Update Max items kept final Widget max = client.getWidget(WidgetInfo.ITEMS_KEPT_MAX); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/TrueItemValue.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/TrueItemValue.java new file mode 100644 index 0000000000..8dc5522417 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemskeptondeath/TrueItemValue.java @@ -0,0 +1,45 @@ +package net.runelite.client.plugins.itemskeptondeath; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import java.util.Set; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import static net.runelite.api.ItemID.ABYSSAL_TENTACLE; +import static net.runelite.api.ItemID.ABYSSAL_WHIP; +import static net.runelite.api.ItemID.GRANITE_CLAMP; +import static net.runelite.api.ItemID.GRANITE_MAUL; +import static net.runelite.api.ItemID.GRANITE_MAUL_24225; +import static net.runelite.api.ItemID.GRANITE_MAUL_24227; +import static net.runelite.api.ItemID.KRAKEN_TENTACLE; +import static net.runelite.api.ItemID.ORNATE_MAUL_HANDLE; + +@Getter +@RequiredArgsConstructor +public enum TrueItemValue +{ + GRANITE_MAUL_HANDLE(GRANITE_MAUL_24225, ImmutableSet.of(ORNATE_MAUL_HANDLE, GRANITE_MAUL)), + GRANITE_MAUL_HANDLE_OR(GRANITE_MAUL_24227, ImmutableSet.of(ORNATE_MAUL_HANDLE, GRANITE_MAUL, GRANITE_CLAMP)), + TENTACLE_WHIP(ABYSSAL_TENTACLE, ImmutableSet.of(ABYSSAL_WHIP, KRAKEN_TENTACLE)); + + private static final ImmutableMap TRUE_ITEM_VALUE_MAP; + + private final int itemID; + private final Set deconstructedItem; + + static + { + ImmutableMap.Builder map = ImmutableMap.builder(); + for (TrueItemValue p : values()) + { + map.put(p.getItemID(), p); + } + TRUE_ITEM_VALUE_MAP = map.build(); + } + + public static TrueItemValue map(int itemId) + { + return TRUE_ITEM_VALUE_MAP.getOrDefault(itemId, null); + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerscouter/PlayerScouter.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerscouter/PlayerScouter.java index 0660c1c264..31ea047b43 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerscouter/PlayerScouter.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerscouter/PlayerScouter.java @@ -63,7 +63,7 @@ import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.EventBus; import net.runelite.client.game.ItemManager; import net.runelite.client.game.ItemMapping; -import net.runelite.client.game.PvPValueBrokenItem; +import net.runelite.client.game.ItemReclaimCost; import net.runelite.client.game.WorldLocation; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -370,10 +370,10 @@ public class PlayerScouter extends Plugin continue; } - if (PvPValueBrokenItem.breaksOnDeath(id)) + if (ItemReclaimCost.breaksOnDeath(id)) { - prices.put(id, itemManager.getBrokenValue(id)); - log.debug("Item has a broken value: Id {}, Value {}", id, itemManager.getBrokenValue(id)); + prices.put(id, itemManager.getRepairValue(id)); + log.debug("Item has a broken value: Id {}, Value {}", id, itemManager.getRepairValue(id)); continue; } diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java index 2b5f812595..0a60baffaa 100644 --- a/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java +++ b/runelite-client/src/test/java/net/runelite/client/plugins/itemskeptondeath/ItemsKeptOnDeathPluginTest.java @@ -36,6 +36,7 @@ import net.runelite.api.Item; import net.runelite.api.ItemDefinition; import net.runelite.api.ItemID; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.ItemReclaimCost; import static net.runelite.client.plugins.itemskeptondeath.ItemsKeptOnDeathPlugin.DeathItems; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -637,8 +638,8 @@ public class ItemsKeptOnDeathPluginTest { final Item defender = mItem(ItemID.AVERNIC_DEFENDER, 1, "Avernic defender", false, 0); final int defenderOffset = FixedPriceItem.AVERNIC_DEFENDER.getOffset(); - final Integer defenderBrokenPrice = BrokenOnDeathItem.getRepairPrice(ItemID.AVERNIC_DEFENDER); - final int defenderExpectedPrice = (defenderBrokenPrice == null ? 0 : defenderBrokenPrice) + defenderOffset; + final ItemReclaimCost defenderBrokenPrice = ItemReclaimCost.of(ItemID.AVERNIC_DEFENDER); + final int defenderExpectedPrice = (defenderBrokenPrice == null ? 0 : defenderBrokenPrice.getValue()) + defenderOffset; assertEquals(defenderExpectedPrice, plugin.getDeathPrice(defender)); final Item[] inv = new Item[]