diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java index 43deff2bb4..957f8867d3 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/GameTimer.java @@ -28,6 +28,7 @@ package net.runelite.client.plugins.timers; import java.time.Duration; import java.time.temporal.ChronoUnit; +import javax.annotation.Nullable; import lombok.AccessLevel; import lombok.Getter; import net.runelite.api.GraphicID; @@ -47,10 +48,7 @@ enum GameTimer HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Half Teleblock", 150, ChronoUnit.SECONDS, true), DMM_FULLTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Full Teleblock", 150, ChronoUnit.SECONDS, true), DMM_HALFTB(SpriteID.SPELL_TELE_BLOCK, GameTimerImageType.SPRITE, "Deadman Mode Half Teleblock", 75, ChronoUnit.SECONDS, true), - ANTIVENOMPLUS(ItemID.ANTIVENOM4_12913, GameTimerImageType.ITEM, "Anti-venom+", 3, ChronoUnit.MINUTES), - ANTIVENOMPLUS_ANTIPOSION(ItemID.SUPERANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom+ Antipoison", 15, ChronoUnit.MINUTES, 3), SUPERANTIFIRE(ItemID.SUPER_ANTIFIRE_POTION4, GameTimerImageType.ITEM, "Super antifire", 3, ChronoUnit.MINUTES), - ANTIDOTEPLUSPLUS(ItemID.ANTIDOTE4_5952, GameTimerImageType.ITEM, "Antidote++", 12, ChronoUnit.MINUTES), BIND(SpriteID.SPELL_BIND, GameTimerImageType.SPRITE, "Bind", GraphicID.BIND, 5, ChronoUnit.SECONDS, true), SNARE(SpriteID.SPELL_SNARE, GameTimerImageType.SPRITE, "Snare", GraphicID.SNARE, 10, ChronoUnit.SECONDS, true), ENTANGLE(SpriteID.SPELL_ENTANGLE, GameTimerImageType.SPRITE, "Entangle", GraphicID.ENTANGLE, 15, ChronoUnit.SECONDS, true), @@ -60,16 +58,10 @@ enum GameTimer ICEBARRAGE(SpriteID.SPELL_ICE_BARRAGE, GameTimerImageType.SPRITE, "Ice barrage", GraphicID.ICE_BARRAGE, 20, ChronoUnit.SECONDS, true), IMBUEDHEART(ItemID.IMBUED_HEART, GameTimerImageType.ITEM, "Imbued heart", GraphicID.IMBUED_HEART, 420, ChronoUnit.SECONDS, true), VENGEANCE(SpriteID.SPELL_VENGEANCE, GameTimerImageType.SPRITE, "Vengeance", 30, ChronoUnit.SECONDS), - ANTIDOTEPLUS(ItemID.ANTIDOTE4, GameTimerImageType.ITEM, "Antidote+", 518, ChronoUnit.SECONDS), - ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom", 1, ChronoUnit.MINUTES), - ANTIVENOM_ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Anti-venom Antipoison", 12, ChronoUnit.MINUTES, 1), EXSUPERANTIFIRE(ItemID.EXTENDED_SUPER_ANTIFIRE4, GameTimerImageType.ITEM, "Extended Super AntiFire", 6, ChronoUnit.MINUTES), - SANFEW(ItemID.SANFEW_SERUM4, GameTimerImageType.ITEM, "Sanfew serum", 6, ChronoUnit.MINUTES), OVERLOAD_RAID(ItemID.OVERLOAD_4_20996, GameTimerImageType.ITEM, "Overload", 5, ChronoUnit.MINUTES, true), PRAYER_ENHANCE(ItemID.PRAYER_ENHANCE_4, GameTimerImageType.ITEM, "Prayer enhance", 290, ChronoUnit.SECONDS, true), GOD_WARS_ALTAR(SpriteID.SKILL_PRAYER, GameTimerImageType.SPRITE, "God wars altar", 10, ChronoUnit.MINUTES), - ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Antipoison", 90, ChronoUnit.SECONDS), - SUPERANTIPOISON(ItemID.SUPERANTIPOISON4, GameTimerImageType.ITEM, "Superantipoison", 346, ChronoUnit.SECONDS), CHARGE(SpriteID.SPELL_CHARGE, GameTimerImageType.SPRITE, "Charge", 6, ChronoUnit.MINUTES), STAFF_OF_THE_DEAD(ItemID.STAFF_OF_THE_DEAD, GameTimerImageType.ITEM, "Staff of the Dead", 1, ChronoUnit.MINUTES), ABYSSAL_SIRE_STUN(ItemID.ABYSSAL_ORPHAN, GameTimerImageType.ITEM, "Abyssal Sire Stun", 30, ChronoUnit.SECONDS, true), @@ -81,17 +73,20 @@ enum GameTimer DIVINE_SUPER_DEFENCE(ItemID.DIVINE_SUPER_DEFENCE_POTION4, GameTimerImageType.ITEM, "Divine Super Defence", 5, ChronoUnit.MINUTES), DIVINE_SUPER_COMBAT(ItemID.DIVINE_SUPER_COMBAT_POTION4, GameTimerImageType.ITEM, "Divine Super Combat", 5, ChronoUnit.MINUTES), DIVINE_RANGING(ItemID.DIVINE_RANGING_POTION4, GameTimerImageType.ITEM, "Divine Ranging", 5, ChronoUnit.MINUTES), - DIVINE_MAGIC(ItemID.DIVINE_MAGIC_POTION4, GameTimerImageType.ITEM, "Divine Magic", 5, ChronoUnit.MINUTES); + DIVINE_MAGIC(ItemID.DIVINE_MAGIC_POTION4, GameTimerImageType.ITEM, "Divine Magic", 5, ChronoUnit.MINUTES), + ANTIPOISON(ItemID.ANTIPOISON4, GameTimerImageType.ITEM, "Antipoison"), + ANTIVENOM(ItemID.ANTIVENOM4, GameTimerImageType.ITEM, "Anti-venom"); + @Nullable private final Duration duration; + @Nullable private final Integer graphicId; private final String description; private final boolean removedOnDeath; - private final Duration initialDelay; private final int imageId; private final GameTimerImageType imageType; - GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit, long delay, boolean removedOnDeath) + GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit, boolean removedOnDeath) { this.description = description; this.graphicId = graphicId; @@ -99,12 +94,6 @@ enum GameTimer this.imageId = imageId; this.imageType = idType; this.removedOnDeath = removedOnDeath; - this.initialDelay = Duration.of(delay, unit); - } - - GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit, boolean removedOnDeath) - { - this(imageId, idType, description, graphicId, time, unit, 0, removedOnDeath); } GameTimer(int imageId, GameTimerImageType idType, String description, long time, ChronoUnit unit, boolean removeOnDeath) @@ -117,13 +106,13 @@ enum GameTimer this(imageId, idType, description, null, time, unit, false); } - GameTimer(int imageId, GameTimerImageType idType, String description, Integer graphicId, long time, ChronoUnit unit) + GameTimer(int imageId, GameTimerImageType idType, String description) { - this(imageId, idType, description, graphicId, time, unit, false); - } - - GameTimer(int imageId, GameTimerImageType idType, String description, long time, ChronoUnit unit, long delay) - { - this(imageId, idType, description, null, time, unit, delay, false); + this.duration = null; + this.graphicId = null; + this.description = description; + this.removedOnDeath = false; + this.imageId = imageId; + this.imageType = idType; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimerTimer.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimerTimer.java index 2a30f1ca9c..8a30de2ade 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimerTimer.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimerTimer.java @@ -25,7 +25,6 @@ package net.runelite.client.plugins.timers; import java.time.Duration; -import java.time.Instant; import java.time.temporal.ChronoUnit; import net.runelite.client.plugins.Plugin; import net.runelite.client.ui.overlay.infobox.InfoBoxPriority; @@ -35,27 +34,13 @@ class TimerTimer extends Timer { private final GameTimer timer; - TimerTimer(GameTimer timer, Plugin plugin) + TimerTimer(GameTimer timer, Duration duration, Plugin plugin) { - super(timer.getDuration().toMillis(), ChronoUnit.MILLIS, null, plugin); + super(duration.toMillis(), ChronoUnit.MILLIS, null, plugin); this.timer = timer; setPriority(InfoBoxPriority.MED); } - @Override - public boolean render() - { - final boolean rendered = super.render(); - - if (rendered) - { - final Duration fromStart = Duration.between(getStartTime(), Instant.now()); - return !fromStart.minus(timer.getInitialDelay()).isNegative(); - } - - return false; - } - public GameTimer getTimer() { return timer; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java index c059587ed7..9b8f4a557b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersConfig.java @@ -44,7 +44,7 @@ public interface TimersConfig extends Config @ConfigItem( keyName = "showAntipoison", name = "Antipoison/Venom timers", - description = "Configures whether timers for Antipoison, Antidote and Antivenom are displayed" + description = "Configures whether timers for poison and venom protection are displayed" ) default boolean showAntiPoison() { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java index 3b6f84823e..fac58b3487 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/timers/TimersPlugin.java @@ -26,6 +26,7 @@ package net.runelite.client.plugins.timers; import com.google.inject.Provides; +import java.time.Duration; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.inject.Inject; @@ -34,6 +35,7 @@ import net.runelite.api.Actor; import net.runelite.api.AnimationID; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; +import net.runelite.api.Constants; import net.runelite.api.EquipmentInventorySlot; import net.runelite.api.GameState; import net.runelite.api.InventoryID; @@ -43,19 +45,19 @@ import net.runelite.api.ItemID; import net.runelite.api.NPC; import net.runelite.api.NpcID; import net.runelite.api.Player; +import net.runelite.api.VarPlayer; import net.runelite.api.Varbits; import net.runelite.api.WorldType; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.AnimationChanged; import net.runelite.api.events.ChatMessage; -import net.runelite.client.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameTick; import net.runelite.api.events.GraphicChanged; import net.runelite.api.events.ItemContainerChanged; -import net.runelite.api.events.PlayerDeath; import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.events.NpcDespawned; +import net.runelite.api.events.PlayerDeath; import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.WidgetHiddenChanged; import net.runelite.api.widgets.Widget; @@ -64,6 +66,7 @@ import net.runelite.api.widgets.WidgetInfo; import static net.runelite.api.widgets.WidgetInfo.PVP_WORLD_SAFE_ZONE; import net.runelite.client.config.ConfigManager; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.game.ItemManager; import net.runelite.client.game.SpriteManager; import net.runelite.client.plugins.Plugin; @@ -82,7 +85,6 @@ public class TimersPlugin extends Plugin { private static final String ANTIFIRE_DRINK_MESSAGE = "You drink some of your antifire potion."; private static final String ANTIFIRE_EXPIRED_MESSAGE = "Your antifire potion has expired."; - private static final String ANTIVENOM_DRINK_MESSAGE = "You drink some of your antivenom potion"; private static final String CANNON_FURNACE_MESSAGE = "You add the furnace."; private static final String CANNON_PICKUP_MESSAGE = "You pick up the cannon. It's really heavy."; private static final String CANNON_REPAIR_MESSAGE = "You repair your cannon, restoring it to working order."; @@ -95,7 +97,6 @@ public class TimersPlugin extends Plugin private static final String IMBUED_HEART_READY_MESSAGE = "Your imbued heart has regained its magical power."; private static final String MAGIC_IMBUE_EXPIRED_MESSAGE = "Your Magic Imbue charge has ended."; private static final String MAGIC_IMBUE_MESSAGE = "You are charged to combine runes!"; - private static final String SANFEW_SERUM_DRINK_MESSAGE = "You drink some of your Sanfew Serum."; private static final String STAFF_OF_THE_DEAD_SPEC_EXPIRED_MESSAGE = "Your protection fades away"; private static final String STAFF_OF_THE_DEAD_SPEC_MESSAGE = "Spirits of deceased evildoers offer you their protection"; private static final String STAMINA_DRINK_MESSAGE = "You drink some of your stamina potion."; @@ -103,7 +104,6 @@ public class TimersPlugin extends Plugin private static final String STAMINA_EXPIRED_MESSAGE = "Your stamina potion has expired."; private static final String SUPER_ANTIFIRE_DRINK_MESSAGE = "You drink some of your super antifire potion"; private static final String SUPER_ANTIFIRE_EXPIRED_MESSAGE = "Your super antifire potion has expired."; - private static final String SUPER_ANTIVENOM_DRINK_MESSAGE = "You drink some of your super antivenom potion"; private static final String KILLED_TELEBLOCK_OPPONENT_TEXT = "Your Tele Block has been removed because you killed "; private static final String PRAYER_ENHANCE_EXPIRED = "Your prayer enhance effect has worn off."; @@ -111,6 +111,8 @@ public class TimersPlugin extends Plugin private static final Pattern FULL_TELEBLOCK_PATTERN = Pattern.compile("A Tele Block spell has been cast on you by (.+)\\. It will expire in 5 minutes\\."); private static final Pattern HALF_TELEBLOCK_PATTERN = Pattern.compile("A Tele Block spell has been cast on you by (.+)\\. It will expire in 2 minutes, 30 seconds\\."); private static final Pattern DIVINE_POTION_PATTERN = Pattern.compile("You drink some of your divine (.+) potion\\."); + private static final int VENOM_VALUE_CUTOFF = -40; // Antivenom < -40 <= Antipoison < 0 + private static final int POISON_TICK_LENGTH = 30; private TimerTimer freezeTimer; private int freezeTime = -1; // time frozen, in game ticks @@ -119,6 +121,8 @@ public class TimersPlugin extends Plugin private int lastWildernessVarb; private int lastVengCooldownVarb; private int lastIsVengeancedVarb; + private int lastPoisonVarp; + private int nextPoisonTick; private WorldPoint lastPoint; private TeleportWidget lastTeleportClicked; private int lastAnimation; @@ -156,6 +160,8 @@ public class TimersPlugin extends Plugin lastAnimation = -1; loggedInRace = false; widgetHiddenChangedOnPvpWorld = false; + lastPoisonVarp = 0; + nextPoisonTick = 0; } @Subscribe @@ -164,6 +170,7 @@ public class TimersPlugin extends Plugin int raidVarb = client.getVar(Varbits.IN_RAID); int vengCooldownVarb = client.getVar(Varbits.VENGEANCE_COOLDOWN); int isVengeancedVarb = client.getVar(Varbits.VENGEANCE_ACTIVE); + int poisonVarp = client.getVar(VarPlayer.POISON); if (lastRaidVarb != raidVarb) { @@ -215,6 +222,36 @@ public class TimersPlugin extends Plugin lastWildernessVarb = inWilderness; } + + if (lastPoisonVarp != poisonVarp && config.showAntiPoison()) + { + final int tickCount = client.getTickCount(); + + if (nextPoisonTick - tickCount <= 0 || lastPoisonVarp == 0) + { + nextPoisonTick = tickCount + POISON_TICK_LENGTH; + } + + if (poisonVarp >= 0) + { + removeGameTimer(ANTIPOISON); + removeGameTimer(ANTIVENOM); + } + else if (poisonVarp >= VENOM_VALUE_CUTOFF) + { + Duration duration = Duration.ofMillis((long) Constants.GAME_TICK_LENGTH * (nextPoisonTick - tickCount + Math.abs((poisonVarp + 1) * POISON_TICK_LENGTH))); + removeGameTimer(ANTIVENOM); + createGameTimer(ANTIPOISON, duration); + } + else + { + Duration duration = Duration.ofMillis((long) Constants.GAME_TICK_LENGTH * (nextPoisonTick - tickCount + Math.abs((poisonVarp + 1 - VENOM_VALUE_CUTOFF) * POISON_TICK_LENGTH))); + removeGameTimer(ANTIPOISON); + createGameTimer(ANTIVENOM, duration); + } + + lastPoisonVarp = poisonVarp; + } } @Subscribe @@ -237,17 +274,6 @@ public class TimersPlugin extends Plugin removeGameTimer(MINIGAME_TELEPORT); } - if (!config.showAntiPoison()) - { - removeGameTimer(ANTIDOTEPLUS); - removeGameTimer(ANTIDOTEPLUSPLUS); - removeGameTimer(SANFEW); - removeGameTimer(ANTIVENOM); - removeGameTimer(ANTIVENOMPLUS); - removeGameTimer(ANTIVENOM_ANTIPOISON); - removeGameTimer(ANTIVENOMPLUS_ANTIPOSION); - } - if (!config.showAntiFire()) { removeGameTimer(ANTIFIRE); @@ -331,63 +357,17 @@ public class TimersPlugin extends Plugin removeGameTimer(ICEBLITZ); removeGameTimer(ICEBARRAGE); } + + if (!config.showAntiPoison()) + { + removeGameTimer(ANTIPOISON); + removeGameTimer(ANTIVENOM); + } } @Subscribe public void onMenuOptionClicked(MenuOptionClicked event) { - if (config.showAntiPoison() - && event.getMenuOption().contains("Drink") - && (event.getId() == ItemID.ANTIDOTE1_5958 - || event.getId() == ItemID.ANTIDOTE2_5956 - || event.getId() == ItemID.ANTIDOTE3_5954 - || event.getId() == ItemID.ANTIDOTE4_5952)) - { - // Needs menu option hook because drink message is intercepting with antipoison message - createGameTimer(ANTIDOTEPLUSPLUS); - return; - } - - if (config.showAntiPoison() - && event.getMenuOption().contains("Drink") - && (event.getId() == ItemID.ANTIDOTE1 - || event.getId() == ItemID.ANTIDOTE2 - || event.getId() == ItemID.ANTIDOTE3 - || event.getId() == ItemID.ANTIDOTE4 - || event.getId() == ItemID.ANTIDOTE_MIX1 - || event.getId() == ItemID.ANTIDOTE_MIX2)) - { - // Needs menu option hook because drink message is intercepting with antipoison message - createGameTimer(ANTIDOTEPLUS); - return; - } - - if (config.showAntiPoison() - && event.getMenuOption().contains("Drink") - && (event.getId() == ItemID.ANTIPOISON1 - || event.getId() == ItemID.ANTIPOISON2 - || event.getId() == ItemID.ANTIPOISON3 - || event.getId() == ItemID.ANTIPOISON4 - || event.getId() == ItemID.ANTIPOISON_MIX1 - || event.getId() == ItemID.ANTIPOISON_MIX2)) - { - createGameTimer(ANTIPOISON); - return; - } - - if (config.showAntiPoison() - && event.getMenuOption().contains("Drink") - && (event.getId() == ItemID.SUPERANTIPOISON1 - || event.getId() == ItemID.SUPERANTIPOISON2 - || event.getId() == ItemID.SUPERANTIPOISON3 - || event.getId() == ItemID.SUPERANTIPOISON4 - || event.getId() == ItemID.ANTIPOISON_SUPERMIX1 - || event.getId() == ItemID.ANTIPOISON_SUPERMIX2)) - { - createGameTimer(SUPERANTIPOISON); - return; - } - if (config.showStamina() && event.getMenuOption().contains("Drink") && (event.getId() == ItemID.STAMINA_MIX1 @@ -517,12 +497,6 @@ public class TimersPlugin extends Plugin removeGameTimer(CANNON); } - if (config.showAntiPoison() && event.getMessage().contains(SUPER_ANTIVENOM_DRINK_MESSAGE)) - { - createGameTimer(ANTIVENOMPLUS); - createGameTimer(ANTIVENOMPLUS_ANTIPOSION); - } - if (config.showMagicImbue() && event.getMessage().equals(MAGIC_IMBUE_MESSAGE)) { createGameTimer(MAGICIMBUE); @@ -575,17 +549,6 @@ public class TimersPlugin extends Plugin removeGameTimer(IMBUEDHEART); } - if (config.showAntiPoison() && event.getMessage().contains(ANTIVENOM_DRINK_MESSAGE)) - { - createGameTimer(ANTIVENOM); - createGameTimer(ANTIVENOM_ANTIPOISON); - } - - if (config.showAntiPoison() && event.getMessage().contains(SANFEW_SERUM_DRINK_MESSAGE)) - { - createGameTimer(SANFEW); - } - if (config.showPrayerEnhance() && event.getMessage().startsWith("You drink some of your") && event.getMessage().contains("prayer enhance")) { createGameTimer(PRAYER_ENHANCE); @@ -893,10 +856,19 @@ public class TimersPlugin extends Plugin } private TimerTimer createGameTimer(final GameTimer timer) + { + if (timer.getDuration() == null) + { + throw new IllegalArgumentException("Timer with no duration"); + } + return createGameTimer(timer, timer.getDuration()); + } + + private TimerTimer createGameTimer(final GameTimer timer, Duration duration) { removeGameTimer(timer); - TimerTimer t = new TimerTimer(timer, this); + TimerTimer t = new TimerTimer(timer, duration, this); switch (timer.getImageType()) { case SPRITE: