Jump to content

Level Scripts

From OpenBOR


levelscript is a level-start event hook. OpenBOR provides two forms: the automatic project-wide data/scripts/level.c script and a levelscript declared by an individual level. Both execute once after the level is loaded and active players are spawned, but before normal level updates begin.

This timing makes level scripts ideal for establishing the initial state of a stage. Common uses include resetting counters, preparing objectives, configuring shared systems, setting level-specific rules, initializing player state, and spawning controller entities.

Forms

Form Scope Setup Execution order
Global level script Every level in the project Create data/scripts/level.c First
Level-specific script Level containing the command Add levelscript to the level definition Second

Both forms use a main() entry point and receive no automatic event variables.

Global Level Script

OpenBOR automatically loads data/scripts/level.c when the file is present. No command is required in a level definition.

void main()
{
    // Perform project-wide level initialization here.
}

The global script executes at the start of every level. Use it for initialization that should be consistent throughout the project, such as clearing stage statistics, preparing common HUD logic, resetting shared objectives, or activating a universal level controller.

Level-Specific Script

Add levelscript to a level definition and provide the path to the script file:

levelscript data/scripts/levels/storm_docks_start.c

The referenced script uses the same entry point as the global form:

void main()
{
    // Perform initialization for this level here.
}

The level-specific script executes only when OpenBOR starts the level containing the command. It is well suited to objectives, environmental rules, encounter controllers, scripted introductions, alternate HUD modes, or other setup unique to that level.

Only one levelscript command is available to a level. Multiple initialization tasks may be organized into functions and called from the script's main() when needed.

Execution

The relevant level-start sequence is:

  1. OpenBOR loads and configures the level.
  2. OpenBOR resets the new level's immediate runtime state.
  3. Active players with remaining lives are spawned.
  4. data/scripts/level.c executes when present.
  5. The level-specific levelscript executes when declared.
  6. OpenBOR enters the normal update loop.

Level data and active player entities are therefore available to both scripts. Ordinary level progression and the first normal update cycle have not yet begun.

The level-specific script executes after the global script, so it can build on or override state established by level.c. This ordering supports a useful division of responsibility: define project defaults globally, then specialize them for the current level.

Level scripts are start events, not recurring updates. Logic that must run continuously belongs in an update script, an entity script, or another appropriate event hook.

Example: Shared and Level-Specific Setup

The following data/scripts/level.c resets several values used throughout a project whenever a level begins:

void main()
{
    setglobalvar("stage_hit_count", 0);
    setglobalvar("stage_damage_total", 0);
    setglobalvar("stage_objective_complete", 0);
}

An individual level can then define its own objective and environmental profile:

levelscript data/scripts/levels/storm_docks_start.c
void main()
{
    setglobalvar("stage_objective", "protect_convoy");
    setglobalvar("stage_weather", "storm");
    setglobalvar("stage_reinforcement_limit", 3);
}

Recurring scripts, HUD logic, spawn scripts, and model scripts may read these values later. The example is intentionally compact - the same arrangement can initialize far more elaborate objective managers, branching encounters, weather controllers, scoring rules, or cinematic systems.

Example: Preparing Active Players

Active player entities already exist when the event runs. This allows a global level script to mark or configure them before the first ordinary update:

void main()
{
    int player;
    int player_count = openborvariant("maxplayers");

    for (player = 0; player < player_count; player++)
    {
        void entity = getplayerproperty(player, "entity");

        if (entity)
        {
            setentityvar(entity, "stage_ready", 1);
        }
    }
}

Other systems can consume stage_ready to begin entrance behavior, apply level-specific equipment, initialize challenge conditions, or coordinate multiplayer presentation. Keeping the start hook focused on setup allows the ongoing behavior to remain in the scripts designed to update it.

Other Uses

Quick applications include:

  • Objective setup - Establish targets, timers, counters, failure conditions, escort data, or challenge rules.
  • System reset - Clear per-stage statistics, temporary resources, encounter flags, or branching state.
  • Player preparation - Apply stage-specific status, equipment, positioning rules, interface modes, or cooperative roles.
  • Environment control - Initialize weather, lighting, palette, camera, audio, or hazard controllers.
  • Encounter management - Spawn or configure invisible controller entities that coordinate complex sequences.
  • Presentation - Prepare introductions, title cards, dialogue systems, custom HUD elements, or cinematic logic.
  • Project defaults - Use level.c to establish a common baseline, then let individual levels replace only the values they need.
Script Relationship
data/scripts/level.c Global start hook that executes first for every level.
levelscript Level-specific start hook that executes after the global hook.
update and updated scripts Recurring global or level hooks used during normal gameplay updates.
spawnscript Executes for an individual spawn entry when that entry creates an entity.
onspawnscript Executes from the spawned entity's model after the entity enters play.
endlevelscript Executes when the level finishes, before fade-out and level unloading.

See Also