Timers - GregHib/void GitHub Wiki
Timers count down every X number of ticks; where X is an interval
specified on the start of the Timer.
Timers are used in situations where something must occur at the start, during or end of the countdown, otherwise a Clock is better suited.
There are two types of Timers:
Timer type | Applies to | Stops counting down |
---|---|---|
Soft | Player, NPC | Never |
Regular | Player | When busy (delayed or interface open) |
Warning
NPC's are limited to one soft timer at a time, Player's have no such limits.
A basic timer is composed of three parts: start, tick & stop.
Start is the only part required as every timer must have an interval
.
timerStart("skull") { player: Player ->
// A skull lasts 1000 ticks / 10 minutes
interval = 1000
// Display a skull over the players head
player.appearance.skull = player["skull", 0]
player.flagAppearance()
}
timerStop("skull") { player: Player ->
// When the timer stops remove the skull sprite from above the players head
player.appearance.skull = -1
player.flagAppearance()
}
// A player is marked as skulled when they attack a new player in the wilderness
combatSwing { player: Player ->
if (player.inWilderness && target is Player && player.isNewTarget(target)) {
// Start the skull timer
player.softTimers.start("skull")
}
}
In this example a player starts an overload
timer which boosts their levels every 15 seconds for 5 minutes in exchange for 500 hitpoints which are returned after the effect wears off.
// Start
timerStart("overload") { player: Player ->
interval = 25 // Every 25 ticks / 15 seconds
// Deal 5 hits of 100
player.queue(name = "overload_hits") {
repeat(5) {
player.directHit(100)
player.setAnimation("overload")
player.setGraphic("overload")
pause(2)
}
}
}
// Every 25 ticks
timerTick("overload") { player: Player ->
// Cancel if 5 minutes are up.
if (player.dec("overload_refreshes_remaining") <= 0) {
cancel()
return@timerTick
}
// Restore boosted levels every 25 ticks
player.levels.boost(Skill.Attack, 5, 0.22)
player.levels.boost(Skill.Strength, 5, 0.22)
player.levels.boost(Skill.Defence, 5, 0.22)
player.levels.boost(Skill.Magic, 7)
player.levels.boost(Skill.Ranged, 4, 0.1923)
}
// Stop
timerStop("overload") { player: Player ->
// Tell the player the overload has worn off
player.message("<dark_red>The effects of overload have worn off and you feel normal again.")
// Restore the players levels to normal and return the hitpoints.
player.levels.restore(Skill.Constitution, 500)
player.levels.clear(Skill.Attack)
player.levels.clear(Skill.Strength)
player.levels.clear(Skill.Defence)
player.levels.clear(Skill.Magic)
player.levels.clear(Skill.Ranged)
}
It can be triggered using timers.start()
// When an overload potion is consumed
consume("overload_#") { player: Player ->
player.timers.start("overload") // Start the overload timer
player["overload_refreshes_remaining"] = 20 // Repeat for 5 minutes
}
Note
As the overload effect is a regular timer it's effects can be prolonged by keeping a menu open when not in combat. This also applies to other effects such as poison.
If a timer should persist after a player logs out, it must be restarted once they log back in
playerSpawn { player: Player ->
if (player["overload_refreshes_remaining", 0] > 0) {
player.timers.restart("overload")
}
}
This will call timerStart
again, but the restart
allows code that should only be executed on the initial start to do so.
timerStart("overload") { player: Player ->
interval = 25
if (restart) {
return@timerStart // If restarted don't deal damage again.
}
player.queue(name = "overload_hits") {
// ...
}
}
You can check if a timer is currently active using the contains(name)
method.
if (player.timers.contains("overload")) {
player.message("You may only use this potion every five minutes.")
return
}