common scheduling patterns
one time delayed action
@Katton.command(name = "warnandtp", permission = "admin")
function warnandtp(sender, args) {
for (player in Katton.players.all()) {
player.sendMessage("&cgame ending in 5 seconds!")
}
Katton.after(5.seconds) {
for (player in Katton.players.all()) {
player.teleport(spawnLocation)
}
}
}
no ID needed here since nothing ever needs to cancel it early
toggleable repeating task (start/stop commands)
var reminderTaskId = 0
var reminderRunning = false
@Katton.command(name = "startreminders", permission = "admin")
function startReminders(sender, args) {
if (reminderRunning) {
sender.sendMessage("&ealready running")
return
}
reminderRunning = true
reminderTaskId = Katton.every(30.seconds) {
for (player in Katton.players.all()) {
player.sendMessage("&7reminder: PVP turns on at 5 minutes!")
}
}
}
@Katton.command(name = "stopreminders", permission = "admin")
function stopReminders(sender, args) {
if (!reminderRunning) {
sender.sendMessage("&enot running")
return
}
reminderRunning = false
Katton.cancel(reminderTaskId)
}
notice the if (reminderRunning) { return } guard at the top of the start command. this stops a player from accidentally starting the same repeating task twice (which would leave the old one still running, uncancellable, since you would have overwritten reminderTaskId with the new one)
self cancelling countdown
covered in depth on Katton.after and Katton.every and countdown timer, the short version:
var count = 5
var taskId = 0
taskId = Katton.every(1.seconds) {
if (count <= 0) {
Katton.cancel(taskId)
return
}
Katton.log.info("" + count)
count = count - 1
}
chained delays with a shrinking interval
instead of Katton.every with a fixed interval, sometimes you want each "round" to be faster than the last. do this by having a function schedule its own next call with Katton.after, using a variable delay:
var roundDelay = 5.0
function nextRound() {
Katton.log.info("round! delay was " + roundDelay)
Katton.after(roundDelay.seconds) {
roundDelay = Math.max(1, roundDelay - 0.25)
nextRound()
}
}
each call to nextRound() schedules exactly one future call to itself, roundDelay seconds later, and then shrinks roundDelay (but never below 1 second) before doing it again, see the full color switch minigame example for this exact pattern used in a real minigame, including how it's stopped with a gameRunning flag instead of Katton.cancel (since there's no single repeating task ID to cancel since each round schedules a fresh task)
stopping a chain (no single task ID exists)
when you use the "chain of Katton.after calls" pattern above, there's no single Katton.every ID to cancel. every round creates a brand new one time task. instead, use a boolean flag that the chain checks before continuing:
var gameRunning = false
function nextRound() {
if (!gameRunning) {
return // the flag was turned off so stop the chain here
}
doRoundStuff()
Katton.after(2.seconds) {
if (!gameRunning) {
return
}
nextRound()
}
}
@Katton.command(name = "stopgame", permission = "admin")
function stopGame(sender, args) {
gameRunning = false // the NEXT scheduled check will see this and stop the chain
}
this is why both the scheduling call and its callback check gameRunning. the flag can flip to false while a delay is already happening so the check has to happen again right before continuing the chain