Control flow
CompilesCode runs top to bottom unless you tell it otherwise. Control flow is how you tell it otherwise.
if and else
Section titled “if and else”let health: int = 40if health <= 0 { $debug.print_line("knocked out", null, false)} else if health < 50 { $debug.print_line("hurt", null, false)} else { $debug.print_line("fine", null, false)}The condition needs no parentheses. The braces are always required, even around one line.
Leaving early with return
Section titled “Leaving early with return”return ends the function immediately. Returning at the top when there’s nothing to do (a guard clause)
keeps the rest of the function about the normal case:
event export fn created() { let child: Entity = $entity.get_child_named("fx", true, $entity.get()) if child { let fx: Component = $support.entity_get_component(child, "effect.vscript") if fx { $component.queue_event("play", fx, null, false) } }}event export fn created() { let child: Entity = $entity.get_child_named("fx", true, $entity.get()) if !child { return } let fx: Component = $support.entity_get_component(child, "effect.vscript") if !fx { return } $component.queue_event("play", fx, null, false)}Both work. The right one reads as a list of reasons to stop, followed by the thing it does.
switch
Section titled “switch”switch picks one branch by comparing a value against several. _ catches everything else:
let round: int = 2switch round { 1 => { $debug.print_line("first round", null, false) } 2 => { $debug.print_line("second round", null, false) } _ => { $debug.print_line("later round", null, false) }}Each branch needs its braces. Only the matching branch runs; there’s no falling through to the next one.
for: counting
Section titled “for: counting”for repeats a block once for each number in a range:
for i in 0..3 { $debug.print_line("i is {}", [i], false) // 0, 1, 2}0..3 counts 0, 1, 2: up to but not including 3. Use ..= to include the end, and step to count in larger
jumps:
for i in 1..=3 { $debug.print_line("{}", [i], false) // 1, 2, 3}for i in 0..10 step 5 { $debug.print_line("{}", [i], false) // 0, 5}The most common use is walking through a list by position:
let names: list = ["plaza", "garage", "roof"]for i in 0..names.len() { let name: string = names.get(i) $debug.print_line("{}: {}", [i, name], false)}while: repeating until done
Section titled “while: repeating until done”while repeats as long as its condition is true:
let mut at: Entity = $entity.get()while at { $debug.print_line("{}", [$entity.get_name(at)], false) at = $entity.get_parent(at)}This climbs from the script’s entity to the top of the hierarchy, printing each name. Make sure something in the loop eventually makes the condition false. A loop that never ends freezes the game.
break and continue
Section titled “break and continue”Inside for or while, break leaves the loop and continue skips to the next time round:
for i in 0..10 { if i == 2 { continue // skip 2 } if i == 5 { break // stop at 5 } $debug.print_line("{}", [i], false) // 0, 1, 3, 4}For programmers
for i in a..b step n is the only for; a and b are expressions, n an integer literal. switch arms take
any expression as the pattern and compare with equality; no ranges, guards or bindings. Everything is a
statement except if … else … used as a value.