Baffles me how much issues skipselect can cause.
I blame you all. No, seriously.
skipselect started as a bolted-on development feature by
@Orochi_X during the Lavalit days around 2007. He later admitted
he doesn't even remember adding it! There were actual flame wars over what it was supposed to mean. Whatever its exact original purpose, it was never designed as the clean, general-purpose, per-level character-forcing command people now assume it is.
Unfortunately, like several other development features from that era, the community immediately started using it in released games. OpenBOR's old, dogmatic backward-compatibility-at-all-costs community policy then made removing or properly redesigning it practically impossible.
Internally,
skipselect is not a simple
“do not display the selection screen” flag. It adds a pseudo-entry to the level order, stores a model name for each player slot, and runs the normal player-selection machinery without displaying the screen. Later revisions allowed multiple
skipselect entries within one set and tied the whole thing into save-game restoration. Consequently, it intersects with models, player joining, lives, credits, score, saved games, and any scripts touching those systems.
For this specific report,
@Kratus is correct. The current logic uses saved lives to guess whether
skipselect is starting a new game or reselecting players during an existing game. The
end command merely marks the preceding level as the end of the set. Completion handling resets the saved level and stage, yet leaves saved player lives and score intact.
When another new game starts, OpenBOR's internal
selectplayer() function first saves the lingering player state, wipes the active player array, then finds saved lives greater than zero and treats the operation as a re-selection. It consequently restores the previous lives, score, and credits instead of initializing a new run. That is the direct cause of the behavior described here.
@Kratus's reset script will work as a temporary workaround, though it should not run unconditionally from
updated.c. Doing that would continuously reset those properties throughout the game. Gate the reset so it executes once when a genuinely new run begins, using whichever controlled startup event best fits the project.
Proper engine correction is to stop guessing from the player's remaining lives. Selection code needs an explicit context telling it whether the caller is starting a new game, re-selecting during the current game, or loading a saved game. That preserves the legitimate existing uses without treating leftover state as creator intent. I have tried to shore
skipselect up for the upcoming release, though this particular path still needs that explicit cleanup. Even once this defect is corrected, forcing a specific model will never play perfectly with every script or feature someone might combine with it. The same is true of nearly anything in a creation toolbox. Some behaviors are simply oil and water, guys - that is how it is.
DC