diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java
index 85dceb6c18..3775ff77c7 100644
--- a/runelite-api/src/main/java/net/runelite/api/Client.java
+++ b/runelite-api/src/main/java/net/runelite/api/Client.java
@@ -456,6 +456,13 @@ public interface Client extends GameEngine
*/
int getEnergy();
+ /**
+ * Gets the current weight of the logged in player.
+ *
+ * @return the weight
+ */
+ int getWeight();
+
/**
* Gets an array of options that can currently be used on other players.
*
diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java
index 0e932b6b85..b1e50160e6 100644
--- a/runelite-api/src/main/java/net/runelite/api/Varbits.java
+++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java
@@ -39,6 +39,11 @@ public enum Varbits
*/
TRANSPARENT_CHATBOX(4608),
+ /*
+ * If the player has an active stamina potion effect or not
+ */
+ RUN_SLOWED_DEPLETION_ACTIVE(25),
+
/**
* If scrollbar in resizable mode chat is on the left
*/
diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java
index 69d5d99657..683482092a 100644
--- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java
+++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java
@@ -254,6 +254,8 @@ public class WidgetID
static final int PRAYER_ORB = 12;
static final int QUICK_PRAYER_ORB = 14; // Has the "Quick-prayers" name
static final int RUN_ORB = 20;
+ static final int TOGGLE_RUN_ORB = 22; // Has the "Toggle run" name
+ static final int RUN_ORB_TEXT = 23;
static final int SPEC_ORB = 28;
}
diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java
index 951e92c2c7..70d684fceb 100644
--- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java
+++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java
@@ -141,6 +141,8 @@ public enum WidgetInfo
MINIMAP_PRAYER_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.PRAYER_ORB),
MINIMAP_QUICK_PRAYER_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.QUICK_PRAYER_ORB),
MINIMAP_RUN_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.RUN_ORB),
+ MINIMAP_TOGGLE_RUN_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.TOGGLE_RUN_ORB),
+ MINIMAP_RUN_ORB_TEXT(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.RUN_ORB_TEXT),
MINIMAP_HEALTH_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.HEALTH_ORB),
MINIMAP_SPEC_ORB(WidgetID.MINIMAP_GROUP_ID, WidgetID.Minimap.SPEC_ORB),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyConfig.java
new file mode 100644
index 0000000000..3c1418411a
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyConfig.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Sean Dewar
+ * 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.runenergy;
+
+import net.runelite.client.config.Config;
+import net.runelite.client.config.ConfigGroup;
+import net.runelite.client.config.ConfigItem;
+
+@ConfigGroup("runenergy")
+public interface RunEnergyConfig extends Config
+{
+ @ConfigItem(
+ keyName = "replaceOrbText",
+ name = "Replace orb text with run time left",
+ description = "Show the remaining run time (in seconds) next in the energy orb."
+ )
+ default boolean replaceOrbText()
+ {
+ return false;
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyOverlay.java
new file mode 100644
index 0000000000..1d501c968b
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyOverlay.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018, Sean Dewar
+ * 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.runenergy;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import javax.inject.Inject;
+import net.runelite.api.Client;
+import net.runelite.api.Point;
+import net.runelite.api.widgets.Widget;
+import net.runelite.api.widgets.WidgetInfo;
+import net.runelite.client.ui.overlay.Overlay;
+import net.runelite.client.ui.overlay.OverlayLayer;
+import net.runelite.client.ui.overlay.OverlayPosition;
+import net.runelite.client.ui.overlay.tooltip.Tooltip;
+import net.runelite.client.ui.overlay.tooltip.TooltipManager;
+import org.apache.commons.lang3.StringUtils;
+
+class RunEnergyOverlay extends Overlay
+{
+ private final RunEnergyPlugin plugin;
+ private final Client client;
+ private final TooltipManager tooltipManager;
+
+ @Inject
+ private RunEnergyOverlay(final RunEnergyPlugin plugin, final Client client, final TooltipManager tooltipManager)
+ {
+ this.plugin = plugin;
+ this.client = client;
+ this.tooltipManager = tooltipManager;
+ setPosition(OverlayPosition.DYNAMIC);
+ setLayer(OverlayLayer.ABOVE_WIDGETS);
+ }
+
+ @Override
+ public Dimension render(Graphics2D graphics)
+ {
+ final Widget runOrb = client.getWidget(WidgetInfo.MINIMAP_TOGGLE_RUN_ORB);
+
+ if (runOrb == null)
+ {
+ return null;
+ }
+
+ final Rectangle bounds = runOrb.getBounds();
+
+ if (bounds.getX() <= 0)
+ {
+ return null;
+ }
+
+ final Point mousePosition = client.getMouseCanvasPosition();
+
+ if (bounds.contains(mousePosition.getX(), mousePosition.getY()))
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Weight: ").append(client.getWeight()).append(" kg")
+ .append("Run Time Remaining: ").append(plugin.getEstimatedRunTimeRemaining(false));
+
+ int secondsUntil100 = plugin.getEstimatedRecoverTimeRemaining();
+ if (secondsUntil100 > 0)
+ {
+ final int minutes = (int) Math.floor(secondsUntil100 / 60.0);
+ final int seconds = (int) Math.floor(secondsUntil100 - (minutes * 60.0));
+
+ sb.append("").append("100% Energy In: ").append(minutes).append(':').append(StringUtils.leftPad(Integer.toString(seconds), 2, "0"));
+ }
+
+ tooltipManager.add(new Tooltip(sb.toString()));
+ }
+
+ return null;
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java
new file mode 100644
index 0000000000..1260df244a
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/runenergy/RunEnergyPlugin.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2018, Sean Dewar
+ * 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.runenergy;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.eventbus.Subscribe;
+import com.google.inject.Provides;
+import javax.inject.Inject;
+import net.runelite.api.Client;
+import net.runelite.api.EquipmentInventorySlot;
+import net.runelite.api.InventoryID;
+import net.runelite.api.Item;
+import net.runelite.api.ItemContainer;
+import static net.runelite.api.ItemID.*;
+import net.runelite.api.Skill;
+import net.runelite.api.Varbits;
+import net.runelite.api.coords.WorldPoint;
+import net.runelite.api.events.ConfigChanged;
+import net.runelite.api.events.GameTick;
+import net.runelite.api.widgets.Widget;
+import net.runelite.api.widgets.WidgetInfo;
+import net.runelite.client.config.ConfigManager;
+import net.runelite.client.plugins.Plugin;
+import net.runelite.client.plugins.PluginDescriptor;
+import net.runelite.client.ui.overlay.OverlayManager;
+import org.apache.commons.lang3.StringUtils;
+
+@PluginDescriptor(
+ name = "Run Energy",
+ description = "Show various information related to run energy",
+ tags = {"overlay", "stamina"}
+)
+public class RunEnergyPlugin extends Plugin
+{
+ // TODO It would be nice if we have the IDs for just the equipped variants of the Graceful set items.
+ private static final ImmutableSet ALL_GRACEFUL_HOODS = ImmutableSet.of(
+ GRACEFUL_HOOD_11851, GRACEFUL_HOOD_13579, GRACEFUL_HOOD_13580, GRACEFUL_HOOD_13591, GRACEFUL_HOOD_13592,
+ GRACEFUL_HOOD_13603, GRACEFUL_HOOD_13604, GRACEFUL_HOOD_13615, GRACEFUL_HOOD_13616, GRACEFUL_HOOD_13627,
+ GRACEFUL_HOOD_13628, GRACEFUL_HOOD_13667, GRACEFUL_HOOD_13668, GRACEFUL_HOOD_21061, GRACEFUL_HOOD_21063
+ );
+
+ private static final ImmutableSet ALL_GRACEFUL_TOPS = ImmutableSet.of(
+ GRACEFUL_TOP_11855, GRACEFUL_TOP_13583, GRACEFUL_TOP_13584, GRACEFUL_TOP_13595, GRACEFUL_TOP_13596,
+ GRACEFUL_TOP_13607, GRACEFUL_TOP_13608, GRACEFUL_TOP_13619, GRACEFUL_TOP_13620, GRACEFUL_TOP_13631,
+ GRACEFUL_TOP_13632, GRACEFUL_TOP_13671, GRACEFUL_TOP_13672, GRACEFUL_TOP_21067, GRACEFUL_TOP_21069
+ );
+
+ private static final ImmutableSet ALL_GRACEFUL_LEGS = ImmutableSet.of(
+ GRACEFUL_LEGS_11857, GRACEFUL_LEGS_13585, GRACEFUL_LEGS_13586, GRACEFUL_LEGS_13597, GRACEFUL_LEGS_13598,
+ GRACEFUL_LEGS_13609, GRACEFUL_LEGS_13610, GRACEFUL_LEGS_13621, GRACEFUL_LEGS_13622, GRACEFUL_LEGS_13633,
+ GRACEFUL_LEGS_13634, GRACEFUL_LEGS_13673, GRACEFUL_LEGS_13674, GRACEFUL_LEGS_21070, GRACEFUL_LEGS_21072
+ );
+
+ private static final ImmutableSet ALL_GRACEFUL_GLOVES = ImmutableSet.of(
+ GRACEFUL_GLOVES_11859, GRACEFUL_GLOVES_13587, GRACEFUL_GLOVES_13588, GRACEFUL_GLOVES_13599, GRACEFUL_GLOVES_13600,
+ GRACEFUL_GLOVES_13611, GRACEFUL_GLOVES_13612, GRACEFUL_GLOVES_13623, GRACEFUL_GLOVES_13624, GRACEFUL_GLOVES_13635,
+ GRACEFUL_GLOVES_13636, GRACEFUL_GLOVES_13675, GRACEFUL_GLOVES_13676, GRACEFUL_GLOVES_21073, GRACEFUL_GLOVES_21075
+ );
+
+ private static final ImmutableSet ALL_GRACEFUL_BOOTS = ImmutableSet.of(
+ GRACEFUL_BOOTS_11861, GRACEFUL_BOOTS_13589, GRACEFUL_BOOTS_13590, GRACEFUL_BOOTS_13601, GRACEFUL_BOOTS_13602,
+ GRACEFUL_BOOTS_13613, GRACEFUL_BOOTS_13614, GRACEFUL_BOOTS_13625, GRACEFUL_BOOTS_13626, GRACEFUL_BOOTS_13637,
+ GRACEFUL_BOOTS_13638, GRACEFUL_BOOTS_13677, GRACEFUL_BOOTS_13678, GRACEFUL_BOOTS_21076, GRACEFUL_BOOTS_21078
+ );
+
+ // Agility skill capes and the non-cosmetic Max capes also count for the Graceful set effect
+ private static final ImmutableSet ALL_GRACEFUL_CAPES = ImmutableSet.of(
+ GRACEFUL_CAPE_11853, GRACEFUL_CAPE_13581, GRACEFUL_CAPE_13582, GRACEFUL_CAPE_13593, GRACEFUL_CAPE_13594,
+ GRACEFUL_CAPE_13605, GRACEFUL_CAPE_13606, GRACEFUL_CAPE_13617, GRACEFUL_CAPE_13618, GRACEFUL_CAPE_13629,
+ GRACEFUL_CAPE_13630, GRACEFUL_CAPE_13669, GRACEFUL_CAPE_13670, GRACEFUL_CAPE_21064, GRACEFUL_CAPE_21066,
+ AGILITY_CAPE, AGILITY_CAPET, MAX_CAPE
+ );
+
+ @Inject
+ private Client client;
+
+ @Inject
+ private OverlayManager overlayManager;
+
+ @Inject
+ private RunEnergyOverlay energyOverlay;
+
+ @Inject
+ private RunEnergyConfig energyConfig;
+
+ private boolean localPlayerRunningToDestination;
+ private WorldPoint prevLocalPlayerLocation;
+
+ @Provides
+ RunEnergyConfig getConfig(ConfigManager configManager)
+ {
+ return configManager.getConfig(RunEnergyConfig.class);
+ }
+
+ @Override
+ protected void startUp() throws Exception
+ {
+ overlayManager.add(energyOverlay);
+ }
+
+ @Override
+ protected void shutDown() throws Exception
+ {
+ overlayManager.remove(energyOverlay);
+ localPlayerRunningToDestination = false;
+ prevLocalPlayerLocation = null;
+ resetRunOrbText();
+ }
+
+ @Subscribe
+ public void onGameTick(GameTick event)
+ {
+ localPlayerRunningToDestination =
+ prevLocalPlayerLocation != null &&
+ client.getLocalDestinationLocation() != null &&
+ prevLocalPlayerLocation.distanceTo(client.getLocalPlayer().getWorldLocation()) > 1;
+
+ prevLocalPlayerLocation = client.getLocalPlayer().getWorldLocation();
+
+ if (energyConfig.replaceOrbText())
+ {
+ setRunOrbText(getEstimatedRunTimeRemaining(true));
+ }
+ }
+
+ @Subscribe
+ public void onConfigChanged(ConfigChanged event)
+ {
+ if (event.getGroup().equals("runenergy") && !energyConfig.replaceOrbText())
+ {
+ resetRunOrbText();
+ }
+ }
+
+ private void setRunOrbText(String text)
+ {
+ Widget runOrbText = client.getWidget(WidgetInfo.MINIMAP_RUN_ORB_TEXT);
+
+ if (runOrbText != null)
+ {
+ runOrbText.setText(text);
+ }
+ }
+
+ private void resetRunOrbText()
+ {
+ setRunOrbText(Integer.toString(client.getEnergy()));
+ }
+
+ String getEstimatedRunTimeRemaining(boolean inSeconds)
+ {
+ // Calculate the amount of energy lost every 2 ticks (0.6 seconds).
+ // Negative weight has the same depletion effect as 0 kg.
+ final int effectiveWeight = Math.max(client.getWeight(), 0);
+ double lossRate = (Math.min(effectiveWeight, 64) / 100.0) + 0.64;
+
+ if (client.getVar(Varbits.RUN_SLOWED_DEPLETION_ACTIVE) != 0)
+ {
+ lossRate *= 0.3; // Stamina effect reduces energy depletion to 30%
+ }
+
+ // Calculate the number of seconds left
+ final double secondsLeft = (client.getEnergy() * 0.6) / lossRate;
+
+ // Return the text
+ if (inSeconds)
+ {
+ return Integer.toString((int) Math.floor(secondsLeft)) + "s";
+ }
+ else
+ {
+ final int minutes = (int) Math.floor(secondsLeft / 60.0);
+ final int seconds = (int) Math.floor(secondsLeft - (minutes * 60.0));
+
+ return Integer.toString(minutes) + ":" + StringUtils.leftPad(Integer.toString(seconds), 2, "0");
+ }
+ }
+
+ private boolean isLocalPlayerWearingFullGraceful()
+ {
+ final ItemContainer equipment = client.getItemContainer(InventoryID.EQUIPMENT);
+
+ if (equipment == null)
+ {
+ return false;
+ }
+
+ final Item[] items = equipment.getItems();
+
+ // Check that the local player is wearing enough items to be using full Graceful
+ // (the Graceful boots will have the highest slot index in the worn set).
+ if (items == null || items.length <= EquipmentInventorySlot.BOOTS.getSlotIdx())
+ {
+ return false;
+ }
+
+ return (ALL_GRACEFUL_HOODS.contains(items[EquipmentInventorySlot.HEAD.getSlotIdx()].getId()) &&
+ ALL_GRACEFUL_TOPS.contains(items[EquipmentInventorySlot.BODY.getSlotIdx()].getId()) &&
+ ALL_GRACEFUL_LEGS.contains(items[EquipmentInventorySlot.LEGS.getSlotIdx()].getId()) &&
+ ALL_GRACEFUL_GLOVES.contains(items[EquipmentInventorySlot.GLOVES.getSlotIdx()].getId()) &&
+ ALL_GRACEFUL_BOOTS.contains(items[EquipmentInventorySlot.BOOTS.getSlotIdx()].getId()) &&
+ ALL_GRACEFUL_CAPES.contains(items[EquipmentInventorySlot.CAPE.getSlotIdx()].getId()));
+ }
+
+ int getEstimatedRecoverTimeRemaining()
+ {
+ if (localPlayerRunningToDestination)
+ {
+ return -1;
+ }
+
+ // Calculate the amount of energy recovered every second
+ double recoverRate = (48 + client.getBoostedSkillLevel(Skill.AGILITY)) / 360.0;
+
+ if (isLocalPlayerWearingFullGraceful())
+ {
+ recoverRate *= 1.3; // 30% recover rate increase from Graceful set effect
+ }
+
+ // Calculate the number of seconds left
+ final double secondsLeft = (100 - client.getEnergy()) / recoverRate;
+ return (int) secondsLeft;
+ }
+}
diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java
index 4a03a94858..20d4336892 100644
--- a/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java
+++ b/runescape-api/src/main/java/net/runelite/rs/api/RSClient.java
@@ -111,6 +111,7 @@ public interface RSClient extends RSGameEngine, Client
int getEnergy();
@Import("weight")
+ @Override
int getWeight();
@Import("baseX")