Create / Mod files / Ships for mods

Ships for mods

A Ship is a whole DESIGN, authored once and spawned by id. It owns the section layout, whether the hull is clad, how far it must be dismantled before it collapses, and the voice it speaks to its pilot with. A Spaceship spawn names it and adds everything that differs per spawn: where it sits, who flies it, which side it is on, what it is permitted to do.

Ships are content like sections, scenarios and styles. Create a new id to add a design, or reuse a base id to rebuild every scenario's corvette at once.

This page is the field-by-field ship reference. For general RON spelling rules such as double parentheses, Some(...), and asset schemes, see RON spelling rules.

Why a ship is content

A full loadout runs to hundreds of lines. Inlining one in every scenario that spawns it means editing a corvette in eleven places and getting eleven slightly different corvettes. A ship id is the fix: one definition, one edit, and a mod can replace it for every scenario that names it.

The Ship item

[
    Ship((
        id: "my_corvette",
        name: "My Corvette",
        design: (
            sections: [
                (
                    id: "fuselage",
                    position: (0.0, 0.0, 0.0),
                    rotation: (0.0, 0.0, 0.0, 1.0),
                    source: Prototype(id: "basic_controller_section"),
                ),
                // ... hull, thruster, and weapon sections ...
            ],
        ),
    )),
]
field type default meaning
id string required what a spawn names this design by. A mod reusing a base id REPLACES that design everywhere
name string required the name a picker shows. Not used at spawn - a spawned ship is named by the scenario object that placed it
design design required the design itself (below)

The design

field type default meaning
sections list [] the hull/thruster/gun/controller layout: one entry per section, each with a ship-local id, a position in BUILD CELLS (one cell is 10 m) and a rotation, both relative to the ship root, and a source (Prototype(id: "<section id>"), with an optional patch over it, or Inline((..)))
integrity integrity all default when the design comes apart (below)
presentation presentation all default what it looks like and sounds like (below)

integrity fields:

field type default meaning
collapse_threshold Option number None structural collapse: the fraction of the health the ship was BUILT with below which whatever is left comes apart and the ship is destroyed. Strict RON Some(0.1); omitted = the engine default 0.05. Lower = the ship must be dismantled further (a capital), Some(0.0) = strip every last section. Clamped to 0..=1

presentation fields:

field type default meaning
skin bool false clad the ship: the game DERIVES an outer skin from the sections at spawn - destructible plates, nothing authored, no id to reference (see Cladding). For hulls built out of the unit-cell sections; modelled parts are their own sizes and do not stand on that lattice
style Option string None the LOOK the cladding wears, by style id: plate materials plus the destructible decoration placed on them. Strict RON Some("raider"); omitted = built-in plate colours and no decoration. An id no loaded style authors fails at lint and stops the game at spawn
collapse_sound Option asset ref None the sound the design makes when it COLLAPSES - the moment it stops being a ship and becomes wreckage, which is ONE event however many frames the sections then take to peel away. Strict RON Some("dep://base/sounds/destroy_ship.wav"). Authored on the design because a spine going is not a section failing loudly; omitted, the ship comes apart to the sound of its own sections
the cockpit voice Option asset refs None lock_on_sound, lock_off_sound, radar_deny_sound, radar_retarget_sound, safety_on_sound, warn_lock_sound, ammo_dry_sound, warn_hull_sound, kill_confirm_sound, torpedo_closing_sound, rcs_loop_sound - the feedback the hull gives its pilot (kill_confirm_sound plays once per hull the player's torpedo blast defeated; torpedo_closing_sound ticks faster as the player's torpedo nears the locked hull, from 8 s out). Authored-or-silent: a sound nobody names plays nothing
warn_hull_fraction number 0.3 the hull fraction the critical alarm fires at, once, on the way down. 0.0 never warns

The voice is the DESIGN's, not its flight computer's: a hull that loses every controller section still knows how to warn about its own structure.

Section entries are the same records a design carried when it was inlined - see section prototypes for the ids the base game ships.

Spawning one

SpawnScenarioObject((
    base: (
        id: "raider_1",
        name: "Raider",
        position: (0.0, 0.0, -3000.0),
        rotation: (0.0, 0.0, 0.0, 1.0),
    ),
    kind: Spaceship((
        controller: AI((engage_delay: Some(8.0))),
        design: Prototype(id: "my_corvette"),
        inventory: {},
        lootable: false,
        credits: 2000,
    )),
)),

Changing one design for one spawn

A scenario that wants a harder flight computer or a fixed magazine does NOT need its own ship. section_patches on the spawn aims the same typed deltas a section reference carries at a section of the resolved design, and they are applied after the design's own, so the spawn wins:

kind: Spaceship((
    controller: AI(()),
    design: Prototype(
        id: "my_corvette",
        section_patches: {
            "fuselage": (config: (health: Some(500.0))),
            "turret_port": (config: (kind: Some(Turret((
                ammunition: Some(Limited(900)),
                reload: Some(Disabled),
            ))))),
        },
    ),
    inventory: {},
    lootable: false,
    credits: 2000,
)),

A section_patches key the design does not carry does nothing at runtime, so the content lint reports it as an error, and so does a patch that argues with the section's kind. The full patch surface is in the sections list.

Reach for a second ship id instead when the difference is what the design IS - the base game ships light_freighter and freighter_derelict as separate hulls because a missing drive, transom and wing are a different ship to fly, not a tweak. The Ledger does the same with its two hauler loads, cargob and cargob_lance: which torpedo TYPE the pods carry decides whether a defender's point defense can answer the salvo at all, and that is the ship, not a tweak to it.

One-off designs

A design nothing else will ever spawn can stay on the spawn:

kind: Spaceship((
    controller: None,
    design: Inline((
        sections: [
            (
                id: "bay",
                position: (0.0, 0.0, 0.0),
                rotation: (0.0, 0.0, 0.0, 1.0),
                source: Prototype(id: "torpedo_section"),
            ),
        ],
    )),
    inventory: {},
    lootable: false,
    credits: 2000,
)),

Inline((..)) takes the same fields as a ship's design. Use it for a scripted battery that is a single tube or a derelict that is five plates; anything a second scenario would spawn belongs in the catalog. It takes no section_patches: it is already this spawn's own.

Overlay and lint

  • A mod ship with a base id REPLACES the base design, so every scenario naming it flies the mod's - the same last-wins overlay sections and styles follow.
  • The same id twice in ONE bundle is a conflict: the first wins and the duplicate is skipped.
  • A design is linted where it is AUTHORED, not where it is spawned: its section prototypes must resolve, its own patches must apply, its sections must not interpenetrate, and its link-point graph must be connected. A spawn's section_patches are linted where the spawn is.
  • A spawn naming a ship no bundle provides is a lint error, and at runtime it spawns an empty root and logs rather than crashing.

Base ships

Every base design is BUILT: cells on a build grid, clad by the derived skin and painted by a style. Nothing in the base game is a modelled mesh.

id what it is
mining_tug Mining Tug - the industrial start: a low work hull of light plate with a two-cell boom off the bow and a mining emitter at its tip (mining_beam), a cargo intake on the aft deck (cargo_intake), a cab forward and three bell drives
salvage_hauler Salvage Hauler - the scavenger start: a deep hold of light plate, a cab on the nose with a mining emitter ahead of it (mining_beam), a cargo intake on the dorsal deck, one point-defense mount and five bell drives in a cross on a stern with its corners cut back. The biggest hold of the start hulls
light_freighter Light Freighter - the transport start: a stack of light plate on a flat spine, a cargo intake on top of the stack, a pod on the starboard flank and five bell drives on a cross-shaped transom. Unarmed
freighter_derelict Light Freighter: Derelict - a yard-fitted freighter (reinforced plate, freight cubes, a tank pod, solar wings) after a raid took its stern: no drive, no transom, the aft tank cube and the starboard wing's outer panel gone. Everything forward of the tear matches the freighter cell for cell, the cab and the collar included
interceptor Interceptor - the bounty hunter start: a compact two-deck body of light plate with stub wings, two point-defense mounts on the top deck, a cargo intake aft of them and three bell drives
raider Raider - the pirate start: a short hull of light plate with a nose stub, an outrigger and a gun boom on the starboard side, a dorsal mount, a cargo intake on the aft deck and four bell drives
patrol_picket Patrol Picket - the military start: a slim dart of light plate with a point-defense mount on the nose face, a second on the dorsal spine, a torpedo bay under the nose (torpedo_keel), a cargo intake on the aft deck, two bell drives and a docking collar off each flank, hatch outboard (port_collar, starboard_collar)
training_picket Training Picket - the tutorial range's hull, flown by the trainer and the drones: a slim dart of light plate with one point-defense mount on the nose face and two bell drives. Scenario-only, with no cargo intake
line_warship Line Warship - the military goal: a long armoured body with six PDC mounts, a railgun on the bow, a torpedo bay on each shoulder, a cargo intake on the aft deck (cargo_intake) and a docking collar off each shoulder, hatch outboard (port_collar, starboard_collar)
debris_plate Debris Plate - loose plating: the small pieces, and most of what a debris field is

Every crewed base hull carries a docking collar on the port flank, port_collar.

A mod may ship MODELLED craft instead, and The Ledger does: its racer, cargoa, cargoa_raider, cargob and cargob_lance are assembled from GLB parts the mod carries under its own gltf/parts/.