Potion Timer
AdvancedDisplayTracks potion effects and displays remaining time. Shows how to monitor stat changes and calculate durations.
20 min read
What It Does
Tracks potion effects and displays remaining time. Shows how to monitor stat changes and calculate durations.
Source Code
java
1package com.example;
2
3import net.runelite.api.Client;
4import net.runelite.api.Skill;
5import net.runelite.api.events.StatChanged;
6import net.runelite.client.eventbus.Subscribe;
7import net.runelite.client.plugins.Plugin;
8import net.runelite.client.plugins.PluginDescriptor;
9import net.runelite.client.ui.overlay.Overlay;
10import net.runelite.client.ui.overlay.OverlayManager;
11import javax.inject.Inject;
12import java.awt.*;
13import java.util.HashMap;
14import java.util.Map;
15
16@PluginDescriptor(
17 name = "Potion Timer",
18 description = "Tracks potion effects"
19)
20public class PotionTimerPlugin extends Plugin {
21 @Inject
22 private Client client;
23
24 @Inject
25 private OverlayManager overlayManager;
26
27 // Track potion start tick and duration in game ticks
28 private static class PotionInfo {
29 int startTick;
30 int durationTicks; // Duration in game ticks (600 ticks = 60 seconds)
31
32 PotionInfo(int startTick, int durationTicks) {
33 this.startTick = startTick;
34 this.durationTicks = durationTicks;
35 }
36 }
37
38 private Map<Skill, PotionInfo> activePotions = new HashMap<>();
39 private int currentTick = 0;
40
41 @Subscribe
42 public void onGameTick(net.runelite.api.events.GameTick event) {
43 currentTick++;
44
45 // Check for expired potions
46 activePotions.entrySet().removeIf(entry -> {
47 PotionInfo info = entry.getValue();
48 return (currentTick - info.startTick) >= info.durationTicks;
49 });
50 }
51
52 @Subscribe
53 public void onStatChanged(StatChanged event) {
54 Skill skill = event.getSkill();
55 int boosted = client.getBoostedSkillLevel(skill);
56 int real = client.getRealSkillLevel(skill);
57
58 if (boosted > real && !activePotions.containsKey(skill)) {
59 // Potion just activated - track start tick
60 // Most potions last 60 seconds = 600 game ticks
61 activePotions.put(skill, new PotionInfo(currentTick, 600));
62 } else if (boosted <= real) {
63 // Potion expired
64 activePotions.remove(skill);
65 }
66 }
67
68 private final Overlay overlay = new Overlay() {
69 @Override
70 public Dimension render(Graphics2D graphics) {
71 graphics.setColor(Color.WHITE);
72 int y = 20;
73
74 for (Map.Entry<Skill, PotionInfo> entry : activePotions.entrySet()) {
75 PotionInfo info = entry.getValue();
76 int elapsedTicks = currentTick - info.startTick;
77 int remainingTicks = info.durationTicks - elapsedTicks;
78 int remainingSeconds = remainingTicks / 10; // Convert ticks to seconds
79
80 graphics.drawString(
81 entry.getKey().getName() + ": " + remainingSeconds + "s",
82 10, y
83 );
84 y += 15;
85 }
86
87 return new Dimension(150, y);
88 }
89 };
90
91 @Override
92 protected void startUp() {
93 overlayManager.add(overlay);
94 }
95
96 @Override
97 protected void shutDown() {
98 overlayManager.remove(overlay);
99 }
100}Code Annotations
Line 24
Map to track potion start times
Line 28
Detect when boost starts
Line 35
Calculate remaining time
API Classes Used
Key Concepts
- •Map to track potion start times
- •Detect when boost starts
- •Calculate remaining time
Next Steps
- Learn about potion durations
- Add different potion types
- Add expiration warnings