itemskeptondeath: fix many edge cases and add tests
This adds support for most degradeable and imbued items, which have death prices that are fixed offsets of the prices of some other reference item, clue boxes, and jewelery. The plugin was refactored largely to be able to add the tests, and now works on our internal DeathItem and ItemStack classes instead of widgets and items. Co-authored-by: Adam <Adam@sigterm.info>
This commit is contained in:
@@ -273,6 +273,18 @@ public class ItemManager
|
||||
* @return item price
|
||||
*/
|
||||
public int getItemPrice(int itemID)
|
||||
{
|
||||
return getItemPrice(itemID, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up an item's price
|
||||
*
|
||||
* @param itemID item id
|
||||
* @param ignoreUntradeableMap should the price returned ignore the {@link UntradeableItemMapping}
|
||||
* @return item price
|
||||
*/
|
||||
public int getItemPrice(int itemID, boolean ignoreUntradeableMap)
|
||||
{
|
||||
if (itemID == ItemID.COINS_995)
|
||||
{
|
||||
@@ -283,10 +295,13 @@ public class ItemManager
|
||||
return 1000;
|
||||
}
|
||||
|
||||
UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(itemID));
|
||||
if (p != null)
|
||||
if (!ignoreUntradeableMap)
|
||||
{
|
||||
return getItemPrice(p.getPriceID()) * p.getQuantity();
|
||||
UntradeableItemMapping p = UntradeableItemMapping.map(ItemVariationMapping.map(itemID));
|
||||
if (p != null)
|
||||
{
|
||||
return getItemPrice(p.getPriceID()) * p.getQuantity();
|
||||
}
|
||||
}
|
||||
|
||||
int price = 0;
|
||||
|
||||
@@ -41,7 +41,9 @@ enum AlwaysLostItem
|
||||
{
|
||||
RUNE_POUCH(ItemID.RUNE_POUCH, true),
|
||||
LOOTING_BAG(ItemID.LOOTING_BAG, false),
|
||||
CLUE_BOX(ItemID.CLUE_BOX, false);
|
||||
CLUE_BOX(ItemID.CLUE_BOX, false),
|
||||
BRACELET_OF_ETHEREUM(ItemID.BRACELET_OF_ETHEREUM, false),
|
||||
BRACELET_OF_ETHEREUM_UNCHARGED(ItemID.BRACELET_OF_ETHEREUM_UNCHARGED, false);
|
||||
|
||||
private final int itemID;
|
||||
private final boolean keptOutsideOfWilderness;
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2019, TheStonedTurtle <https://github.com/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 java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
/**
|
||||
* Degradable/Non-rechargeable Jewelry death prices are usually determined by the amount of charges the item has left.
|
||||
* The price of each charge is based on the GE price of the fully charged item divided by the maximum item charges
|
||||
* Charge price = GE Price / Max Charges
|
||||
* Death Price = Charge price * Current Charges
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
enum DynamicPriceItem
|
||||
{
|
||||
GAMES_NECKLACE1(ItemID.GAMES_NECKLACE1, 1, 8, ItemID.GAMES_NECKLACE8),
|
||||
GAMES_NECKLACE2(ItemID.GAMES_NECKLACE2, 2, 8, ItemID.GAMES_NECKLACE8),
|
||||
GAMES_NECKLACE3(ItemID.GAMES_NECKLACE3, 3, 8, ItemID.GAMES_NECKLACE8),
|
||||
GAMES_NECKLACE4(ItemID.GAMES_NECKLACE4, 4, 8, ItemID.GAMES_NECKLACE8),
|
||||
GAMES_NECKLACE5(ItemID.GAMES_NECKLACE5, 5, 8, ItemID.GAMES_NECKLACE8),
|
||||
GAMES_NECKLACE6(ItemID.GAMES_NECKLACE6, 6, 8, ItemID.GAMES_NECKLACE8),
|
||||
GAMES_NECKLACE7(ItemID.GAMES_NECKLACE7, 7, 8, ItemID.GAMES_NECKLACE8),
|
||||
|
||||
RING_OF_DUELING1(ItemID.RING_OF_DUELING1, 1, 8, ItemID.RING_OF_DUELING8),
|
||||
RING_OF_DUELING2(ItemID.RING_OF_DUELING2, 2, 8, ItemID.RING_OF_DUELING8),
|
||||
RING_OF_DUELING3(ItemID.RING_OF_DUELING3, 3, 8, ItemID.RING_OF_DUELING8),
|
||||
RING_OF_DUELING4(ItemID.RING_OF_DUELING4, 4, 8, ItemID.RING_OF_DUELING8),
|
||||
RING_OF_DUELING5(ItemID.RING_OF_DUELING5, 5, 8, ItemID.RING_OF_DUELING8),
|
||||
RING_OF_DUELING6(ItemID.RING_OF_DUELING6, 6, 8, ItemID.RING_OF_DUELING8),
|
||||
RING_OF_DUELING7(ItemID.RING_OF_DUELING7, 7, 8, ItemID.RING_OF_DUELING8),
|
||||
|
||||
RING_OF_RETURNING1(ItemID.RING_OF_RETURNING1, 1, 5, ItemID.RING_OF_RETURNING5),
|
||||
RING_OF_RETURNING2(ItemID.RING_OF_RETURNING2, 2, 5, ItemID.RING_OF_RETURNING5),
|
||||
RING_OF_RETURNING3(ItemID.RING_OF_RETURNING3, 3, 5, ItemID.RING_OF_RETURNING5),
|
||||
RING_OF_RETURNING4(ItemID.RING_OF_RETURNING4, 4, 5, ItemID.RING_OF_RETURNING5),
|
||||
|
||||
NECKLACE_OF_PASSAGE1(ItemID.NECKLACE_OF_PASSAGE1, 1, 5, ItemID.NECKLACE_OF_PASSAGE5),
|
||||
NECKLACE_OF_PASSAGE2(ItemID.NECKLACE_OF_PASSAGE2, 2, 5, ItemID.NECKLACE_OF_PASSAGE5),
|
||||
NECKLACE_OF_PASSAGE3(ItemID.NECKLACE_OF_PASSAGE3, 3, 5, ItemID.NECKLACE_OF_PASSAGE5),
|
||||
NECKLACE_OF_PASSAGE4(ItemID.NECKLACE_OF_PASSAGE4, 4, 5, ItemID.NECKLACE_OF_PASSAGE5),
|
||||
|
||||
BURNING_AMULET1(ItemID.BURNING_AMULET1, 1, 5, ItemID.BURNING_AMULET5),
|
||||
BURNING_AMULET2(ItemID.BURNING_AMULET2, 2, 5, ItemID.BURNING_AMULET5),
|
||||
BURNING_AMULET3(ItemID.BURNING_AMULET3, 3, 5, ItemID.BURNING_AMULET5),
|
||||
BURNING_AMULET4(ItemID.BURNING_AMULET4, 4, 5, ItemID.BURNING_AMULET5);
|
||||
|
||||
private final int itemId;
|
||||
private final int currentCharges;
|
||||
private final int maxCharges;
|
||||
private final int chargedId;
|
||||
|
||||
private static final Map<Integer, DynamicPriceItem> DYNAMIC_ITEMS;
|
||||
|
||||
static
|
||||
{
|
||||
final ImmutableMap.Builder<Integer, DynamicPriceItem> map = ImmutableMap.builder();
|
||||
for (final DynamicPriceItem p : values())
|
||||
{
|
||||
map.put(p.itemId, p);
|
||||
}
|
||||
DYNAMIC_ITEMS = map.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the price off the partially charged jewelry based on the base items price
|
||||
* @param basePrice price of the base item, usually the trade-able variant
|
||||
* @return death price of the current DynamicPriceItem
|
||||
*/
|
||||
int calculateDeathPrice(final int basePrice)
|
||||
{
|
||||
return (basePrice / maxCharges) * currentCharges;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static DynamicPriceItem find(int itemId)
|
||||
{
|
||||
return DYNAMIC_ITEMS.get(itemId);
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ package net.runelite.client.plugins.itemskeptondeath;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
@@ -36,7 +35,6 @@ import net.runelite.api.ItemID;
|
||||
* Some items have a fixed price that is added to its default value when calculating death prices.
|
||||
* These are typically imbued items, such as Berserker ring (i), to help it protect over the non-imbued variants.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
enum FixedPriceItem
|
||||
{
|
||||
@@ -66,10 +64,161 @@ enum FixedPriceItem
|
||||
|
||||
IMBUED_RING_OF_THE_GODS_I(ItemID.RING_OF_THE_GODS_I, 2000),
|
||||
IMBUED_TREASONOUS_RING_I(ItemID.TREASONOUS_RING_I, 2000),
|
||||
IMBUED_TYRANNICAL_RING_I(ItemID.TYRANNICAL_RING_I, 2000);
|
||||
IMBUED_TYRANNICAL_RING_I(ItemID.TYRANNICAL_RING_I, 2000),
|
||||
|
||||
GRACEFUL_HOOD(ItemID.GRACEFUL_HOOD, 1965),
|
||||
GRACEFUL_CAPE(ItemID.GRACEFUL_CAPE, 2460),
|
||||
GRACEFUL_TOP(ItemID.GRACEFUL_TOP, 2345),
|
||||
GRACEFUL_LEGS(ItemID.GRACEFUL_LEGS, 2290),
|
||||
GRACEFUL_GLOVES(ItemID.GRACEFUL_GLOVES, 1970),
|
||||
GRACEFUL_BOOTS(ItemID.GRACEFUL_BOOTS, 2060),
|
||||
|
||||
ANGLER_HAT(ItemID.ANGLER_HAT, 2600),
|
||||
ANGLER_TOP(ItemID.ANGLER_TOP, 3550),
|
||||
ANGLER_WADERS(ItemID.ANGLER_WADERS, 4400),
|
||||
ANGLER_BOOTS(ItemID.ANGLER_BOOTS, 5300),
|
||||
|
||||
PROSPECTOR_HELMET(ItemID.PROSPECTOR_HELMET, 2640),
|
||||
PROSPECTOR_JACKET(ItemID.PROSPECTOR_JACKET, 3550),
|
||||
PROSPECTOR_LEGS(ItemID.PROSPECTOR_LEGS, 4460),
|
||||
PROSPECTOR_BOOTS(ItemID.PROSPECTOR_BOOTS, 5370),
|
||||
|
||||
LUMBERJACK_HAT(ItemID.LUMBERJACK_HAT, 19950),
|
||||
LUMBERJACK_TOP(ItemID.LUMBERJACK_TOP, 19950),
|
||||
LUMBERJACK_LEGS(ItemID.LUMBERJACK_LEGS, 19950),
|
||||
LUMBERJACK_BOOTS(ItemID.LUMBERJACK_BOOTS, 19950),
|
||||
|
||||
ROGUE_MASK(ItemID.ROGUE_MASK, 725),
|
||||
ROGUE_TOP(ItemID.ROGUE_TOP, 575),
|
||||
ROGUE_TROUSERS(ItemID.ROGUE_TROUSERS, 500),
|
||||
ROGUE_GLOVES(ItemID.ROGUE_GLOVES, 650),
|
||||
ROGUE_BOOTS(ItemID.ROGUE_BOOTS, 650),
|
||||
|
||||
RING_OF_WEALTH_1(ItemID.RING_OF_WEALTH_1, 500, ItemID.RING_OF_WEALTH),
|
||||
RING_OF_WEALTH_2(ItemID.RING_OF_WEALTH_2, 1000, ItemID.RING_OF_WEALTH),
|
||||
RING_OF_WEALTH_3(ItemID.RING_OF_WEALTH_3, 1500, ItemID.RING_OF_WEALTH),
|
||||
RING_OF_WEALTH_4(ItemID.RING_OF_WEALTH_4, 2000, ItemID.RING_OF_WEALTH),
|
||||
|
||||
AMULET_OF_GLORY1(ItemID.AMULET_OF_GLORY1, 500, ItemID.AMULET_OF_GLORY),
|
||||
AMULET_OF_GLORY2(ItemID.AMULET_OF_GLORY2, 1000, ItemID.AMULET_OF_GLORY),
|
||||
AMULET_OF_GLORY3(ItemID.AMULET_OF_GLORY3, 1500, ItemID.AMULET_OF_GLORY),
|
||||
AMULET_OF_GLORY5(ItemID.AMULET_OF_GLORY5, 2500, ItemID.AMULET_OF_GLORY),
|
||||
|
||||
COMBAT_BRACELET1(ItemID.COMBAT_BRACELET1, 500, ItemID.COMBAT_BRACELET),
|
||||
COMBAT_BRACELET2(ItemID.COMBAT_BRACELET2, 1000, ItemID.COMBAT_BRACELET),
|
||||
COMBAT_BRACELET3(ItemID.COMBAT_BRACELET3, 1500, ItemID.COMBAT_BRACELET),
|
||||
COMBAT_BRACELET5(ItemID.COMBAT_BRACELET5, 2500, ItemID.COMBAT_BRACELET),
|
||||
|
||||
SKILLS_NECKLACE1(ItemID.SKILLS_NECKLACE1, 500, ItemID.SKILLS_NECKLACE),
|
||||
SKILLS_NECKLACE2(ItemID.SKILLS_NECKLACE2, 1000, ItemID.SKILLS_NECKLACE),
|
||||
SKILLS_NECKLACE3(ItemID.SKILLS_NECKLACE3, 1500, ItemID.SKILLS_NECKLACE),
|
||||
SKILLS_NECKLACE4(ItemID.SKILLS_NECKLACE5, 2500, ItemID.SKILLS_NECKLACE),
|
||||
|
||||
AHRIMS_HOOD_25(ItemID.AHRIMS_HOOD_25, 2500, ItemID.AHRIMS_HOOD_0),
|
||||
AHRIMS_HOOD_50(ItemID.AHRIMS_HOOD_50, 5000, ItemID.AHRIMS_HOOD_0),
|
||||
AHRIMS_HOOD_75(ItemID.AHRIMS_HOOD_75, 7500, ItemID.AHRIMS_HOOD_0),
|
||||
AHRIMS_HOOD_100(ItemID.AHRIMS_HOOD_100, 10000, ItemID.AHRIMS_HOOD_0),
|
||||
AHRIMS_ROBETOP_25(ItemID.AHRIMS_ROBETOP_25, 2500, ItemID.AHRIMS_ROBETOP_0),
|
||||
AHRIMS_ROBETOP_50(ItemID.AHRIMS_ROBETOP_50, 5000, ItemID.AHRIMS_ROBETOP_0),
|
||||
AHRIMS_ROBETOP_75(ItemID.AHRIMS_ROBETOP_75, 7500, ItemID.AHRIMS_ROBETOP_0),
|
||||
AHRIMS_ROBETOP_100(ItemID.AHRIMS_ROBETOP_100, 10000, ItemID.AHRIMS_ROBETOP_0),
|
||||
AHRIMS_ROBESKIRT_25(ItemID.AHRIMS_ROBESKIRT_25, 2500, ItemID.AHRIMS_ROBESKIRT_0),
|
||||
AHRIMS_ROBESKIRT_50(ItemID.AHRIMS_ROBESKIRT_50, 5000, ItemID.AHRIMS_ROBESKIRT_0),
|
||||
AHRIMS_ROBESKIRT_75(ItemID.AHRIMS_ROBESKIRT_75, 7500, ItemID.AHRIMS_ROBESKIRT_0),
|
||||
AHRIMS_ROBESKIRT_100(ItemID.AHRIMS_ROBESKIRT_100, 10000, ItemID.AHRIMS_ROBESKIRT_0),
|
||||
AHRIMS_STAFF_25(ItemID.AHRIMS_STAFF_25, 2500, ItemID.AHRIMS_STAFF_0),
|
||||
AHRIMS_STAFF_50(ItemID.AHRIMS_STAFF_50, 5000, ItemID.AHRIMS_STAFF_0),
|
||||
AHRIMS_STAFF_75(ItemID.AHRIMS_STAFF_75, 7500, ItemID.AHRIMS_STAFF_0),
|
||||
AHRIMS_STAFF_100(ItemID.AHRIMS_STAFF_100, 10000, ItemID.AHRIMS_STAFF_0),
|
||||
|
||||
KARILS_COIF_25(ItemID.KARILS_COIF_25, 2500, ItemID.KARILS_COIF_0),
|
||||
KARILS_COIF_50(ItemID.KARILS_COIF_50, 5000, ItemID.KARILS_COIF_0),
|
||||
KARILS_COIF_75(ItemID.KARILS_COIF_75, 7500, ItemID.KARILS_COIF_0),
|
||||
KARILS_COIF_100(ItemID.KARILS_COIF_100, 10000, ItemID.KARILS_COIF_0),
|
||||
KARILS_LEATHERTOP_25(ItemID.KARILS_LEATHERTOP_25, 2500, ItemID.KARILS_LEATHERTOP_0),
|
||||
KARILS_LEATHERTOP_50(ItemID.KARILS_LEATHERTOP_50, 5000, ItemID.KARILS_LEATHERTOP_0),
|
||||
KARILS_LEATHERTOP_75(ItemID.KARILS_LEATHERTOP_75, 7500, ItemID.KARILS_LEATHERTOP_0),
|
||||
KARILS_LEATHERTOP_100(ItemID.KARILS_LEATHERTOP_100, 10000, ItemID.KARILS_LEATHERTOP_0),
|
||||
KARILS_LEATHERSKIRT_25(ItemID.KARILS_LEATHERSKIRT_25, 2500, ItemID.KARILS_LEATHERSKIRT_0),
|
||||
KARILS_LEATHERSKIRT_50(ItemID.KARILS_LEATHERSKIRT_50, 5000, ItemID.KARILS_LEATHERSKIRT_0),
|
||||
KARILS_LEATHERSKIRT_75(ItemID.KARILS_LEATHERSKIRT_75, 7500, ItemID.KARILS_LEATHERSKIRT_0),
|
||||
KARILS_LEATHERSKIRT_100(ItemID.KARILS_LEATHERSKIRT_100, 10000, ItemID.KARILS_LEATHERSKIRT_0),
|
||||
KARILS_CROSSBOW_25(ItemID.KARILS_CROSSBOW_25, 2500, ItemID.KARILS_CROSSBOW_0),
|
||||
KARILS_CROSSBOW_50(ItemID.KARILS_CROSSBOW_50, 5000, ItemID.KARILS_CROSSBOW_0),
|
||||
KARILS_CROSSBOW_75(ItemID.KARILS_CROSSBOW_75, 7500, ItemID.KARILS_CROSSBOW_0),
|
||||
KARILS_CROSSBOW_100(ItemID.KARILS_CROSSBOW_100, 10000, ItemID.KARILS_CROSSBOW_0),
|
||||
|
||||
DHAROKS_HELM_25(ItemID.DHAROKS_HELM_25, 2500, ItemID.DHAROKS_HELM_0),
|
||||
DHAROKS_HELM_50(ItemID.DHAROKS_HELM_50, 5000, ItemID.DHAROKS_HELM_0),
|
||||
DHAROKS_HELM_75(ItemID.DHAROKS_HELM_75, 7500, ItemID.DHAROKS_HELM_0),
|
||||
DHAROKS_HELM_100(ItemID.DHAROKS_HELM_100, 10000, ItemID.DHAROKS_HELM_0),
|
||||
DHAROKS_PLATEBODY_25(ItemID.DHAROKS_PLATEBODY_25, 2500, ItemID.DHAROKS_PLATEBODY_0),
|
||||
DHAROKS_PLATEBODY_50(ItemID.DHAROKS_PLATEBODY_50, 5000, ItemID.DHAROKS_PLATEBODY_0),
|
||||
DHAROKS_PLATEBODY_75(ItemID.DHAROKS_PLATEBODY_75, 7500, ItemID.DHAROKS_PLATEBODY_0),
|
||||
DHAROKS_PLATEBODY_100(ItemID.DHAROKS_PLATEBODY_100, 10000, ItemID.DHAROKS_PLATEBODY_0),
|
||||
DHAROKS_PLATELEGS_25(ItemID.DHAROKS_PLATELEGS_25, 2500, ItemID.DHAROKS_PLATELEGS_0),
|
||||
DHAROKS_PLATELEGS_50(ItemID.DHAROKS_PLATELEGS_50, 5000, ItemID.DHAROKS_PLATELEGS_0),
|
||||
DHAROKS_PLATELEGS_75(ItemID.DHAROKS_PLATELEGS_75, 7500, ItemID.DHAROKS_PLATELEGS_0),
|
||||
DHAROKS_PLATELEGS_100(ItemID.DHAROKS_PLATELEGS_100, 10000, ItemID.DHAROKS_PLATELEGS_0),
|
||||
DHAROKS_GREATAXE_25(ItemID.DHAROKS_GREATAXE_25, 2500, ItemID.DHAROKS_GREATAXE_0),
|
||||
DHAROKS_GREATAXE_50(ItemID.DHAROKS_GREATAXE_50, 5000, ItemID.DHAROKS_GREATAXE_0),
|
||||
DHAROKS_GREATAXE_75(ItemID.DHAROKS_GREATAXE_75, 7500, ItemID.DHAROKS_GREATAXE_0),
|
||||
DHAROKS_GREATAXE_100(ItemID.DHAROKS_GREATAXE_100, 10000, ItemID.DHAROKS_GREATAXE_0),
|
||||
|
||||
GUTHANS_HELM_25(ItemID.GUTHANS_HELM_25, 2500, ItemID.GUTHANS_HELM_0),
|
||||
GUTHANS_HELM_50(ItemID.GUTHANS_HELM_50, 5000, ItemID.GUTHANS_HELM_0),
|
||||
GUTHANS_HELM_75(ItemID.GUTHANS_HELM_75, 7500, ItemID.GUTHANS_HELM_0),
|
||||
GUTHANS_HELM_100(ItemID.GUTHANS_HELM_100, 10000, ItemID.GUTHANS_HELM_0),
|
||||
GUTHANS_PLATEBODY_25(ItemID.GUTHANS_PLATEBODY_25, 2500, ItemID.GUTHANS_PLATEBODY_0),
|
||||
GUTHANS_PLATEBODY_50(ItemID.GUTHANS_PLATEBODY_50, 5000, ItemID.GUTHANS_PLATEBODY_0),
|
||||
GUTHANS_PLATEBODY_75(ItemID.GUTHANS_PLATEBODY_75, 7500, ItemID.GUTHANS_PLATEBODY_0),
|
||||
GUTHANS_PLATEBODY_100(ItemID.GUTHANS_PLATEBODY_100, 10000, ItemID.GUTHANS_PLATEBODY_0),
|
||||
GUTHANS_CHAINSKIRT_25(ItemID.GUTHANS_CHAINSKIRT_25, 2500, ItemID.GUTHANS_CHAINSKIRT_0),
|
||||
GUTHANS_CHAINSKIRT_50(ItemID.GUTHANS_CHAINSKIRT_50, 5000, ItemID.GUTHANS_CHAINSKIRT_0),
|
||||
GUTHANS_CHAINSKIRT_75(ItemID.GUTHANS_CHAINSKIRT_75, 7500, ItemID.GUTHANS_CHAINSKIRT_0),
|
||||
GUTHANS_CHAINSKIRT_100(ItemID.GUTHANS_CHAINSKIRT_100, 10000, ItemID.GUTHANS_CHAINSKIRT_0),
|
||||
GUTHANS_WARSPEAR_25(ItemID.GUTHANS_WARSPEAR_25, 2500, ItemID.GUTHANS_WARSPEAR_0),
|
||||
GUTHANS_WARSPEAR_50(ItemID.GUTHANS_WARSPEAR_50, 5000, ItemID.GUTHANS_WARSPEAR_0),
|
||||
GUTHANS_WARSPEAR_75(ItemID.GUTHANS_WARSPEAR_75, 7500, ItemID.GUTHANS_WARSPEAR_0),
|
||||
GUTHANS_WARSPEAR_100(ItemID.GUTHANS_WARSPEAR_100, 10000, ItemID.GUTHANS_WARSPEAR_0),
|
||||
|
||||
TORAGS_HELM_25(ItemID.TORAGS_HELM_25, 2500, ItemID.TORAGS_HELM_0),
|
||||
TORAGS_HELM_50(ItemID.TORAGS_HELM_50, 5000, ItemID.TORAGS_HELM_0),
|
||||
TORAGS_HELM_75(ItemID.TORAGS_HELM_75, 7500, ItemID.TORAGS_HELM_0),
|
||||
TORAGS_HELM_100(ItemID.TORAGS_HELM_100, 10000, ItemID.TORAGS_HELM_0),
|
||||
TORAGS_PLATEBODY_25(ItemID.TORAGS_PLATEBODY_25, 2500, ItemID.TORAGS_PLATEBODY_0),
|
||||
TORAGS_PLATEBODY_50(ItemID.TORAGS_PLATEBODY_50, 5000, ItemID.TORAGS_PLATEBODY_0),
|
||||
TORAGS_PLATEBODY_75(ItemID.TORAGS_PLATEBODY_75, 7500, ItemID.TORAGS_PLATEBODY_0),
|
||||
TORAGS_PLATEBODY_100(ItemID.TORAGS_PLATEBODY_100, 10000, ItemID.TORAGS_PLATEBODY_0),
|
||||
TORAGS_PLATELEGS_25(ItemID.TORAGS_PLATELEGS_25, 2500, ItemID.TORAGS_PLATELEGS_0),
|
||||
TORAGS_PLATELEGS_50(ItemID.TORAGS_PLATELEGS_50, 5000, ItemID.TORAGS_PLATELEGS_0),
|
||||
TORAGS_PLATELEGS_75(ItemID.TORAGS_PLATELEGS_75, 7500, ItemID.TORAGS_PLATELEGS_0),
|
||||
TORAGS_PLATELEGS_100(ItemID.TORAGS_PLATELEGS_100, 10000, ItemID.TORAGS_PLATELEGS_0),
|
||||
TORAGS_HAMMERS_25(ItemID.TORAGS_HAMMERS_25, 2500, ItemID.TORAGS_HAMMERS_0),
|
||||
TORAGS_HAMMERS_50(ItemID.TORAGS_HAMMERS_50, 5000, ItemID.TORAGS_HAMMERS_0),
|
||||
TORAGS_HAMMERS_75(ItemID.TORAGS_HAMMERS_75, 7500, ItemID.TORAGS_HAMMERS_0),
|
||||
TORAGS_HAMMERS_100(ItemID.TORAGS_HAMMERS_100, 10000, ItemID.TORAGS_HAMMERS_0),
|
||||
|
||||
VERACS_HELM_25(ItemID.VERACS_HELM_25, 2500, ItemID.VERACS_HELM_0),
|
||||
VERACS_HELM_50(ItemID.VERACS_HELM_50, 5000, ItemID.VERACS_HELM_0),
|
||||
VERACS_HELM_75(ItemID.VERACS_HELM_75, 7500, ItemID.VERACS_HELM_0),
|
||||
VERACS_HELM_100(ItemID.VERACS_HELM_100, 10000, ItemID.VERACS_HELM_0),
|
||||
VERACS_BRASSARD_25(ItemID.VERACS_BRASSARD_25, 2500, ItemID.VERACS_BRASSARD_0),
|
||||
VERACS_BRASSARD_50(ItemID.VERACS_BRASSARD_50, 5000, ItemID.VERACS_BRASSARD_0),
|
||||
VERACS_BRASSARD_75(ItemID.VERACS_BRASSARD_75, 7500, ItemID.VERACS_BRASSARD_0),
|
||||
VERACS_BRASSARD_100(ItemID.VERACS_BRASSARD_100, 10000, ItemID.VERACS_BRASSARD_0),
|
||||
VERACS_PLATESKIRT_25(ItemID.VERACS_PLATESKIRT_25, 2500, ItemID.VERACS_PLATESKIRT_0),
|
||||
VERACS_PLATESKIRT_50(ItemID.VERACS_PLATESKIRT_50, 5000, ItemID.VERACS_PLATESKIRT_0),
|
||||
VERACS_PLATESKIRT_75(ItemID.VERACS_PLATESKIRT_75, 7500, ItemID.VERACS_PLATESKIRT_0),
|
||||
VERACS_PLATESKIRT_100(ItemID.VERACS_PLATESKIRT_100, 10000, ItemID.VERACS_PLATESKIRT_0),
|
||||
VERACS_FLAIL_25(ItemID.VERACS_FLAIL_25, 2500, ItemID.VERACS_FLAIL_0),
|
||||
VERACS_FLAIL_50(ItemID.VERACS_FLAIL_50, 5000, ItemID.VERACS_FLAIL_0),
|
||||
VERACS_FLAIL_75(ItemID.VERACS_FLAIL_75, 7500, ItemID.VERACS_FLAIL_0),
|
||||
VERACS_FLAIL_100(ItemID.VERACS_FLAIL_100, 10000, ItemID.VERACS_FLAIL_0);
|
||||
|
||||
private final int itemId;
|
||||
private final int offset;
|
||||
private final int baseId;
|
||||
|
||||
private static final Map<Integer, FixedPriceItem> FIXED_ITEMS;
|
||||
|
||||
@@ -83,6 +232,18 @@ enum FixedPriceItem
|
||||
FIXED_ITEMS = map.build();
|
||||
}
|
||||
|
||||
FixedPriceItem(final int itemId, final int offset, final int baseId)
|
||||
{
|
||||
this.itemId = itemId;
|
||||
this.offset = offset;
|
||||
this.baseId = baseId;
|
||||
}
|
||||
|
||||
FixedPriceItem(final int itemId, final int offset)
|
||||
{
|
||||
this(itemId, offset, -1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static FixedPriceItem find(int itemId)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019, TheStonedTurtle <https://github.com/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 lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
class ItemStack
|
||||
{
|
||||
private int id;
|
||||
private int qty;
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.itemskeptondeath;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -32,7 +33,10 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
@@ -54,6 +58,7 @@ import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.ItemMapping;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
@@ -69,6 +74,16 @@ public class ItemsKeptOnDeathPlugin extends Plugin
|
||||
private static final int DEEP_WILDY = 20;
|
||||
private static final Pattern WILDERNESS_LEVEL_PATTERN = Pattern.compile("^Level: (\\d+).*");
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@VisibleForTesting
|
||||
static class DeathItems
|
||||
{
|
||||
private final List<ItemStack> keptItems;
|
||||
private final List<ItemStack> lostItems;
|
||||
private final boolean hasAlwaysLost;
|
||||
}
|
||||
|
||||
// Item Container helpers
|
||||
private static final int MAX_ROW_ITEMS = 8;
|
||||
private static final int ITEM_X_OFFSET = 5;
|
||||
@@ -98,9 +113,12 @@ public class ItemsKeptOnDeathPlugin extends Plugin
|
||||
private WidgetButton deepWildyButton;
|
||||
private WidgetButton lowWildyButton;
|
||||
|
||||
private boolean isSkulled;
|
||||
private boolean protectingItem;
|
||||
private int wildyLevel;
|
||||
@VisibleForTesting
|
||||
boolean isSkulled;
|
||||
@VisibleForTesting
|
||||
boolean protectingItem;
|
||||
@VisibleForTesting
|
||||
int wildyLevel;
|
||||
|
||||
@Subscribe
|
||||
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||
@@ -223,97 +241,12 @@ public class ItemsKeptOnDeathPlugin extends Plugin
|
||||
final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);
|
||||
final Item[] equip = equipment == null ? new Item[0] : equipment.getItems();
|
||||
|
||||
final List<Item> items = new ArrayList<>();
|
||||
Collections.addAll(items, inv);
|
||||
Collections.addAll(items, equip);
|
||||
final DeathItems deathItems = calculateKeptLostItems(inv, equip);
|
||||
|
||||
// Sort by item price
|
||||
items.sort(Comparator.comparing(this::getDeathPrice).reversed());
|
||||
|
||||
boolean hasAlwaysLost = false;
|
||||
int keepCount = getDefaultItemsKept();
|
||||
|
||||
final List<Widget> keptItems = new ArrayList<>();
|
||||
final List<Widget> lostItems = new ArrayList<>();
|
||||
for (final Item i : items)
|
||||
{
|
||||
final int id = i.getId();
|
||||
int itemQuantity = i.getQuantity();
|
||||
|
||||
if (id == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final ItemComposition c = itemManager.getItemComposition(i.getId());
|
||||
|
||||
// Bonds are always kept and do not count towards the limit.
|
||||
if (id == ItemID.OLD_SCHOOL_BOND || id == ItemID.OLD_SCHOOL_BOND_UNTRADEABLE)
|
||||
{
|
||||
final Widget itemWidget = createItemWidget(kept, itemQuantity, c);
|
||||
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, itemQuantity, c.getName());
|
||||
keptItems.add(itemWidget);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Certain items are always lost on death and have a white outline which we need to add
|
||||
final AlwaysLostItem alwaysLostItem = AlwaysLostItem.getByItemID(i.getId());
|
||||
if (alwaysLostItem != null)
|
||||
{
|
||||
// Some of these items are kept on death (outside wildy), like the Rune pouch. Ignore them
|
||||
if (!alwaysLostItem.isKeptOutsideOfWilderness() || wildyLevel > 0)
|
||||
{
|
||||
final Widget itemWidget = createItemWidget(lost, itemQuantity, c);
|
||||
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 0, itemQuantity, c.getName());
|
||||
itemWidget.setBorderType(2); // white outline
|
||||
lostItems.add(itemWidget);
|
||||
hasAlwaysLost = true;
|
||||
continue;
|
||||
}
|
||||
// the rune pouch is "always lost" but its kept outside of pvp, and does not count towards your keep count
|
||||
}
|
||||
else if (keepCount > 0)
|
||||
{
|
||||
// Keep most valuable items regardless of trade-ability.
|
||||
if (i.getQuantity() > keepCount)
|
||||
{
|
||||
final Widget itemWidget = createItemWidget(kept, keepCount, c);
|
||||
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, keepCount, c.getName());
|
||||
keptItems.add(itemWidget);
|
||||
itemQuantity -= keepCount;
|
||||
keepCount = 0;
|
||||
// Fall through to below to drop the rest of the stack
|
||||
}
|
||||
else
|
||||
{
|
||||
final Widget itemWidget = createItemWidget(kept, itemQuantity, c);
|
||||
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, itemQuantity, c.getName());
|
||||
keptItems.add(itemWidget);
|
||||
keepCount -= i.getQuantity();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Items are kept if:
|
||||
// 1) is not tradeable
|
||||
// 2) is under the deep wilderness line
|
||||
// 3) is outside of the wilderness, or item has a broken form
|
||||
if (!Pets.isPet(id)
|
||||
&& !isTradeable(c) && wildyLevel <= DEEP_WILDY
|
||||
&& (wildyLevel <= 0 || BrokenOnDeathItem.isBrokenOnDeath(i.getId())))
|
||||
{
|
||||
final Widget itemWidget = createItemWidget(kept, itemQuantity, c);
|
||||
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 1, itemQuantity, c.getName());
|
||||
keptItems.add(itemWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, the item is lost
|
||||
final Widget itemWidget = createItemWidget(lost, itemQuantity, c);
|
||||
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, 0, itemQuantity, c.getName());
|
||||
lostItems.add(itemWidget);
|
||||
}
|
||||
}
|
||||
final List<Widget> keptItems = deathItems.getKeptItems().stream()
|
||||
.map(item -> createItemWidget(kept, item, true)).collect(Collectors.toList());
|
||||
final List<Widget> lostItems = deathItems.getLostItems().stream()
|
||||
.map(item -> createItemWidget(lost, item, false)).collect(Collectors.toList());
|
||||
|
||||
int rows = (keptItems.size() + MAX_ROW_ITEMS - 1) / MAX_ROW_ITEMS;
|
||||
// Show an empty row if there isn't anything
|
||||
@@ -328,36 +261,205 @@ public class ItemsKeptOnDeathPlugin extends Plugin
|
||||
positionWidgetItems(kept, keptItems);
|
||||
positionWidgetItems(lost, lostItems);
|
||||
|
||||
updateKeptWidgetInfoText(hasAlwaysLost, keptItems, lostItems);
|
||||
updateKeptWidgetInfoText(deathItems.isHasAlwaysLost(), keptItems, lostItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates which items will be kept/lost. first list is kept items, second is lost.
|
||||
*
|
||||
* @param inv players inventory
|
||||
* @param equip players equipement
|
||||
* @return list of items kept followed by a list of items lost
|
||||
*/
|
||||
@VisibleForTesting
|
||||
DeathItems calculateKeptLostItems(final Item[] inv, final Item[] equip)
|
||||
{
|
||||
final List<Item> items = new ArrayList<>();
|
||||
Collections.addAll(items, inv);
|
||||
Collections.addAll(items, equip);
|
||||
|
||||
// Sort by item price
|
||||
items.sort(Comparator.comparing(this::getDeathPrice).reversed());
|
||||
|
||||
boolean hasClueBox = false;
|
||||
boolean hasAlwaysLost = false;
|
||||
int keepCount = getDefaultItemsKept();
|
||||
|
||||
final List<ItemStack> keptItems = new ArrayList<>();
|
||||
final List<ItemStack> lostItems = new ArrayList<>();
|
||||
|
||||
for (final Item i : items)
|
||||
{
|
||||
final int id = i.getId();
|
||||
int qty = i.getQuantity();
|
||||
if (id == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bonds are always kept and do not count towards the limit.
|
||||
if (id == ItemID.OLD_SCHOOL_BOND || id == ItemID.OLD_SCHOOL_BOND_UNTRADEABLE)
|
||||
{
|
||||
keptItems.add(new ItemStack(id, qty));
|
||||
continue;
|
||||
}
|
||||
|
||||
final AlwaysLostItem alwaysLostItem = AlwaysLostItem.getByItemID(id);
|
||||
if (alwaysLostItem != null && (!alwaysLostItem.isKeptOutsideOfWilderness() || wildyLevel > 0))
|
||||
{
|
||||
hasAlwaysLost = true;
|
||||
hasClueBox = hasClueBox || id == ItemID.CLUE_BOX;
|
||||
lostItems.add(new ItemStack(id, qty));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keepCount > 0)
|
||||
{
|
||||
// Keep most valuable items regardless of trade-ability.
|
||||
if (i.getQuantity() > keepCount)
|
||||
{
|
||||
keptItems.add(new ItemStack(id, keepCount));
|
||||
qty -= keepCount;
|
||||
keepCount = 0;
|
||||
// Fall through to determine if the rest of the stack should drop
|
||||
}
|
||||
else
|
||||
{
|
||||
keptItems.add(new ItemStack(id, qty));
|
||||
keepCount -= qty;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Items are kept if:
|
||||
// 1) is not tradeable
|
||||
// 2) is under the deep wilderness line
|
||||
// 3) is outside of the wilderness, or item has a broken form
|
||||
if (!Pets.isPet(id)
|
||||
&& !LostIfNotProtected.isLostIfNotProtected(id)
|
||||
&& !isTradeable(itemManager.getItemComposition(id)) && wildyLevel <= DEEP_WILDY
|
||||
&& (wildyLevel <= 0 || BrokenOnDeathItem.isBrokenOnDeath(i.getId())))
|
||||
{
|
||||
keptItems.add(new ItemStack(id, qty));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, the item is lost
|
||||
lostItems.add(new ItemStack(id, qty));
|
||||
}
|
||||
}
|
||||
|
||||
if (hasClueBox)
|
||||
{
|
||||
boolean alreadyProtectingClue = false;
|
||||
for (final ItemStack item : keptItems)
|
||||
{
|
||||
if (isClueBoxable(item.getId()))
|
||||
{
|
||||
alreadyProtectingClue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyProtectingClue)
|
||||
{
|
||||
int clueId = -1;
|
||||
// Clue box protects the last clue in your inventory so loop over the players inv
|
||||
for (final Item i : inv)
|
||||
{
|
||||
final int id = i.getId();
|
||||
if (id != -1 && isClueBoxable(id))
|
||||
{
|
||||
clueId = id;
|
||||
}
|
||||
}
|
||||
|
||||
if (clueId != -1)
|
||||
{
|
||||
// Move the boxed item to the kept items container and remove it from the lost items container
|
||||
for (final ItemStack boxableItem : lostItems)
|
||||
{
|
||||
if (boxableItem.getId() == clueId)
|
||||
{
|
||||
if (boxableItem.getQty() > 1)
|
||||
{
|
||||
boxableItem.setQty(boxableItem.getQty() - 1);
|
||||
keptItems.add(new ItemStack(clueId, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
lostItems.remove(boxableItem);
|
||||
keptItems.add(boxableItem);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new DeathItems(keptItems, lostItems, hasAlwaysLost);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isClueBoxable(final int itemID)
|
||||
{
|
||||
final String name = itemManager.getItemComposition(itemID).getName();
|
||||
return name.contains("Clue scroll (") || name.contains("Reward casket (");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the price of an item
|
||||
*
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
private int getDeathPrice(Item item)
|
||||
@VisibleForTesting
|
||||
int getDeathPrice(Item item)
|
||||
{
|
||||
// 1) Check if the death price is dynamically calculated, if so return that value
|
||||
// 2) If death price is based off another item default to that price, otherwise apply normal ItemMapping GE price
|
||||
// 3) If still no price, default to store price
|
||||
// 4) Apply fixed price offset if applicable
|
||||
|
||||
int itemId = item.getId();
|
||||
// Unnote/unplaceholder item
|
||||
int canonicalizedItemId = itemManager.canonicalize(itemId);
|
||||
int exchangePrice = itemManager.getItemPrice(canonicalizedItemId);
|
||||
int exchangePrice = 0;
|
||||
|
||||
final DynamicPriceItem dynamicPrice = DynamicPriceItem.find(canonicalizedItemId);
|
||||
if (dynamicPrice != null)
|
||||
{
|
||||
final int basePrice = itemManager.getItemPrice(dynamicPrice.getChargedId(), true);
|
||||
return dynamicPrice.calculateDeathPrice(basePrice);
|
||||
}
|
||||
|
||||
// Some items have artificially offset death prices - such as ring imbues
|
||||
// which are +2k over the non imbues. Check if the item has a fixed price offset
|
||||
final FixedPriceItem fixedPrice = FixedPriceItem.find(canonicalizedItemId);
|
||||
if (fixedPrice != null && fixedPrice.getBaseId() != -1)
|
||||
{
|
||||
// Grab base item price
|
||||
exchangePrice = itemManager.getItemPrice(fixedPrice.getBaseId(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Account for items whose death value comes from their tradeable variant (barrows) or components (ornate kits)
|
||||
for (final int mappedID : ItemMapping.map(canonicalizedItemId))
|
||||
{
|
||||
exchangePrice += itemManager.getItemPrice(mappedID, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (exchangePrice == 0)
|
||||
{
|
||||
final ItemComposition c1 = itemManager.getItemComposition(canonicalizedItemId);
|
||||
exchangePrice = c1.getPrice();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some items have artifically applied death prices - such as ring imbues
|
||||
// which are +2k over the non imbues. Check if the item has a fixed price.
|
||||
FixedPriceItem fixedPrice = FixedPriceItem.find(canonicalizedItemId);
|
||||
if (fixedPrice != null)
|
||||
{
|
||||
// Apply fixed price offset
|
||||
exchangePrice += fixedPrice.getOffset();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply fixed price offset
|
||||
exchangePrice += fixedPrice == null ? 0 : fixedPrice.getOffset();
|
||||
|
||||
return exchangePrice;
|
||||
}
|
||||
|
||||
@@ -589,21 +691,29 @@ public class ItemsKeptOnDeathPlugin extends Plugin
|
||||
/**
|
||||
* Creates an Item Widget for use inside the Kept on Death Interface
|
||||
*
|
||||
* @param qty Amount of item
|
||||
* @param c Items Composition
|
||||
* @return
|
||||
* @param parent Widget to add element too as a child
|
||||
* @param item the TempItem representing the item
|
||||
* @param kept is the item being shown in the kept items container
|
||||
* @return the Widget that was added to the `parent`
|
||||
*/
|
||||
private static Widget createItemWidget(final Widget parent, final int qty, final ItemComposition c)
|
||||
private Widget createItemWidget(final Widget parent, final ItemStack item, boolean kept)
|
||||
{
|
||||
final int id = item.getId();
|
||||
final int qty = item.getQty();
|
||||
final ItemComposition c = itemManager.getItemComposition(id);
|
||||
|
||||
final Widget itemWidget = parent.createChild(-1, WidgetType.GRAPHIC);
|
||||
itemWidget.setItemId(c.getId());
|
||||
itemWidget.setItemQuantity(qty);
|
||||
itemWidget.setHasListener(true);
|
||||
itemWidget.setOriginalWidth(Constants.ITEM_SPRITE_WIDTH);
|
||||
itemWidget.setOriginalHeight(Constants.ITEM_SPRITE_HEIGHT);
|
||||
itemWidget.setBorderType(1);
|
||||
|
||||
itemWidget.setItemId(id);
|
||||
itemWidget.setItemQuantity(qty);
|
||||
itemWidget.setAction(1, String.format("Item: <col=ff981f>%s", c.getName()));
|
||||
itemWidget.setOnOpListener(ScriptID.DEATH_KEEP_ITEM_EXAMINE, kept ? 1 : 0, qty, c.getName());
|
||||
itemWidget.setHasListener(true);
|
||||
|
||||
final AlwaysLostItem alwaysLostItem = AlwaysLostItem.getByItemID(id);
|
||||
final boolean whiteBorder = alwaysLostItem != null && (!alwaysLostItem.isKeptOutsideOfWilderness() || wildyLevel > 0);
|
||||
itemWidget.setBorderType(whiteBorder ? 2 : 1);
|
||||
|
||||
return itemWidget;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2019, TheStonedTurtle <https://github.com/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.ImmutableSet;
|
||||
import java.util.Set;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
final class LostIfNotProtected
|
||||
{
|
||||
private static final Set<Integer> ITEMS = ImmutableSet.of(
|
||||
ItemID.AMULET_OF_THE_DAMNED,
|
||||
ItemID.RING_OF_CHAROS, ItemID.RING_OF_CHAROSA,
|
||||
ItemID.LUNAR_STAFF,
|
||||
ItemID.SHADOW_SWORD,
|
||||
ItemID.KERIS, ItemID.KERISP, ItemID.KERISP_10583, ItemID.KERISP_10584
|
||||
);
|
||||
|
||||
public static boolean isLostIfNotProtected(int id)
|
||||
{
|
||||
return ITEMS.contains(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user