Jump to content

Loading

From OpenBOR
Revision as of 21:01, 20 August 2026 by Dcurrent (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


Loading is a global script event that executes while OpenBOR prepares and repaints a loading display. Creators enable the hook by placing loading.c in data/scripts.

The event receives the current progress value and its corresponding maximum. This makes it useful for branded loading presentation, custom progress indicators, rotating hints, diagnostic information, animated decoration, and other project-wide behavior that should appear while models or levels are being prepared.

loading.c executes before OpenBOR adds the configured native loading bar and text to the display queue. Script drawing can therefore compose with the native loading screen during the same repaint.

Usage

Create the following file in the project:

data/scripts/loading.c

The file uses a standard main() entry point:

void main()
{
    // Build or update loading presentation here.
}

OpenBOR loads and compiles loading.c with the other global scripts. No model or level command attaches it. The same script handles eligible loading repaints throughout the project.

The loading script is available before ordinary models are loaded, and level-loading calls occur before the incoming level is fully constructed. Systems used by loading.c should therefore remain independent of the model or level currently being prepared. General drawing resources, project state, and assets loaded specifically for the loading interface remain available across these phases.

Automatic Variables

OpenBOR provides the following local variables before each execution:

Variable Type Description
value Integer Current progress value. The unit depends on the loading phase. Value -1 identifies an initialization repaint.
max Integer Maximum value for the current loading phase. Divide value by max to obtain normalized progress when value is nonnegative and max is greater than zero.

The raw values are progress measurements rather than percentages. Their units vary according to what OpenBOR is loading.

Loading Phases

Phase value max Notes
Initialization repaint -1 1 Forces the loading display to initialize before ordinary progress updates. The script receives the negative value before native loading code normalizes it.
Model loading Number of models loaded so far Total number of models selected for loading Count-based progress used while OpenBOR prepares cached models.
Level loading Current parser position in the level file Total level-file size File-position progress used while OpenBOR reads and constructs the level.

More than one initialization repaint may occur during a session. Model loading, ordinary level loading, and a level-specific loading-background change can each initialize their applicable presentation. Treat value < 0 as the beginning of the current loading-display phase rather than a one-time engine-start event.

Normalized progress is the portable interpretation across phases:

void main()
{
    float progress = 0.0;

    if (value >= 0 && max > 0)
    {
        progress = value;
        progress /= max;
    }

    // progress now ranges from 0.0 to 1.0 during ordinary loading.
}

Execution and Drawing Order

Each eligible loading repaint follows this sequence:

  1. OpenBOR clears the sprite queue used for the loading display.
  2. OpenBOR assigns value and max, then executes data/scripts/loading.c.
  3. The configured native loading bar is added when its loading-screen type includes a bar.
  4. Native Loading... text is added when a loading-screen type is enabled.
  5. The configured loading background is copied or the working screen is cleared when the type includes a background.
  6. OpenBOR draws the completed sprite queue, presents the screen, and clears the queue.

Drawing functions such as drawstring(), drawbox(), drawline(), drawsprite(), and drawscreen() append content to the loading display queue. Their output is available for the same repaint.

Queue sorting still follows the Z and sorting values supplied to each drawing function. Native elements being queued after the script does not automatically place them above script content. Creators can select appropriate Z values to position custom elements behind, among, or above the native loading presentation.

Loading Screen Configuration

The loading event and native loading-screen configuration work together. Level-order commands loadingbg and loadingbg2 configure the presentation used for model loading and level loading respectively:

loadingbg  {type} {bar_x} {bar_y} {bar_size} {text_x} {text_y} {font} {refresh_ms}
loadingbg2 {type} {bar_x} {bar_y} {bar_size} {text_x} {text_y} {font} {refresh_ms}

Loading-screen types are:

Value Presentation
0 No configured loading screen
1 Background and native progress bar
2 Background without the native progress bar
3 Native progress bar without the configured background

Any enabled type also adds the native Loading... text. The background image is data/bgs/loading for loadingbg and data/bgs/loading2 for loadingbg2, subject to the project's custom background path.

Individual level files may use their own loadingbg command to replace the second loading presentation while that level is being parsed. The global loading.c script remains the active event hook and automatically composes with whichever loading configuration is current.

Enabling a loading-screen type also enables repeated queue drawing and screen presentation for progress updates. With type 0, OpenBOR presents only the initial fallback loading repaint. The hook can still execute on eligible progress updates, though queued script drawing from those later calls is not presented by the normal loading-display path.

Refresh Frequency

loading.c executes when the loading display reaches its configured repaint interval. The refresh_ms argument controls this interval in milliseconds. Supplying 0 selects the default interval of 100 milliseconds.

OpenBOR forces a repaint for initialization and completion regardless of the interval:

  • value < 0 forces an initialization repaint.
  • value == max forces the completed-state repaint.

Intermediate progress updates are time-limited. Rapidly loaded models or level-file lines may therefore advance value several times between script executions. Logic should use the supplied current values instead of assuming that every intermediate value will be observed.

Loading repaints use host-time milliseconds, not gameplay ticks or the regular update loop. Animation or cycling effects may use an appropriate real-time source when their timing must remain independent of loading speed.

Example: Custom Progress Bar

This example converts either count-based or file-position progress into a 240-pixel bar:

void main()
{
    int track_width = 240;
    int filled_width = 0;
    int track_color = rgbcolor(24, 24, 24);
    int fill_color = rgbcolor(232, 176, 48);
    float progress = 0.0;

    if (value >= 0 && max > 0)
    {
        progress = value;
        progress /= max;
        filled_width = progress * track_width;
    }

    drawbox(20, 224, track_width, 8, 1000000, track_color);

    if (filled_width > 0)
    {
        drawbox(20, 224, filled_width, 8, 1000001, fill_color);
    }
}

The same calculation works during model and level loading because it uses the ratio between value and max instead of assuming a particular raw unit.

Example: Phase-Aware Message

This example changes the displayed message for initialization, active progress, and completion:

void main()
{
    if (value < 0)
    {
        drawstring(16, 204, 0, "PREPARING RESOURCES", 1000000);
    }
    else if (value >= max)
    {
        drawstring(16, 204, 0, "READY", 1000000);
    }
    else
    {
        drawstring(16, 204, 0, "LOADING", 1000000);
    }
}

Creators can extend the same pattern with rotating hints, current chapter information, control reminders, or visual transitions without building a full loading-screen walkthrough into the event script.

Resource Reuse

The script instance persists across loading events. Optional oncreate() and ondestroy() lifecycle functions are useful for preparing and releasing sprites, screens, arrays, or other resources used by the loading interface.

Loading reusable assets once allows each main() execution to focus on progress calculation and queue construction. This is especially effective for elaborate interfaces containing animated decorations, logos, tips, multiple layers, or subscreen composition.

Other Uses

Quick applications include:

  • Project branding - Display logos, title treatments, chapter art, or a consistent visual identity during all loading phases.
  • Progress visualization - Build bars, rings, segmented meters, numeric percentages, model counters, or other custom indicators.
  • Loading hints - Rotate controls, mechanics, character information, objectives, lore, or contextual advice.
  • Animated presentation - Move decorations, cycle sprites, pulse colors, or composite subscreens at the configured repaint cadence.
  • Phase feedback - Distinguish preparation, active loading, and completion using the negative initialization value and normalized progress.
  • Diagnostics - Expose raw progress values, verify loading phases, measure presentation timing, or confirm that a loading configuration is active.
  • Audio coordination - Synchronize loading presentation with project audio or the optional native loading-music behavior.
Script Relationship
level.c Global event executed after a level has finished loading and is ready to begin.
levelscript Level-specific start event executed after the level has been constructed.
update.c Global recurring gameplay update hook. It does not drive loading-display repaint frequency.
updated.c Global late-cycle gameplay and presentation hook. Loading uses its own separate repaint path.

See Also