-
Notifications
You must be signed in to change notification settings - Fork 0
ships.Class.ShipLoadout
@elite-dangerous-almanac/core / ships / ShipLoadout
Defined in: src/ships/ship-loadout.ts:539
A fitted ship — read a SLEF export, or assemble a hull from scratch.
- Construct — fromSlef, fromLoadout, empty, default. The constructor is private; every build starts at one of these four.
- Inspect — shipSymbol, shipName, shipIdent, unladenMass, cargoCapacity, fuelCapacity, hullValue, modulesValue, rebuy, sourcePurchase, importOutcomes, slots, fittedModuleAt, fittedModules, modulesForSlot, availableBlueprints, availableExperimentalEffects, validation().
-
Edit — setModule, removeModule, repairFixedMount,
applyBlueprint, setExperimentalEffect,
completeEngineeringGrade, setPreEngineeredVariant,
clearEngineering, setModuleEnabled, setModulePriority. Each
returns
thisunless it reports a result of its own. -
Analyse — not here. Jump range, mass, cost, power, heat, mobility, shields,
armour and firepower live on
BuildMetrics, which reads this build:
BuildMetrics.of(build).maxJumpRange(). The split lets an outfitting editor import the editors without the calculations, and a viewer the calculations without the editors. - Export — toLoadoutEvent, toSlef, toSlefString.
A property is a fact this build already carries; a method does something. Every getter above is an identity, an aggregate figure, or what a capture stated — it computes nothing, takes no options, and never throws. Everything that does work is a call: reading the catalogues, enumerating mounts, editing the fit, exporting it, and every figure on BuildMetrics.
The rule makes the split predictable, not harmless. Two of those calls take no
argument and read like facts — validation(), which revalidates
the whole fit, and fittedModules(), which allocates and
deeply freezes a fresh snapshot on every call — so they are methods by the rule above
even though a reader may reach for them as properties. A forgotten () still hands
you the function rather than the value, and in plain JavaScript nothing complains:
build.fittedModules is a function reference, build.fittedModules() is the list.
TypeScript catches it; a .js consumer will not.
Read a build a player already flies, and ask it what an outfitting screen shows.
Every figure below is one build's — a Krait Phantom explorer. Figures the capture
already stated — unladenMass here — are trusted verbatim while the fit they
describe survives import; the rest are computed from the fit.
import { BuildMetrics } from '@elite-dangerous-almanac/core/ships/build-metrics';
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
import type { LoadoutEvent } from '@elite-dangerous-almanac/core/ships/slef';
// A `Loadout` line lifted from a player journal, parsed.
declare const event: LoadoutEvent;
const build = ShipLoadout.fromLoadout(event);
build.shipSymbol; // -> 'krait_light'
build.shipName; // -> 'Jenny Longuet'
build.unladenMass; // -> 388.830017 (tonnes)
const metrics = BuildMetrics.of(build);
metrics.maxJumpRange(); // -> 60.5478 (ly, best single jump)
metrics.powerBudget().withinBudget; // -> true
metrics.shieldMetrics()?.strength; // -> 743.12 (MJ)
metrics.armourMetrics().hitPoints; // -> 307.8get cargoCapacity():
number
Defined in: src/ships/ship-loadout.ts:848
Cargo capacity, in tonnes — a capture's CargoCapacity on the same terms as
unladenMass, otherwise the sum of the fitted racks.
number
get fuelCapacity():
FuelCapacity
Defined in: src/ships/ship-loadout.ts:832
Fuel-tank capacities, in tonnes — a capture's FuelCapacity on the same terms as
unladenMass, otherwise the fitted tanks plus the hull's own reserve.
get hullValue():
number|null
Defined in: src/ships/ship-loadout.ts:870
Hull cost in credits represented by the build, or null if unknown.
This is the live figure, kept coherent with edits: an import's own HullValue
until something invalidates it. For the capture's figure as captured — which no
edit changes — read sourcePurchase.
number | null
get importOutcomes(): readonly
LoadoutImportOutcome[]
Defined in: src/ships/ship-loadout.ts:946
Changes made while importing this build, in source order, followed by the fixed mounts stocked from the hull defaults because the source named none, in the defaults' own order.
Each entry names the exact slot, and the source identity where the source gave one.
emptied means an unknown module was removed from a removable mount; defaulted
names the stock article fitted to armour, a core internal or the cargo hatch, with
a null sourceSymbol when the source named nothing there at all.
readonly LoadoutImportOutcome[]
A deeply frozen list. It is empty for builds created with ShipLoadout.empty or ShipLoadout.default, and for imports that needed no normalization.
get modulesValue():
number|null
Defined in: src/ships/ship-loadout.ts:881
Fitted-modules cost in credits represented by the build, or null if
unknown — including after an edit or import normalization discarded an import's
figure, since no catalogue records what a replaced module was bought for. Unlike
mass and capacity it is not recomputed from what remains; sourcePurchase
keeps the captured figure and BuildMetrics.buildCost prices the current fit.
number | null
get rebuy():
number|null
Defined in: src/ships/ship-loadout.ts:891
Insurance rebuy cost in credits represented by the build, or null if
unknown. Discarded by an edit or by import normalization for the same reason as
modulesValue, and likewise kept by sourcePurchase;
BuildMetrics.buildCost rebuys the current fit at catalogue prices instead.
number | null
get shipIdent():
string|null
Defined in: src/ships/ship-loadout.ts:803
The player-given ID plate, or null if the build has none.
string | null
get shipName():
string|null
Defined in: src/ships/ship-loadout.ts:798
The player-given ship name, or null if the build has none.
string | null
get shipSymbol():
string
Defined in: src/ships/ship-loadout.ts:793
The hull's internal id, e.g. "explorer_nx".
string
get sourcePurchase():
SourcePurchaseRecord|null
Defined in: src/ships/ship-loadout.ts:928
What the capture this build came from said was paid for it — a read-only
SourcePurchaseRecord, or null for a build assembled here or imported
from a capture that quoted no credits at all.
The record is provenance about the source, so it is fixed at import and survives every edit: fit, remove or engineer whatever you like and it still reports the figures the capture carried, for the modules the capture carried them for. That is what hullValue, modulesValue and rebuy cannot do — they describe the build in hand, so an edit that invalidates one drops it.
A captured price belongs to one commander's purchase history, discounts included; the library's own figures are catalogue retail. Export quotes retail unless asked otherwise — see LoadoutExportOptions.credits.
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
import { getSourceModuleValue } from '@elite-dangerous-almanac/core/ships/source-purchase';
declare const slefJson: string;
const build = ShipLoadout.fromSlef(slefJson);
const paid = build.sourcePurchase!;
paid.hullValue; // -> 189326510, as captured
getSourceModuleValue(paid, 'powerplant')?.value; // -> what that plant cost its owner
build.removeModule('Slot05_Size4');
build.modulesValue; // -> null unavailable after the edit
paid.modulesValue; // -> 192625195, the captured figureSourcePurchaseRecord | null
get unladenMass():
number
Defined in: src/ships/ship-loadout.ts:816
Hull + modules mass with an empty tank and no cargo, in tonnes.
A capture's own UnladenMass stands while the fit it described survives import
(see fromLoadout); otherwise this is the hull's hullMass plus every
fitted module's post-engineering mass, and importOutcomes is the only
report that the figure is the normalized fit's rather than the capture's.
number
applyBlueprint(
slotKey,blueprintSymbol,options):this
Defined in: src/ships/ship-loadout.ts:1580
Engineer the module in a slot — apply a blueprint (with a grade and quality) and an optional experimental effect, computing the resulting stat modifiers.
The modifiers are stored on the fitted module with journal-equivalent labels and
Frontier's float32 arithmetic, so the build's own calculations pick them up. The
block keeps the BlueprintName you passed. Weapon recipe internals such as
BurstInterval are exposed as the derived RateOfFire and DamagePerSecond
labels a journal writes, and module-specific aliases use the journal spelling too
(MaximumRange, Range); recipe-only values a journal serializes no label for
stay available through FittedModule.effectiveStats, which is what keeps
burst and reload-cycle calculations faithful.
Which recipe an id names can depend on the module. The game writes
Sensor_LongRange for both a sensor suite's modification and a utility scanner's,
and the two roll different stats in opposite directions, so the id is resolved
against the module's own menu before anything is computed. Reading a stored block
back means resolving it the same way: resolveBlueprintForModule in
ships/blueprint-journal is that lookup.
string
The slot whose module to engineer, matched case-insensitively (journal spelling).
string
The blueprint recipe's Frontier symbol, e.g. "FSD_LongRange".
ApplyBlueprintOptions: grade (1–5), optional quality
(0–1, default 1), and optional experimental effect symbol. A nullish
experimental means no effect, the same as leaving it out. Each is read once,
before anything is checked, so an accessor cannot answer the check and the use
differently.
this
this, for chaining.
If the slot is empty, or the blueprint/grade/experimental is
unknown, or quality is outside [0, 1].
If slotKey or blueprintSymbol is not a string, options is not an
object, or options.experimentalEffectSymbol carries a value that is not a string — a nullish
one is no effect, not a wrong type. Also if the fitted module has no stats to
engineer, is final and accepts no further engineering, is not offered the blueprint
by its own menu, is not offered the experimental effect by it, or the id names a
fixed event-reward identity rather than a craftable recipe — use
setPreEngineeredVariant for those. Finally, if the catalogue does not carry
every base stat the recipe modifies: incomplete engineering is rejected rather than
stored as a partial journal modifier block.
import { BuildMetrics } from '@elite-dangerous-almanac/core/ships/build-metrics';
import { getModuleBySymbol } from '@elite-dangerous-almanac/core/ships/modules';
import { CORE_MODULES } from '@elite-dangerous-almanac/core/ships/modules-core';
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
const fsd = getModuleBySymbol('Int_Hyperdrive_Size6_Class5', CORE_MODULES)!;
build.setModule('FrameShiftDrive', fsd)
.applyBlueprint('FrameShiftDrive', 'FSD_LongRange', {
grade: 5,
experimentalEffectSymbol: 'special_fsd_heavy',
});
BuildMetrics.of(build).maxJumpRange(); // uses the engineered optimal massavailableBlueprints(
slotKey): readonlyAvailableBlueprint[]
Defined in: src/ships/ship-loadout.ts:1154
Return the computable blueprint candidates for a fitted module symbol.
string
Slot key, matched case-insensitively.
readonly AvailableBlueprint[]
Frozen blueprint descriptors: the ordinary engineering menu first, then
bespoke Mercenary upgrade recipes. An 'ordinary' candidate is available to the
stock module; a 'mercenary' candidate is purchase-specific. Applying that bespoke
blueprint identifies the matching Mercenary article even though its bare module
symbol does not.
Returns an empty array when the slot is empty, unresolved or final, or the module
symbol has neither route.
If slotKey is not a string.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
build.availableBlueprints('FrameShiftDrive').map(({ blueprintSymbol }) => blueprintSymbol);availableExperimentalEffects(
slotKey): readonlystring[]
Defined in: src/ships/ship-loadout.ts:1178
Return the computable experimental effects offered to a fitted module.
string
Slot key, matched case-insensitively.
readonly string[]
Frozen Frontier effect ids in engineering-menu order, or an empty array when the slot is empty, unresolved, final, or has no experimental menu.
If slotKey is not a string.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
build.availableExperimentalEffects('FrameShiftDrive');
// -> ['special_fsd_heavy', ...]clearEngineering(
slotKey):this
Defined in: src/ships/ship-loadout.ts:2251
Strip engineering from a slot's module, restoring its base stats.
string
The slot to de-engineer, matched case-insensitively (journal spelling).
this
this, for chaining. A no-op if the slot is empty or unmodified.
If slotKey is not a string, or the fitted article is final
pre-engineered and its baked engineering cannot be removed.
Clearing a Mercenary article removes its purchase-exclusive blueprint identity.
Its FittedModule.preEngineeredVariant then reads null.
completeEngineeringGrade(
slotKey):EngineeringNormalizationResult
Defined in: src/ships/ship-loadout.ts:1983
Recompute the fitted module's current engineering identity at quality 1.
Imported modifier values remain authoritative until this method is called. An ordinary or Mercenary recipe is rerolled through the package calculator; a fixed reward rebuilds its hand-authored modifiers and optional effect without losing its purchase identity. A refusal never changes the loadout.
A block that names a blueprint and grade but states no Modifiers at all is rolled
here too, even at quality 1 — SLEF permits that identity-only shape and Inara
writes it, so a capture of a completed roll would otherwise stay stock. A stated
modifier array, empty or partial, is left alone at quality 1.
string
The engineered slot, matched case-insensitively.
EngineeringNormalizationResult
A frozen result identifying a normalized, unchanged or unsupported state.
If slotKey is not a string.
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
const partial = ShipLoadout.default('SideWinder').applyBlueprint(
'FrameShiftDrive',
'FSD_LongRange',
{ grade: 5, quality: 0.42 },
);
const imported = ShipLoadout.fromLoadout(partial.toLoadoutEvent());
imported.completeEngineeringGrade('FrameShiftDrive').kind; // -> 'normalized'
imported.fittedModuleAt('FrameShiftDrive')?.engineering?.Quality; // -> 1fittedModuleAt(
slotKey):FittedModule|null
Defined in: src/ships/ship-loadout.ts:1088
A deeply frozen, point-in-time view of the module in a slot.
string
Slot key, matched case-insensitively.
FittedModule | null
A detached, frozen view, or null when the slot is empty or unknown.
If slotKey is not a string.
fittedModules(): readonly
FittedModule[]
Defined in: src/ships/ship-loadout.ts:1124
Every fitted module as a deeply frozen point-in-time view.
readonly FittedModule[]
Detached module snapshots in the order the build carries them. The array and every nested record are frozen; query again after an edit for current state.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
build.fittedModules().map((module) => `${module.slot}: ${module.symbol}`);modulesForSlot(
slotKey):OutfittingModule[]
Defined in: src/ships/ship-loadout.ts:1208
The modules that fit a given slot — its size, kind and any restriction all satisfied, with candidates that would worsen a one-per-ship or module-count limit omitted.
string
The slot key to fit, matched case-insensitively (journal spelling).
The fitting modules, in complete-catalogue order.
This is the outfitting offer, so the fifteen grantOnly
articles are never in it: each is a second identity for a module the game already
sells — Int_Engine_Size2_Class1_free is the 2E Thrusters — and listing both puts
the same article on the screen twice, once with no price. A build that already
carries one keeps it; only the choices are filtered.
If the hull has no slot with that key.
If slotKey is not a string.
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
ShipLoadout.empty('Anaconda').modulesForSlot('FrameShiftDrive');removeModule(
slotKey):this
Defined in: src/ships/ship-loadout.ts:1476
Empty a slot.
string
The slot key to clear, matched case-insensitively (journal spelling).
this
this, for chaining. Clearing an already-empty removable slot is a no-op.
If slotKey is not a string.
If the slot is the built-in cargo hatch; is a required core or armour mount; or removing the module would worsen a per-ship module-count excess. Required mounts may be replaced with setModule but cannot be emptied.
repairFixedMount(
slotKey):FixedMountRepairResult
Defined in: src/ships/ship-loadout.ts:1253
Refit a fixed mount from this hull's stock loadout.
string
Fixed slot key, matched case-insensitively.
A frozen FixedMountRepairResult. Refusals leave the build unchanged.
This is the repair path for the mounts setModule does not expose as ordinary
edits — in practice the built-in cargo hatch. The stock article keeps the mount's
On, Priority and Health and none of the replaced module's engineering or
captured value, as import normalization does. Every entry point already fills these
mounts, so a build this package produced answers unchanged.
If slotKey is not a string.
If a known hull has no slot with that key.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const imported: ShipLoadout;
imported.repairFixedMount('CargoHatch').status; // -> 'unchanged'setExperimentalEffect(
slotKey,experimental):ExperimentalEffectMutationResult
Defined in: src/ships/ship-loadout.ts:1776
Add, replace or remove only the fitted module's experimental effect.
Ordinary and Mercenary engineering is recomputed at its current blueprint, grade and quality. A fixed reward instead retains its hand-authored modifiers and purchase identity while the requested effect is composed with them. Refused edits leave the build unchanged and return stable structured data.
string
The engineered slot, matched case-insensitively.
string | null
Experimental-effect symbol, or null to remove the effect.
ExperimentalEffectMutationResult
A frozen result identifying an update, no-op or lossless refusal.
If slotKey or a non-null experimental is not a string.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
build.setExperimentalEffect('FrameShiftDrive', 'special_fsd_heavy');
build.setExperimentalEffect('FrameShiftDrive', null);setModule(
slotKey,module):this
Defined in: src/ships/ship-loadout.ts:1357
Fit a module into a slot, replacing whatever is there.
string
The slot key to fit into, matched case-insensitively (journal spelling). An occupied slot keeps the key the build already spells it with, so fitting into an import never renames one of its mounts.
The module to fit (resolve it from a catalogue first, e.g. with
getModuleBySymbol). The complete record is snapshotted, so a result from
getPreEngineeredStats or a record you adjusted yourself keeps its stats — but it
must name an article the built-in catalogue carries, and it may not drop that
article's mass, cargoCapacity or fuelCapacity, which every build sums, nor
state one as anything but a finite number.
this
this, for chaining.
This is an incremental editor: every call must avoid worsening the current build's module-count excess, so fit an allowance-increasing module before the weapons it permits. Use ShipLoadout.fromLoadout to consume a complete snapshot instead, where order does not matter.
Fitting is a fresh mount: the slot's On, Priority and Health are reset. Set
them again if your screen keeps a priority group across a swap.
If the hull has no slot with that key.
If slotKey is not a string, or module fails any of the
conditions above — null/undefined (e.g. a getModuleBySymbol miss), not an
outfitting module, an uncatalogued symbol, or a missing or non-finite summed stat.
If the module does not fit the slot (wrong kind, too large, or a restriction the module does not satisfy), conflicts with a one-per-ship family already fitted elsewhere, or worsens a per-ship module-count excess.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
import { getModuleBySymbol } from '@elite-dangerous-almanac/core/ships/modules';
import { CORE_MODULES } from '@elite-dangerous-almanac/core/ships/modules-core';
const fsd = getModuleBySymbol('Int_Hyperdrive_Size6_Class5', CORE_MODULES)!;
const tank = getModuleBySymbol('Int_FuelTank_Size6_Class3', CORE_MODULES)!;
build.setModule('FrameShiftDrive', fsd).setModule('Slot01_Size7', tank);setModuleEnabled(
slotKey,on):this
Defined in: src/ships/ship-loadout.ts:2290
Switch a fitted module on or off.
string
The slot's journal key, e.g. "PowerPlant", matched
case-insensitively.
boolean
true to power it, false to switch it off.
this
this, for chaining.
If the slot is empty.
If slotKey is not a string.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
build.setModuleEnabled('TinyHardpoint6', false); // an unpowered heat sinksetModulePriority(
slotKey,priority):this
Defined in: src/ships/ship-loadout.ts:2306
Set a fitted module's power-priority group.
string
The slot's journal key, matched case-insensitively.
number
The journal's zero-based group, 0–4. Note that the
outfitting panel — and BuildMetrics.powerBudget's bands[].priority — number the same
five groups 1–5.
this
this, for chaining.
If the slot is empty, or priority is not an integer in [0, 4].
If slotKey is not a string.
setPreEngineeredVariant(
slotKey,variant):this
Defined in: src/ships/ship-loadout.ts:2177
Fit a pre-engineered variant into a slot, replacing whatever is there.
The variant's fixed stats and journal engineering block are resolved together.
Articles carry Level, Quality: 1, any baked experimental effect and their fixed
modifiers. Because the variant names its base module, a decorative identity cannot
be applied to an unrelated damage-bearing module.
A Mercenary variant whose fixed modifier block has not been published retains the
stock catalogue stats and omits Modifiers rather than claiming it changes none.
string
The slot key to fit into, matched case-insensitively.
The pre-engineered catalogue variant to fit.
this
this, for chaining.
If variant is not a pre-engineered variant or one of its
authored modifier labels cannot be resolved for its base module.
If no catalogue row matches the supplied module, blueprint, grade, experimental effect and acquisition route.
If the variant's base module does not fit the slot or violates a fitted-module limit.
import { getPreEngineeredVariants } from '@elite-dangerous-almanac/core/ships/pre-engineered';
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
const festive = getPreEngineeredVariants('Hpt_FlakMortar_Turret_Medium')
.find((variant) => variant.blueprintSymbol === 'Decorative_Red')!;
const build = ShipLoadout.empty('Krait_MkII')
.setPreEngineeredVariant('MediumHardpoint1', festive);
build.fittedModuleAt('MediumHardpoint1')?.effectiveStats?.damage; // -> 0.34slots(
kind?): readonlyLoadoutSlot[]
Defined in: src/ships/ship-loadout.ts:1048
Frozen point-in-time views of the hull's mounts in outfitting-panel order.
Optionally keep only one mount kind. Omit it for every mount.
readonly LoadoutSlot[]
Detached, frozen slot views. Repeated reads for the same kind reuse the
same snapshots until a state-changing edit.
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
const emptyHardpoints = ShipLoadout.empty('Sidewinder').slots('hardpoint');
emptyHardpoints.every((slot) => slot.module === null); // truetoLoadoutEvent(
options?):LoadoutEvent
Defined in: src/ships/ship-loadout.ts:2364
This build as a journal Loadout event — the data half of a SLEF entry.
LoadoutExportOptions = {}
Module ordering and how sparse to be about power state.
A fresh event. Every top-level figure is recomputed from the hull and
the fitted modules rather than echoed from whatever an import supplied — the one
exception being the credits, when credits: 'source' asks for the capture's own.
Any figure that cannot be worked out is left out rather than emitted as a stale
or zero value — SLEF requires nothing beyond Ship and Modules.
Credits are quoted at retail by default: the bare hull's hullCost plus every
fitted module's catalogue list price, with Rebuy 5% of the two. A source's own
HullValue / ModulesValue / Value figures are deliberately not quoted here,
because they record one commander's purchase history — the Deep Black's modules
are all 12.25% off list — and purchase discounts are not a property of the build.
They are not lost either: pass credits: 'source' to export the
sourcePurchase record instead, as provenance rather than as a price.
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
const event = build.toLoadoutEvent();
event.MaxJumpRange; // recomputed, not the exporter's claim
event.HullValue; // the catalogue's list price
build.toLoadoutEvent({ credits: 'source' }).HullValue; // what the capture paidtoSlef(
options):Slef
Defined in: src/ships/ship-loadout.ts:2405
This build as a one-entry SLEF export.
Ordering, power state, and the envelope header.
The export. Several builds travel together as
toSlef([a.toLoadoutEvent(), b.toLoadoutEvent()]) using the function of the same
name from ./slef.
toSlefString(
options):string
Defined in: src/ships/ship-loadout.ts:2422
This build as SLEF JSON — ready to write to a file or put on the clipboard.
As toSlef, plus indent (compact by default).
string
import type { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
declare const build: ShipLoadout;
build.toSlefString({ header: { appName: 'MyApp', appVersion: '1.0.0' } });validation():
LoadoutValidation
Defined in: src/ships/ship-loadout.ts:981
Structural validity and operational completeness of this build.
The validation report, recomputed from the current fit on every call.
valid asks whether the fit is legal: a module in a nonexistent or incompatible
slot, a duplicated exclusive family, a module count past the build's allowance, or
a ship heavier than its own thrusters can move makes it false. complete asks
that and whether armour and the seven core mounts are filled — every build fills
those, so on a build the two answers agree. Neither question reports import
normalization, so read importOutcomes beside them.
The thruster rule weighs the fitted thrusters' post-engineering maxMass against
what the ship comes to at each load it can reach without being re-fitted:
unladenMass alone, then with a full main tank, then
with a full hold as well. The lightest of those that is
already too heavy is what gets reported. A ship that cannot move on a full tank is
an error — it never leaves the pad, where the tank always is one — while a ship
that only fails with the hold full is a warning, and leaves the build valid and
complete: how much cargo to take is the pilot's call. Either way
BuildMetrics.mobilityMetrics reports
a speed of zero at the load in question.
A capture may state a mass nobody can weigh — a negative UnladenMass, or an
engineering modifier that drives a rating below zero. Neither is refused here:
this method reports a build rather than rejecting one, so an unweighable figure is
left out and the rule it feeds simply does not run. The figure itself is still
reported, as a thrown one, by whichever BuildMetrics
calculation reads it.
staticdefault(shipSymbol):ShipLoadout
Defined in: src/ships/ship-loadout.ts:770
Start a new build with the modules supplied on a stock ship.
string
The hull's internal symbol, e.g. "SideWinder"
(case-insensitive).
ShipLoadout
A complete, ready-to-edit stock loadout. The build is independent of the frozen shared catalogue: edits affect this instance only.
If shipSymbol is not a string, or no default loadout exists
for that hull.
This batteries-included factory resolves calculations through the complete module
catalogue already used by ShipLoadout. If only the stock slot/module identities
are needed, getDefaultLoadout from ./default-loadouts avoids that cost.
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
const stock = ShipLoadout.default('SideWinder');
stock.validation().complete; // -> true
stock.fittedModuleAt('FrameShiftDrive')?.symbol;
// -> 'Int_Hyperdrive_Size2_Class1'
staticempty(shipSymbol):ShipLoadout
Defined in: src/ships/ship-loadout.ts:720
Start a new build for a hull with only its stock core modules fitted.
string
The hull's internal symbol, e.g. "Anaconda"
(case-insensitive).
ShipLoadout
A loadout on the hull's stock bulkhead, core internals and cargo hatch, with every hardpoint, utility mount and optional internal left open. Use default for a build that also carries the hull's stock weapons and optional internals.
If shipSymbol is not a string, or no hull with that symbol
has a known slot layout.
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';
ShipLoadout.empty('Sidewinder').slots('hardpoint').length; // -> 2
staticfromLoadout(event):ShipLoadout
Defined in: src/ships/ship-loadout.ts:669
Build from a bare journal Loadout event (the data half of a SLEF entry).
A Loadout event object.
ShipLoadout
The loadout.
Capture and instance state (timestamp, ShipID, HullHealth, Hot) and
engineering provenance (Engineer, EngineerID, BlueprintID) stay out of the
durable build. A pre-engineered article — a reward, a Mercenary purchase, a
Guardian weapon — is identified where the capture's evidence names one uniquely,
and the catalogue's stat block then supplies the values the capture omits; the
capture's own modifiers stay authoritative over it.
Modules are imported as one complete snapshot, so their order does not affect
per-ship count allowances. An entry stands as the event stated it when the mount
can hold the article the catalogue resolves, when its slot is a known cosmetic or
hull-geometry key (PaintJob, ShipCockpit, a numbered decal, …), or when it is
the built-in cargo hatch. Everything else is normalized, and every change is
recorded by importOutcomes: an unresolved module in a removable mount is
discarded, while armour, the seven core internals and the cargo hatch are filled
from the hull defaults whenever the event left no article that mount can hold — an
unresolved symbol, a resolved one the mount refuses, and no entry at all are
corrected alike, each keeping the source's On, Priority and Health. A
removable mount may stand empty, so an article it refuses stays where the event
put it and is reported by validation() instead.
Normalization makes the captured aggregates untrustworthy, so they are dropped:
unladenMass, cargoCapacity and fuelCapacity are recomputed
from the fit that remains, modulesValue and rebuy read null, and
sourcePurchase still reports what the capture stated. A mount stocked from
absence is the exception where its stock article is free and weightless — the
bulkhead and the cargo hatch both are — and every figure stands.
Use this factory rather than replaying a complete loadout through the incremental setModule editor.
If the event is not shaped like one. What is checked is the
structure a build is assembled from and the fields that name things in it: event
must be an object with an array of module objects in Modules, each carrying a
string Slot and Item, no two claiming the same slot; event.Ship must name a
known hull; an Engineering block must be an object and its Modifiers an array
of objects each carrying a string Label, whenever the key is there at all; that
block's BlueprintName and ExperimentalEffect must be strings when they carry a
value. A modifier's Label is required rather than checked-when-present because it
is the only thing saying which stat moved. Every remaining field — every number,
every flag, a modifier's value beside its label — is trusted, so use
ShipLoadout.fromSlef (or parseSlef) for input you did not produce,
which reports all of them.
staticfromSlef(input,index?):ShipLoadout
Defined in: src/ships/ship-loadout.ts:602
Build from a SLEF export.
unknown
The SLEF JSON string, or an already-parsed SLEF object (see parseSlef for accepted shapes).
number = 0
Which entry to take when the export holds several builds. Defaults to the first.
ShipLoadout
The loadout for that entry.
Module normalization follows ShipLoadout.fromLoadout; inspect importOutcomes for modules that were emptied or defaulted.
If input is a string that is not valid JSON.
If the export holds no usable loadout, index is out of range,
or the selected entry names a hull absent from the catalogue.
Guides
astro
Classes (1)
ProceduralSystem
Properties
Accessors
Methods
Interfaces (16)
Type Aliases (3)
Variables (11)
Functions (37)
- absoluteBoxelToBoxelCode
- boxelCodeToAbsoluteBoxel
- boxelCodeToLetters
- boxelEdgeLy
- boxelInternalSize
- canonicalizeSectorName
- canonicalizeSystemName
- decodeModSystemAddress
- decodeSystemAddress
- encodeModSystemAddress
- encodeSystemAddress
- findHandAuthoredRegionAt
- formatSystemName
- getCodexRegion
- getCodexRegionByName
- getHandAuthoredRegionOrigin
- getNebulaByName
- isPermitLockedRegionName
- isPermitLockedSystemName
- isProceduralSystemName
- lettersToBoxelCode
- massCodeToSizeClass
- nearestNebulae
- nebulaeWithin
- parseSystemName
- permitLockedRegionForSystemName
- permitLockedSystemForAddress
- permitLockedSystemForName
- permitLockForSystemName
- resolveNamingRegionOrigin
- sectorGridPositionFromGalacticPosition
- sectorGridPositionFromName
- sectorNameFromGalacticPosition
- sectorNameFromGridPosition
- sizeClassToMassCode
- toSystemAddress
- tryToSystemAddress
commodities
Interfaces (1)
Type Aliases (1)
Variables (3)
Functions (3)
equipment
Interfaces (6)
Type Aliases (8)
Variables (3)
Functions (10)
Subpath modules (2)
i18n
Interfaces (1)
Type Aliases (1)
Functions (17)
- getBlueprintName
- getCalculationIssueMessage
- getEngineeringGroupName
- getExperimentalEffectDescription
- getExperimentalEffectName
- getLoadoutEditErrorMessage
- getLoadoutIssueMessage
- getLoadoutSlotName
- getMaterialName
- getMicroResourceName
- getModuleName
- getOutfittingFamilyName
- getPreEngineeredVariantName
- getShipManufacturer
- getShipName
- getSlefDiagnosticMessage
- getSlotRestrictionLabel
materials
Enumerations (2)
Interfaces (2)
Type Aliases (2)
Variables (9)
ships
Classes (3)
BuildMetrics
Methods
- armourMetrics()
- buildCost()
- buildMass()
- cellBanks()
- distributorMetrics()
- distributorMetricsResult()
- frameShiftDrive()
- frameShiftDriveMassFactor()
- fuelPerJump()
- heatMetrics()
- heatMetricsResult()
- jumpRange()
- jumpRangeSummary()
- ladenJumpRange()
- loadout()
- maxJumpRange()
- mobilityCapacitorMetrics()
- mobilityCapacitorMetricsResult()
- mobilityMetrics()
- mobilityMetricsResult()
- powerBudget()
- shieldCapacitorMetrics()
- shieldCapacitorMetricsResult()
- shieldMetrics()
- shieldMetricsResult()
- shieldRecovery()
- shieldRecoveryResult()
- standardLoad()
- standardLoadResult()
- thrusters()
- totalRange()
- weaponMetrics()
- weaponsCapacitorMetrics()
- of()
LoadoutEditError
Constructors
Properties
Methods
ShipLoadout
Accessors
- cargoCapacity
- fuelCapacity
- hullValue
- importOutcomes
- modulesValue
- rebuy
- shipIdent
- shipName
- shipSymbol
- sourcePurchase
- unladenMass
Methods
- applyBlueprint()
- availableBlueprints()
- availableExperimentalEffects()
- clearEngineering()
- completeEngineeringGrade()
- fittedModuleAt()
- fittedModules()
- modulesForSlot()
- removeModule()
- repairFixedMount()
- setExperimentalEffect()
- setModule()
- setModuleEnabled()
- setModulePriority()
- setPreEngineeredVariant()
- slots()
- toLoadoutEvent()
- toSlef()
- toSlefString()
- validation()
- default()
- empty()
- fromLoadout()
- fromSlef()
Interfaces (125)
- AmmunitionCapacity
- AmmunitionStats
- ApplyBlueprintOptions
- ArmourInput
- ArmourMetrics
- AvailableBlueprint
- Blueprint
- BlueprintFeature
- BlueprintGrade
- BlueprintModuleEngineering
- BuildCost
- BuildCredits
- BuildMass
- BuildSlotBase
- BuildWeaponMetrics
- BulkheadParams
- CalculationIssue
- CellBankInput
- CellBankMetrics
- CellBankSummary
- CoreBuildSlot
- CoreSlots
- DamageComponents
- DamageDistribution
- DamageResistanceParams
- DamageSplit
- DamageTypeValues
- DistributorCapacitorMetrics
- DistributorInput
- DistributorMetrics
- DistributorOptions
- DistributorPips
- EngineeringMaterial
- EngineeringModifier
- EngineeringNormalizationUnchanged
- EngineeringNormalizationUnsupported
- EngineeringNormalized
- EngineeringOptionGroup
- ExperimentalContribution
- ExperimentalEffect
- ExperimentalEffectUnchanged
- ExperimentalEffectUnsupported
- ExperimentalEffectUpdated
- FittedModule
- FittedWeaponMetrics
- FrameShiftDriveJumpStats
- FrameShiftDriveParams
- FuelCapacity
- GunsightPoint
- HardpointBuildSlot
- HardpointSlotSpec
- HeatInput
- HeatMetrics
- HeatState
- HeatWeapon
- HullReinforcementParams
- JumpOptions
- JumpRangeSummary
- LoadoutCalculationModule
- LoadoutEvent
- LoadoutExportOptions
- LoadoutIssue
- LoadoutMass
- LoadoutModule
- LoadoutValidation
- LoadoutValidationInput
- MassCurveStats
- MobilityCapacitorInput
- MobilityCapacitorMetrics
- MobilityCapacitorOptions
- MobilityInput
- MobilityMetrics
- ModuleLimitEntry
- ModuleLimitIncrease
- ModuleLimitUsage
- ModuleReinforcementParams
- OptionalBuildSlot
- OptionalSlotSpec
- OutfittingModule
- OutfittingModuleIdentity
- OutfittingModuleStats
- ParsedSlot
- PowerBand
- PowerBudget
- PowerConsumer
- PowerConsumerResult
- PowerDistributorStats
- PowerGenerationStats
- PreEngineeredModifier
- PreEngineeredVariant
- ProjectileRangeBoundaries
- ShieldBoosterParams
- ShieldCapacitorInput
- ShieldCapacitorMetrics
- ShieldCapacitorOptions
- ShieldGeneratorParams
- ShieldInput
- ShieldMetrics
- ShieldRecovery
- ShieldRecoveryInput
- ShieldRecoveryOptions
- ShieldRegenerationStats
- Ship
- ShipSlots
- SimpleBuildSlot
- SlefDiagnostic
- SlefEntry
- SlefExportOptions
- SlefHeader
- SlefInspection
- SlefStringifyOptions
- SourceModuleValue
- SourcePurchaseRecord
- StandardLoadInputs
- ThrusterCurveParams
- ThrusterParams
- TotalRangeDetails
- ValidationModule
- WeaponDamageStats
- WeaponMetrics
- WeaponsCapacitorInput
- WeaponsCapacitorMetrics
- WeaponsOptions
- WeaponStats
- WeaponTotals
Type Aliases (44)
- BlueprintGrades
- BuildSlot
- CalculationIssueReason
- CalculationResult
- CoreSlotType
- DamageResistances
- DamageType
- EngineeringGroupId
- EngineeringNormalizationCode
- EngineeringNormalizationResult
- ExperimentalEffectMutationCode
- ExperimentalEffectMutationResult
- FixedMountRepairResult
- GunsightOffset
- HardpointRestriction
- ImmovableReason
- LoadoutEditErrorCode
- LoadoutImportOutcome
- LoadoutIssueCode
- LoadoutIssueParam
- LoadoutIssueParams
- LoadoutSlot
- ModifierMethod
- ModuleCategory
- ModuleEngineering
- ModuleExclusionGroup
- ModuleFitConstraint
- ModuleGuidance
- ModuleLimitGroup
- ModuleMount
- ModuleRating
- ModuleSlot
- OptionalRestriction
- OutfittingFamilyId
- PreEngineeredAcquisition
- ShipGunsight
- ShipGunsightCatalogue
- Slef
- SlefConstraint
- SlefDiagnosticCode
- SlotKind
- SlotRestriction
- StandardLoad
- ThrusterLoad
Variables (10)
Functions (85)
- ammunitionCapacity
- armourMetrics
- armourPiercingFactor
- calculateCargoCapacity
- calculateFuelCapacity
- calculateModuleLimits
- calculateUnladenMass
- cellBankSummary
- combinedRateOfFire
- computeModifiers
- damageFalloff
- damagePerSecond
- distributorMetrics
- effectiveHitPoints
- effectiveWeaponThermalLoad
- energyPerSecond
- enumerateSlots
- equilibriumHeatLevel
- frameShiftDriveMassFactor
- fuelPerJump
- getBlueprint
- getBlueprintGrade
- getBlueprintsForModule
- getBulkheadsForShip
- getEngineeringGroup
- getExperimentalEffect
- getExperimentalsForBlueprint
- getExperimentalsForModule
- getLoadoutModifier
- getModuleBySymbol
- getModulesByName
- getPreEngineeredJournalModifiers
- getPreEngineeredModifiers
- getPreEngineeredStats
- getPreEngineeredVariants
- getShipByName
- getShipBySymbol
- getShipGunsight
- getShipSlots
- getSourceModuleValue
- hasFrameShiftDriveJumpStats
- hasMassCurveStats
- hasPowerDistributorStats
- hasPowerGenerationStats
- hasShieldRegenerationStats
- hasWeaponDamageStats
- heatLevelAtTime
- heatMetrics
- heatPerSecond
- identifyPreEngineeredVariant
- inspectSlef
- isPreEngineered
- mapDamageTypes
- mobilityCapacitorMetrics
- mobilityMetrics
- parseSlef
- parseSlotName
- powerBudget
- projectGunsight
- resolveBlueprintForModule
- secondsToHeatLevel
- shieldCapacitorMetrics
- shieldMassCurveMultiplier
- shieldMetrics
- shieldRecovery
- shieldStrength
- singleJumpRange
- sourcePurchaseFromLoadout
- splitDamage
- stackArmourResistance
- stackShieldResistance
- stringifySlef
- sumMaterials
- sumSourceModuleValues
- sumWeaponMetrics
- sustainedDamagePerSecond
- sustainedFireFactor
- systemsResistance
- thrusterMassCurveMultiplier
- toSlef
- totalRange
- unresolvedModifiers
- validateLoadout
- weaponMetrics
- weaponsCapacitorMetrics