HyperScript
Docs

← All of the Docs The basics

Loops

Guide and examples
loop 3 times:
    send "Hello!"

for each {_name} in sorted server.players:
    send "&7 - &f%{_name}%"

loop all players: runs its block once for every player who is online:

loop all players:
    add 10 to {%loop-player%.coins}
    send "&a%player.name% gave you 10 coins!" to loop-player

Inside any loop, loop-value is what the loop is on: the number of the round, the element of the list, the player.

loop 3 times:
    send "&7Round %loop-value%"

loop from 10 to 1:
    send "&e%loop-value%..."
    wait 1 second
send "&aGo!"

loop from 0 to 100 by 25:
    send "&7%loop-value%%"

loop {queue}:
    send "&7%loop-index%. &f%loop-value%"

In a loop inside a loop the values are numbered from the outside in: loop-value-1 belongs to the first loop, loop-value-2 to the one inside it.

loop from 1 to 3:
    loop from 1 to 3:
        send "&7%loop-value-1% x %loop-value-2% = &f%loop-value-1 * loop-value-2%"

A loop can take some of what it goes through only, and say what to do when there was nothing:

loop all players with permission "staff.alerts":
    send "&c%player.name% needs help." to loop-player
else:
    send "&7No staff are online."

loop {queue} where loop-value is not player.name:
    send "&7%loop-index%. &f%loop-value%"

loop blocks within 3 blocks of player:
    if block at loop-value is "fire":
        set block at loop-value to air

A counter, and a table's names and values:

loop 5 times with {_i}:
    send "&7Round %{_i}%"

for each {_name}, {_place} in {warp}:
    send "&b%{_name}% &7is at %{_place}%"

break and continue steer a loop from inside:

for each {_name} in {queue}:
    if {_name} is "Steve":
        continue
    if size of {_picked} >= 3:
        break
    append {_name} to {_picked}

A while loop repeats for as long as its condition holds:

set {_n} to 3
while {_n} > 0:
    send "&e%{_n}%..."
    wait 1 second
    subtract 1 from {_n}
send "&aGo!"
  • loop <n> times: repeats its block. To protect the server it refuses more than 100,000 (loop-limit in config.yml changes that) repetitions.
  • for each {_item} in <list>: runs its block once per element, with the element in the local.
  • loop <n> times with {_i}: puts the number of the round, from 1, in the local.
  • loop from <a> to <b>: counts from the one number to the other, both included, and loop-value is the number: loop from 1 to 5 is 1, 2, 3, 4, 5 and loop from 5 to 1 is 5, 4, 3, 2, 1. by <n> is how far apart the numbers are: loop from 0 to 10 by 5 is 0, 5, 10, and loop from 0 to 1 by 0.25 works as well. Which way it counts is said by the two ends, so by is never negative, and it stops at the last number that does not pass the end: loop from 10 to 0 by 3 is 10, 7, 4, 1. The same limit as for loop <n> times applies.
  • loop <list>: goes through a list without a local to name: loop {queue}:, loop sorted server.players:. The element is loop-value. Given a number it goes round that many times, so loop {_n}: is loop {_n} times:.
  • loop-value is what the loop around the line is on. In loop <n> times and while that is the number of the round; in loop from the number; in for each and loop <list> the element (with for each {_key}, {_value} the value); in loop all players the player, like loop-player; in countdown the seconds left; in repeat the round. In text it is %loop-value%, and it can be written loop_value.
  • loop-index is which round the loop is on, from 1, whatever the loop goes through: "%loop-index%. %loop-value%" numbers a list.
  • In a loop inside a loop, loop-value-1 is the value of the outermost loop, loop-value-2 of the loop inside it, and so on; loop-index-1, loop-index-2 likewise. The plain loop-value is always the innermost loop's, the one the line is directly in. A number that no loop has (loop-value-3 inside two loops) is refused when the script loads, and so is loop-value outside a loop. To subtract from it, leave a space: loop-value - 1.
  • for each {_key}, {_value} in {table}: goes through every name under a table and the value stored there, for saved tables ({warp}, {%player%.homes}) and local ones ({_data}) alike.
  • repeat every <time> for <time>: runs its block, waits, and runs it again until the time is up; see Waiting.
  • countdown 10 seconds: is a repeat that counts: its block runs once a second and seconds left is 10, then 9, down to 1. The lines after the block run when it has reached the end, so they are where "Go!" belongs. break ends it early.
  • once every 5 seconds for player: runs its block at most that often for each player, which is a cooldown around any lines you like; else: under it is where "wait a moment" goes. It can also be written at most once every 5 seconds for player:.
  • once for player: runs its block the first time a player gets there and never again; once per day for player: once in each day by the server's calendar, so a reward taken at 23:59 can be taken again at 00:00. Put a name after once (once "daily" per day for player:) if the block may be moved or changed later: without one HyperScript tells the once blocks of a script apart by what they say, and one that is rewritten counts as new. else: works as after if.
  • loop all players: goes through whoever is online when it starts. Inside it, loop-player (in text, %loop-player%) is the name of the player the loop is on (it can also be written loop player or loop_player, which are the same word), and player is still whoever ran the command or caused the event. Everything that takes a player takes loop-player: loop-player's location, health of loop-player, {%loop-player%.coins}, send "..." to loop-player, loop-player has permission "x". loop-number is which round the loop is on, starting at 1; it is the same as loop-index and works in every loop.
  • loop all players takes what says which of them: with permission "<node>", in world "<name>", within <n> blocks of <location>, or where <condition>, in which loop-player is each player in turn: loop all players where health of loop-player < 5:. The same works wherever something is done to all players: send "..." to all players with permission "staff", send title "Go!" to all players in world "arena".
  • loop <list> where <condition>: goes through the elements the condition holds for only; in the condition loop-value is the element. loop-index then counts the ones that were kept.
  • Anything that gives a list can be looped over: loop blocks within 3 blocks of player: and loop blocks from {_a} to {_b}: (each loop-value is the location of a block, so block at loop-value is what is there), loop entities within 10 blocks of player:, loop players within 10 blocks of player:, loop items in inventory of player:. Blocks are counted before the loop starts, and more than loop-limit of them are refused.
  • else: directly under a loop runs when the loop never went round: the list was empty or was never set, nobody was online, the condition of a while did not hold the first time.
  • while <condition>: checks the condition before every round.
  • break loop 1 and continue loop 1 reach a loop further out, by the same numbers as loop-value-1: 1 is the outermost. break loop 1 leaves that loop and every loop inside it; continue loop 1 ends the loops inside it and starts its next round. They take a condition like the plain ones: break loop 1 if {_found} is set.
  • break leaves the loop it is in and carries on after it. continue skips the rest of this round and starts the next. In nested loops both act on the innermost one.
  • stop inside a loop ends the whole trigger, not just the loop.
  • All three take a condition on the same line: stop if {_coins} < 100, continue if loop-player is player.name, break unless {_found} is set. stop with <text> tells the player something first: stop with "&cNot enough coins." if {_coins} < 100.
  • A while loop that goes round 100,000 times (loop-limit in config.yml) without a wait is stopped with an error in the console, so a condition that never becomes false cannot freeze the server. A loop that waits each round may run for as long as you like.