Jump to content

Player Join Scripts

From OpenBOR
Revision as of 21:26, 20 August 2026 by Dcurrent (talk | contribs) (Created page with "Category:Player Category:Script Category:Script Events '''Join scripts''' are global event hooks that execute when a player completes an in-progress join and enters active play. OpenBOR provides numbered scripts for slot-specific behavior and a shared <code>joinall.c</code> script for handling every player through one event listener. The numbered series consists of: * <code>data/scripts/join1.c</code> * <code>data/scripts/join2.c</code> * <code>data/script...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)


Join scripts are global event hooks that execute when a player completes an in-progress join and enters active play. OpenBOR provides numbered scripts for slot-specific behavior and a shared joinall.c script for handling every player through one event listener.

The numbered series consists of:

  • data/scripts/join1.c
  • data/scripts/join2.c
  • data/scripts/join3.c
  • data/scripts/join4.c

The shared listener is:

  • data/scripts/joinall.c

Join scripts execute after OpenBOR creates the joining player's entity. This makes them useful for party scaling, cooperative encounter adjustments, player-specific initialization, join effects, role assignment, shared objectives, statistics, announcements, and other systems that should react immediately when the active player group changes.

Usage

Create any desired join-script files in data/scripts. OpenBOR loads them automatically, so no model, level, or project command is required.

join#.c is documentation shorthand in which # represents the player number. Literal filenames use 1 through 4.

File Scope Player identification
data/scripts/join1.c Player 1 Filename - index 0
data/scripts/join2.c Player 2 Filename - index 1
data/scripts/join3.c Player 3 Filename - index 2
data/scripts/join4.c Player 4 Filename - index 3
data/scripts/joinall.c Every player Local variable playerindex

Projects may use only the numbered files, only joinall.c, or both layers together.

Join Event

Join scripts respond to the native in-progress join routine. The event occurs after a vacant player slot begins joining, completes its character or color selection as applicable, and confirms entry while joining is permitted.

The event does not represent every player entity creation. It is distinct from:

  • Initial player creation when a level begins.
  • Respawning an existing player after a lost life.
  • Spawning an arbitrary player-type entity through level or script commands.
  • Creating any other entity from a model that happens to use Onspawnscript.

Each completed in-progress join executes the applicable join-script chain once.

Execution Order

OpenBOR performs the relevant join sequence in this order:

  1. The player confirms an allowed in-progress join.
  2. OpenBOR initializes the player's lives and stored spawn health and magic values.
  3. OpenBOR creates the player's entity with its native player-spawn routine.
  4. The corresponding numbered script, join1.c through join4.c, executes when present.
  5. joinall.c executes when present and receives playerindex.
  6. OpenBOR clears the player's pending join input.
  7. Native post-join behavior continues, including the configured enemy-drop and level-timer reset behavior.

The new player entity already exists when either join-script layer begins. Scripts may therefore retrieve the entity through the player property API and immediately inspect or configure it.

The numbered script always executes before joinall.c. Shared logic can consequently consume state established by the slot-specific script during the same event.

Numbered Join Scripts

Numbered join scripts are tied to the player slot identified by their filename. They receive no automatic event variables because the player identity is already fixed by that filename.

void main()
{
    // join2.c always represents Player 2, player index 1.
    setglobalvar("player_two_joined", 1);
    setglobalvar("player_two_role", "support");
}

Slot-specific files are convenient when each player position has a distinct responsibility, starting package, interface, camera role, team assignment, or other fixed behavior.

Joinall

joinall.c is the shared listener for every player slot. OpenBOR supplies one automatic local variable:

Variable Type Description
playerindex Integer Zero-based index of the player who completed the join. Values range from 0 through 3 for Players 1 through 4.
void main()
{
    setglobalvar("last_joined_playerindex", playerindex);
    setglobalvar("party_changed", 1);
}

The zero-based index matches OpenBOR's player property and scripting conventions:

playerindex Player label Corresponding numbered script
0 Player 1 join1.c
1 Player 2 join2.c
2 Player 3 join3.c
3 Player 4 join4.c

joinall.c does not receive an automatic entity reference. The joining entity is available from the player slot because native spawning has already completed:

void main()
{
    void joined_entity = getplayerproperty(playerindex, "entity");

    if (joined_entity)
    {
        setglobalvar("joined_player_ready", playerindex);
    }
}

Creators can use joined_entity immediately with the entity property API, binding functions, visual effects, or other systems that operate on active entities.

Combining Numbered and Shared Logic

Both layers may participate in the same join. Their fixed execution order supports a useful division of responsibility:

  • Numbered join#.c performs slot-specific setup.
  • Shared joinall.c performs project-wide reconciliation after that setup.

For example, numbered scripts might assign asymmetric cooperative roles while joinall.c recounts the active party, rescales an encounter, refreshes shared objectives, and displays a common join effect.

void main()
{
    int active_players = 0;
    int index = 0;

    for (index = 0; index < 4; index++)
    {
        if (getplayerproperty(index, "entity"))
        {
            active_players++;
        }
    }

    setglobalvar("active_player_count", active_players);
    setglobalvar("rebalance_encounter", 1);
}

This compact shared listener responds to whichever slot joined without duplicating the party-reconciliation logic across four files.

Choosing a Join Script

Need Recommended hook
Behavior unique to one fixed player slot Corresponding join#.c
The same behavior for every joining player joinall.c
Fixed slot setup followed by common party handling Numbered join#.c and joinall.c together
Behavior whenever any entity using a model is created Onspawnscript
Behavior when an existing player returns after losing a life Respawn Scripts

Other Uses

Quick applications include:

  • Party scaling - Recalculate enemy counts, durability, aggression, hazards, rewards, or encounter phases when the party grows.
  • Cooperative rules - Enable team mechanics, shared resources, revival systems, combined objectives, or multiplayer-only routes.
  • Player setup - Assign slot-specific roles, starting equipment, colors, resources, control modes, or interface elements.
  • Join presentation - Play sounds, queue visual effects, display announcements, or introduce the arriving player.
  • Camera coordination - Recalculate camera targets, split attention, stage boundaries, or multiplayer tracking behavior.
  • Objective reconciliation - Add the player to escorts, survival conditions, team counters, voting systems, or synchronized sequences.
  • Statistics and achievements - Record participation, join timing, party composition, or cooperative milestones.
  • Development tools - Log join order, inspect selected models, verify slot state, or test multiplayer entry conditions.
Script Relationship
Respawn Scripts Execute when an existing player returns after losing a life. The numbered script runs before respawnall.c.
Die Scripts Execute when a player loses a life. The numbered script runs before dieall.c.
Onspawnscript Model event that executes for entity creation generally, including entities that are not player-controlled joins.
Keyscript Layered player-input events that may participate in beginning and confirming an in-progress join.
level.c Global level-start event. Initial player creation is separate from the in-progress join event.
Score Scripts Numbered and shared global listeners for player score adjustments.

See Also