Suppliestracker: Rework and more tracking (#2145)

Suppliestracker: Rework and more tracking

Co-authored-by: Owain van Brakel <owain.vanbrakel@gmail.com>
This commit is contained in:
Owain van Brakel
2019-12-20 08:55:59 +01:00
committed by GitHub
10 changed files with 1064 additions and 308 deletions

View File

@@ -340,6 +340,7 @@ public final class AnimationID
public static final int BARRAGE_ANIMATION = 1979;
public static final int BLITZ_ANIMATION = 1978;
public static final int CHIN_ANIMATION = 7618;
public static final int SCYTHE_OF_VITUR_ANIMATION = 8056;
// Gauntlet Hunleff
public static final int HUNLEFF_TRAMPLE = 8420;

View File

@@ -24,15 +24,23 @@
*/
package net.runelite.api.events;
import javax.annotation.Nullable;
import lombok.Value;
/**
* an event posted when a cannonball is fired
*/
public class CannonballFired implements Event
@Value
public class CannonChanged implements Event
{
public static final CannonballFired INSTANCE = new CannonballFired();
/**
* The projectile id.
*/
@Nullable
private final Integer cannonballId;
private CannonballFired()
{
// noop
}
/**
* The amount of cannonballs left.
*/
private final int cannonballs;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2019, Davis Cook <https://github.com/daviscook477>
* 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.events;
import javax.annotation.Nullable;
import lombok.Value;
import net.runelite.api.GameObject;
import net.runelite.api.coords.WorldPoint;
/**
* an event posted when a cannonball is fired
*/
@Value
public class CannonPlaced implements Event
{
/**
* Cannon placed or picked up.
*/
private final boolean placed;
/**
* The location of the cannon.
*/
@Nullable
private final WorldPoint cannonLocation;
/**
* The cannon object.
*/
@Nullable
private final GameObject cannon;
}

View File

@@ -30,28 +30,19 @@ import java.awt.Color;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.AnimationID;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.InventoryID;
import net.runelite.api.ItemID;
import static net.runelite.api.ObjectID.CANNON_BASE;
import net.runelite.api.Player;
import net.runelite.api.Projectile;
import static net.runelite.api.ProjectileID.CANNONBALL;
import static net.runelite.api.ProjectileID.GRANITE_CANNONBALL;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.CannonChanged;
import net.runelite.api.events.CannonPlaced;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.ProjectileSpawned;
import net.runelite.client.Notifier;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
@@ -72,13 +63,10 @@ import net.runelite.client.util.ItemUtil;
)
public class CannonPlugin extends Plugin
{
private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)");
private static final int MAX_CBALLS = 30;
private static final ImmutableSet<Integer> CANNON_PARTS = ImmutableSet.of(
ItemID.CANNON_BASE, ItemID.CANNON_STAND, ItemID.CANNON_BARRELS, ItemID.CANNON_FURNACE
);
private CannonCounter counter;
private boolean skipProjectileCheckThisTick;
@Getter(AccessLevel.PACKAGE)
private int cballsLeft;
@@ -161,7 +149,6 @@ public class CannonPlugin extends Plugin
lock = false;
cballsLeft = 0;
removeCounter();
skipProjectileCheckThisTick = false;
spotPoints.clear();
}
@@ -221,34 +208,17 @@ public class CannonPlugin extends Plugin
}
@Subscribe
private void onGameObjectSpawned(GameObjectSpawned event)
private void onCannonPlaced(CannonPlaced cannonPlacedEvent)
{
final GameObject gameObject = event.getGameObject();
final Player localPlayer = client.getLocalPlayer();
if (gameObject.getId() == CANNON_BASE && !cannonPlaced &&
localPlayer.getWorldLocation().distanceTo(gameObject.getWorldLocation()) <= 2 &&
localPlayer.getAnimation() == AnimationID.BURYING_BONES)
{
cannonPosition = gameObject.getWorldLocation();
cannon = gameObject;
}
cannonPlaced = cannonPlacedEvent.isPlaced();
cannonPosition = cannonPlacedEvent.getCannonLocation();
cannon = cannonPlacedEvent.getCannon();
}
@Subscribe
private void onProjectileSpawned(ProjectileSpawned event)
private void onCannonballFired(CannonChanged cannonChangedEvent)
{
final Projectile projectile = event.getProjectile();
if ((projectile.getId() == CANNONBALL || projectile.getId() == GRANITE_CANNONBALL) && cannonPosition != null)
{
final WorldPoint projectileLoc = WorldPoint.fromLocal(client, projectile.getX1(), projectile.getY1(), client.getPlane());
if (projectileLoc.equals(cannonPosition) && !skipProjectileCheckThisTick)
{
cballsLeft--;
}
}
cballsLeft = cannonChangedEvent.getCannonballs();
}
@Subscribe
@@ -261,84 +231,14 @@ public class CannonPlugin extends Plugin
if (event.getMessage().equals("You add the furnace."))
{
cannonPlaced = true;
addCounter();
cballsLeft = 0;
}
if (event.getMessage().contains("You pick up the cannon")
|| event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!"))
{
cannonPlaced = false;
cballsLeft = 0;
removeCounter();
}
if (event.getMessage().startsWith("You load the cannon with"))
{
Matcher m = NUMBER_PATTERN.matcher(event.getMessage());
if (m.find())
{
// The cannon will usually refill to MAX_CBALLS, but if the
// player didn't have enough cannonballs in their inventory,
// it could fill up less than that. Filling the cannon to
// cballsLeft + amt is not always accurate though because our
// counter doesn't decrease if the player has been too far away
// from the cannon due to the projectiels not being in memory,
// so our counter can be higher than it is supposed to be.
int amt = Integer.parseInt(m.group());
if (cballsLeft + amt >= MAX_CBALLS)
{
skipProjectileCheckThisTick = true;
cballsLeft = MAX_CBALLS;
}
else
{
cballsLeft += amt;
}
}
else if (event.getMessage().equals("You load the cannon with one cannonball."))
{
if (cballsLeft + 1 >= MAX_CBALLS)
{
skipProjectileCheckThisTick = true;
cballsLeft = MAX_CBALLS;
}
else
{
cballsLeft++;
}
}
}
if (event.getMessage().contains("Your cannon is out of ammo!"))
{
skipProjectileCheckThisTick = true;
// If the player was out of range of the cannon, some cannonballs
// may have been used without the client knowing, so having this
// extra check is a good idea.
cballsLeft = 0;
if (this.showEmptyCannonNotification)
{
notifier.notify("Your cannon is out of ammo!");
}
}
if (event.getMessage().startsWith("You unload your cannon and receive Cannonball")
|| event.getMessage().startsWith("You unload your cannon and receive Granite cannonball"))
{
skipProjectileCheckThisTick = true;
cballsLeft = 0;
}
}
@Subscribe
private void onGameTick(GameTick event)
{
skipProjectileCheckThisTick = false;
}
Color getStateColor()

View File

@@ -29,17 +29,35 @@ package net.runelite.client.plugins.openosrs;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.AnimationID;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import static net.runelite.api.ObjectID.CANNON_BASE;
import net.runelite.api.Player;
import net.runelite.api.Projectile;
import static net.runelite.api.ProjectileID.CANNONBALL;
import static net.runelite.api.ProjectileID.GRANITE_CANNONBALL;
import static net.runelite.api.ScriptID.BANK_PIN_OP;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.CannonChanged;
import net.runelite.api.events.CannonPlaced;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.ProjectileSpawned;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.widgets.WidgetID;
import static net.runelite.api.widgets.WidgetInfo.*;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.Keybind;
import net.runelite.client.config.OpenOSRSConfig;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.input.KeyListener;
@@ -60,7 +78,7 @@ import net.runelite.client.util.HotkeyListener;
public class OpenOSRSPlugin extends Plugin
{
private final openosrsKeyListener keyListener = new openosrsKeyListener();
private final List<String> HidePlugins = Arrays.asList("hidePlugins", "hidePvmPlugins", "hidePvpPlugins", "hideSkillingPlugins", "hideUtilityPlugins", "hideExternalPlugins");
private static final List<String> HidePlugins = Arrays.asList("hidePlugins", "hidePvmPlugins", "hidePvpPlugins", "hideSkillingPlugins", "hideUtilityPlugins", "hideExternalPlugins");
@Inject
private OpenOSRSConfig config;
@@ -73,6 +91,18 @@ public class OpenOSRSPlugin extends Plugin
@Inject
private ClientThread clientThread;
@Inject
private EventBus eventBus;
private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)");
private static final int MAX_CBALLS = 30;
private int cballsLeft;
private WorldPoint cannonPosition;
private GameObject cannon;
private boolean cannonPlaced;
private boolean skipProjectileCheckThisTick;
private int entered = -1;
private int enterIdx;
private boolean expectInput;
@@ -174,6 +204,136 @@ public class OpenOSRSPlugin extends Plugin
}
}
@Subscribe
private void onChatMessage(ChatMessage event)
{
if (event.getType() != ChatMessageType.SPAM && event.getType() != ChatMessageType.GAMEMESSAGE)
{
return;
}
if (event.getMessage().equals("You add the furnace."))
{
cballsLeft = 0;
eventBus.post(CannonPlaced.class, new CannonPlaced(true, cannonPosition, cannon));
eventBus.post(CannonChanged.class, new CannonChanged(null, cballsLeft));
cannonPlaced = true;
}
if (event.getMessage().contains("You pick up the cannon")
|| event.getMessage().contains("Your cannon has decayed. Speak to Nulodion to get a new one!"))
{
cballsLeft = 0;
eventBus.post(CannonPlaced.class, new CannonPlaced(false, null, null));
eventBus.post(CannonChanged.class, new CannonChanged(null, cballsLeft));
cannonPlaced = false;
}
if (event.getMessage().startsWith("You load the cannon with"))
{
Matcher m = NUMBER_PATTERN.matcher(event.getMessage());
if (m.find())
{
// The cannon will usually refill to MAX_CBALLS, but if the
// player didn't have enough cannonballs in their inventory,
// it could fill up less than that. Filling the cannon to
// cballsLeft + amt is not always accurate though because our
// counter doesn't decrease if the player has been too far away
// from the cannon due to the projectiels not being in memory,
// so our counter can be higher than it is supposed to be.
int amt = Integer.parseInt(m.group());
if (cballsLeft + amt >= MAX_CBALLS)
{
skipProjectileCheckThisTick = true;
cballsLeft = MAX_CBALLS;
}
else
{
cballsLeft += amt;
}
}
else if (event.getMessage().equals("You load the cannon with one cannonball."))
{
if (cballsLeft + 1 >= MAX_CBALLS)
{
skipProjectileCheckThisTick = true;
cballsLeft = MAX_CBALLS;
}
else
{
cballsLeft++;
}
}
eventBus.post(CannonChanged.class, new CannonChanged(null, cballsLeft));
}
if (event.getMessage().contains("Your cannon is out of ammo!"))
{
skipProjectileCheckThisTick = true;
// If the player was out of range of the cannon, some cannonballs
// may have been used without the client knowing, so having this
// extra check is a good idea.
cballsLeft = 0;
eventBus.post(CannonChanged.class, new CannonChanged(null, cballsLeft));
}
if (event.getMessage().startsWith("You unload your cannon and receive Cannonball")
|| event.getMessage().startsWith("You unload your cannon and receive Granite cannonball"))
{
skipProjectileCheckThisTick = true;
cballsLeft = 0;
eventBus.post(CannonChanged.class, new CannonChanged(null, cballsLeft));
}
}
@Subscribe
private void onGameTick(GameTick event)
{
skipProjectileCheckThisTick = false;
}
@Subscribe
private void onGameObjectSpawned(GameObjectSpawned event)
{
final GameObject gameObject = event.getGameObject();
final Player localPlayer = client.getLocalPlayer();
if (gameObject.getId() == CANNON_BASE && !cannonPlaced &&
localPlayer != null && localPlayer.getWorldLocation().distanceTo(gameObject.getWorldLocation()) <= 2 &&
localPlayer.getAnimation() == AnimationID.BURYING_BONES)
{
cannonPosition = gameObject.getWorldLocation();
cannon = gameObject;
}
}
@Subscribe
private void onProjectileSpawned(ProjectileSpawned event)
{
if (!cannonPlaced)
{
return;
}
final Projectile projectile = event.getProjectile();
if ((projectile.getId() == CANNONBALL || projectile.getId() == GRANITE_CANNONBALL) && cannonPosition != null)
{
final WorldPoint projectileLoc = WorldPoint.fromLocal(client, projectile.getX1(), projectile.getY1(), client.getPlane());
if (projectileLoc.equals(cannonPosition) && !skipProjectileCheckThisTick)
{
cballsLeft--;
eventBus.post(CannonChanged.class, new CannonChanged(projectile.getId(), cballsLeft));
}
}
}
private void handleKey(char c)
{
if (client.getWidget(WidgetID.BANK_PIN_GROUP_ID, BANK_PIN_INSTRUCTION_TEXT.getChildId()) == null

View File

@@ -28,6 +28,7 @@ package net.runelite.client.plugins.suppliestracker;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import static net.runelite.api.ItemID.*;
/**
* The potential types that supplies can be along with a categorization function
@@ -40,7 +41,10 @@ public enum ItemType
POTION("Potions"),
RUNE("Runes"),
AMMO("Ammo"),
TELEPORT("Teleports");
TELEPORT("Teleports"),
COINS("Coins"),
JEWELLERY("Jewellery"),
CHARGES("Charges");
@Getter(AccessLevel.PACKAGE)
private String label;
@@ -74,6 +78,20 @@ public enum ItemType
{
return ItemType.TELEPORT;
}
if (item.getId() == COINS_995)
{
return ItemType.COINS;
}
if (item.getName().toLowerCase().contains("ring of") || item.getName().toLowerCase().contains("amulet") ||
item.getName().toLowerCase().contains("bracelet") || item.getName().toLowerCase().contains("necklace"))
{
return ItemType.JEWELLERY;
}
if (item.getId() == SCYTHE_OF_VITUR || item.getId() == SANGUINESTI_STAFF ||
item.getId() == TRIDENT_OF_THE_SEAS || item.getId() == TRIDENT_OF_THE_SWAMP)
{
return ItemType.CHARGES;
}
return ItemType.FOOD;
}
}

View File

@@ -43,36 +43,38 @@ import net.runelite.api.ItemDefinition;
import static net.runelite.api.ItemID.*;
import net.runelite.api.util.Text;
import net.runelite.client.game.ItemManager;
import static net.runelite.client.plugins.suppliestracker.SuppliesTrackerPlugin.POTION_PATTERN;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
import net.runelite.client.util.AsyncBufferedImage;
import net.runelite.client.util.QuantityFormatter;
@Singleton
class SuppliesBox extends JPanel
abstract class SuppliesBox extends JPanel
{
private static final int ITEMS_PER_ROW = 5;
public final ItemManager itemManager;
protected final SuppliesTrackerPlugin plugin;
private final JPanel itemContainer = new JPanel();
private final JLabel priceLabel = new JLabel();
private final JLabel subTitleLabel = new JLabel();
private final ItemManager itemManager;
@Getter(AccessLevel.PACKAGE)
private final String id;
private final SuppliesTrackerPlugin plugin;
private final SuppliesTrackerPanel panel;
@Getter(AccessLevel.PACKAGE)
private final List<SuppliesTrackerItem> trackedItems = new ArrayList<>();
private long totalPrice;
private final String id;
@Getter(AccessLevel.PACKAGE)
private final ItemType type;
SuppliesBox(final ItemManager itemManager, final String id,
final SuppliesTrackerPlugin plugin, final SuppliesTrackerPanel panel,
final ItemType type)
@Getter(AccessLevel.PACKAGE)
private final List<SuppliesTrackerItem> trackedItems = new ArrayList<>();
private long totalPrice;
protected SuppliesBox(
ItemManager itemManager,
String id,
SuppliesTrackerPlugin plugin,
SuppliesTrackerPanel panel,
ItemType type)
{
this.id = id;
this.itemManager = itemManager;
@@ -80,6 +82,38 @@ class SuppliesBox extends JPanel
this.panel = panel;
this.type = type;
render();
}
abstract String buildTooltip(int itemId, int qty, SuppliesTrackerItem item);
public static SuppliesBox of(
ItemManager itemManager,
String id,
SuppliesTrackerPlugin plugin,
SuppliesTrackerPanel panel,
ItemType type)
{
switch (type)
{
case JEWELLERY:
return new JewellerySuppliesBox(itemManager, id, plugin, panel, type);
case CHARGES:
return new ChargesSuppliesBox(itemManager, id, plugin, panel, type);
case FOOD:
return new FoodSuppliesBox(itemManager, id, plugin, panel, type);
case POTION:
return new PotionSuppliesBox(itemManager, id, plugin, panel, type);
}
return new DefaultSuppliesBox(itemManager, id, plugin, panel, type);
}
/**
* Builds the box onto the panel
*/
private void render()
{
setLayout(new BorderLayout(0, 1));
setBorder(new EmptyBorder(5, 0, 0, 0));
@@ -127,6 +161,11 @@ class SuppliesBox extends JPanel
setVisible(false);
}
/**
* Adds item to trackedItems
*
* @param item item to be checked
*/
void update(SuppliesTrackerItem item)
{
trackedItems.removeIf(r -> r.getId() == item.getId());
@@ -134,6 +173,11 @@ class SuppliesBox extends JPanel
setVisible(trackedItems.size() > 0);
}
/**
* Removes item from trackedItems
*
* @param item item to be checked
*/
private void remove(SuppliesTrackerItem item)
{
trackedItems.removeIf(r -> r.getId() == item.getId());
@@ -141,12 +185,20 @@ class SuppliesBox extends JPanel
setVisible(trackedItems.size() > 0);
}
/**
* Clears trackedItems
*/
void clearAll()
{
trackedItems.clear();
setVisible(false);
}
/**
* Adds the total cost of all items to be returned
*
* @return the total cost of all tracked items
*/
long getTotalSupplies()
{
long totalSupplies = 0;
@@ -162,6 +214,9 @@ class SuppliesBox extends JPanel
return totalPrice;
}
/**
* Runs buildItems method and recalculates supplies cost and quantity.
*/
void rebuild()
{
buildItems();
@@ -183,6 +238,19 @@ class SuppliesBox extends JPanel
repaint();
}
/**
* Changes itemId to single use variant
*
* @param name name to be checked
* @param itemId is either changed or returned to method
* @return returns updated itemId
*/
abstract int getModifiedItemId(String name, int itemId);
/**
* Builds an arraylist of items based off trackedItems and populates
* boxes with item information
*/
private void buildItems()
{
final List<SuppliesTrackerItem> items = new ArrayList<>(trackedItems);
@@ -210,7 +278,7 @@ class SuppliesBox extends JPanel
{
final SuppliesTrackerItem item = items.get(i);
final JLabel imageLabel = new JLabel();
imageLabel.setToolTipText(buildToolTip(getModifiedItemId(item.getName(), item.getId()), item.getQuantity()));
imageLabel.setToolTipText(buildTooltip(getModifiedItemId(item.getName(), item.getId()), item.getQuantity(), item));
imageLabel.setVerticalAlignment(SwingConstants.CENTER);
imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
@@ -238,110 +306,396 @@ class SuppliesBox extends JPanel
itemContainer.repaint();
}
private int getModifiedItemId(String name, int itemId)
private static class JewellerySuppliesBox extends SuppliesBox
{
if (SuppliesTrackerPlugin.isPotion(name))
protected JewellerySuppliesBox(ItemManager itemManager, String id, SuppliesTrackerPlugin plugin, SuppliesTrackerPanel panel, ItemType type)
{
return getSingleDose(name);
}
if (SuppliesTrackerPlugin.isCake(name, itemId))
{
return getSlice(itemId);
}
if (SuppliesTrackerPlugin.isPizzaPie(name))
{
return getHalf(itemId);
super(itemManager, id, plugin, panel, type);
}
return itemId;
@Override
final String buildTooltip(int itemId, int qty, SuppliesTrackerItem item)
{
ItemDefinition itemDef = itemManager.getItemDefinition(itemId);
final String name = itemDef.getName();
StringBuilder tooltip = new StringBuilder();
if (name.toLowerCase().contains("glory"))
{
tooltip.append("Amulet of Glory(6) x ")
.append(qty)
.append("/6 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(AMULET_OF_GLORY6) * qty) / 6))
.append("gp)");
}
else if (name.toLowerCase().contains("dueling"))
{
tooltip.append("Ring of Dueling(8) x ")
.append(qty)
.append("/8 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(RING_OF_DUELING8) * qty) / 8))
.append("gp)");
}
else if (name.toLowerCase().contains("wealth"))
{
tooltip.append("Ring of Wealth(5) x ")
.append(qty)
.append("/5 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(RING_OF_WEALTH_5) * qty) / 5))
.append("gp)");
}
else if (name.toLowerCase().contains("combat"))
{
tooltip.append("Combat Bracelet(6) x ")
.append(qty)
.append("/6 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(COMBAT_BRACELET6) * qty) / 6))
.append("gp)");
}
else if (name.toLowerCase().contains("games"))
{
tooltip.append("Games Necklace(8) x ")
.append(qty)
.append("/8 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(GAMES_NECKLACE8) * qty) / 8))
.append("gp)");
}
else if (name.toLowerCase().contains("skills"))
{
tooltip.append("Skills Necklace(6) x ")
.append(qty)
.append("/6 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(SKILLS_NECKLACE6) * qty) / 6))
.append("gp)");
}
else if (name.toLowerCase().contains("passage"))
{
tooltip.append("Necklace of Passage(5) x ")
.append(qty)
.append("/5 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(NECKLACE_OF_PASSAGE5) * qty) / 5))
.append("gp)");
}
else if (name.toLowerCase().contains("burning"))
{
tooltip.append("Burning Amulet(5) x ")
.append(qty)
.append("/5 (")
.append(QuantityFormatter.quantityToStackSize((itemManager.getItemPrice(BURNING_AMULET5) * qty) / 5))
.append("gp)");
}
return tooltip.toString();
}
@Override
int getModifiedItemId(String name, int itemId)
{
return itemId;
}
}
//Switches full cake ids to get the image for slice
private int getSlice(int itemId)
private static class ChargesSuppliesBox extends SuppliesBox
{
switch (itemId)
protected ChargesSuppliesBox(ItemManager itemManager, String id, SuppliesTrackerPlugin plugin, SuppliesTrackerPanel panel, ItemType type)
{
case CAKE:
itemId = SLICE_OF_CAKE;
break;
case CHOCOLATE_CAKE:
itemId = CHOCOLATE_SLICE;
break;
}
return itemId;
}
//Switches full pizza and pie ids to get the image for half
private int getHalf(int itemId)
{
switch (itemId)
{
case ANCHOVY_PIZZA:
itemId = _12_ANCHOVY_PIZZA;
break;
case MEAT_PIZZA:
itemId = _12_MEAT_PIZZA;
break;
case PINEAPPLE_PIZZA:
itemId = _12_PINEAPPLE_PIZZA;
break;
case PLAIN_PIZZA:
itemId = _12_PLAIN_PIZZA;
break;
case REDBERRY_PIE:
itemId = HALF_A_REDBERRY_PIE;
break;
case GARDEN_PIE:
itemId = HALF_A_GARDEN_PIE;
break;
case SUMMER_PIE:
itemId = HALF_A_SUMMER_PIE;
break;
case FISH_PIE:
itemId = HALF_A_FISH_PIE;
break;
case BOTANICAL_PIE:
itemId = HALF_A_BOTANICAL_PIE;
break;
case MUSHROOM_PIE:
itemId = HALF_A_MUSHROOM_PIE;
break;
case ADMIRAL_PIE:
itemId = HALF_AN_ADMIRAL_PIE;
break;
case WILD_PIE:
itemId = HALF_A_WILD_PIE;
break;
case APPLE_PIE:
itemId = HALF_AN_APPLE_PIE;
break;
case MEAT_PIE:
itemId = HALF_A_MEAT_PIE;
break;
}
return itemId;
}
private int getSingleDose(String name)
{
String nameModified = name.replace("(4)", "(1)");
int itemId = 0;
if (itemManager.search(nameModified).size() > 0)
{
itemId = itemManager.search(nameModified).get(0).getId();
super(itemManager, id, plugin, panel, type);
}
return itemId;
@Override
final String buildTooltip(int itemId, int qty, SuppliesTrackerItem item)
{
StringBuilder tooltip = new StringBuilder();
switch (itemId)
{
case SCYTHE_OF_VITUR:
tooltip.append("<html>")
.append("Blood Rune x ")
.append(qty * 3)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
itemManager.getItemPrice(BLOOD_RUNE) * qty * 3)
)
.append("gp)")
.append("<br>")
.append("Vial of Blood x ")
.append(qty).append("/100 (")
.append(QuantityFormatter.quantityToStackSize(
(itemManager.getItemPrice(VIAL_OF_BLOOD_22446) * qty) / 100)
)
.append("gp)")
.append("</br>")
.append("</html>");
return tooltip.toString();
case SANGUINESTI_STAFF:
tooltip.append("Blood Rune x ")
.append(qty * 3).append(" (")
.append(QuantityFormatter.quantityToStackSize(
itemManager.getItemPrice(BLOOD_RUNE) * qty * 3)
)
.append("gp)");
return tooltip.toString();
case TRIDENT_OF_THE_SEAS:
tooltip.append("<html>")
.append("Chaos Rune x ")
.append(qty).append(" (")
.append(QuantityFormatter.quantityToStackSize(
itemManager.getItemPrice(CHAOS_RUNE) * qty)
)
.append("gp)")
.append("<br>")
.append("Death Rune x ")
.append(qty)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
itemManager.getItemPrice(DEATH_RUNE) * qty)
)
.append("gp)")
.append("</br>")
.append("<br>")
.append("Fire Rune x ")
.append(qty * 5)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
(itemManager.getItemPrice(FIRE_RUNE) * qty) * 5)
)
.append("gp)")
.append("</br>")
.append("<br>")
.append("Coins x ")
.append(qty * 10)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
(itemManager.getItemPrice(COINS_995) * qty) * 10)
)
.append("gp)")
.append("</br>")
.append("</html>");
return tooltip.toString();
case TRIDENT_OF_THE_SWAMP:
tooltip.append("<html>")
.append("Chaos Rune x ")
.append(qty)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
itemManager.getItemPrice(CHAOS_RUNE) * qty)
)
.append("gp)")
.append("<br>")
.append("Death Rune x ")
.append(qty)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
(itemManager.getItemPrice(DEATH_RUNE) * qty))
)
.append("gp)")
.append("</br>")
.append("<br>")
.append("Fire Rune x ")
.append(qty * 5)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
(itemManager.getItemPrice(FIRE_RUNE) * qty) * 5)
)
.append("gp)")
.append("</br>")
.append("<br>")
.append("Zulrah's Scales x ")
.append(qty)
.append(" (")
.append(QuantityFormatter.quantityToStackSize(
(itemManager.getItemPrice(ZULRAHS_SCALES) * qty))
)
.append("gp)")
.append("</br>")
.append("</html>");
return tooltip.toString();
}
return tooltip.toString();
}
@Override
int getModifiedItemId(String name, int itemId)
{
return itemId;
}
}
private String buildToolTip(int itemId, int qty)
private static class FoodSuppliesBox extends SuppliesBox
{
ItemDefinition item = this.itemManager.getItemDefinition(itemId);
final String name = item.getName();
final long price = itemManager.getItemPrice(itemId);
return name + " x " + qty + " (" + QuantityFormatter.quantityToStackSize(price * qty) + ") ";
protected FoodSuppliesBox(ItemManager itemManager, String id, SuppliesTrackerPlugin plugin, SuppliesTrackerPanel panel, ItemType type)
{
super(itemManager, id, plugin, panel, type);
}
@Override
final String buildTooltip(int itemId, int qty, SuppliesTrackerItem item)
{
ItemDefinition itemDef = itemManager.getItemDefinition(itemId);
final String name = itemDef.getName();
final long price = itemManager.getItemPrice(itemId);
return name + " x " + qty + " (" + QuantityFormatter.quantityToStackSize(price * qty) + ") ";
}
@Override
int getModifiedItemId(String name, int itemId)
{
if (SuppliesTrackerPlugin.isCake(name, itemId))
{
return getSlice(itemId);
}
if (SuppliesTrackerPlugin.isPizzaPie(name))
{
return getHalf(itemId);
}
return itemId;
}
//Switches full cake ids to get the image for slice
private static int getSlice(int itemId)
{
switch (itemId)
{
case CAKE:
itemId = SLICE_OF_CAKE;
break;
case CHOCOLATE_CAKE:
itemId = CHOCOLATE_SLICE;
break;
}
return itemId;
}
//Switches full pizza and pie ids to get the image for half
private static int getHalf(int itemId)
{
switch (itemId)
{
case ANCHOVY_PIZZA:
itemId = _12_ANCHOVY_PIZZA;
break;
case MEAT_PIZZA:
itemId = _12_MEAT_PIZZA;
break;
case PINEAPPLE_PIZZA:
itemId = _12_PINEAPPLE_PIZZA;
break;
case PLAIN_PIZZA:
itemId = _12_PLAIN_PIZZA;
break;
case REDBERRY_PIE:
itemId = HALF_A_REDBERRY_PIE;
break;
case GARDEN_PIE:
itemId = HALF_A_GARDEN_PIE;
break;
case SUMMER_PIE:
itemId = HALF_A_SUMMER_PIE;
break;
case FISH_PIE:
itemId = HALF_A_FISH_PIE;
break;
case BOTANICAL_PIE:
itemId = HALF_A_BOTANICAL_PIE;
break;
case MUSHROOM_PIE:
itemId = HALF_A_MUSHROOM_PIE;
break;
case ADMIRAL_PIE:
itemId = HALF_AN_ADMIRAL_PIE;
break;
case WILD_PIE:
itemId = HALF_A_WILD_PIE;
break;
case APPLE_PIE:
itemId = HALF_AN_APPLE_PIE;
break;
case MEAT_PIE:
itemId = HALF_A_MEAT_PIE;
break;
}
return itemId;
}
}
private static class PotionSuppliesBox extends SuppliesBox
{
protected PotionSuppliesBox(ItemManager itemManager, String id, SuppliesTrackerPlugin plugin, SuppliesTrackerPanel panel, ItemType type)
{
super(itemManager, id, plugin, panel, type);
}
@Override
final String buildTooltip(int itemId, int qty, SuppliesTrackerItem item)
{
ItemDefinition itemDef = itemManager.getItemDefinition(itemId);
final String name = itemDef.getName();
final long price = itemManager.getItemPrice(plugin.getPotionID(name.replaceAll(POTION_PATTERN, "(4)"))) / 4;
return name + " x " + qty + " (" + QuantityFormatter.quantityToStackSize(price * qty) + ") ";
}
@Override
int getModifiedItemId(String name, int itemId)
{
if (SuppliesTrackerPlugin.isPotion(name))
{
return getSingleDose(name);
}
return itemId;
}
/**
* Turns a potion itemid into the single dose id
*
* @param name potion name to be checked
* @return itemid of single dose potion
*/
private int getSingleDose(String name)
{
String nameModified = name.replace("(4)", "(1)");
int itemId = 0;
if (itemManager.search(nameModified).size() > 0)
{
itemId = itemManager.search(nameModified).get(0).getId();
}
return itemId;
}
}
private static class DefaultSuppliesBox extends SuppliesBox
{
protected DefaultSuppliesBox(ItemManager itemManager, String id, SuppliesTrackerPlugin plugin, SuppliesTrackerPanel panel, ItemType type)
{
super(itemManager, id, plugin, panel, type);
}
@Override
final String buildTooltip(int itemId, int qty, SuppliesTrackerItem item)
{
ItemDefinition itemDef = itemManager.getItemDefinition(itemId);
final String name = itemDef.getName();
final long price = itemManager.getItemPrice(itemId);
return name + " x " + qty + " (" + QuantityFormatter.quantityToStackSize(price * qty) + ") ";
}
@Override
int getModifiedItemId(String name, int itemId)
{
return itemId;
}
}
}

View File

@@ -54,4 +54,26 @@ public interface SuppliesTrackerConfig extends Config
{
return BlowpipeDartType.MITHRIL;
}
@ConfigTitleSection(
keyName = "chargesBoxTitle",
name = "Charges Box",
description = "",
position = 2
)
default Title chargesBoxTitle()
{
return new Title();
}
@ConfigItem(
keyName = "chargesBox",
name = "Show weapons charges used box?",
description = "Separates items with charges to show how many of those charges you used.",
titleSection = "chargesBoxTitle"
)
default boolean chargesBox()
{
return false;
}
}

View File

@@ -53,9 +53,10 @@ class SuppliesTrackerPanel extends PluginPanel
private static final String HTML_LABEL_TEMPLATE =
"<html><body style='color:%s'>%s<span style='color:white'>%s</span></body></html>";
// Handle loot logs
// Handle supplies logs
private final JPanel logsContainer = new JPanel();
//Boxes for holding supplies
private final List<SuppliesBox> boxList = new ArrayList<>();
private final PluginErrorPanel errorPanel = new PluginErrorPanel();
@@ -97,9 +98,10 @@ class SuppliesTrackerPanel extends PluginPanel
overallPanel.add(overallIcon, BorderLayout.WEST);
overallPanel.add(overallInfo, BorderLayout.CENTER);
//Sorts boxes into usage types
for (ItemType type : ItemType.values())
{
SuppliesBox newBox = new SuppliesBox(itemManager, type.getLabel(), plugin, this, type);
SuppliesBox newBox = SuppliesBox.of(itemManager, type.getLabel(), plugin, this, type);
logsContainer.add(newBox);
boxList.add(newBox);
}
@@ -135,16 +137,6 @@ class SuppliesTrackerPanel extends PluginPanel
overallPanel.setVisible(false);
}
/**
* loads an img to the icon on the header
*
* @param img the img for the header icon
*/
void loadHeaderIcon(BufferedImage img)
{
overallIcon.setIcon(new ImageIcon(img));
}
/**
* convert key value pair to html formatting needed to display nicely
*
@@ -158,6 +150,16 @@ class SuppliesTrackerPanel extends PluginPanel
return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR), key, valueStr);
}
/**
* loads an img to the icon on the header
*
* @param img the img for the header icon
*/
void loadHeaderIcon(BufferedImage img)
{
overallIcon.setIcon(new ImageIcon(img));
}
/**
* Add an item to the supply panel by placing it into the correct box
*
@@ -191,6 +193,8 @@ class SuppliesTrackerPanel extends PluginPanel
}
overallCost = 0;
//Checks all supply boxes for total price
for (SuppliesBox box : boxList)
{
overallCost += box.getTotalPrice();

View File

@@ -41,11 +41,8 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.SwingUtilities;
import lombok.extern.slf4j.Slf4j;
import static net.runelite.api.AnimationID.BARRAGE_ANIMATION;
import static net.runelite.api.AnimationID.BLITZ_ANIMATION;
import static net.runelite.api.AnimationID.BLOWPIPE_ATTACK;
import static net.runelite.api.AnimationID.HIGH_LEVEL_MAGIC_ATTACK;
import static net.runelite.api.AnimationID.LOW_LEVEL_MAGIC_ATTACK;
import static net.runelite.api.AnimationID.*;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.EquipmentInventorySlot;
import net.runelite.api.InventoryID;
@@ -57,7 +54,8 @@ import static net.runelite.api.ItemID.*;
import net.runelite.api.Player;
import net.runelite.api.VarPlayer;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.CannonballFired;
import net.runelite.api.events.CannonChanged;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.MenuOptionClicked;
@@ -68,15 +66,12 @@ import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import static net.runelite.client.plugins.suppliestracker.ActionType.CAST;
import static net.runelite.client.plugins.suppliestracker.ActionType.CONSUMABLE;
import static net.runelite.client.plugins.suppliestracker.ActionType.TELEPORT;
import static net.runelite.client.plugins.suppliestracker.ActionType.*;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.ImageUtil;
import net.runelite.http.api.item.ItemPrice;
@PluginDescriptor(
name = "Supplies Used Tracker",
description = "Tracks supplies used during the session",
@@ -88,41 +83,53 @@ import net.runelite.http.api.item.ItemPrice;
@Slf4j
public class SuppliesTrackerPlugin extends Plugin
{
private static final String POTION_PATTERN = "[(]\\d[)]";
//Regex patterns
static final String POTION_PATTERN = "[(]\\d[)]";
private static final String EAT_PATTERN = "^eat";
private static final String DRINK_PATTERN = "^drink";
private static final String TELEPORT_PATTERN = "^teleport";
private static final String TELETAB_PATTERN = "^break";
private static final String SPELL_PATTERN = "^cast|^grand\\sexchange|^outside|^seers|^yanille";
//Equipment slot constants
private static final int EQUIPMENT_MAINHAND_SLOT = EquipmentInventorySlot.WEAPON.getSlotIdx();
private static final int EQUIPMENT_AMMO_SLOT = EquipmentInventorySlot.AMMO.getSlotIdx();
private static final int EQUIPMENT_CAPE_SLOT = EquipmentInventorySlot.CAPE.getSlotIdx();
//Ava's calculations
private static final double NO_AVAS_PERCENT = 1.0;
private static final double ASSEMBLER_PERCENT = 0.20;
private static final double ACCUMULATOR_PERCENT = 0.28;
private static final double ATTRACTOR_PERCENT = 0.40;
//blowpipe attack timings
private static final int BLOWPIPE_TICKS_RAPID_PVM = 2;
private static final int BLOWPIPE_TICKS_RAPID_PVP = 3;
private static final int BLOWPIPE_TICKS_NORMAL_PVM = 3;
private static final int BLOWPIPE_TICKS_NORMAL_PVP = 4;
//blowpipe scale usage
private static final double SCALES_PERCENT = 0.66;
//Max use amounts
private static final int POTION_DOSES = 4, CAKE_DOSES = 3, PIZZA_PIE_DOSES = 2;
private static final Random random = new Random();
// id array for checking thrown items and runes
private static final int[] THROWING_IDS = new int[]{BRONZE_DART, IRON_DART, STEEL_DART, BLACK_DART, MITHRIL_DART, ADAMANT_DART, RUNE_DART, DRAGON_DART, BRONZE_KNIFE, IRON_KNIFE, STEEL_KNIFE, BLACK_KNIFE, MITHRIL_KNIFE, ADAMANT_KNIFE, RUNE_KNIFE, BRONZE_THROWNAXE, IRON_THROWNAXE, STEEL_THROWNAXE, MITHRIL_THROWNAXE, ADAMANT_THROWNAXE, RUNE_THROWNAXE, DRAGON_KNIFE, DRAGON_KNIFE_22812, DRAGON_KNIFE_22814, DRAGON_KNIFEP_22808, DRAGON_KNIFEP_22810, DRAGON_KNIFEP, DRAGON_THROWNAXE, CHINCHOMPA_10033, RED_CHINCHOMPA_10034, BLACK_CHINCHOMPA};
private static final int[] RUNE_IDS = new int[]{AIR_RUNE, WATER_RUNE, EARTH_RUNE, MIND_RUNE, BODY_RUNE, COSMIC_RUNE, CHAOS_RUNE, NATURE_RUNE, LAW_RUNE, DEATH_RUNE, ASTRAL_RUNE, BLOOD_RUNE, SOUL_RUNE, WRATH_RUNE, MIST_RUNE, DUST_RUNE, MUD_RUNE, SMOKE_RUNE, STEAM_RUNE, LAVA_RUNE};
//Hold Supply Data
private static final Map<Integer, SuppliesTrackerItem> suppliesEntry = new HashMap<>();
private ItemContainer old;
private final Deque<MenuAction> actionStack = new ArrayDeque<>();
//Item arrays
private final String[] RAIDS_CONSUMABLES = new String[]{"xeric's", "elder", "twisted", "revitalisation", "overload", "prayer enhance", "pysk", "suphi", "leckish", "brawk", "mycil", "roqed", "kyren", "guanic", "prael", "giral", "phluxia", "kryket", "murng", "psykk"};
private final int[] TRIDENT_OF_THE_SEAS_IDS = new int[]{TRIDENT_OF_THE_SEAS, TRIDENT_OF_THE_SEAS_E, TRIDENT_OF_THE_SEAS_FULL};
private final int[] TRIDENT_OF_THE_SWAMP_IDS = new int[]{TRIDENT_OF_THE_SWAMP_E, TRIDENT_OF_THE_SWAMP, UNCHARGED_TOXIC_TRIDENT_E, UNCHARGED_TOXIC_TRIDENT};
private ItemContainer old;
private int ammoId = 0;
private int ammoAmount = 0;
private int thrownId = 0;
@@ -133,8 +140,6 @@ public class SuppliesTrackerPlugin extends Plugin
private int mainHand = 0;
private SuppliesTrackerPanel panel;
private NavigationButton navButton;
private final String[] RAIDS_CONSUMABLES = new String[]{"xeric's", "elder", "twisted", "revitalisation", "overload", "prayer enhance", "pysk", "suphi", "leckish", "brawk", "mycil", "roqed", "kyren", "guanic", "prael", "giral", "phluxia", "kryket", "murng", "psykk"};
private int attackStyleVarbit = -1;
private int ticks = 0;
private int ticksInAnimation;
@@ -151,6 +156,38 @@ public class SuppliesTrackerPlugin extends Plugin
@Inject
private Client client;
/**
* Checks if item name is potion
*
* @param name the name of the item
* @return if the item is a potion - i.e. has a (1) (2) (3) or (4) in the name
*/
static boolean isPotion(String name)
{
return name.contains("(4)") ||
name.contains("(3)") ||
name.contains("(2)") ||
name.contains("(1)");
}
/**
* Checks if item name is pizza or pie
*
* @param name the name of the item
* @return if the item is a pizza or a pie - i.e. has pizza or pie in the name
*/
static boolean isPizzaPie(String name)
{
return name.toLowerCase().contains("pizza") ||
name.toLowerCase().contains(" pie");
}
static boolean isCake(String name, int itemId)
{
return name.toLowerCase().contains("cake") ||
itemId == ItemID.CHOCOLATE_SLICE;
}
@Override
protected void startUp()
{
@@ -190,14 +227,14 @@ public class SuppliesTrackerPlugin extends Plugin
{
ticks++;
}
if (ticks == ticksInAnimation && (player.getAnimation() == BLOWPIPE_ATTACK))
if (ticks == ticksInAnimation &&
(player.getAnimation() == BLOWPIPE_ATTACK))
{
double ava_percent = getAccumulatorPercent();
// randomize the usage of supplies since we CANNOT actually get real supplies used
if (random.nextDouble() <= ava_percent)
{
buildEntries(config.blowpipeAmmo().getDartID());
}
if (random.nextDouble() <= SCALES_PERCENT)
{
@@ -223,10 +260,12 @@ public class SuppliesTrackerPlugin extends Plugin
switch (capeID)
{
case AVAS_ASSEMBLER:
case AVAS_ASSEMBLER_L:
case ASSEMBLER_MAX_CAPE:
percent = ASSEMBLER_PERCENT;
break;
case AVAS_ACCUMULATOR:
case AVAS_ACCUMULATOR_23609:
case ACCUMULATOR_MAX_CAPE:
// TODO: the ranging cape can be used as an attractor so this could be wrong
case RANGING_CAPE:
@@ -243,10 +282,12 @@ public class SuppliesTrackerPlugin extends Plugin
@Subscribe
private void onVarbitChanged(VarbitChanged event)
{
if (attackStyleVarbit == -1 || attackStyleVarbit != client.getVar(VarPlayer.ATTACK_STYLE))
if (attackStyleVarbit == -1 ||
attackStyleVarbit != client.getVar(VarPlayer.ATTACK_STYLE))
{
attackStyleVarbit = client.getVar(VarPlayer.ATTACK_STYLE);
if (attackStyleVarbit == 0 || attackStyleVarbit == 3)
if (attackStyleVarbit == 0 ||
attackStyleVarbit == 3)
{
ticksInAnimation = BLOWPIPE_TICKS_NORMAL_PVM;
if (client.getLocalPlayer() != null &&
@@ -294,7 +335,8 @@ public class SuppliesTrackerPlugin extends Plugin
break;
}
}
if (isRune && (newItem.getId() != oldItem.getId() || newItem.getQuantity() != oldItem.getQuantity()))
if (isRune && (newItem.getId() != oldItem.getId() ||
newItem.getQuantity() != oldItem.getQuantity()))
{
int quantity = oldItem.getQuantity();
if (newItem.getId() == oldItem.getId())
@@ -317,8 +359,12 @@ public class SuppliesTrackerPlugin extends Plugin
}
@Subscribe
private void onCannonballFired(CannonballFired cannonballFired)
private void onCannonballFired(CannonChanged cannonChanged)
{
if (cannonChanged.getCannonballId() == null)
{
return;
}
buildEntries(CANNONBALL);
}
@@ -330,35 +376,53 @@ public class SuppliesTrackerPlugin extends Plugin
if (animationChanged.getActor().getAnimation() == HIGH_LEVEL_MAGIC_ATTACK)
{
//Trident of the seas
if (mainHand == TRIDENT_OF_THE_SEAS || mainHand == TRIDENT_OF_THE_SEAS_E || mainHand == TRIDENT_OF_THE_SEAS_FULL)
for (int tridentOfTheSeas : TRIDENT_OF_THE_SEAS_IDS)
{
buildEntries(CHAOS_RUNE);
buildEntries(DEATH_RUNE);
buildEntries(FIRE_RUNE, 5);
buildEntries(COINS_995, 10);
if (mainHand == tridentOfTheSeas)
{
if (config.chargesBox())
{
buildChargesEntries(TRIDENT_OF_THE_SEAS);
}
else
{
buildEntries(CHAOS_RUNE);
buildEntries(DEATH_RUNE);
buildEntries(FIRE_RUNE, 5);
buildEntries(COINS_995, 10);
}
break;
}
}
//Trident of the swamp
else if (mainHand == TRIDENT_OF_THE_SWAMP_E || mainHand == TRIDENT_OF_THE_SWAMP || mainHand == UNCHARGED_TOXIC_TRIDENT_E || mainHand == UNCHARGED_TOXIC_TRIDENT)
for (int tridentOfTheSwamp : TRIDENT_OF_THE_SWAMP_IDS)
{
buildEntries(CHAOS_RUNE);
buildEntries(DEATH_RUNE);
buildEntries(FIRE_RUNE, 5);
buildEntries(ZULRAHS_SCALES);
if (mainHand == tridentOfTheSwamp)
{
if (config.chargesBox())
{
buildChargesEntries(TRIDENT_OF_THE_SWAMP);
}
else
{
buildEntries(CHAOS_RUNE);
buildEntries(DEATH_RUNE);
buildEntries(FIRE_RUNE, 5);
buildEntries(ZULRAHS_SCALES);
}
break;
}
}
//Sang Staff
else if (mainHand == SANGUINESTI_STAFF || mainHand == SANGUINESTI_STAFF_UNCHARGED)
if (mainHand == SANGUINESTI_STAFF)
{
buildEntries(BLOOD_RUNE, 3);
}
else
{
old = client.getItemContainer(InventoryID.INVENTORY);
if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a ->
a.getType() == CAST))
if (config.chargesBox())
{
MenuAction newAction = new MenuAction(CAST, old.getItems());
actionStack.push(newAction);
buildChargesEntries(SANGUINESTI_STAFF);
}
else
{
buildEntries(BLOOD_RUNE, 3);
}
}
}
@@ -373,17 +437,30 @@ public class SuppliesTrackerPlugin extends Plugin
actionStack.push(newAction);
}
}
else if (animationChanged.getActor().getAnimation() == BARRAGE_ANIMATION || animationChanged.getActor().getAnimation() == BLITZ_ANIMATION )
else if (animationChanged.getActor().getAnimation() == BARRAGE_ANIMATION ||
animationChanged.getActor().getAnimation() == BLITZ_ANIMATION)
{
old = client.getItemContainer(InventoryID.INVENTORY);
if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a ->
a.getType() == CAST))
a.getType() == CAST))
{
MenuAction newAction = new MenuAction(CAST, old.getItems());
actionStack.push(newAction);
}
}
else if (animationChanged.getActor().getAnimation() == SCYTHE_OF_VITUR_ANIMATION)
{
if (config.chargesBox())
{
buildChargesEntries(SCYTHE_OF_VITUR);
}
else
{
buildEntries(BLOOD_RUNE, 3);
buildEntries(COINS_995, itemManager.getItemPrice(VIAL_OF_BLOOD_22446) / 100);
}
}
}
}
@@ -392,7 +469,8 @@ public class SuppliesTrackerPlugin extends Plugin
{
ItemContainer itemContainer = itemContainerChanged.getItemContainer();
if (itemContainer == client.getItemContainer(InventoryID.INVENTORY) && old != null)
if (itemContainer == client.getItemContainer(InventoryID.INVENTORY) &&
old != null)
{
while (!actionStack.isEmpty())
{
@@ -415,7 +493,8 @@ public class SuppliesTrackerPlugin extends Plugin
itemFrame = (MenuAction.ItemAction) frame;
int teleid = itemFrame.getItemID();
int slot = itemFrame.getSlot();
if (itemContainer.getItems()[slot].getId() != oldInv[slot].getId() || itemContainer.getItems()[slot].getQuantity() != oldInv[slot].getQuantity())
if (itemContainer.getItems()[slot].getId() != oldInv[slot].getId() ||
itemContainer.getItems()[slot].getQuantity() != oldInv[slot].getQuantity())
{
buildEntries(teleid);
}
@@ -574,8 +653,9 @@ public class SuppliesTrackerPlugin extends Plugin
old = client.getItemContainer(InventoryID.INVENTORY);
// Makes stack only contains one teleport type to stop from adding multiple of one teleport
if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a ->
a.getType() == TELEPORT))
if (old != null && old.getItems() != null &&
actionStack.stream().noneMatch(a ->
a.getType() == TELEPORT))
{
int teleid = event.getIdentifier();
MenuAction newAction = new MenuAction.ItemAction(TELEPORT, old.getItems(), teleid, event.getParam0());
@@ -592,39 +672,117 @@ public class SuppliesTrackerPlugin extends Plugin
old = client.getItemContainer(InventoryID.INVENTORY);
if (old != null && old.getItems() != null && actionStack.stream().noneMatch(a ->
a.getType() == CAST))
a.getType() == CAST))
{
MenuAction newAction = new MenuAction(CAST, old.getItems());
actionStack.push(newAction);
}
}
//Adds tracking to Master Scroll Book
if (event.getOption().toLowerCase().equals("activate"))
{
String target = event.getTarget();
if (target.toLowerCase().contains("teleport scroll"))
{
switch (target.toLowerCase().substring(target.indexOf(">") + 1))
{
case "watson teleport scroll":
buildEntries(WATSON_TELEPORT);
break;
case "zul-andra teleport scroll":
buildEntries(ZULANDRA_TELEPORT);
break;
case "nardah teleport scroll":
buildEntries(NARDAH_TELEPORT);
break;
case "digsite teleport scroll":
buildEntries(DIGSITE_TELEPORT);
break;
case "feldip hills teleport scroll":
buildEntries(FELDIP_HILLS_TELEPORT);
break;
case "lunar isle teleport scroll":
buildEntries(LUNAR_ISLE_TELEPORT);
break;
case "mort'ton teleport scroll":
buildEntries(MORTTON_TELEPORT);
break;
case "pest control teleport scroll":
buildEntries(PEST_CONTROL_TELEPORT);
break;
case "piscatoris teleport scroll":
buildEntries(PISCATORIS_TELEPORT);
break;
case "iorwerth camp teleport scroll":
buildEntries(IORWERTH_CAMP_TELEPORT);
break;
case "mos le'harmless teleport scroll":
buildEntries(MOS_LEHARMLESS_TELEPORT);
break;
case "lumberyard teleport scroll":
buildEntries(LUMBERYARD_TELEPORT);
break;
case "revenant cave teleport scroll":
buildEntries(REVENANT_CAVE_TELEPORT);
break;
case "tai bwo wannai teleport scroll":
buildEntries(TAI_BWO_WANNAI_TELEPORT);
break;
case "key master teleport":
buildEntries(KEY_MASTER_TELEPORT);
}
}
}
}
/**
* Checks if item name is potion
*
* @param name the name of the item
* @return if the item is a potion - i.e. has a (1) (2) (3) or (4) in the name
*/
static boolean isPotion(String name)
@Subscribe
void onChatMessage(ChatMessage event)
{
return name.contains("(4)") || name.contains("(3)") || name.contains("(2)") || name.contains("(1)");
}
/**
* Checks if item name is pizza or pie
*
* @param name the name of the item
* @return if the item is a pizza or a pie - i.e. has pizza or pie in the name
*/
static boolean isPizzaPie(String name)
{
return name.toLowerCase().contains("pizza") || name.toLowerCase().contains(" pie");
}
static boolean isCake(String name, int itemId)
{
return name.toLowerCase().contains("cake") || itemId == ItemID.CHOCOLATE_SLICE;
String message = event.getMessage();
if (event.getType() == ChatMessageType.GAMEMESSAGE || event.getType() == ChatMessageType.SPAM)
{
if (message.toLowerCase().contains("your amulet has") ||
message.toLowerCase().contains("your amulet's last charge"))
{
buildChargesEntries(AMULET_OF_GLORY6);
}
else if (message.toLowerCase().contains("your ring of dueling has") ||
message.toLowerCase().contains("your ring of dueling crumbles"))
{
buildChargesEntries(RING_OF_DUELING8);
}
else if (message.toLowerCase().contains("your ring of wealth has"))
{
buildChargesEntries(RING_OF_WEALTH_5);
}
else if (message.toLowerCase().contains("your combat bracelet has") ||
message.toLowerCase().contains("your combat bracelet's last charge"))
{
buildChargesEntries(COMBAT_BRACELET6);
}
else if (message.toLowerCase().contains("your games necklace has") ||
message.toLowerCase().contains("your games necklace crumbles"))
{
buildChargesEntries(GAMES_NECKLACE8);
}
else if (message.toLowerCase().contains("your skills necklace has") ||
message.toLowerCase().contains("your skills necklace's last charge"))
{
buildChargesEntries(SKILLS_NECKLACE6);
}
else if (message.toLowerCase().contains("your necklace of passage has") ||
message.toLowerCase().contains("your necklace of passage crumbles"))
{
buildChargesEntries(NECKLACE_OF_PASSAGE5);
}
else if (message.toLowerCase().contains("your burning amulet has") ||
message.toLowerCase().contains("your burning amulet crumbles"))
{
buildChargesEntries(BURNING_AMULET5);
}
}
}
/**
@@ -725,11 +883,89 @@ public class SuppliesTrackerPlugin extends Plugin
newQuantity,
calculatedPrice);
suppliesEntry.put(itemId, newEntry);
SwingUtilities.invokeLater(() ->
panel.addItem(newEntry));
}
/**
* Add an item to the supply tracker
*
* @param itemId the id of the item
*/
private void buildChargesEntries(int itemId)
{
final ItemDefinition itemComposition = itemManager.getItemDefinition(itemId);
String name = itemComposition.getName();
long calculatedPrice = 0;
int newQuantity;
if (suppliesEntry.containsKey(itemId))
{
newQuantity = suppliesEntry.get(itemId).getQuantity() + 1;
}
else
{
newQuantity = 1;
}
switch (itemId)
{
case AMULET_OF_GLORY6:
calculatedPrice = ((itemManager.getItemPrice(AMULET_OF_GLORY6) * newQuantity) / 6);
break;
case RING_OF_DUELING8:
calculatedPrice = ((itemManager.getItemPrice(RING_OF_DUELING8) * newQuantity) / 8);
break;
case RING_OF_WEALTH_5:
calculatedPrice = ((itemManager.getItemPrice(RING_OF_WEALTH_5) * newQuantity) / 5);
break;
case COMBAT_BRACELET6:
calculatedPrice = ((itemManager.getItemPrice(COMBAT_BRACELET6) * newQuantity) / 6);
break;
case GAMES_NECKLACE8:
calculatedPrice = ((itemManager.getItemPrice(GAMES_NECKLACE8) * newQuantity) / 8);
break;
case SKILLS_NECKLACE6:
calculatedPrice = ((itemManager.getItemPrice(SKILLS_NECKLACE6) * newQuantity) / 6);
break;
case NECKLACE_OF_PASSAGE5:
calculatedPrice = ((itemManager.getItemPrice(NECKLACE_OF_PASSAGE5) * newQuantity) / 5);
break;
case BURNING_AMULET5:
calculatedPrice = ((itemManager.getItemPrice(BURNING_AMULET5) * newQuantity) / 5);
break;
case SCYTHE_OF_VITUR:
calculatedPrice = (itemManager.getItemPrice(BLOOD_RUNE) * newQuantity * 3) + (itemManager.getItemPrice(VIAL_OF_BLOOD_22446) * newQuantity / 100);
break;
case TRIDENT_OF_THE_SWAMP:
calculatedPrice = (itemManager.getItemPrice(CHAOS_RUNE) * newQuantity) + (itemManager.getItemPrice(DEATH_RUNE) * newQuantity) +
(itemManager.getItemPrice(FIRE_RUNE) * newQuantity) + (itemManager.getItemPrice(ZULRAHS_SCALES) * newQuantity);
break;
case TRIDENT_OF_THE_SEAS:
calculatedPrice = (itemManager.getItemPrice(CHAOS_RUNE) * newQuantity) + (itemManager.getItemPrice(DEATH_RUNE) * newQuantity) +
(itemManager.getItemPrice(FIRE_RUNE) * newQuantity) + (itemManager.getItemPrice(COINS_995) * newQuantity * 10);
break;
case SANGUINESTI_STAFF:
calculatedPrice = (itemManager.getItemPrice(BLOOD_RUNE) * newQuantity * 3);
break;
}
// write the new quantity and calculated price for this entry
SuppliesTrackerItem newEntry = new SuppliesTrackerItem(
itemId,
name,
newQuantity,
calculatedPrice);
suppliesEntry.put(itemId, newEntry);
SwingUtilities.invokeLater(() ->
panel.addItem(newEntry));
}
/**
* reset all item stacks
*/
@@ -754,7 +990,7 @@ public class SuppliesTrackerPlugin extends Plugin
* @param name the given name
* @return the item id for this name
*/
private int getPotionID(String name)
int getPotionID(String name)
{
int itemId = 0;
@@ -822,7 +1058,6 @@ public class SuppliesTrackerPlugin extends Plugin
case HALF_A_MEAT_PIE:
itemId = MEAT_PIE;
break;
// note behavior of case means both below cases return CAKE
case _23_CAKE:
case SLICE_OF_CAKE:
itemId = CAKE;