End Level Scripts
endlevelscript is a level-finish event hook. OpenBOR provides two forms: the automatic project-wide data/scripts/endlevel.c script and an endlevelscript declared by an individual level. Both execute once after the active level loop ends, while the level and its remaining entities are still loaded, but before fade-out and level unloading.
This timing makes endlevel scripts useful for finalizing stage results, recording statistics, awarding conditional bonuses, committing custom progression, synchronizing player state, and cleaning up shared systems. The event is the closing counterpart to levelscript.
Forms
| Form | Scope | Setup | Execution order |
|---|---|---|---|
| Global endlevel script | Every level in the project | Create data/scripts/endlevel.c
|
First |
| Level-specific endlevel script | Level containing the command | Add endlevelscript to the level definition
|
Second |
Both forms use a main() entry point and receive no automatic event variables.
Global Endlevel Script
OpenBOR automatically loads data/scripts/endlevel.c when the file is present. No command is required in a level definition.
void main()
{
// Perform project-wide level finalization here.
}
The global script executes whenever an active level ends. Use it for finalization shared throughout the project, such as collecting stage statistics, closing objective systems, storing custom player results, or preparing information consumed by later menus and levels.
Level-Specific Endlevel Script
Add endlevelscript to a level definition and provide the path to the script file:
endlevelscript data/scripts/levels/storm_docks_end.c
The referenced script uses the same entry point as the global form:
void main()
{
// Finalize this level's unique systems here.
}
The level-specific script executes only when OpenBOR ends the level containing the command. It is well suited to recording unique objectives, resolving branching state, awarding stage-specific bonuses, closing custom encounters, or preserving results that have meaning only within that level.
Only one endlevelscript command is available to a level. Multiple finalization tasks may be organized into functions and called from the script's main() when needed.
Execution
The relevant level-end sequence is:
- OpenBOR exits the active level update loop.
data/scripts/endlevel.cexecutes when present.- The level-specific
endlevelscriptexecutes when declared. - OpenBOR performs the normal fade-out unless fade-out is disabled.
- Player health, MP, and rush maximum are captured from remaining player entities.
- Level audio is stopped according to the project's music-overlap settings.
- OpenBOR unloads the level and its entities.
- Game flow continues to the completion screen, game-over sequence, next level, or other applicable destination.
The level and its remaining entities are therefore available to both scripts. Their properties, entity variables, level state, and project variables can still be inspected or modified before teardown.
The level-specific script executes after the global script, so it can build on or replace state established by endlevel.c. This supports the same division of responsibility as level-start scripts: apply project-wide finalization first, then specialize it for the level that just ended.
Endlevel scripts execute after recurring level updates have stopped. Changes intended to be captured, stored, or consumed by later game flow take effect normally. Multi-step victory sequences, animated exits, or other behavior requiring continued updates should complete before the level is allowed to end, with the endlevel hook used to finalize the result.
Completion and Other End Conditions
Despite the name, an endlevel script is not limited to successful completion. It executes whenever the active level loop terminates, including ordinary completion, loss of all players, forced completion, forced game over, and other paths that end the level.
Projects that need to distinguish outcomes can maintain an objective or result value during gameplay, then inspect that value in the endlevel script. This arrangement allows the same hook to finalize successful clears, failed objectives, alternate exits, and custom victory conditions without hard-coding a single interpretation of "level ended."
Example: Preserve Stage Results
The following global script copies custom stage counters into values that later menus, levels, or scripts can read:
void main()
{
setglobalvar(
"previous_stage_hits",
getglobalvar("stage_hit_count")
);
setglobalvar(
"previous_stage_damage",
getglobalvar("stage_damage_total")
);
setglobalvar(
"previous_stage_objective",
getglobalvar("stage_objective_complete")
);
}
The example assumes other scripts maintain the stage counters during gameplay. The endlevel hook provides one reliable point to close the record before the current level is unloaded.
Example: Build a Level Result
This level-specific script converts several values maintained during gameplay into a compact rank and unlock result:
void main()
{
int stage_cleared = getglobalvar("stage_was_cleared");
int objective_complete =
getglobalvar("stage_objective_complete");
int damage_total = getglobalvar("stage_damage_total");
int rank = 0;
if (stage_cleared)
{
rank = 1;
if (objective_complete)
{
rank++;
}
if (damage_total < 500)
{
rank++;
}
}
setglobalvar("storm_docks_rank", rank);
setglobalvar(
"storm_docks_bonus_unlocked",
stage_cleared && objective_complete
);
}
Other scripts establish the clear, objective, and damage values while the level is active. The endlevel hook converts them into a final result after gameplay ends but before the level data is discarded. Completion screens, later levels, menus, or save logic can consume the stored rank and unlock flag.
Other Uses
Quick applications include:
- Stage statistics - Store hit counts, damage totals, elapsed time, defeats, collectibles, or challenge performance before teardown.
- Objective resolution - Commit success, failure, optional goals, rank, medals, or alternate outcome flags.
- Player rewards - Award score, resources, unlocks, equipment, lives, or custom progression according to player or team performance.
- Branch preparation - Preserve choices and encounter results for later level-order, menu, dialogue, or selection logic.
- State synchronization - Copy temporary level or entity data into project variables that remain available after the level is unloaded.
- System cleanup - Close custom controllers, clear temporary references, and return shared subsystems to their neutral state.
- Result presentation - Prepare values consumed by completion screens, custom HUDs, scenes, reports, or post-level menus.
Related Scripts
| Script | Relationship |
|---|---|
| level scripts | Execute when a level begins. They are the opening counterparts to endlevel scripts. |
data/scripts/endlevel.c
|
Global level-end hook that executes first for every level. |
| endlevelscript | Level-specific level-end hook that executes after the global hook. |
| update and updated scripts | Recurring hooks used while the level's active update loop is running. |