The VScript Book

Chapter 0.5: Repeating Actions with Loops

Sometimes you need to repeat an action multiple times. Imagine you want to spawn 5 explosive barrels. You could write:

printl("Spawning green barrel number 1")
printl("Spawning green barrel number 2")
printl("Spawning green barrel number 3")
printl("Spawning green barrel number 4")
...

This is repetitive and inefficient. What if you needed to spawn 100? This is where loops are essential.

The for Loop

A for loop is perfect when you know exactly how many times you want to repeat an action. It has three parts in its parentheses, separated by semicolons:

  1. Initializer: A temporary counter variable is created (local i = 0). This runs once at the very beginning.
  2. Condition: The loop continues as long as this question is true (i < 5). It's checked before each repetition.
  3. Incrementer: An action to perform after each repetition (i++, which is shorthand for i = i + 1).
// This loop will run 100 times.
for (local i = 0; i < 100; i++) {
    // The code inside these curly braces is the "loop body".
    printl("Spawning green barrel number " + i)
}
printl("All barrels spawned.")

Output:

Spawning green barrel number 0
Spawning green barrel number 1
Spawning green barrel number 2
Spawning green barrel number 3
Spawning green barrel number 4
...
Spawning green barrel number 99
All barrels spawned.

Notice the counter i starts at 0 and goes up to 99. When i becomes 100, the condition 100 < 100 is false, and the loop stops.

The while Loop

A while loop is used when you don't know how many repetitions you need. It repeats as long as a condition remains true. This is great for actions that depend on player behavior or game state.

local playerIsInPoisonGoo = true
local playerHealth = 100

// This loop will continue as long as the player is in the goo.
while (playerIsInPoisonGoo == true) {
    playerHealth -= 0.1 // Damage the player
    printl("Player health is now: " + playerHealth)
    
    // In a real game, another piece of code would set playerIsInPoisonGoo to false.
    // For this example, let's just stop it manually after some damage.
    if (playerHealth <= 70) {
        playerIsInPoisonGoo = false
    }
}
printl("Player has escaped the goo!")

Beware of infinite loops! If the condition in a while loop never becomes false, it will freeze the script's execution, leading to a potential game hang or crash.

A Critical VScript Concept: No "Waiting" in Loops

The poison goo example works because the condition to stop the loop (playerHealth <= 70) is inside the loop itself. It's crucial to understand that VScript code is synchronous—it has a one-track mind and can only do one thing at a time.

While your while loop is running, the entire script execution is paused on that loop. This means you cannot use a while loop to wait for an external event, like a player pressing a button or leaving a trigger zone. The code that checks if the player has left the zone will never get a chance to run!

If you need to wait for a change in game state, use these event-driven patterns instead:
  • Think Functions: To check something at a regular interval.
  • Delayed EntFire calls or logic_timer: To schedule a single action in the future.
  • ActionScheduler: (PCapture-Lib) For complex timed sequences.