Skip to content

Checkpoint

A Checkpoint is a sequenced objective marker. The engine defines the class and provides a .sequence accessor — a number used to order checkpoints in a race or quest sequence.

Inheritance: component → destructible → object → checkpoint. The datatype adds exactly one property.

Important — minimal vanilla usage. Searching vanilla MD and aiscripts for class.checkpoint returns zero results. The class is engine-defined and exposed to scripts, but no vanilla cue, mission, or aiscript actively uses it. This makes checkpoint:

  • A modder hook for custom race / time-trial / sequenced-objective mods.
  • A safe class to spawn-and-destroy without colliding with vanilla content.
  • A reminder that scriptproperties datatypes don’t always correspond to live gameplay systems.

If you want to add race tracks or sequenced flight challenges, this class is what the engine intends for that.

PropertyTypeDescription
.sequenceintSequence number — ordering for a series of checkpoints (e.g. 1, 2, 3, … for a race)
PropertySourceDescription
.sector / .zone / .positionobjectWhere the checkpoint is
.macrocomponentCheckpoint variant
.knownnamecomponentDisplay name
.knowntoplayercomponentPlayer has discovered it
<create_object
name="$Checkpoint"
macro="$CheckpointMacro"
owner="faction.ownerless"
sector="$Sector">
<position x="$x" y="$y" z="$z"/>
</create_object>

There is no .sequence setter exposed via a clean action. To set the sequence on a custom checkpoint, you typically use macro-level configuration or <set_value> on a parallel script-side tracking variable. Vanilla has no <set_checkpoint_sequence> action.

<find_object name="$Checkpoints"
space="$Sector"
class="class.checkpoint"
multiple="true"/>

Sort by sequence number (for race-style mods)

Section titled “Sort by sequence number (for race-style mods)”
<sort_list name="$Checkpoints"
sortbyvalue="$loop.element.sequence"/>
<set_value name="$Next" exact="null"/>
<do_for_each name="$cp" in="$Checkpoints">
<do_if value="$cp.sequence == $CurrentSequence + 1">
<set_value name="$Next" exact="$cp"/>
<break/>
</do_if>
</do_for_each>

There is no event_checkpoint_X family. Checkpoint progression is observed through:

EventWhenNotes
event_object_destroyedCheckpoint destroyed (player flew through and the mod cue removed it)Standard pattern
event_object_changed_sectorShip moved sectors — race-progress proxyMod cues typically poll position vs checkpoint position

Most race-style mods build their own polling loop: every do_while tick, check player position against $Next.position; if within threshold, advance to next sequence number.

  • Zero vanilla MD/aiscript usage of class.checkpoint. This is documented but unused. If you encounter this class in another script, it’s almost certainly from a mod, not vanilla.
  • .sequence is set at macro level, not at runtime. There’s no clean script API to mutate it. Build your race-tracking via a parallel $RaceState variable in your mod.
  • Checkpoint vs Navbeacon — pick correctly. Navbeacon is for player-visible map labels. Checkpoint is for sequenced objective markers. Different abstractions.
  • No engine “player passed through checkpoint” event. You build the trigger yourself via proximity polling or trigger-collider macros.
  • .sequence is a plain int — no validation that it’s contiguous. A mod could create checkpoints with sequence 1, 5, 9; the engine accepts it. Validate ordering in your mod’s setup code.

Example 1: Spawn a simple 3-checkpoint race in a sector

Section titled “Example 1: Spawn a simple 3-checkpoint race in a sector”
<set_value name="$Positions" exact="[
[10000, 0, 10000],
[-10000, 0, 0],
[0, 0, -10000]
]"/>
<set_value name="$i" exact="1"/>
<do_for_each name="$pos" in="$Positions">
<create_object
name="$cp"
macro="$CheckpointMacro"
owner="faction.ownerless"
sector="$Sector">
<position
x="$pos.{1}"
y="$pos.{2}"
z="$pos.{3}"/>
</create_object>
<set_value name="$i" operation="add" exact="1"/>
</do_for_each>
<write_to_logbook
text="'Race set up with 3 checkpoints in '
+ $Sector.knownname"/>
<cue name="RaceProgress" instantiate="true">
<conditions>
<event_cue_signalled cue="this"/>
</conditions>
<actions>
<find_object name="$CPs"
space="$RaceSector"
class="class.checkpoint"
multiple="true"/>
<set_value name="$Next" exact="null"/>
<do_for_each name="$cp" in="$CPs">
<do_if value="$cp.sequence == $PlayerSequence + 1">
<set_value name="$Next" exact="$cp"/>
<break/>
</do_if>
</do_for_each>
<do_if value="@$Next
and player.ship.distanceto.{$Next} lt 2000m">
<set_value name="$PlayerSequence"
operation="add" exact="1"/>
<write_to_logbook
text="'Checkpoint ' + $PlayerSequence
+ ' passed!'"/>
</do_if>
</actions>
</cue>
  • Race-style mod scaffolding: Architectural overview Race / time-trial framework — how a mod might build a full race system on top of class.checkpoint.
  • Why some script classes are unused: Architectural overview Reserved engine classes — Egosoft sometimes exposes engine concepts for modders even when the base game doesn’t use them.
  • Navbeacon — player-visible map markers (different role).
  • Sector — where checkpoints exist.
  • Ship — what passes through checkpoints.