ships.Interface.OutfittingModuleIdentity - Elite-Dangerous-Almanac/Almanac-Core GitHub Wiki
@elite-dangerous-almanac/core / ships / OutfittingModuleIdentity
Defined in: src/ships/modules.ts:272
Identity, classification, fit constraints, and price for one outfitting module.
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.
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',
};
readonlycategory:ModuleCategory
Defined in: src/ships/modules.ts:286
Which kind of slot the module fits.
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.
readonlyclass:number
Defined in: src/ships/modules.ts:360
The module size, 0–8 — the number in the "5A" the outfitting screen shows.
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.
readonlyoptionalcost?:number
Defined in: src/ships/modules.ts:492
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.
Absent on the handful of records no registry prices: the grant-only *_free
articles, the Community Goal Corrosion Resistant Cargo Racks, which no station
sells but which are not free, and the 1B shield generator. Treat undefined as
"unknown", never as free; see
data/ships/SOURCES.md.
readonlyengineeringGroup:EngineeringGroupId|null
Defined in: src/ships/modules.ts:291
Stable engineering-menu family, or null when the stock module has no ordinary
engineering menu. See EngineeringGroupId.
readonlyoptionalentitlement?:string
Defined in: src/ships/modules.ts:383
Frontier's DLC / purchase-grant entitlement token, e.g.
"ELITE_HORIZONS_V_PLANETARY_LANDINGS". Present only on gated modules.
readonlyoptionalexclusionGroup?:ModuleExclusionGroup
Defined in: src/ships/modules.ts:465
One-per-ship family, absent when the module has no exclusive fitting rule. Two fitted modules sharing this id are structurally invalid.
readonlyfamilyId:OutfittingFamilyId
Defined in: src/ships/modules.ts:307
Stable outfitting family used to group an outfitting list, such as
'cargoRacks', 'shieldGenerators' or 'beamLasers'. See
OutfittingFamilyId.
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.
readonlyoptionalgrantOnly?:true
Defined in: src/ships/modules.ts:403
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.
They are the starter *_free fittings and the 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.
readonlyoptionalguidance?:ModuleGuidance
Defined in: src/ships/modules.ts:372
A missile/torpedo hardpoint's guidance. Present only on the launchers that have one; absent on everything else.
readonlyoptionallimitGroup?:"experimentalWeapon"
Defined in: src/ships/modules.ts:471
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.
readonlyoptionallimitIncrease?:ModuleLimitIncrease
Defined in: src/ships/modules.ts:480
Increase this fitted module grants to a per-ship count allowance.
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.
readonlyoptionalmount?:ModuleMount
Defined in: src/ships/modules.ts:367
How the weapon is aimed. Present only on hardpoint weapons that have a mount variant; absent on every other module.
readonlyname:string
Defined in: src/ships/modules.ts:351
Stable, descriptive English name, e.g. "Pulse Laser".
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.
readonlyrating:ModuleRating
Defined in: src/ships/modules.ts:362
The grade letter, A–I — the letter in the "5A" the screen shows.
readonlyoptionalrestrictedToShips?: readonlystring[]
Defined in: src/ships/modules.ts:415
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.
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.
readonlyoptionalrestrictedToSlot?:SlotRestriction
Defined in: src/ships/modules.ts:460
The slot restriction a module requires — it fits only mounts carrying this SlotRestriction, and no unrestricted mount at all.
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
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.
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'
}
readonlyoptionalship?:string
Defined in: src/ships/modules.ts:378
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.
readonlyoptionalslot?:ModuleSlot
Defined in: src/ships/modules.ts:338
The one fixed mount this module fills, when it fills one: 'armour' or one of
the seven CoreSlotType core functions.
Present on every core module, and on the 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.
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
readonlysymbol:string
Defined in: src/ships/modules.ts:274
Internal identifier, e.g. "Hpt_PulseLaser_Fixed_Small". Unique — the module's key.