Updatedscript
updatedscript is a level-specific recurring event hook. It executes late in each eligible outer update cycle, after entity simulation and standard display-queue construction. The global data/scripts/updated.c hook executes first, followed by the current level's updatedscript. OpenBOR then draws the completed sprite queue.
This position makes updatedscript the level's final recurring control point before presentation. It can evaluate the results of the current simulation, resolve stage-specific systems using finalized state, append custom presentation to the current display queue, and prepare values for the next cycle without placing level-only logic in the global updated script.
Usage
Add updatedscript to a level definition and provide the path to the script file:
updatedscript data/scripts/levels/storm_docks_updated.c
The referenced script uses a main() entry point and receives no automatic event variables.
void main()
{
// Perform recurring late-cycle level logic here.
}
OpenBOR loads the script with the level and executes it only while that level remains available. No project-wide script file or model command is required.
Only one updatedscript command is available to a level. Multiple recurring tasks may be organized into functions and called from the script's main().
Inline Script
The command also supports an inline script block:
updatedscript @script
void main()
{
int objective_complete = getglobalvar("storm_docks_complete");
if (objective_complete)
{
drawstring(8, 16, 0, "OBJECTIVE COMPLETE", 1000000);
}
}
@end_script
Inline form is useful for concise level-only behavior. External files are easier to reuse and organize when the late-cycle controller contains several systems or helper functions.
Execution
The relevant outer update sequence is:
- OpenBOR refreshes timing and player input state.
- Global
data/scripts/update.cexecutes when present. - The current level's updatescript executes when declared.
- OpenBOR processes applicable key-script events.
- OpenBOR advances logical time and performs scrolling, timer, and entity simulation work as required.
- OpenBOR clears the working screen and constructs the standard background, interface, text, and entity display queues.
- Global
data/scripts/updated.cexecutes when present. - The current level's
updatedscriptexecutes when declared. - OpenBOR processes the remaining control work, draws the completed sprite queue, presents the screen, and clears the queue.
Global updated.c always executes before the level updatedscript. The level hook can therefore consume common late-cycle state established by updated.c, specialize it for the current stage, or add level-specific presentation to the same display queue.
Simulation for the cycle has already completed when updatedscript begins. State produced by entity updates, movement, scrolling, timers, attacks, and other simulation work is available for final evaluation. This is particularly useful when a decision should account for everything that happened during the current cycle rather than the state that existed at its beginning.
Display Queue Position
Standard background, status, text, and entity display entries are normally queued before updatedscript. The queue has not yet been drawn. Script drawing functions such as drawstring(), drawbox(), drawsprite(), and drawscreen() can therefore append presentation that appears in the same screen update.
Queue placement still follows each drawing function's layer, Z, and sorting rules. Calling a drawing function later does not by itself force the result above every existing item.
Changes to entity or level state also take effect immediately, though standard entity display entries for the current cycle have already been prepared. Such changes naturally influence later logic and the next display-queue build. Custom drawing added directly by updatedscript can appear during the current cycle.
This combination supports both roles cleanly:
- Post-simulation control - Evaluate finalized gameplay state and prepare subsequent behavior.
- Current-cycle presentation - Add overlays, messages, flashes, subscreens, debugging information, or other custom draw work before the queue is rendered.
Execution Frequency
updatedscript executes once per eligible outer update cycle. Outer update frequency is independent of OpenBOR's logical clock and may vary with the selected update limit, display synchronization, platform timing, and runtime conditions.
One execution therefore does not necessarily represent one logical tick. Each outer cycle may contain no entity simulation step or may process several logical ticks before reaching updatedscript. Gameplay duration should be measured with openborvariant("elapsed_time") or another suitable time source instead of counting executions.
During an in-game update cycle, the updated hooks are not suppressed by the pause flag. updatedscript can consequently execute during paused cycles even though simulation and standard display-queue preparation are paused. Enabling alwaysupdate expands eligibility to other update calls, provided the level remains loaded.
Level Scope
Global updated.c is appropriate for late-cycle systems used throughout a project. Level updatedscript supplies the same phase with a narrower lifetime and direct ownership by one level.
This separation keeps stage-specific resolution and presentation with the stage that uses them. Universal overlay managers, diagnostics, or project-wide post-simulation systems can remain in updated.c, while individual levels provide their own objectives, encounter resolution, environmental composition, cinematic treatment, or late-cycle coordination.
Example: Post-Simulation Encounter Resolution
The following compact controller advances an encounter after participating systems report that no targets remain:
void main()
{
int phase = getglobalvar("foundry_phase");
int enemies_remaining = getglobalvar("foundry_enemies_remaining");
if (phase == 2 && enemies_remaining <= 0)
{
setglobalvar("foundry_phase", 3);
setglobalvar("foundry_gate_open", 1);
}
}
Entity scripts or other encounter components may update foundry_enemies_remaining during simulation. Running the decision in updatedscript lets the level controller evaluate the resulting state after those updates have finished for the cycle.
Example: Same-Cycle Objective Message
This example adds a timed message after the standard display entries are prepared:
void main()
{
long elapsed = openborvariant("elapsed_time");
long message_until = getglobalvar("foundry_message_until");
if (message_until > elapsed)
{
drawstring(8, 16, 0, "COOLING SYSTEM DISABLED", 1000000);
}
}
The text is added to the current display queue and appears when OpenBOR draws that queue later in the same cycle. Logical time controls the duration, so the message does not depend on outer update frequency.
Choosing an Update Hook
| Hook | Scope | Phase | Typical responsibility |
|---|---|---|---|
data/scripts/update.c
|
Project-wide | First recurring script in the outer update cycle | Universal managers and common early-cycle state |
| level updatescript | Current level | After global update.c, before key events and simulation
|
Stage-specific preparation, rules, objectives, and encounter control |
| model script | Individual active entity | Entity simulation | Per-entity recurring behavior |
data/scripts/updated.c
|
Project-wide | After simulation and standard display-queue construction | Universal post-simulation logic and late presentation |
| level updatedscript | Current level | After global updated.c, before the display queue is drawn
|
Stage-specific final evaluation and same-cycle presentation |
These hooks complement one another. Projects can distribute work according to ownership and timing instead of forcing unrelated systems into a single recurring script.
Other Uses
Quick applications include:
- Encounter resolution - Confirm wave completion, release exits, choose the next phase, or reconcile multi-part battle state after entity updates.
- Objectives - Evaluate escorts, survival conditions, collectibles, simultaneous targets, or optional challenges using the cycle's resulting state.
- Custom presentation - Queue messages, overlays, flashes, letterboxing, subscreens, weather effects, lighting treatments, or cinematic elements for the current screen update.
- Environment coordination - Capture resulting camera, scrolling, hazard, palette, or stage state for presentation and subsequent logic.
- Multiplayer reconciliation - Evaluate the complete participating-player state after movement, damage, defeat, joining, or other simulation work.
- Transition preparation - Set values consumed at the start of the next cycle, request a new phase, or coordinate a clean handoff between systems.
- Development tools - Display current state, verify entity counts, inspect timing, expose camera values, or append level-specific diagnostics.
Related Scripts
| Script | Relationship |
|---|---|
| update.c | Global early-cycle hook that executes before the level's updatescript.
|
| updatescript | Level-specific early-cycle hook that executes before key events and simulation. |
| updated.c | Global late-cycle hook that executes before the level's updatedscript.
|
| updatedscript | Level-specific late-cycle hook that executes after global updated.c and before display-queue drawing.
|
| updateentityscript | Recurring model hook executed as part of entity simulation. |
| levelscript | One-time level-start hook used to establish initial state before recurring updates begin. |
| endlevelscript | One-time level-end hook used to finalize state after recurring updates stop. |