Skip to content

ships.Interface.OutfittingModuleIdentity

github-actions[bot] edited this page Aug 26, 2026 · 73 revisions

@elite-dangerous-almanac/core / ships / OutfittingModuleIdentity

Interface: OutfittingModuleIdentity

Defined in: src/ships/modules.ts:254

Identity, classification, fit constraints, and price for one outfitting module.

Remarks

The core identity fields (symbol, name, category, familyId, class, and rating) are always present. Optional fields describe fit restrictions, purchase entitlement, and price. Performance data belongs to OutfittingModuleStats; the complete flat catalogue record is OutfittingModule.

Example

import type { OutfittingModuleIdentity } from '@elite-dangerous-almanac/core/ships/modules';

const identity: OutfittingModuleIdentity = {
  symbol: 'CustomBeamLaser',
  category: 'hardpoint',
  engineeringGroup: 'beamLasers',
  familyId: 'beamLasers',
  name: 'Custom Beam Laser',
  class: 2,
  rating: 'D',
};

Extended by

Properties

category

readonly category: ModuleCategory

Defined in: src/ships/modules.ts:268

Which kind of slot the module fits.

Remarks

Derived from the catalogue the record was read from rather than stored on it — CORE_MODULES is what makes a record 'core' — so it is always present and always agrees with the catalogue you found the module in — it is written after the record's own fields, so the file wins outright. That also makes it the last key on the record, which is worth knowing only if you serialize one and compare the resulting string.


class

readonly class: number

Defined in: src/ships/modules.ts:342

The module size, 08 — the number in the "5A" the outfitting screen shows.

Remarks

Frontier calls this the module class; it is the slot-size number, not the grade letter (that is OutfittingModule.rating). Named class to match the source registry.


cost?

readonly optional cost?: number

Defined in: src/ships/modules.ts:474

Standard purchase price, in credits — the base list price before any station discount or markup, which is what an outfitting screen quotes at 0% discount.

Remarks

Absent on the handful of records no registry prices: the starter *_free variants, the size-8 frame shift drives, and a few internals no outfitting registry carries a figure for — among them the two Corrosion Resistant Cargo Racks no station sells, which are not free. Treat undefined as "unknown", never as free — see data/ships/SOURCES.md.


engineeringGroup

readonly engineeringGroup: EngineeringGroupId | null

Defined in: src/ships/modules.ts:273

Stable engineering-menu family, or null when the stock module has no ordinary engineering menu. See EngineeringGroupId.


entitlement?

readonly optional entitlement?: string

Defined in: src/ships/modules.ts:365

Frontier's DLC / purchase-grant entitlement token, e.g. "ELITE_HORIZONS_V_PLANETARY_LANDINGS". Present only on gated modules.


exclusionGroup?

readonly optional exclusionGroup?: ModuleExclusionGroup

Defined in: src/ships/modules.ts:447

One-per-ship family, absent when the module has no exclusive fitting rule. Two fitted modules sharing this id are structurally invalid.


familyId

readonly familyId: OutfittingFamilyId

Defined in: src/ships/modules.ts:289

Stable outfitting family used to group an outfitting list, such as 'cargoRacks', 'shieldGenerators' or 'beamLasers'. See OutfittingFamilyId.

Remarks

Every record carries one, core modules included, so every choice ShipLoadout.modulesForSlot returns has a family. Closely related variants share it: Bi-Weave and Prismatic generators are 'shieldGenerators', Mk II and corrosion-resistant racks are 'cargoRacks', and a Powerplay or pre-engineered variant stays with its base weapon's family.

OUTFITTING_FAMILIES gives the canonical English display name; getOutfittingFamilyName in i18n/module-families gives a localized one.


grantOnly?

readonly optional grantOnly?: true

Defined in: src/ships/modules.ts:385

true on an article that arrives granted — with a hull or with a bundle — and that no outfitting screen sells. Absent on every module a station offers.

Remarks

The fifteen are the nine starter *_free fittings and the six bundle-granted Vessel Hangars. Each is a second identity for an article the game already sells: Int_Engine_Size2_Class1_free is the 2E Thrusters again, which is why ShipLoadout.modulesForSlot leaves them out — a picker that offered both would list "2E Thrusters" twice, once unpriced.

They are still real fitted articles, so they stay in the catalogues and every lookup resolves one: a build imported from a journal can carry one, and getModuleBySymbol answers for it like any other symbol. Absent is not false — nothing carries grantOnly: false.

Do not read it as a price: OutfittingModule.cost is missing on these but also on articles that are sold and simply unpriced by every registry.


guidance?

readonly optional guidance?: ModuleGuidance

Defined in: src/ships/modules.ts:354

A missile/torpedo hardpoint's guidance. Present only on the launchers that have one; absent on everything else.


limitGroup?

readonly optional limitGroup?: "experimentalWeapon"

Defined in: src/ships/modules.ts:453

Per-ship count limit this fitted module consumes, absent when it consumes none. Read the base allowance and current usage with calculateModuleLimits from ships/module-limits rather than inferring the family from a symbol or name.


limitIncrease?

readonly optional limitIncrease?: ModuleLimitIncrease

Defined in: src/ships/modules.ts:462

Increase this fitted module grants to a per-ship count allowance.

Remarks

The Experimental Weapon Stabiliser grants one additional experimental weapon at class 3 and two at class 5. The grant comes from the fitted article; module power state does not change structural fitting validity.


mount?

readonly optional mount?: ModuleMount

Defined in: src/ships/modules.ts:349

How the weapon is aimed. Present only on hardpoint weapons that have a mount variant; absent on every other module.


name

readonly name: string

Defined in: src/ships/modules.ts:333

Stable, descriptive English name, e.g. "Pulse Laser".

Remarks

This is a canonical library label, not a byte-exact copy of the game's localized UI text: abbreviations such as FSD and AFM are expanded for readability. It is not localized and is not suitable as a localization key.

Not unique — the game shows most modules at several sizes and ratings, and every hull's armour shares the same five names. Use OutfittingModule.symbol as the key; getModulesByName returns every match.


rating

readonly rating: ModuleRating

Defined in: src/ships/modules.ts:344

The grade letter, AI — the letter in the "5A" the screen shows.


restrictedToShips?

readonly optional restrictedToShips?: readonly string[]

Defined in: src/ships/modules.ts:397

The hull symbol(s) a module is restricted to, when it is ship-specific — e.g. ["Explorer_NX"] for the Python Mk II's MkII Gravity Optimised thrusters.

Remarks

Present only on the handful of non-armour modules limited to particular hulls. Armour is ship-specific too, but that restriction lives in OutfittingModule.ship / getBulkheadsForShip, not here. Symbols match Ship.symbol.


restrictedToSlot?

readonly optional restrictedToSlot?: SlotRestriction

Defined in: src/ships/modules.ts:442

The slot restriction a module requires — it fits only mounts carrying this SlotRestriction, and no unrestricted mount at all.

Remarks

Not to be confused with OutfittingModule.slot, which names one mount the module fills; this narrows a whole family of them, and the two never appear on the same record.

The mirror image of BuildSlot.restriction, and the other half of the same rule: a mount's restriction says which modules it takes, this says which mounts a module goes in. Most restricted families bind one way only — a cargo rack fits a cargo mount and any unrestricted optional — so this is present on just the five records the game sells for one kind of mount and nowhere else:

Module Requires
Int_PlanetApproachSuite, Int_PlanetApproachSuite_Advanced planetaryApproachSuite
Int_LargeCargoRack_Size7_Class1, Int_LargeCargoRack_Size8_class1 (Mk II Cargo Rack) cargo
Int_MultiDroneControl_MiningV2_Size5_Class5 (Mk II Mining Multi-Limpet Controller) limpetController

It composes with OutfittingModule.restrictedToShips rather than replacing it: the Mk II racks name both the hull that can buy them and the kind of mount they go in, and a build must satisfy both. Where a module names a hull and nothing else — the Mk II Vessel Hangars, say — it fits that hull's ordinary optionals like anything else. As with OutfittingModule.slot, the rule is read off the record rather than the symbol.

Example

import { getModuleBySymbol } from '@elite-dangerous-almanac/core/ships/modules';
import { INTERNAL_MODULES } from '@elite-dangerous-almanac/core/ships/modules-internal';
import { ShipLoadout } from '@elite-dangerous-almanac/core/ships/ship-loadout';

const rack = getModuleBySymbol('Int_LargeCargoRack_Size8_class1', INTERNAL_MODULES)!;
rack.restrictedToSlot; // -> 'cargo'
ShipLoadout.empty('PantherMkII').setModule('Cargo01', rack); // fits
try {
    ShipLoadout.empty('PantherMkII').setModule('Slot01_Size8', rack);
} catch (error) {
    if (error instanceof TypeError) error.message;
    // -> 'ShipLoadout.setModule: Int_LargeCargoRack_Size8_class1 → Slot01_Size8: module only fits a mount that takes cargo racks and fuel tanks'
}

ship?

readonly optional ship?: string

Defined in: src/ships/modules.ts:360

The hull an armour variant belongs to, e.g. "Anaconda". Present only on the core-category armour modules, which are the one ship-specific module; absent on every generic module.


slot?

readonly optional slot?: ModuleSlot

Defined in: src/ships/modules.ts:320

The one fixed mount this module fills, when it fills one: 'armour' or one of the seven CoreSlotType core functions.

Remarks

Present on every core module, and on the fifteen Guardian Hybrid power plants and power distributors — which Frontier files under internal, but which go in a core mount. Absent on everything else, because there is no one mount to name: a weapon, a utility fitting or an ordinary optional internal fits any mount of its kind that is large enough.

This is the module's half of the fit rule and BuildSlot.core is the mount's half; ShipLoadout.setModule matches the two. The rule is read off the record, not off the symbol: Int_Engine_* being thrusters is a naming habit the Python Mk II's Int_MkIIAgileBoost_* already breaks, and a record you assembled yourself without a slot will not go into a core mount at all. Resolve records from a catalogue (getModuleBySymbol) and the question does not arise.

A fuelTank is the one module that fits somewhere else as well: its own core mount and any optional slot large enough.

Example

import { getModuleBySymbol } from '@elite-dangerous-almanac/core/ships/modules';

getModuleBySymbol('Int_Hyperdrive_Size5_Class5')?.slot; // -> 'frameShiftDrive'
getModuleBySymbol('Anaconda_Armour_Grade1')?.slot;      // -> 'armour'
getModuleBySymbol('Int_CargoRack_Size4_Class1')?.slot;  // -> undefined

symbol

readonly symbol: string

Defined in: src/ships/modules.ts:256

Internal identifier, e.g. "Hpt_PulseLaser_Fixed_Small". Unique — the module's key.

API

Guides
astro
Classes (1)
ProceduralSystem

Properties

Accessors

Methods

Interfaces (16)
Type Aliases (3)
Variables (11)
Functions (37)
Subpath modules (3)
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)
materials
Enumerations (2)
Interfaces (2)
Type Aliases (2)
Variables (9)
Functions (9)
ships
Classes (3)
BuildMetrics

Methods

LoadoutEditError

Constructors

Properties

Methods

ShipLoadout

Accessors

Methods

Interfaces (125)
Type Aliases (44)
Variables (10)
Functions (85)
Subpath modules (8)

Clone this wiki locally