@elite-dangerous-almanac/core 0.2.12 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/PROVENANCE/ships/SOURCES.md +61 -16
  2. package/dist/{chunk-OSMBAFRW.js → chunk-2GVJNKFW.js} +1 -1
  3. package/dist/{chunk-OSMBAFRW.js.map → chunk-2GVJNKFW.js.map} +1 -1
  4. package/dist/{chunk-Q5ALV3DI.js → chunk-3I2I5KG4.js} +1 -1
  5. package/dist/{chunk-25EECUZ2.js → chunk-55R4MYWV.js} +1 -1
  6. package/dist/{chunk-UVX7RCMP.js → chunk-BI3EFLQ7.js} +1 -1
  7. package/dist/chunk-HE4XE3WR.js +1 -0
  8. package/dist/chunk-HE4XE3WR.js.map +1 -0
  9. package/dist/{chunk-XQJERZUS.js → chunk-HWOP7QWK.js} +1 -1
  10. package/dist/{chunk-DEY44PHF.js → chunk-JEHKGTP2.js} +1 -1
  11. package/dist/{chunk-4T3TTYUT.js → chunk-P3DGQUID.js} +1 -1
  12. package/dist/{chunk-4T3TTYUT.js.map → chunk-P3DGQUID.js.map} +1 -1
  13. package/dist/{chunk-F44QX47A.js → chunk-Q75JSMU6.js} +1 -1
  14. package/dist/{chunk-F44QX47A.js.map → chunk-Q75JSMU6.js.map} +1 -1
  15. package/dist/chunk-QQFZEOPB.js +1 -0
  16. package/dist/chunk-QQFZEOPB.js.map +1 -0
  17. package/dist/{chunk-DBJKLXLS.js → chunk-SRPCHXW2.js} +1 -1
  18. package/dist/{chunk-3GNYPM6J.js → chunk-T6BIFKPU.js} +1 -1
  19. package/dist/{chunk-3GNYPM6J.js.map → chunk-T6BIFKPU.js.map} +1 -1
  20. package/dist/chunk-ZBB7Q3OZ.js +1 -0
  21. package/dist/chunk-ZBB7Q3OZ.js.map +1 -0
  22. package/dist/ships/armour.js +1 -1
  23. package/dist/ships/build-metrics.js +1 -1
  24. package/dist/ships/index.js +1 -1
  25. package/dist/ships/loadout-validation.d.ts +1 -1
  26. package/dist/ships/loadout-validation.js +1 -1
  27. package/dist/ships/modules-all.js +1 -1
  28. package/dist/ships/modules-hardpoint.js +1 -1
  29. package/dist/ships/modules.d.ts +26 -13
  30. package/dist/ships/modules.js +1 -1
  31. package/dist/ships/pre-engineered-stats.js +1 -1
  32. package/dist/ships/resistances.d.ts +3 -2
  33. package/dist/ships/resistances.js +1 -1
  34. package/dist/ships/shield-capacitor.js +1 -1
  35. package/dist/ships/shields.js +1 -1
  36. package/dist/ships/ship-loadout.js +1 -1
  37. package/dist/ships/weapons.d.ts +2 -0
  38. package/dist/ships/weapons.js +1 -1
  39. package/package.json +1 -1
  40. package/dist/chunk-AAU7OM47.js +0 -1
  41. package/dist/chunk-AAU7OM47.js.map +0 -1
  42. package/dist/chunk-BUQLUEQS.js +0 -1
  43. package/dist/chunk-BUQLUEQS.js.map +0 -1
  44. package/dist/chunk-P6HCQ2YE.js +0 -1
  45. package/dist/chunk-P6HCQ2YE.js.map +0 -1
  46. /package/dist/{chunk-Q5ALV3DI.js.map → chunk-3I2I5KG4.js.map} +0 -0
  47. /package/dist/{chunk-25EECUZ2.js.map → chunk-55R4MYWV.js.map} +0 -0
  48. /package/dist/{chunk-UVX7RCMP.js.map → chunk-BI3EFLQ7.js.map} +0 -0
  49. /package/dist/{chunk-XQJERZUS.js.map → chunk-HWOP7QWK.js.map} +0 -0
  50. /package/dist/{chunk-DEY44PHF.js.map → chunk-JEHKGTP2.js.map} +0 -0
  51. /package/dist/{chunk-DBJKLXLS.js.map → chunk-SRPCHXW2.js.map} +0 -0
@@ -18,6 +18,7 @@ Referred to throughout by source name; the pin is here, once.
18
18
  | Elite Dangerous in-game verification | game version `4.4.0.3`; direct in-game observation | 2026-08-14 UTC |
19
19
  | Elite Dangerous in-game purchase capture | no game version recorded; nine `ModuleBuyAndStore` journal entries from market `128666762`, 17:34-17:37, at a 10% and a 2.5% outfitting discount | 2026-08-30 UTC |
20
20
  | Elite Dangerous in-game outfitting observation | no game version recorded; direct in-game observation that outfitting offers no non-SCO size-8 frame shift drive | 2026-08-30 UTC |
21
+ | Elite Dangerous in-game SCO outfitting observation | no game version recorded; direct in-game observation that outfitting offers no SCO frame shift drive below the size of the mount being outfitted | 2026-09-17 UTC |
21
22
  | Elite Dangerous Large Planetary Vehicle Hangar readings | **unreleased** — observation of the modules an unreleased update adds, plus outfitting and journal `ModuleBuy` readings at a 10% and 2.5% discount | 2026-09-02 UTC |
22
23
 
23
24
  Every `eddb.js` derivation uses the baseline snapshot unless its catalogue note names
@@ -434,17 +435,29 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
434
435
  in the symbol and the display name.
435
436
  - **Derivation:** the symbol family is the classification, exactly as it is for `slot`
436
437
  above, and it is applied once here so that consumers read a datum instead of
437
- matching `Int_Hyperdrive_Overcharge` themselves which a pre-engineered or fitted
438
- article's symbol does not always let them do. Stored as a sparse flag rather than a
439
- `true`/`false` pair on every drive, following `alwaysPowered` and
440
- `guardianZoneResistance`.
441
- - **Nothing else is derived from it.** The two lines share every jump constant this
442
- catalogue carries (`optMass`, `maxFuel`, `fuelMul`, `fuelPower`, and the
443
- `fsdHeatRate`, which is a function of a drive's size alone — 10, 14, 18, 27, 37, 43
444
- and 50 for sizes 2 to 8, identical on the plain and SCO lines at every size), so no
445
- calculation reads the flag; the
446
- overcharged supercruise behaviour the drives are named for has no published figures
447
- and none are stored.
438
+ matching `Int_Hyperdrive_Overcharge` themselves. Every record carrying the flag has
439
+ `Overcharge` in its symbol today and no other record does, so the two agree; stating
440
+ the capability keeps that agreement from being something a consumer has to rely on.
441
+ Stored as a sparse flag rather than a `true`/`false` pair on every drive, following
442
+ `alwaysPowered` and `guardianZoneResistance`.
443
+ - **The two lines share every jump constant this catalogue carries** `optMass`,
444
+ `maxFuel`, `fuelMul`, `fuelPower`, and the `fsdHeatRate`, which is a function of a
445
+ drive's size alone: 10, 14, 18, 27, 37, 43 and 50 for sizes 2 to 8, and where both
446
+ lines offer a size they state the same value. The overcharged supercruise behaviour
447
+ the drives are named for has no published figures and none are stored. The plain line
448
+ runs from size 2 to 7 and the SCO line from 2 to 8, so size 8 is stated on the SCO
449
+ line alone.
450
+ - **An SCO drive is sold only at the size of the mount being outfitted.** Outfitting
451
+ offers a class-4 SCO drive for a class-4 frame shift drive mount and not for a
452
+ class-5 one, where it does offer a class-4 plain drive — an SCO drive cannot be
453
+ underfitted.
454
+ - **Source:** Elite Dangerous in-game SCO outfitting observation, pinned above.
455
+ - **Derivation:** none; the observation is recorded as stated. No catalogue field
456
+ carries it — the drives are exactly the records `supercruiseOvercharge` already
457
+ marks, and every one of them states a `class` matching the `Size` token in its
458
+ symbol, so the flag and the class are together sufficient to state the rule.
459
+ Neither registry source carries a field stating such a restriction, so the
460
+ observation is the only evidence for it.
448
461
  - **`cabinCapacity` — a passenger cabin's berths.** The `passengerCabins` records
449
462
  carry it; every other record in all four catalogues omits it, and no cabin carries a
450
463
  zero. It is the module's own seat count, not the ship's.
@@ -732,10 +745,11 @@ the armour modules, blueprint grade rolls and crafting costs remain unverified t
732
745
  It also did not unambiguously settle the shield-generator resistances, shield-booster
733
746
  properties or probe radius. Those values are not changed on guesswork. For the
734
747
  anti-xeno, Guardian and special weapons whose damage observed in-game does not reduce honestly
735
- to one conventional scalar, `damageComponents` preserves the exact amounts. The two
736
- channel types not established by in-game verification remain `unclassified`. The
737
- projectile-limited hardpoints carry their boundary parameters observed in-game in
738
- `projectileRange`; those parameters are not presented as effective ranges.
748
+ to one conventional scalar, `damageComponents` preserves the exact amounts. It read the
749
+ Enzyme Missile Rack's two channels as amounts without settling the minor one's type; that
750
+ type is caustic, and the note below records the correction. The projectile-limited
751
+ hardpoints carry their boundary parameters observed in-game in `projectileRange`; those
752
+ parameters are not presented as effective ranges.
739
753
 
740
754
  **A journal capture is a third source, and it reaches fields in-game verification does
741
755
  not.** Every engineered module in a `Loadout` states its own _unmodified_ value beside
@@ -847,7 +861,7 @@ Resource Siphon, the corrections are:
847
861
  | Beam Laser, Cannon, Fragment Cannon, Multi-Cannon, Plasma Accelerator, Rail Gun, Shock Cannon and Point Defence records | damage / thermal load | `damage` and `thermalLoad` read from the module panel per symbol |
848
862
  | Advanced Plasma Accelerator, Imperial Hammer, Shock Cannons and Mk II Plasma Shock Accelerator | burst interval / combined rate of fire | exact cycle values derived with the catalogue's documented formula |
849
863
  | mining, utility and Guardian hardpoints | clip, distributor draw, reload, jitter, falloff and maximum range | observed values per symbol |
850
- | anti-xeno, Guardian and special weapons | scalar, distribution and exact damage components | one component record per weapon |
864
+ | anti-xeno, Guardian and special weapons | scalar, distribution and exact damage components | a component record wherever the damage needs more than a share |
851
865
  | AX missiles, subsurface displacement missiles and seismic charge launchers | projectile boundary parameters; misleading ordinary ranges absent | `projectileRange` stored; `maximumRange` and `falloffRange` absent |
852
866
 
853
867
  In-game verification gives the integer thruster/FSD masses, 1.1/1.2 enhanced-thruster
@@ -879,6 +893,37 @@ EDSY's 40 / 70. The catalogue stores the displayed values without further deriva
879
893
  applies the same correction to their exact thermal and anti-xeno components. The two
880
894
  panel readings have no upstream immutable revision.
881
895
 
896
+ **The Mk II Plasma Shock Accelerator's damage type is Plasma, and it is stored as
897
+ `absolute`.** Plasma is a type of its own, not a second name for absolute damage, and the
898
+ stored share is not a claim that Frontier calls the channel absolute. What the two types
899
+ share is the only property a damage calculation reads from either: nothing resists them.
900
+ No shield generator, armour or hull reinforcement carries a Plasma resistance any more
901
+ than it carries an absolute one, so the whole of this weapon's output lands whatever the
902
+ target has fitted, and a share stored as `absolute` computes its effect exactly. The same
903
+ reading already stores the Operations Plasma conversion's Plasma share as `absolute`,
904
+ under "Engineering (blueprints and experimental effects)" below. What the storage costs is
905
+ the distinction itself, which is why it is written down here: should Frontier ever give a
906
+ defensive module a Plasma resistance, the two types stop agreeing, and this weapon and
907
+ that blueprint are the records to revisit.
908
+
909
+ Its `damageComponents` record goes with the `unclassified` spelling it replaces.
910
+ `damageComponents` preserves amounts a fractional split cannot state honestly — an
911
+ anti-xeno overlay, or a channel whose type is not established — and one conventional type
912
+ at the full scalar is neither.
913
+
914
+ **The Enzyme Missile Rack's minor damage channel is Caustic.** Of the 5 damage its round
915
+ carries, 4 are explosive and 1 is caustic. The amounts are what in-game verification
916
+ established; the minor channel's type it did not, and the share was stored as
917
+ `unclassified` for exactly as long as that was the whole of what was known. The type is
918
+ caustic, and the catalogue's own vocabulary says so twice over: Frontier's symbol for the
919
+ weapon is `Hpt_CausticMissile_Fixed_Medium`, and the enzyme it delivers is the damage the
920
+ Caustic Sink Launcher exists to shed. This is not the Mk II's situation above. Caustic is
921
+ a type the defensive side of the catalogue already names — `causticResistance` on the
922
+ armour and hull reinforcement records meets it, and it is one of the four resistances a build carries —
923
+ so the spelling decides whether a defender's caustic resistance reaches this weapon's
924
+ minor channel at all. `unclassified` would have kept it out of that arithmetic on a point
925
+ the game does settle.
926
+
882
927
  **Values that look wrong and are not.** Three records break the pattern their family
883
928
  follows and are confirmed outright by EDSY. Recorded so the "breaks its family's curve"
884
929
  heuristic does not keep rediscovering them:
@@ -1 +1 @@
1
- import{ALL_MODULES}from"./chunk-UVX7RCMP.js";import{findInKeyIndex,findByKey,filterByKey,createKeyIndex}from"./chunk-BKWLI44T.js";var MODULES_BY_SYMBOL=/* @__PURE__ */createKeyIndex(ALL_MODULES,"symbol");function builtInModuleBySymbol(symbol,label){return findInKeyIndex(MODULES_BY_SYMBOL,symbol,label)}function getModuleBySymbol(symbol,modules=ALL_MODULES){return modules===ALL_MODULES?builtInModuleBySymbol(symbol,"getModuleBySymbol: symbol"):findByKey(modules,"symbol",symbol,"getModuleBySymbol: symbol")}function getModulesByName(name,modules=ALL_MODULES){return filterByKey(modules,"name",name,"getModulesByName: name")}function getBulkheadsForShip(ship,modules=ALL_MODULES){return filterByKey(modules,"ship",ship,"getBulkheadsForShip: ship")}export{builtInModuleBySymbol,getBulkheadsForShip,getModuleBySymbol,getModulesByName};//# sourceMappingURL=chunk-OSMBAFRW.js.map
1
+ import{ALL_MODULES}from"./chunk-BI3EFLQ7.js";import{findInKeyIndex,findByKey,filterByKey,createKeyIndex}from"./chunk-BKWLI44T.js";var MODULES_BY_SYMBOL=/* @__PURE__ */createKeyIndex(ALL_MODULES,"symbol");function builtInModuleBySymbol(symbol,label){return findInKeyIndex(MODULES_BY_SYMBOL,symbol,label)}function getModuleBySymbol(symbol,modules=ALL_MODULES){return modules===ALL_MODULES?builtInModuleBySymbol(symbol,"getModuleBySymbol: symbol"):findByKey(modules,"symbol",symbol,"getModuleBySymbol: symbol")}function getModulesByName(name,modules=ALL_MODULES){return filterByKey(modules,"name",name,"getModulesByName: name")}function getBulkheadsForShip(ship,modules=ALL_MODULES){return filterByKey(modules,"ship",ship,"getBulkheadsForShip: ship")}export{builtInModuleBySymbol,getBulkheadsForShip,getModuleBySymbol,getModulesByName};//# sourceMappingURL=chunk-2GVJNKFW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ships/internal/module-symbol-index.ts","../src/ships/modules.ts"],"names":["ALL_MODULES","findInKeyIndex","findByKey","filterByKey","createKeyIndex","MODULES_BY_SYMBOL","builtInModuleBySymbol","symbol","label","getModuleBySymbol","modules","getModulesByName","name","getBulkheadsForShip","ship"],"mappings":"O,2HAMA,IAAMK,iCAAoCD,eAAeJ,YAAa,UAS/D,SAASM,sBAAsBC,OAAgBC,OAClD,OAAOP,eAAeI,kBAAmBE,OAAQC,MACrD,CC62BO,SAASC,kBACZF,OACAG,QAAuCV,aAEvC,OAAOU,UAAYV,YACbM,sBAAsBC,OAAQ,6BAC9BL,UAAUQ,QAAS,SAAUH,OAAQ,4BAC/C,CAoBO,SAASI,iBACZC,KACAF,QAAuCV,aAEvC,OAAOG,YAAYO,QAAS,OAAQE,KAAM,yBAC9C,CA8BO,SAASC,oBACZC,KACAJ,QAAuCV,aAEvC,OAAOG,YAAYO,QAAS,OAAQI,KAAM,4BAC9C,QAAAR,sBAAAO,oBAAAJ,kBAAAE"}
1
+ {"version":3,"sources":["../src/ships/internal/module-symbol-index.ts","../src/ships/modules.ts"],"names":["ALL_MODULES","findInKeyIndex","findByKey","filterByKey","createKeyIndex","MODULES_BY_SYMBOL","builtInModuleBySymbol","symbol","label","getModuleBySymbol","modules","getModulesByName","name","getBulkheadsForShip","ship"],"mappings":"O,2HAMA,IAAMK,iCAAoCD,eAAeJ,YAAa,UAS/D,SAASM,sBAAsBC,OAAgBC,OAClD,OAAOP,eAAeI,kBAAmBE,OAAQC,MACrD,CC03BO,SAASC,kBACZF,OACAG,QAAuCV,aAEvC,OAAOU,UAAYV,YACbM,sBAAsBC,OAAQ,6BAC9BL,UAAUQ,QAAS,SAAUH,OAAQ,4BAC/C,CAoBO,SAASI,iBACZC,KACAF,QAAuCV,aAEvC,OAAOG,YAAYO,QAAS,OAAQE,KAAM,yBAC9C,CA8BO,SAASC,oBACZC,KACAJ,QAAuCV,aAEvC,OAAOG,YAAYO,QAAS,OAAQI,KAAM,4BAC9C,QAAAR,sBAAAO,oBAAAJ,kBAAAE"}
@@ -1 +1 @@
1
- import{mapDamageTypes,stackArmourResistance,effectiveHitPoints}from"./chunk-F44QX47A.js";var reinforcementResistances=(sources,type)=>sources.map(source=>source[`${type}Resistance`]??0);function armourMetrics(input){const bulkhead=input.bulkhead??{};const reinforcements=input.reinforcements??[];const moduleReinforcements=input.moduleReinforcements??[];const bulkheads=input.baseArmour*(1+(bulkhead.hullBoost??0));const reinforcement=reinforcements.reduce((sum,pack)=>sum+(pack.hullReinforcement??0)+input.baseArmour*(pack.hullBoost??0),0);const hitPoints=bulkheads+reinforcement;const resistances=Object.freeze(mapDamageTypes(type=>stackArmourResistance(bulkhead[`${type}Resistance`]??0,reinforcementResistances(reinforcements,type))));return Object.freeze({hitPoints:hitPoints,bulkheads:bulkheads,reinforcement:reinforcement,resistances:resistances,effectiveHitPoints:Object.freeze(effectiveHitPoints(hitPoints,resistances)),moduleArmour:moduleReinforcements.reduce((sum,pack)=>sum+(pack.integrity??0),0),moduleProtection:1-moduleReinforcements.reduce((product,pack)=>product*(1-(pack.moduleProtection??0)),1)})}export{armourMetrics};//# sourceMappingURL=chunk-Q5ALV3DI.js.map
1
+ import{mapDamageTypes,stackArmourResistance,effectiveHitPoints}from"./chunk-Q75JSMU6.js";var reinforcementResistances=(sources,type)=>sources.map(source=>source[`${type}Resistance`]??0);function armourMetrics(input){const bulkhead=input.bulkhead??{};const reinforcements=input.reinforcements??[];const moduleReinforcements=input.moduleReinforcements??[];const bulkheads=input.baseArmour*(1+(bulkhead.hullBoost??0));const reinforcement=reinforcements.reduce((sum,pack)=>sum+(pack.hullReinforcement??0)+input.baseArmour*(pack.hullBoost??0),0);const hitPoints=bulkheads+reinforcement;const resistances=Object.freeze(mapDamageTypes(type=>stackArmourResistance(bulkhead[`${type}Resistance`]??0,reinforcementResistances(reinforcements,type))));return Object.freeze({hitPoints:hitPoints,bulkheads:bulkheads,reinforcement:reinforcement,resistances:resistances,effectiveHitPoints:Object.freeze(effectiveHitPoints(hitPoints,resistances)),moduleArmour:moduleReinforcements.reduce((sum,pack)=>sum+(pack.integrity??0),0),moduleProtection:1-moduleReinforcements.reduce((product,pack)=>product*(1-(pack.moduleProtection??0)),1)})}export{armourMetrics};//# sourceMappingURL=chunk-3I2I5KG4.js.map
@@ -1 +1 @@
1
- import{validateLoadout}from"./chunk-3GNYPM6J.js";import{calculateModuleLimits}from"./chunk-KPETDYQX.js";import{publishLoadoutInternals,normalizeLoadoutEvent,preEngineeredVariantFor,moduleFitProblem,effectiveModule,moduleFitError}from"./chunk-BUQLUEQS.js";import{getShipBySymbol}from"./chunk-C4FUV6GF.js";import{parseSlef,toSlef,stringifySlef,getLoadoutModifier}from"./chunk-T4MKUKYS.js";import{getSourceModuleValue}from"./chunk-NIURLW2F.js";import{statesInertModifiers,rolledOverFixedArticle,isNonOutfittingSlot,isBuiltInHullModule,cloneLoadoutModule,cloneModuleStats,availableBlueprintsFor,availableExperimentalsFor,ownKeyIn,BUILT_IN_HULL_SYMBOL,FITTED_ITEM,blueprintAvailableFor,blueprintRoutesFor,experimentalAvailableFor,primitiveEngineeringInputsFor,missingBaseLabels,journalModifiersFor,getPreEngineeredStats,getPreEngineeredJournalModifiers,getPreEngineeredModifiers,ordinaryEngineeringProof,unresolvedModifiers,matchingKeyIn,isCargoHatchSlot,orderBySlotLayout}from"./chunk-P6HCQ2YE.js";import{builtInModuleBySymbol}from"./chunk-OSMBAFRW.js";import{getPreEngineeredVariants}from"./chunk-EXHZ4CFB.js";import{ALL_MODULES}from"./chunk-UVX7RCMP.js";import{singleJumpRange}from"./chunk-VTMCSCXV.js";import{calculateUnladenMass,calculatePassengerCapacity,calculateCargoCapacity,calculateFuelCapacity}from"./chunk-C3LLPLLD.js";import{fixedSlotReason,stockedMountKind}from"./chunk-M6J7KP7G.js";import{getBlueprintGrade}from"./chunk-WDAYRHXR.js";import{getDefaultLoadout}from"./chunk-KY7KSPU6.js";import{getExperimentalEffect}from"./chunk-77I24V6B.js";import{ammunitionCapacity}from"./chunk-AA3K5XUE.js";import{baseStats,computeModifiers,labelsForDamageType,scaleForLabel}from"./chunk-U73MBQ45.js";import{resolveBlueprintForModule}from"./chunk-2J6NNI3Y.js";import{getExperimentalsForModule}from"./chunk-M4STXLXO.js";import{loadoutSlotName}from"./chunk-KAA4VOOB.js";import{parseSlotName,enumerateSlots}from"./chunk-RAO35XDF.js";import{normalizeKey,CATALOGUE_KEY}from"./chunk-BKWLI44T.js";import{truncate,describeValue,requireString,requireStringIfPresent}from"./chunk-PKWVG2JY.js";import{deepFreeze}from"./chunk-DURKO7JU.js";var REBUY_FRACTION=.05;function exportLoadoutEvent(input,options){const fromSource=options.credits==="source";const source=fromSource?input.sourcePurchase:null;const totals=source!==null&&!input.sourceTotalsVoided&&sourceTotalsHold(input.modules,source)?source:null;const hullValue=fromSource?source?.hullValue??null:input.retailHullValue;const modulesValue=fromSource?totals?.modulesValue??null:computedModulesValue(input.modules,input.statsFor);const rebuy=fromSource?totals?.rebuy??null:hullValue===null||modulesValue===null?null:Math.trunc((hullValue+modulesValue)*REBUY_FRACTION);return{Ship:input.shipSymbol.toLowerCase(),...input.shipName===void 0?{}:{ShipName:input.shipName},...input.shipIdent===void 0?{}:{ShipIdent:input.shipIdent},...hullValue===null?{}:{HullValue:hullValue},...modulesValue===null?{}:{ModulesValue:modulesValue},UnladenMass:input.unladenMass,CargoCapacity:input.cargoCapacity,...input.maxJumpRange===null?{}:{MaxJumpRange:input.maxJumpRange},FuelCapacity:{Main:input.fuelCapacity.main,Reserve:input.fuelCapacity.reserve},...rebuy===null?{}:{Rebuy:rebuy},Modules:exportModules(input,options,fromSource)}}function exportModules(input,options,fromSource){const ordered=options.moduleOrder==="slots"?slotOrderedModules(input.modules,input.layout):[...input.modules.values()];return ordered.map(module=>{const on=module.On??(options.explicitPower?true:void 0);const priority=module.Priority??(options.explicitPower?0:void 0);const value=fromSource?sourceModuleValue(module,input.sourcePurchase):moduleValue(module,input.statsFor);return{Slot:module.Slot,Item:module.Item.toLowerCase(),...on===void 0?{}:{On:on},...priority===void 0?{}:{Priority:priority},...module.Health===void 0?{}:{Health:module.Health},...typeof value==="number"?{Value:value}:{},...module.Engineering===void 0?{}:{Engineering:cloneLoadoutModule(module).Engineering}}})}function slotOrderedModules(modules,layout){return orderBySlotLayout([...modules.values()],layout,module=>module.Slot)}function computedModulesValue(modules,statsFor){let sum=0;for(const module of modules.values()){const value=moduleValue(module,statsFor);if(value==="unknown")return null;if(value!=="free")sum+=value}return sum}function moduleValue(module,statsFor){const stats=statsFor(module);if(stats!==null)return stats.cost??"unknown";return isNonOutfittingSlot(module.Slot)||isBuiltInHullModule(module)?"free":"unknown"}var SOURCE_ITEM="ShipLoadout: sourcePurchase moduleValues[].item";function sourceModuleValue(module,source){const entry=source===null?null:getSourceModuleValue(source,module.Slot);if(entry===null)return"unknown";return normalizeKey(entry.item,SOURCE_ITEM)===normalizeKey(module.Item,FITTED_ITEM)?entry.value:"unknown"}function sourceTotalsHold(modules,source){for(const entry of source.moduleValues){const key=matchingKeyIn(modules,entry.slot);const fitted=key===null?void 0:modules.get(key);if(!fitted)return false;if(isCargoHatchSlot(entry.slot)&&entry.value===0)continue;if(normalizeKey(fitted.Item,FITTED_ITEM)!==normalizeKey(entry.item,SOURCE_ITEM)){return false}}return true}var SLOT_KEY="ShipLoadout: slotKey";var FITTED_SLOT="ShipLoadout: fitted module Slot";var LoadoutEditError=class extends TypeError{code;constraint;params;constructor(message,code,params,constraint){super(message);this.code=code;this.params=deepFreeze(structuredClone(params));if(constraint!==void 0)this.constraint=constraint}};var experimentalEffectUnsupported=(code,params)=>deepFreeze({kind:"unsupported",code:code,params:params});var engineeringNormalizationUnsupported=(code,params)=>deepFreeze({kind:"unsupported",code:code,params:params});function weighable(tonnes){return tonnes!==void 0&&Number.isFinite(tonnes)&&tonnes>=0?tonnes:void 0}var AGGREGATE_STATS=["mass","cargoCapacity","cabinCapacity","fuelCapacity"];var ShipLoadout=class _ShipLoadout{#ship;#shipSymbol;#modules;#moduleStats;#primitiveModifiers;#top;#sourcePurchase;#importOutcomes;#slotCache=/* @__PURE__ */new Map;#layoutCache;constructor(ship,shipSymbol,modules,top,sourcePurchase=null,moduleStats=/* @__PURE__ */new Map,primitiveModifiers=/* @__PURE__ */new Map,importOutcomes=deepFreeze([])){this.#ship=ship;this.#shipSymbol=shipSymbol;this.#modules=modules;this.#top=top;this.#sourcePurchase=sourcePurchase;this.#moduleStats=moduleStats;this.#primitiveModifiers=primitiveModifiers;this.#importOutcomes=importOutcomes;publishLoadoutInternals(this,{ship:ship,modules:()=>[...this.#modules.values()],effectiveModules:()=>this.#modulesForEffectiveStats(),effectiveModule:module=>this.#moduleForEffectiveStats(module),statsFor:module=>this.#statsFor(module),layout:()=>this.#layout(),resolveDrive:()=>this.#resolveDrive(),frameShiftDriveModule:()=>this.#frameShiftDrive()?.module,calculationModules:()=>this.#calculationModules(),statedMainFuel:()=>this.#top.FuelCapacity?.Main})}static fromSlef(input,index=0){const entries=parseSlef(input);const entry=entries[index];if(!entry){throw new TypeError(`ShipLoadout.fromSlef: no entry at index ${truncate(index)} (have ${entries.length})`)}const imported=normalizeLoadoutEvent(entry.data);const ship=getShipBySymbol(imported.shipSymbol);if(!ship){throw new TypeError(`ShipLoadout.fromSlef: unknown hull "${truncate(imported.shipSymbol)}"`)}return _ShipLoadout.#fromImported(imported,ship)}static fromLoadout(event){if(event===null||typeof event!=="object"){throw new TypeError(`ShipLoadout.fromLoadout: event must be a Loadout event, received ${describeValue(event)}`)}const imported=normalizeLoadoutEvent(event);const ship=getShipBySymbol(imported.shipSymbol);if(!ship){throw new TypeError(`ShipLoadout.fromLoadout: unknown hull "${truncate(imported.shipSymbol)}"`)}return _ShipLoadout.#fromImported(imported,ship)}static#fromImported(imported,ship){const outcomes=[...imported.outcomes];const loadout=new _ShipLoadout(ship,imported.shipSymbol,imported.modules,imported.top,imported.sourcePurchase,imported.moduleStats,imported.primitiveModifiers,outcomes);const{UnladenMass:UnladenMass,CargoCapacity:CargoCapacity,FuelCapacity:FuelCapacity}=imported.top;for(const module of[...imported.modules.values()]){const unresolved=loadout.#rollStatedRecipe(module);if(unresolved!==null)outcomes.push(unresolved)}if(UnladenMass!==void 0)loadout.#top.UnladenMass=UnladenMass;if(CargoCapacity!==void 0)loadout.#top.CargoCapacity=CargoCapacity;if(FuelCapacity!==void 0)loadout.#top.FuelCapacity=FuelCapacity;deepFreeze(outcomes);return loadout}#rollStatedRecipe(module){const engineering=module.Engineering;if(!engineering||typeof engineering.BlueprintName!=="string")return null;const stated=engineering.Modifiers;const stats=this.#statsFor(module);if(stated!==void 0&&(this.#moduleStats.has(module.Slot)||stats===null||!statesInertModifiers(stats,stated))){return null}if(stated===void 0&&this.#moduleStats.has(module.Slot)){const variant=preEngineeredVariantFor(module);if(variant?.acquisition!=="mercenary"||engineering.Level<=variant.grade){return null}}try{this.applyBlueprint(module.Slot,engineering.BlueprintName,{grade:engineering.Level,quality:engineering.Quality??1,...typeof engineering.ExperimentalEffect==="string"?{experimentalEffectSymbol:engineering.ExperimentalEffect}:{}});if(stated!==void 0){return{action:"rerolledEngineering",slot:module.Slot,sourceSymbol:module.Item,blueprintSymbol:engineering.BlueprintName}}const passedOver=rolledOverFixedArticle(module.Item,engineering);return passedOver===null?null:{action:"ambiguousEngineering",slot:module.Slot,sourceSymbol:module.Item,blueprintSymbol:engineering.BlueprintName,preEngineeredVariant:passedOver}}catch(error){if(!(error instanceof TypeError)&&!(error instanceof RangeError))throw error;return{action:"unresolvedEngineering",slot:module.Slot,sourceSymbol:module.Item,blueprintSymbol:engineering.BlueprintName}}}static empty(shipSymbol){const requested=requireString(shipSymbol,"ShipLoadout.empty: shipSymbol");const ship=getShipBySymbol(requested);if(!ship){throw new TypeError(`ShipLoadout.empty: no slot layout for hull "${truncate(shipSymbol)}"`)}const fitted=(getDefaultLoadout(ship.symbol)?.modules??[]).filter(module=>{const parsed=parseSlotName(module.slot);return parsed!==null&&fixedSlotReason(parsed)!==null});return new _ShipLoadout(ship,ship.symbol,new Map(fitted.map(module=>[module.slot,{Slot:module.slot,Item:module.symbol}])),{})}static default(shipSymbol){const requested=requireString(shipSymbol,"ShipLoadout.default: shipSymbol");const ship=getShipBySymbol(requested);if(!ship){throw new TypeError(`ShipLoadout.default: no default loadout for hull "${truncate(shipSymbol)}"`)}const loadout=getDefaultLoadout(ship.symbol);return new _ShipLoadout(ship,loadout.symbol,new Map(loadout.modules.map(module=>[module.slot,{Slot:module.slot,Item:module.symbol}])),{})}get shipSymbol(){return this.#shipSymbol}get shipName(){return this.#top.ShipName??null}get shipIdent(){return this.#top.ShipIdent??null}get unladenMass(){return this.#top.UnladenMass??this.#computedUnladenMass()}#computedUnladenMass(){return calculateUnladenMass(this.#ship.hullMass,this.#calculationModules())}get fuelCapacity(){const cap=this.#top.FuelCapacity;if(cap?.Main!==void 0&&cap.Reserve!==void 0){return Object.freeze({main:cap.Main,reserve:cap.Reserve})}const computed=this.#computedFuelCapacity();return Object.freeze({main:cap?.Main??computed.main,reserve:cap?.Reserve??computed.reserve})}get cargoCapacity(){return this.#top.CargoCapacity??this.#computedCargoCapacity()}get passengerCapacity(){return calculatePassengerCapacity(this.#calculationModules())}#computedCargoCapacity(){return calculateCargoCapacity(this.#calculationModules())}#computedFuelCapacity(){return calculateFuelCapacity(this.#ship.reserveFuelCapacity,this.#calculationModules())}get hullValue(){return this.#top.HullValue??null}get modulesValue(){return this.#top.ModulesValue??null}get rebuy(){return this.#top.Rebuy??null}get sourcePurchase(){return this.#sourcePurchase}get importOutcomes(){return this.#importOutcomes}validation(){const slots=this.#layout();const byKey=new Map(slots.map(slot=>[normalizeKey(slot.key,CATALOGUE_KEY),slot]));const modules=[...this.#modules.values()].map(module=>{const stats=this.#statsFor(module);const slot=byKey.get(normalizeKey(module.Slot,FITTED_SLOT));const builtIn=stats===null&&isNonOutfittingSlot(module.Slot)||isBuiltInHullModule(module);const fitProblem=stats&&slot&&!builtIn?moduleFitProblem(this.#shipSymbol,slot,stats):null;const thrusterMaxMass=weighable(stats?.slot==="thrusters"?effectiveModule(this.#moduleForEffectiveStats(module),stats)?.maxMass:void 0);return{slot:module.Slot,symbol:module.Item,requiresKnownSlot:!builtIn,fitError:fitProblem?.message??null,...fitProblem===null?{}:{fitConstraint:fitProblem.constraint},...fitProblem?.params===void 0?{}:{fitParams:fitProblem.params},...stats?.exclusionGroup===void 0?{}:{exclusionGroup:stats.exclusionGroup},...stats?.limitGroup===void 0?{}:{limitGroup:stats.limitGroup},...stats?.limitIncrease===void 0?{}:{limitIncrease:stats.limitIncrease},...thrusterMaxMass===void 0?{}:{thrusterMaxMass:thrusterMaxMass}}});const dry=weighable(this.unladenMass);const fuel=weighable(this.fuelCapacity.main);const cargo=weighable(this.cargoCapacity);const mass=dry===void 0?void 0:{dry:dry,...fuel===void 0?{}:{fuel:fuel},...fuel===void 0||cargo===void 0?{}:{cargo:cargo}};return validateLoadout({shipSymbol:this.#shipSymbol,slots:slots,modules:modules,...mass===void 0?{}:{mass:mass}})}slots(kind){const cached=this.#slotCache.get(kind);if(cached!==void 0)return cached;const slots=kind===void 0?this.#layout():this.#layout().filter(slot=>slot.kind===kind);const currentLimits=this.#moduleLimits();const value=deepFreeze(slots.map(slot=>{const stats=this.#moduleStatsAt(slot.key);const fixedReason=fixedSlotReason(slot);const immovableReason=fixedReason!==null?fixedReason:stats?.limitIncrease!==void 0&&this.#moduleLimitRegression(slot.key,null,currentLimits,stats)!==null?"moduleLimit":null;return{...slot,name:loadoutSlotName(slot),module:this.fittedModuleAt(slot.key),removable:immovableReason===null,...immovableReason===null?{}:{immovableReason:immovableReason}}}));this.#slotCache.set(kind,value);return value}fittedModuleAt(slotKey){const module=this.#fittedModuleFor(slotKey);if(!module)return null;const raw=cloneLoadoutModule(module);const stats=this.#statsFor(module);const effective=effectiveModule(this.#moduleForEffectiveStats(module),stats);return deepFreeze({slot:module.Slot,symbol:raw.Item,on:raw.On,priority:raw.Priority,health:raw.Health,value:raw.Value,engineering:raw.Engineering,raw:raw,stats:stats===null?null:cloneModuleStats(stats),effectiveStats:effective===null?null:cloneModuleStats(effective),ammunition:ammunitionCapacity(effective),preEngineeredVariant:preEngineeredVariantFor(raw)})}fittedModules(){return deepFreeze([...this.#modules.keys()].flatMap(key=>{const fitted=this.fittedModuleAt(key);return fitted===null?[]:[fitted]}))}availableBlueprints(slotKey){const module=this.#fittedModuleFor(slotKey);return deepFreeze(module?availableBlueprintsFor(module.Item,this.#statsFor(module)):[])}availableExperimentalEffects(slotKey){const module=this.#fittedModuleFor(slotKey);const stats=module?this.#statsFor(module):null;const variant=module?preEngineeredVariantFor(module):null;return deepFreeze(module&&!(stats?.category==="hardpoint"&&variant?.acquisition==="mercenary")?availableExperimentalsFor(module.Item,stats):[])}modulesForSlot(slotKey){const slot=this.#requireSlot(slotKey);const occupied=new Set([...this.#modules.values()].flatMap(fitted=>{if(normalizeKey(fitted.Slot,FITTED_SLOT)===normalizeKey(slot.key,CATALOGUE_KEY))return[];const group=this.#statsFor(fitted)?.exclusionGroup;return group===void 0?[]:[group]}));const currentLimits=this.#moduleLimits();const currentStats=this.#moduleStatsAt(slot.key);return ALL_MODULES.filter(module=>module.grantOnly===void 0&&moduleFitError(this.#shipSymbol,slot,module)===null&&(module.exclusionGroup===void 0||!occupied.has(module.exclusionGroup))&&this.#moduleLimitRegression(slot.key,module,currentLimits,currentStats)===null)}repairFixedMount(slotKey){const requested=requireString(slotKey,SLOT_KEY);const wanted=normalizeKey(requested,SLOT_KEY);const slot=this.#requireSlot(requested);const fittedKey=this.#fittedKey(requested);const resultSlot=fittedKey??requested;const canonicalKey=slot.key;if(fixedSlotReason(slot)===null){return deepFreeze({status:"refused",slot:resultSlot,reason:"notFixedMount"})}const current=this.#fittedModuleFor(requested);const currentStats=current?this.#statsFor(current):null;const valid=current!==void 0&&currentStats!==null&&(slot.kind==="cargoHatch"?isBuiltInHullModule(current):moduleFitProblem(this.#shipSymbol,slot,currentStats)===null);if(valid){return deepFreeze({status:"unchanged",slot:current.Slot,symbol:current.Item})}const defaultModule=getDefaultLoadout(this.#shipSymbol)?.modules.find(module=>normalizeKey(module.slot,CATALOGUE_KEY)===wanted);if(!defaultModule){return deepFreeze({status:"defaultUnavailable",slot:resultSlot})}const ownKey=ownKeyIn(this.#modules,canonicalKey);const replacement={Slot:ownKey,Item:defaultModule.symbol,...current?.On===void 0?{}:{On:current.On},...current?.Priority===void 0?{}:{Priority:current.Priority},...current?.Health===void 0?{}:{Health:current.Health}};const replacementStats=builtInModuleBySymbol(defaultModule.symbol,"ShipLoadout.repairFixedMount")??(isBuiltInHullModule(replacement)?builtInModuleBySymbol(BUILT_IN_HULL_SYMBOL,"ShipLoadout.repairFixedMount"):null);if(!replacementStats){return deepFreeze({status:"defaultUnavailable",slot:resultSlot,symbol:defaultModule.symbol})}this.#replaceModule(ownKey,replacement,replacementStats);return deepFreeze({status:"repaired",slot:ownKey,symbol:defaultModule.symbol})}setModule(slotKey,module){const slot=this.#requireSlot(slotKey);if(module===null||module===void 0){throw new TypeError(`ShipLoadout.setModule: no module supplied for "${truncate(slotKey)}" (did the module lookup return undefined?)`)}if(typeof module.symbol!=="string"){throw new TypeError(`ShipLoadout.setModule: module for "${truncate(slotKey)}" must be an outfitting module, received ${describeValue(module)}`)}module=cloneModuleStats(module);const catalogued=builtInModuleBySymbol(module.symbol,FITTED_ITEM);if(catalogued===null){throw new TypeError(`ShipLoadout.setModule: no module is catalogued as "${truncate(module.symbol)}"`)}for(const field of AGGREGATE_STATS){const stated=module[field];if(stated===void 0){if(catalogued[field]===void 0)continue;throw new TypeError(`ShipLoadout.setModule: the supplied record for "${truncate(module.symbol)}" has no ${field}`)}if(typeof stated!=="number"||!Number.isFinite(stated)){throw new TypeError(`ShipLoadout.setModule: the supplied record for "${truncate(module.symbol)}" states a ${field} of ${describeValue(stated)}`)}}const problem=moduleFitProblem(this.#shipSymbol,slot,module);if(problem){if(problem.constraint==="immutableSlot"){throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${problem.message}`,"immutableSlot",{slot:slot.key})}throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${problem.message}`,"incompatibleModule",{...problem.params,slot:slot.key,symbol:module.symbol,constraint:problem.constraint},problem.constraint)}if(module.exclusionGroup!==void 0){const conflict=[...this.#modules.values()].find(fitted=>normalizeKey(fitted.Slot,FITTED_SLOT)!==normalizeKey(slot.key,CATALOGUE_KEY)&&this.#statsFor(fitted)?.exclusionGroup===module.exclusionGroup);if(conflict){throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${module.exclusionGroup} is limited to one per ship (already fitted in ${truncate(conflict.Slot)})`,"duplicateExclusiveModule",{exclusionGroup:module.exclusionGroup,slot:slot.key,symbol:module.symbol,previousSlot:conflict.Slot,previousSymbol:conflict.Item})}}const limitProblem=this.#moduleLimitRegression(slot.key,module);if(limitProblem!==null){throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${limitProblem.group} would have ${limitProblem.count} modules but the ship allows ${limitProblem.limit}`,"moduleLimitExceeded",{group:limitProblem.group,count:limitProblem.count,limit:limitProblem.limit,slot:slot.key,symbol:module.symbol})}const key=this.#fittedKey(slotKey)??slot.key;this.#replaceModule(key,{Slot:key,Item:module.symbol},module);return this}removeModule(slotKey){const wanted=normalizeKey(slotKey,SLOT_KEY);if(wanted==="cargohatch"){throw new LoadoutEditError("ShipLoadout.removeModule: the cargoHatch slot cannot be changed","immutableSlot",{slot:"CargoHatch"})}const parsed=parseSlotName(slotKey);const slot=this.#layout().find(candidate=>normalizeKey(candidate.key,CATALOGUE_KEY)===wanted);if(parsed!==null&&fixedSlotReason(parsed)==="requiredSlot"){const fittedKey=this.#fittedKey(slotKey);const key2=slot?.key??fittedKey??slotKey;throw new LoadoutEditError(`ShipLoadout.removeModule: the ${truncate(key2)} slot is required and cannot be emptied`,"requiredSlot",{slot:key2})}const key=this.#fittedKey(slotKey);if(key!==null){const limitProblem=this.#moduleLimitRegression(key,null);if(limitProblem!==null){const fitted=this.#modules.get(key);throw new LoadoutEditError(`ShipLoadout.removeModule: ${truncate(slotKey)}: ${limitProblem.group} would have ${limitProblem.count} modules but the ship allows ${limitProblem.limit}`,"moduleLimitExceeded",{group:limitProblem.group,count:limitProblem.count,limit:limitProblem.limit,slot:key,...fitted===void 0?{}:{symbol:fitted.Item}})}this.#replaceModule(key,null)}return this}applyBlueprint(slotKey,blueprintSymbol,options){requireString(blueprintSymbol,"ShipLoadout.applyBlueprint: blueprintSymbol");if(options===null||typeof options!=="object"){throw new TypeError(`ShipLoadout.applyBlueprint: options must be an object with a grade, received ${describeValue(options)}`)}const wantedGrade=options.grade;const wantedQuality=options.quality;let wantedExperimental=options.experimentalEffectSymbol??void 0;requireStringIfPresent(wantedExperimental,"ShipLoadout.applyBlueprint: options.experimentalEffectSymbol");const module=this.#fittedModuleFor(slotKey);if(!module){throw new RangeError(`ShipLoadout.applyBlueprint: slot "${truncate(slotKey)}" is empty`)}const fittedStats=this.#statsFor(module);if(!fittedStats){throw new TypeError(`ShipLoadout.applyBlueprint: no stats for module "${truncate(module.Item)}"`)}const recipe=resolveBlueprintForModule(module.Item,blueprintSymbol);const named=recipe===blueprintSymbol?`"${truncate(blueprintSymbol)}"`:`"${truncate(blueprintSymbol)}" (${truncate(recipe)} on this module)`;const written=blueprintSymbol.trim().toLowerCase();const resolved=recipe.trim().toLowerCase();const mercenaryHardpoint=fittedStats.category==="hardpoint"?getPreEngineeredVariants(module.Item).find(variant=>variant.acquisition==="mercenary"&&(variant.blueprintSymbol.toLowerCase()===written||variant.blueprintSymbol.toLowerCase()===resolved)):void 0;if(mercenaryHardpoint){const locked=mercenaryHardpoint.experimentalEffectSymbol;if(wantedExperimental!==void 0&&(locked===void 0||locked.trim().toLowerCase()!==wantedExperimental.trim().toLowerCase())){throw new TypeError(`ShipLoadout.applyBlueprint: Mercenary hardpoint "${truncate(module.Item)}" keeps its purchased experimental effect`)}wantedExperimental=locked}if(getPreEngineeredVariants(module.Item).some(variant=>variant.acquisition==="eventReward"&&(variant.blueprintSymbol.toLowerCase()===written||variant.blueprintSymbol.toLowerCase()===resolved))){throw new TypeError(`ShipLoadout.applyBlueprint: ${named} is a fixed pre-engineered identity, not a craftable blueprint; use setPreEngineeredVariant to fit its fixed article`)}if(!Number.isInteger(wantedGrade)||wantedGrade<1||wantedGrade>5){throw new RangeError(`ShipLoadout.applyBlueprint: no blueprint ${named} grade ${truncate(wantedGrade)}`)}const grade=getBlueprintGrade(recipe,wantedGrade);if(!grade){throw new RangeError(`ShipLoadout.applyBlueprint: no blueprint ${named} grade ${truncate(wantedGrade)}`)}let experimental;if(wantedExperimental!==void 0){experimental=getExperimentalEffect(wantedExperimental);if(!experimental){throw new RangeError(`ShipLoadout.applyBlueprint: unknown experimental effect "${truncate(wantedExperimental)}"`)}}const quality=wantedQuality??1;if(!Number.isFinite(quality)||quality<0||quality>1){throw new RangeError(`ShipLoadout.applyBlueprint: quality must be a finite number in [0, 1]`)}if(fittedStats.engineeringLocked){throw new TypeError(`ShipLoadout.applyBlueprint: module "${truncate(module.Item)}" is a final pre-engineered article and accepts no further engineering`)}if(!blueprintAvailableFor(module.Item,blueprintSymbol)){const offered=[...blueprintRoutesFor(module.Item)].map(([blueprint,route])=>`${blueprint} (${route})`);throw new TypeError(offered.length>0?`ShipLoadout.applyBlueprint: module "${truncate(module.Item)}" is not offered blueprint ${named}; available candidates are ${offered.join(", ")}`:`ShipLoadout.applyBlueprint: no registry lists an engineering menu for module "${truncate(module.Item)}"`)}if(wantedExperimental!==void 0&&!experimentalAvailableFor(module.Item,wantedExperimental)&&mercenaryHardpoint===void 0){const offered=getExperimentalsForModule(module.Item);throw new TypeError(`ShipLoadout.applyBlueprint: module "${truncate(module.Item)}" is not offered experimental effect "${truncate(wantedExperimental)}"; it takes ${offered.length>0?offered.join(", "):"no experimental effect"}`)}const stats=this.#engineeringBaseStats(module)??fittedStats;const base=baseStats(stats);const canonical=primitiveEngineeringInputsFor(stats,grade,experimental);const missing=missingBaseLabels(stats,base,canonical.grade.features,canonical.experimental?.modifiers);if(missing.length>0){throw new TypeError(`ShipLoadout.applyBlueprint: cannot compute ${named} for module "${truncate(module.Item)}"; missing base stats for ${missing.join(", ")}`)}const damageDistribution=experimental?.damageDistribution??grade.damageDistribution;const primitiveModifiers=computeModifiers(base,canonical.grade,quality,canonical.experimental);const modifiers=journalModifiersFor(stats,primitiveModifiers);if(damageDistribution){for(const type of["kinetic","thermal","explosive","absolute"]){const value=damageDistribution[type];if(value===void 0)continue;const label=labelsForDamageType(type)[0];if(label===void 0)continue;const damageModifier={Label:label,Value:value*scaleForLabel(label),OriginalValue:(stats.damageDistribution?.[type]??0)*scaleForLabel(label)};modifiers.push(damageModifier);primitiveModifiers.push(damageModifier)}}const engineering={BlueprintName:blueprintSymbol,Level:wantedGrade,Quality:quality,...wantedExperimental!==void 0?{ExperimentalEffect:wantedExperimental}:{},Modifiers:modifiers};this.#replaceModule(module.Slot,{...module,Engineering:engineering},stats,primitiveModifiers);return this}setExperimentalEffect(slotKey,experimental){if(experimental!==null){requireString(experimental,"ShipLoadout.setExperimentalEffect: experimental")}const wanted=experimental;const module=this.#fittedModuleFor(slotKey);if(!module)return experimentalEffectUnsupported("emptySlot",{slot:slotKey});const stats=this.#statsFor(module);if(!stats){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const engineering=module.Engineering;if(!engineering){return experimentalEffectUnsupported("notEngineered",{slot:module.Slot,symbol:module.Item})}if(stats.engineeringLocked){return experimentalEffectUnsupported("finalArticle",{slot:module.Slot,symbol:module.Item})}const previous=engineering.ExperimentalEffect??null;if(previous===null&&wanted===null||previous!==null&&wanted!==null&&previous.trim().toLowerCase()===wanted.trim().toLowerCase()){return deepFreeze({kind:"unchanged",experimentalEffectSymbol:previous})}const variant=preEngineeredVariantFor(module);if(stats.category==="hardpoint"&&variant?.acquisition==="mercenary"){return experimentalEffectUnsupported("unsupportedExperimentalEffect",{slot:module.Slot,symbol:module.Item,...wanted===null?{}:{experimental:wanted}})}let effect;if(wanted!==null){effect=getExperimentalEffect(wanted);if(!effect){return experimentalEffectUnsupported("unknownExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:wanted})}const restoresBakedEffect=variant?.experimentalEffectSymbol!==void 0&&variant.acquisition!=="mercenary"&&variant.experimentalEffectSymbol.trim().toLowerCase()===wanted.trim().toLowerCase();if(!experimentalAvailableFor(module.Item,wanted)&&!restoresBakedEffect){return experimentalEffectUnsupported("unsupportedExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:wanted})}}if(variant&&variant.acquisition!=="mercenary"){const stock=this.#engineeringBaseStats(module);if(!stock){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const missing=missingBaseLabels(stock,baseStats(stock),[],effect?.modifiers);if(missing.length>0){return experimentalEffectUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}const{experimentalEffectSymbol:originalEffect,...withoutEffect}=variant;const adjusted=wanted===null?withoutEffect:{...withoutEffect,experimentalEffectSymbol:wanted};const resolved=getPreEngineeredStats(withoutEffect);if(!resolved){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const replacement={BlueprintName:engineering.BlueprintName,Level:engineering.Level,Quality:engineering.Quality,...wanted===null?{}:{ExperimentalEffect:wanted},Modifiers:getPreEngineeredJournalModifiers(adjusted)};this.#replaceModule(module.Slot,{...module,Engineering:replacement},cloneModuleStats(resolved),getPreEngineeredModifiers(adjusted))}else{const blueprint=engineering.BlueprintName;const grade=engineering.Level;const quality=engineering.Quality;if(typeof blueprint!=="string"||!Number.isInteger(grade)||grade<1||grade>5){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const currentEffect=previous===null?void 0:getExperimentalEffect(previous)??null;if(ordinaryEngineeringProof(module.Item,engineering,currentEffect)==="unproven"){return experimentalEffectUnsupported("unidentifiedPreEngineeredVariant",{slot:module.Slot,symbol:module.Item,blueprint:blueprint})}const recipe=resolveBlueprintForModule(module.Item,blueprint);const blueprintGrade=getBlueprintGrade(recipe,grade);if(!blueprintGrade||!blueprintAvailableFor(module.Item,blueprint)||!Number.isFinite(quality)||quality<0||quality>1){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item,blueprint:blueprint,grade:grade})}const base=this.#engineeringBaseStats(module)??stats;const canonical=primitiveEngineeringInputsFor(base,blueprintGrade,effect);const missing=missingBaseLabels(base,baseStats(base),canonical.grade.features,canonical.experimental?.modifiers);if(missing.length>0){return experimentalEffectUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}this.applyBlueprint(module.Slot,blueprint,{grade:grade,quality:quality,...wanted===null?{}:{experimentalEffectSymbol:wanted}})}return deepFreeze({kind:"updated",previousExperimentalEffectSymbol:previous,experimentalEffectSymbol:wanted})}completeEngineeringGrade(slotKey){const module=this.#fittedModuleFor(slotKey);if(!module)return engineeringNormalizationUnsupported("emptySlot",{slot:slotKey});const stats=this.#statsFor(module);if(!stats){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const engineering=module.Engineering;if(!engineering){return engineeringNormalizationUnsupported("notEngineered",{slot:module.Slot,symbol:module.Item})}if(stats.engineeringLocked){return engineeringNormalizationUnsupported("finalArticle",{slot:module.Slot,symbol:module.Item})}if(engineering.Quality===1&&engineering.Modifiers!==void 0){return deepFreeze({kind:"unchanged"})}const previousQuality=engineering.Quality;if(!Number.isFinite(previousQuality)||previousQuality<0||previousQuality>1){return engineeringNormalizationUnsupported("invalidQuality",{slot:module.Slot,symbol:module.Item})}const experimental=engineering.ExperimentalEffect??null;const effect=experimental===null?void 0:getExperimentalEffect(experimental)??void 0;if(experimental!==null&&!effect){return engineeringNormalizationUnsupported("unknownExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:experimental})}const blueprint=engineering.BlueprintName;const grade=engineering.Level;if(typeof blueprint!=="string"||!Number.isInteger(grade)||grade<1||grade>5){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const variant=preEngineeredVariantFor(module);const restoresBakedEffect=variant?.experimentalEffectSymbol!==void 0&&(variant.acquisition!=="mercenary"||stats.category==="hardpoint")&&variant.experimentalEffectSymbol.trim().toLowerCase()===experimental?.trim().toLowerCase();if(experimental!==null&&!experimentalAvailableFor(module.Item,experimental)&&!restoresBakedEffect){return engineeringNormalizationUnsupported("unsupportedExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:experimental})}if(variant&&variant.acquisition!=="mercenary"){const stock=this.#engineeringBaseStats(module);if(!stock){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const missing=missingBaseLabels(stock,baseStats(stock),[],effect?.modifiers);if(missing.length>0){return engineeringNormalizationUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}const{experimentalEffectSymbol:originalEffect,...withoutEffect}=variant;const adjusted=experimental===null?withoutEffect:{...withoutEffect,experimentalEffectSymbol:experimental};const resolved=getPreEngineeredStats(withoutEffect);if(!resolved){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const replacement={BlueprintName:engineering.BlueprintName,Level:engineering.Level,Quality:1,...experimental===null?{}:{ExperimentalEffect:experimental},Modifiers:getPreEngineeredJournalModifiers(adjusted)};this.#replaceModule(module.Slot,{...module,Engineering:replacement},cloneModuleStats(resolved),getPreEngineeredModifiers(adjusted))}else{const proof=ordinaryEngineeringProof(module.Item,engineering,effect);if(proof==="unproven"||proof==="proven"&&!blueprintAvailableFor(module.Item,blueprint)){return engineeringNormalizationUnsupported("unidentifiedPreEngineeredVariant",{slot:module.Slot,symbol:module.Item,blueprint:blueprint})}const recipe=resolveBlueprintForModule(module.Item,blueprint);const blueprintGrade=getBlueprintGrade(recipe,grade);if(!blueprintGrade||!blueprintAvailableFor(module.Item,blueprint)){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item,blueprint:blueprint,grade:grade})}const base=this.#engineeringBaseStats(module)??stats;const canonical=primitiveEngineeringInputsFor(base,blueprintGrade,effect);const missing=missingBaseLabels(base,baseStats(base),canonical.grade.features,canonical.experimental?.modifiers);if(missing.length>0){return engineeringNormalizationUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}this.applyBlueprint(module.Slot,blueprint,{grade:grade,quality:1,...experimental===null?{}:{experimentalEffectSymbol:experimental}})}return deepFreeze({kind:"normalized",previousQuality:previousQuality,quality:1})}setPreEngineeredVariant(slotKey,variant){if(variant===null||typeof variant!=="object"){throw new TypeError(`ShipLoadout.setPreEngineeredVariant: variant must be a pre-engineered variant, received ${describeValue(variant)}`)}requireString(variant.symbol,"ShipLoadout.setPreEngineeredVariant: variant.symbol");requireString(variant.blueprintSymbol,"ShipLoadout.setPreEngineeredVariant: variant.blueprintSymbol");requireString(variant.acquisition,"ShipLoadout.setPreEngineeredVariant: variant.acquisition");requireStringIfPresent(variant.experimentalEffectSymbol,"ShipLoadout.setPreEngineeredVariant: variant.experimentalEffectSymbol");const known=getPreEngineeredVariants(variant.symbol).find(candidate=>candidate.blueprintSymbol.toLowerCase()===variant.blueprintSymbol.toLowerCase()&&candidate.grade===variant.grade&&(candidate.experimentalEffectSymbol?.toLowerCase()??"")===(variant.experimentalEffectSymbol?.toLowerCase()??"")&&candidate.acquisition===variant.acquisition);if(!known){throw new RangeError(`ShipLoadout.setPreEngineeredVariant: no catalogued variant "${truncate(variant.blueprintSymbol)}" for module "${truncate(variant.symbol)}"`)}const stats=getPreEngineeredStats(known);const unresolved=unresolvedModifiers(known);if(unresolved.length>0){throw new TypeError(`ShipLoadout.setPreEngineeredVariant: cannot resolve "${truncate(variant.blueprintSymbol)}" for module "${truncate(variant.symbol)}"; missing base stats for ${unresolved.join(", ")}`)}this.setModule(slotKey,stats);const module=this.#fittedModuleFor(slotKey);const journalModifiers=getPreEngineeredJournalModifiers(known);const engineering={BlueprintName:known.blueprintSymbol,Level:known.grade,Quality:1,...known.experimentalEffectSymbol===void 0?{}:{ExperimentalEffect:known.experimentalEffectSymbol},...journalModifiers.length>0?{Modifiers:journalModifiers}:{}};this.#replaceModule(module.Slot,{...module,Engineering:engineering},cloneModuleStats(stats),getPreEngineeredModifiers(known));return this}clearEngineering(slotKey){const module=this.#fittedModuleFor(slotKey);if(module&&this.#statsFor(module)?.engineeringLocked){throw new TypeError(`ShipLoadout.clearEngineering: module "${truncate(module.Item)}" is a final pre-engineered article and its engineering cannot be removed`)}if(module?.Engineering){const baseStats2=this.#engineeringBaseStats(module);const bare={Slot:module.Slot,Item:module.Item};if(module.On!==void 0)bare.On=module.On;if(module.Priority!==void 0){bare.Priority=module.Priority}if(module.Health!==void 0)bare.Health=module.Health;if(module.Value!==void 0)bare.Value=module.Value;this.#replaceModule(module.Slot,bare,baseStats2??void 0)}return this}setModuleEnabled(slotKey,on){this.#patchModule(slotKey,{On:on});return this}setModulePriority(slotKey,priority){if(!Number.isInteger(priority)||priority<0||priority>4){throw new RangeError(`ShipLoadout: power priority must be an integer 0-4, got ${truncate(priority)}`)}this.#patchModule(slotKey,{Priority:priority});return this}#patchModule(slotKey,patch){const module=this.#fittedModuleFor(slotKey);if(!module){throw new RangeError(`ShipLoadout: slot "${truncate(slotKey)}" is empty`)}this.#modules.set(module.Slot,cloneLoadoutModule({...module,...patch}));this.#slotCache.clear()}toLoadoutEvent(options={}){const unladenMass=this.#computedUnladenMass();const cargoCapacity=this.#computedCargoCapacity();const fuel=this.#computedFuelCapacity();const maxJumpRange=this.#exportableJumpRange(unladenMass);return exportLoadoutEvent({shipSymbol:this.#shipSymbol,...this.#top.ShipName===void 0?{}:{shipName:this.#top.ShipName},...this.#top.ShipIdent===void 0?{}:{shipIdent:this.#top.ShipIdent},modules:this.#modules,layout:this.#layout(),sourcePurchase:this.#sourcePurchase,retailHullValue:this.#ship.hullCost,unladenMass:unladenMass,cargoCapacity:cargoCapacity,fuelCapacity:fuel,maxJumpRange:maxJumpRange,sourceTotalsVoided:this.#importOutcomes.some(outcome=>{if(outcome.sourceSymbol!==null)return false;const parsed=parseSlotName(outcome.slot);return parsed!==null&&stockedMountKind(parsed)==="core"}),statsFor:module=>this.#statsFor(module)},options)}toSlef(options){return toSlef(this.toLoadoutEvent(options),options.header)}toSlefString(options){return stringifySlef(this.toSlef(options),{indent:options.indent??0})}#exportableJumpRange(unladenMass){let drive;try{drive=this.#resolveDrive()}catch{return null}if(drive===null)return null;const tank=this.#computedFuelCapacity();return singleJumpRange(unladenMass,Math.min(tank.main,drive.maxFuel),drive)}#layout(){if(this.#layoutCache===void 0){this.#layoutCache=Object.freeze(enumerateSlots(this.#ship))}return this.#layoutCache}#requireSlot(slotKey){const wanted=normalizeKey(slotKey,SLOT_KEY);const slot=this.#layout().find(s=>normalizeKey(s.key,CATALOGUE_KEY)===wanted);if(!slot){throw new RangeError(`ShipLoadout: hull "${truncate(this.#shipSymbol)}" has no slot "${truncate(slotKey)}"`)}return slot}#fittedKey(slotKey){return matchingKeyIn(this.#modules,normalizeKey(slotKey,SLOT_KEY))}#fittedModuleFor(slotKey){const key=this.#fittedKey(slotKey);return key===null?void 0:this.#modules.get(key)}#calculationModules(){return[...this.#modules.values()].map(module=>({mass:this.#moduleMass(module),cargoCapacity:this.#moduleCapacity(module,"CargoCapacity","cargoCapacity"),cabinCapacity:this.#moduleCapacity(module,"CabinCapacity","cabinCapacity"),fuelCapacity:this.#moduleCapacity(module,"FuelCapacity","fuelCapacity")}))}#moduleLimits(){const entries=[...this.#modules.values()].flatMap(module=>{const stats=this.#statsFor(module);return stats===null?[]:[stats]});return calculateModuleLimits(entries)}#moduleStatsAt(slotKey){const fitted=this.#fittedModuleFor(slotKey);return fitted===void 0?null:this.#statsFor(fitted)}#engineeringBaseStats(module){const fitted=this.#statsFor(module);if(!module.Engineering||preEngineeredVariantFor(module)===null)return fitted;const stock=builtInModuleBySymbol(module.Item,FITTED_ITEM);if(!stock)return fitted;return fitted?.engineeringLocked?cloneModuleStats({...stock,engineeringLocked:true}):stock}#moduleForEffectiveStats(module){const modifiers=this.#primitiveModifiers.get(module.Slot);if(modifiers===void 0||module.Engineering===void 0)return module;return{...module,Engineering:{...module.Engineering,Modifiers:modifiers}}}#modulesForEffectiveStats(){return[...this.#modules.values()].map(module=>this.#moduleForEffectiveStats(module))}#moduleLimitRegression(slotKey,replacement,current=this.#moduleLimits(),previous=this.#moduleStatsAt(slotKey)){if(previous?.limitGroup===void 0&&previous?.limitIncrease===void 0&&replacement?.limitGroup===void 0&&replacement?.limitIncrease===void 0){return null}for(const usage of current){const count=usage.count-Number(previous?.limitGroup===usage.group)+Number(replacement?.limitGroup===usage.group);const increase=usage.increase-(previous?.limitIncrease?.group===usage.group?previous.limitIncrease.amount:0)+(replacement?.limitIncrease?.group===usage.group?replacement.limitIncrease.amount:0);const limit=usage.baseLimit+increase;const excess=Math.max(0,count-limit);if(excess>usage.excess){return{...usage,increase:increase,limit:limit,count:count,excess:excess}}}return null}#replaceModule(slotKey,replacement,replacementStats,primitiveModifiers){const previous=this.#modules.get(slotKey)??null;this.#adjustImportedFigures(previous,replacement,replacementStats);if(replacement===null){this.#modules.delete(slotKey);this.#moduleStats.delete(slotKey);this.#primitiveModifiers.delete(slotKey)}else{this.#modules.set(slotKey,cloneLoadoutModule(replacement));if(replacementStats!==void 0)this.#moduleStats.set(slotKey,replacementStats);if(primitiveModifiers===void 0)this.#primitiveModifiers.delete(slotKey);else this.#primitiveModifiers.set(slotKey,primitiveModifiers)}this.#slotCache.clear()}#adjustImportedFigures(previous,next,nextStats){if(this.#top.UnladenMass!==void 0){this.#top.UnladenMass+=this.#moduleMass(next,nextStats)-this.#moduleMass(previous)}if(this.#top.CargoCapacity!==void 0){this.#top.CargoCapacity+=this.#moduleCapacity(next,"CargoCapacity","cargoCapacity",nextStats)-this.#moduleCapacity(previous,"CargoCapacity","cargoCapacity")}if(this.#top.FuelCapacity?.Main!==void 0){const reserve=this.#top.FuelCapacity.Reserve;this.#top.FuelCapacity={Main:this.#top.FuelCapacity.Main+this.#moduleCapacity(next,"FuelCapacity","fuelCapacity",nextStats)-this.#moduleCapacity(previous,"FuelCapacity","fuelCapacity"),...reserve===void 0?{}:{Reserve:reserve}}}if(normalizeKey(previous?.Item,FITTED_ITEM)===normalizeKey(next?.Item,FITTED_ITEM)){return}if(previous!==null&&isCargoHatchSlot(previous.Slot)||next!==null&&isCargoHatchSlot(next.Slot)){return}delete this.#top.ModulesValue;delete this.#top.Rebuy}#moduleMass(module,statsOverride){if(module===null)return 0;if(isCargoHatchSlot(module.Slot))return 0;const modified=getLoadoutModifier(module,"Mass");if(modified!==null)return modified;return(statsOverride??this.#statsFor(module))?.mass??0}#moduleCapacity(module,modifierLabel,field,statsOverride){if(module===null)return 0;if(isCargoHatchSlot(module.Slot))return 0;const modified=getLoadoutModifier(module,modifierLabel);if(modified!==null)return modified;return(statsOverride??this.#statsFor(module))?.[field]??0}#frameShiftDrive(){for(const m of this.#modules.values()){const stats=this.#statsFor(m);if(stats?.slot==="frameShiftDrive")return{module:m,stats:stats}}return void 0}#resolveDrive(){const fsd=this.#frameShiftDrive();if(!fsd)return null;const{module:fsdModule,stats:base}=fsd;if(base.fuelMul===void 0||base.fuelPower===void 0){throw new TypeError(`ShipLoadout: the fitted record for frame shift drive "${truncate(fsdModule.Item)}" has no jump constants`)}const optMass=getLoadoutModifier(fsdModule,"FSDOptimalMass")??base.optMass;const maxFuel=getLoadoutModifier(fsdModule,"MaxFuelPerJump")??base.maxFuel;if(optMass===void 0||maxFuel===void 0){const missing=[...optMass===void 0?["optMass"]:[],...maxFuel===void 0?["maxFuel"]:[]];throw new TypeError(`ShipLoadout: the fitted record for frame shift drive "${truncate(fsdModule.Item)}" has no ${missing.join(" or ")}`)}return{optMass:optMass,maxFuel:maxFuel,fuelMul:base.fuelMul,fuelPower:base.fuelPower,jumpBoost:this.#resolveJumpBoost()}}#resolveJumpBoost(){for(const m of this.#modules.values()){const stats=this.#statsFor(m);if(stats?.engineeringGroup!=="fsdBoosters"&&(stats?.jumpBoost===void 0||stats.jumpBoost===0)){continue}if(m.On===false)continue;if(stats?.jumpBoost===void 0){throw new TypeError(`ShipLoadout: the fitted record for FSD booster "${truncate(m.Item)}" has no jumpBoost`)}return stats.jumpBoost}return 0}#statsFor(module){if(module===null)return null;const stats=this.#moduleStats.get(module.Slot)??builtInModuleBySymbol(module.Item,FITTED_ITEM);if(stats)return stats;return isBuiltInHullModule(module)?builtInModuleBySymbol(BUILT_IN_HULL_SYMBOL,"ShipLoadout: built-in module"):null}};export{LoadoutEditError,ShipLoadout};//# sourceMappingURL=chunk-25EECUZ2.js.map
1
+ import{validateLoadout}from"./chunk-T6BIFKPU.js";import{calculateModuleLimits}from"./chunk-KPETDYQX.js";import{publishLoadoutInternals,normalizeLoadoutEvent,preEngineeredVariantFor,moduleFitProblem,effectiveModule,moduleFitError}from"./chunk-ZBB7Q3OZ.js";import{getShipBySymbol}from"./chunk-C4FUV6GF.js";import{parseSlef,toSlef,stringifySlef,getLoadoutModifier}from"./chunk-T4MKUKYS.js";import{getSourceModuleValue}from"./chunk-NIURLW2F.js";import{statesInertModifiers,rolledOverFixedArticle,isNonOutfittingSlot,isBuiltInHullModule,cloneLoadoutModule,cloneModuleStats,availableBlueprintsFor,availableExperimentalsFor,ownKeyIn,BUILT_IN_HULL_SYMBOL,FITTED_ITEM,blueprintAvailableFor,blueprintRoutesFor,experimentalAvailableFor,primitiveEngineeringInputsFor,missingBaseLabels,journalModifiersFor,getPreEngineeredStats,getPreEngineeredJournalModifiers,getPreEngineeredModifiers,ordinaryEngineeringProof,unresolvedModifiers,matchingKeyIn,isCargoHatchSlot,orderBySlotLayout}from"./chunk-HE4XE3WR.js";import{builtInModuleBySymbol}from"./chunk-2GVJNKFW.js";import{getPreEngineeredVariants}from"./chunk-EXHZ4CFB.js";import{ALL_MODULES}from"./chunk-BI3EFLQ7.js";import{singleJumpRange}from"./chunk-VTMCSCXV.js";import{calculateUnladenMass,calculatePassengerCapacity,calculateCargoCapacity,calculateFuelCapacity}from"./chunk-C3LLPLLD.js";import{fixedSlotReason,stockedMountKind}from"./chunk-M6J7KP7G.js";import{getBlueprintGrade}from"./chunk-WDAYRHXR.js";import{getDefaultLoadout}from"./chunk-KY7KSPU6.js";import{getExperimentalEffect}from"./chunk-77I24V6B.js";import{ammunitionCapacity}from"./chunk-AA3K5XUE.js";import{baseStats,computeModifiers,labelsForDamageType,scaleForLabel}from"./chunk-U73MBQ45.js";import{resolveBlueprintForModule}from"./chunk-2J6NNI3Y.js";import{getExperimentalsForModule}from"./chunk-M4STXLXO.js";import{loadoutSlotName}from"./chunk-KAA4VOOB.js";import{parseSlotName,enumerateSlots}from"./chunk-RAO35XDF.js";import{normalizeKey,CATALOGUE_KEY}from"./chunk-BKWLI44T.js";import{truncate,describeValue,requireString,requireStringIfPresent}from"./chunk-PKWVG2JY.js";import{deepFreeze}from"./chunk-DURKO7JU.js";var REBUY_FRACTION=.05;function exportLoadoutEvent(input,options){const fromSource=options.credits==="source";const source=fromSource?input.sourcePurchase:null;const totals=source!==null&&!input.sourceTotalsVoided&&sourceTotalsHold(input.modules,source)?source:null;const hullValue=fromSource?source?.hullValue??null:input.retailHullValue;const modulesValue=fromSource?totals?.modulesValue??null:computedModulesValue(input.modules,input.statsFor);const rebuy=fromSource?totals?.rebuy??null:hullValue===null||modulesValue===null?null:Math.trunc((hullValue+modulesValue)*REBUY_FRACTION);return{Ship:input.shipSymbol.toLowerCase(),...input.shipName===void 0?{}:{ShipName:input.shipName},...input.shipIdent===void 0?{}:{ShipIdent:input.shipIdent},...hullValue===null?{}:{HullValue:hullValue},...modulesValue===null?{}:{ModulesValue:modulesValue},UnladenMass:input.unladenMass,CargoCapacity:input.cargoCapacity,...input.maxJumpRange===null?{}:{MaxJumpRange:input.maxJumpRange},FuelCapacity:{Main:input.fuelCapacity.main,Reserve:input.fuelCapacity.reserve},...rebuy===null?{}:{Rebuy:rebuy},Modules:exportModules(input,options,fromSource)}}function exportModules(input,options,fromSource){const ordered=options.moduleOrder==="slots"?slotOrderedModules(input.modules,input.layout):[...input.modules.values()];return ordered.map(module=>{const on=module.On??(options.explicitPower?true:void 0);const priority=module.Priority??(options.explicitPower?0:void 0);const value=fromSource?sourceModuleValue(module,input.sourcePurchase):moduleValue(module,input.statsFor);return{Slot:module.Slot,Item:module.Item.toLowerCase(),...on===void 0?{}:{On:on},...priority===void 0?{}:{Priority:priority},...module.Health===void 0?{}:{Health:module.Health},...typeof value==="number"?{Value:value}:{},...module.Engineering===void 0?{}:{Engineering:cloneLoadoutModule(module).Engineering}}})}function slotOrderedModules(modules,layout){return orderBySlotLayout([...modules.values()],layout,module=>module.Slot)}function computedModulesValue(modules,statsFor){let sum=0;for(const module of modules.values()){const value=moduleValue(module,statsFor);if(value==="unknown")return null;if(value!=="free")sum+=value}return sum}function moduleValue(module,statsFor){const stats=statsFor(module);if(stats!==null)return stats.cost??"unknown";return isNonOutfittingSlot(module.Slot)||isBuiltInHullModule(module)?"free":"unknown"}var SOURCE_ITEM="ShipLoadout: sourcePurchase moduleValues[].item";function sourceModuleValue(module,source){const entry=source===null?null:getSourceModuleValue(source,module.Slot);if(entry===null)return"unknown";return normalizeKey(entry.item,SOURCE_ITEM)===normalizeKey(module.Item,FITTED_ITEM)?entry.value:"unknown"}function sourceTotalsHold(modules,source){for(const entry of source.moduleValues){const key=matchingKeyIn(modules,entry.slot);const fitted=key===null?void 0:modules.get(key);if(!fitted)return false;if(isCargoHatchSlot(entry.slot)&&entry.value===0)continue;if(normalizeKey(fitted.Item,FITTED_ITEM)!==normalizeKey(entry.item,SOURCE_ITEM)){return false}}return true}var SLOT_KEY="ShipLoadout: slotKey";var FITTED_SLOT="ShipLoadout: fitted module Slot";var LoadoutEditError=class extends TypeError{code;constraint;params;constructor(message,code,params,constraint){super(message);this.code=code;this.params=deepFreeze(structuredClone(params));if(constraint!==void 0)this.constraint=constraint}};var experimentalEffectUnsupported=(code,params)=>deepFreeze({kind:"unsupported",code:code,params:params});var engineeringNormalizationUnsupported=(code,params)=>deepFreeze({kind:"unsupported",code:code,params:params});function weighable(tonnes){return tonnes!==void 0&&Number.isFinite(tonnes)&&tonnes>=0?tonnes:void 0}var AGGREGATE_STATS=["mass","cargoCapacity","cabinCapacity","fuelCapacity"];var ShipLoadout=class _ShipLoadout{#ship;#shipSymbol;#modules;#moduleStats;#primitiveModifiers;#top;#sourcePurchase;#importOutcomes;#slotCache=/* @__PURE__ */new Map;#layoutCache;constructor(ship,shipSymbol,modules,top,sourcePurchase=null,moduleStats=/* @__PURE__ */new Map,primitiveModifiers=/* @__PURE__ */new Map,importOutcomes=deepFreeze([])){this.#ship=ship;this.#shipSymbol=shipSymbol;this.#modules=modules;this.#top=top;this.#sourcePurchase=sourcePurchase;this.#moduleStats=moduleStats;this.#primitiveModifiers=primitiveModifiers;this.#importOutcomes=importOutcomes;publishLoadoutInternals(this,{ship:ship,modules:()=>[...this.#modules.values()],effectiveModules:()=>this.#modulesForEffectiveStats(),effectiveModule:module=>this.#moduleForEffectiveStats(module),statsFor:module=>this.#statsFor(module),layout:()=>this.#layout(),resolveDrive:()=>this.#resolveDrive(),frameShiftDriveModule:()=>this.#frameShiftDrive()?.module,calculationModules:()=>this.#calculationModules(),statedMainFuel:()=>this.#top.FuelCapacity?.Main})}static fromSlef(input,index=0){const entries=parseSlef(input);const entry=entries[index];if(!entry){throw new TypeError(`ShipLoadout.fromSlef: no entry at index ${truncate(index)} (have ${entries.length})`)}const imported=normalizeLoadoutEvent(entry.data);const ship=getShipBySymbol(imported.shipSymbol);if(!ship){throw new TypeError(`ShipLoadout.fromSlef: unknown hull "${truncate(imported.shipSymbol)}"`)}return _ShipLoadout.#fromImported(imported,ship)}static fromLoadout(event){if(event===null||typeof event!=="object"){throw new TypeError(`ShipLoadout.fromLoadout: event must be a Loadout event, received ${describeValue(event)}`)}const imported=normalizeLoadoutEvent(event);const ship=getShipBySymbol(imported.shipSymbol);if(!ship){throw new TypeError(`ShipLoadout.fromLoadout: unknown hull "${truncate(imported.shipSymbol)}"`)}return _ShipLoadout.#fromImported(imported,ship)}static#fromImported(imported,ship){const outcomes=[...imported.outcomes];const loadout=new _ShipLoadout(ship,imported.shipSymbol,imported.modules,imported.top,imported.sourcePurchase,imported.moduleStats,imported.primitiveModifiers,outcomes);const{UnladenMass:UnladenMass,CargoCapacity:CargoCapacity,FuelCapacity:FuelCapacity}=imported.top;for(const module of[...imported.modules.values()]){const unresolved=loadout.#rollStatedRecipe(module);if(unresolved!==null)outcomes.push(unresolved)}if(UnladenMass!==void 0)loadout.#top.UnladenMass=UnladenMass;if(CargoCapacity!==void 0)loadout.#top.CargoCapacity=CargoCapacity;if(FuelCapacity!==void 0)loadout.#top.FuelCapacity=FuelCapacity;deepFreeze(outcomes);return loadout}#rollStatedRecipe(module){const engineering=module.Engineering;if(!engineering||typeof engineering.BlueprintName!=="string")return null;const stated=engineering.Modifiers;const stats=this.#statsFor(module);if(stated!==void 0&&(this.#moduleStats.has(module.Slot)||stats===null||!statesInertModifiers(stats,stated))){return null}if(stated===void 0&&this.#moduleStats.has(module.Slot)){const variant=preEngineeredVariantFor(module);if(variant?.acquisition!=="mercenary"||engineering.Level<=variant.grade){return null}}try{this.applyBlueprint(module.Slot,engineering.BlueprintName,{grade:engineering.Level,quality:engineering.Quality??1,...typeof engineering.ExperimentalEffect==="string"?{experimentalEffectSymbol:engineering.ExperimentalEffect}:{}});if(stated!==void 0){return{action:"rerolledEngineering",slot:module.Slot,sourceSymbol:module.Item,blueprintSymbol:engineering.BlueprintName}}const passedOver=rolledOverFixedArticle(module.Item,engineering);return passedOver===null?null:{action:"ambiguousEngineering",slot:module.Slot,sourceSymbol:module.Item,blueprintSymbol:engineering.BlueprintName,preEngineeredVariant:passedOver}}catch(error){if(!(error instanceof TypeError)&&!(error instanceof RangeError))throw error;return{action:"unresolvedEngineering",slot:module.Slot,sourceSymbol:module.Item,blueprintSymbol:engineering.BlueprintName}}}static empty(shipSymbol){const requested=requireString(shipSymbol,"ShipLoadout.empty: shipSymbol");const ship=getShipBySymbol(requested);if(!ship){throw new TypeError(`ShipLoadout.empty: no slot layout for hull "${truncate(shipSymbol)}"`)}const fitted=(getDefaultLoadout(ship.symbol)?.modules??[]).filter(module=>{const parsed=parseSlotName(module.slot);return parsed!==null&&fixedSlotReason(parsed)!==null});return new _ShipLoadout(ship,ship.symbol,new Map(fitted.map(module=>[module.slot,{Slot:module.slot,Item:module.symbol}])),{})}static default(shipSymbol){const requested=requireString(shipSymbol,"ShipLoadout.default: shipSymbol");const ship=getShipBySymbol(requested);if(!ship){throw new TypeError(`ShipLoadout.default: no default loadout for hull "${truncate(shipSymbol)}"`)}const loadout=getDefaultLoadout(ship.symbol);return new _ShipLoadout(ship,loadout.symbol,new Map(loadout.modules.map(module=>[module.slot,{Slot:module.slot,Item:module.symbol}])),{})}get shipSymbol(){return this.#shipSymbol}get shipName(){return this.#top.ShipName??null}get shipIdent(){return this.#top.ShipIdent??null}get unladenMass(){return this.#top.UnladenMass??this.#computedUnladenMass()}#computedUnladenMass(){return calculateUnladenMass(this.#ship.hullMass,this.#calculationModules())}get fuelCapacity(){const cap=this.#top.FuelCapacity;if(cap?.Main!==void 0&&cap.Reserve!==void 0){return Object.freeze({main:cap.Main,reserve:cap.Reserve})}const computed=this.#computedFuelCapacity();return Object.freeze({main:cap?.Main??computed.main,reserve:cap?.Reserve??computed.reserve})}get cargoCapacity(){return this.#top.CargoCapacity??this.#computedCargoCapacity()}get passengerCapacity(){return calculatePassengerCapacity(this.#calculationModules())}#computedCargoCapacity(){return calculateCargoCapacity(this.#calculationModules())}#computedFuelCapacity(){return calculateFuelCapacity(this.#ship.reserveFuelCapacity,this.#calculationModules())}get hullValue(){return this.#top.HullValue??null}get modulesValue(){return this.#top.ModulesValue??null}get rebuy(){return this.#top.Rebuy??null}get sourcePurchase(){return this.#sourcePurchase}get importOutcomes(){return this.#importOutcomes}validation(){const slots=this.#layout();const byKey=new Map(slots.map(slot=>[normalizeKey(slot.key,CATALOGUE_KEY),slot]));const modules=[...this.#modules.values()].map(module=>{const stats=this.#statsFor(module);const slot=byKey.get(normalizeKey(module.Slot,FITTED_SLOT));const builtIn=stats===null&&isNonOutfittingSlot(module.Slot)||isBuiltInHullModule(module);const fitProblem=stats&&slot&&!builtIn?moduleFitProblem(this.#shipSymbol,slot,stats):null;const thrusterMaxMass=weighable(stats?.slot==="thrusters"?effectiveModule(this.#moduleForEffectiveStats(module),stats)?.maxMass:void 0);return{slot:module.Slot,symbol:module.Item,requiresKnownSlot:!builtIn,fitError:fitProblem?.message??null,...fitProblem===null?{}:{fitConstraint:fitProblem.constraint},...fitProblem?.params===void 0?{}:{fitParams:fitProblem.params},...stats?.exclusionGroup===void 0?{}:{exclusionGroup:stats.exclusionGroup},...stats?.limitGroup===void 0?{}:{limitGroup:stats.limitGroup},...stats?.limitIncrease===void 0?{}:{limitIncrease:stats.limitIncrease},...thrusterMaxMass===void 0?{}:{thrusterMaxMass:thrusterMaxMass}}});const dry=weighable(this.unladenMass);const fuel=weighable(this.fuelCapacity.main);const cargo=weighable(this.cargoCapacity);const mass=dry===void 0?void 0:{dry:dry,...fuel===void 0?{}:{fuel:fuel},...fuel===void 0||cargo===void 0?{}:{cargo:cargo}};return validateLoadout({shipSymbol:this.#shipSymbol,slots:slots,modules:modules,...mass===void 0?{}:{mass:mass}})}slots(kind){const cached=this.#slotCache.get(kind);if(cached!==void 0)return cached;const slots=kind===void 0?this.#layout():this.#layout().filter(slot=>slot.kind===kind);const currentLimits=this.#moduleLimits();const value=deepFreeze(slots.map(slot=>{const stats=this.#moduleStatsAt(slot.key);const fixedReason=fixedSlotReason(slot);const immovableReason=fixedReason!==null?fixedReason:stats?.limitIncrease!==void 0&&this.#moduleLimitRegression(slot.key,null,currentLimits,stats)!==null?"moduleLimit":null;return{...slot,name:loadoutSlotName(slot),module:this.fittedModuleAt(slot.key),removable:immovableReason===null,...immovableReason===null?{}:{immovableReason:immovableReason}}}));this.#slotCache.set(kind,value);return value}fittedModuleAt(slotKey){const module=this.#fittedModuleFor(slotKey);if(!module)return null;const raw=cloneLoadoutModule(module);const stats=this.#statsFor(module);const effective=effectiveModule(this.#moduleForEffectiveStats(module),stats);return deepFreeze({slot:module.Slot,symbol:raw.Item,on:raw.On,priority:raw.Priority,health:raw.Health,value:raw.Value,engineering:raw.Engineering,raw:raw,stats:stats===null?null:cloneModuleStats(stats),effectiveStats:effective===null?null:cloneModuleStats(effective),ammunition:ammunitionCapacity(effective),preEngineeredVariant:preEngineeredVariantFor(raw)})}fittedModules(){return deepFreeze([...this.#modules.keys()].flatMap(key=>{const fitted=this.fittedModuleAt(key);return fitted===null?[]:[fitted]}))}availableBlueprints(slotKey){const module=this.#fittedModuleFor(slotKey);return deepFreeze(module?availableBlueprintsFor(module.Item,this.#statsFor(module)):[])}availableExperimentalEffects(slotKey){const module=this.#fittedModuleFor(slotKey);const stats=module?this.#statsFor(module):null;const variant=module?preEngineeredVariantFor(module):null;return deepFreeze(module&&!(stats?.category==="hardpoint"&&variant?.acquisition==="mercenary")?availableExperimentalsFor(module.Item,stats):[])}modulesForSlot(slotKey){const slot=this.#requireSlot(slotKey);const occupied=new Set([...this.#modules.values()].flatMap(fitted=>{if(normalizeKey(fitted.Slot,FITTED_SLOT)===normalizeKey(slot.key,CATALOGUE_KEY))return[];const group=this.#statsFor(fitted)?.exclusionGroup;return group===void 0?[]:[group]}));const currentLimits=this.#moduleLimits();const currentStats=this.#moduleStatsAt(slot.key);return ALL_MODULES.filter(module=>module.grantOnly===void 0&&moduleFitError(this.#shipSymbol,slot,module)===null&&(module.exclusionGroup===void 0||!occupied.has(module.exclusionGroup))&&this.#moduleLimitRegression(slot.key,module,currentLimits,currentStats)===null)}repairFixedMount(slotKey){const requested=requireString(slotKey,SLOT_KEY);const wanted=normalizeKey(requested,SLOT_KEY);const slot=this.#requireSlot(requested);const fittedKey=this.#fittedKey(requested);const resultSlot=fittedKey??requested;const canonicalKey=slot.key;if(fixedSlotReason(slot)===null){return deepFreeze({status:"refused",slot:resultSlot,reason:"notFixedMount"})}const current=this.#fittedModuleFor(requested);const currentStats=current?this.#statsFor(current):null;const valid=current!==void 0&&currentStats!==null&&(slot.kind==="cargoHatch"?isBuiltInHullModule(current):moduleFitProblem(this.#shipSymbol,slot,currentStats)===null);if(valid){return deepFreeze({status:"unchanged",slot:current.Slot,symbol:current.Item})}const defaultModule=getDefaultLoadout(this.#shipSymbol)?.modules.find(module=>normalizeKey(module.slot,CATALOGUE_KEY)===wanted);if(!defaultModule){return deepFreeze({status:"defaultUnavailable",slot:resultSlot})}const ownKey=ownKeyIn(this.#modules,canonicalKey);const replacement={Slot:ownKey,Item:defaultModule.symbol,...current?.On===void 0?{}:{On:current.On},...current?.Priority===void 0?{}:{Priority:current.Priority},...current?.Health===void 0?{}:{Health:current.Health}};const replacementStats=builtInModuleBySymbol(defaultModule.symbol,"ShipLoadout.repairFixedMount")??(isBuiltInHullModule(replacement)?builtInModuleBySymbol(BUILT_IN_HULL_SYMBOL,"ShipLoadout.repairFixedMount"):null);if(!replacementStats){return deepFreeze({status:"defaultUnavailable",slot:resultSlot,symbol:defaultModule.symbol})}this.#replaceModule(ownKey,replacement,replacementStats);return deepFreeze({status:"repaired",slot:ownKey,symbol:defaultModule.symbol})}setModule(slotKey,module){const slot=this.#requireSlot(slotKey);if(module===null||module===void 0){throw new TypeError(`ShipLoadout.setModule: no module supplied for "${truncate(slotKey)}" (did the module lookup return undefined?)`)}if(typeof module.symbol!=="string"){throw new TypeError(`ShipLoadout.setModule: module for "${truncate(slotKey)}" must be an outfitting module, received ${describeValue(module)}`)}module=cloneModuleStats(module);const catalogued=builtInModuleBySymbol(module.symbol,FITTED_ITEM);if(catalogued===null){throw new TypeError(`ShipLoadout.setModule: no module is catalogued as "${truncate(module.symbol)}"`)}for(const field of AGGREGATE_STATS){const stated=module[field];if(stated===void 0){if(catalogued[field]===void 0)continue;throw new TypeError(`ShipLoadout.setModule: the supplied record for "${truncate(module.symbol)}" has no ${field}`)}if(typeof stated!=="number"||!Number.isFinite(stated)){throw new TypeError(`ShipLoadout.setModule: the supplied record for "${truncate(module.symbol)}" states a ${field} of ${describeValue(stated)}`)}}const problem=moduleFitProblem(this.#shipSymbol,slot,module);if(problem){if(problem.constraint==="immutableSlot"){throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${problem.message}`,"immutableSlot",{slot:slot.key})}throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${problem.message}`,"incompatibleModule",{...problem.params,slot:slot.key,symbol:module.symbol,constraint:problem.constraint},problem.constraint)}if(module.exclusionGroup!==void 0){const conflict=[...this.#modules.values()].find(fitted=>normalizeKey(fitted.Slot,FITTED_SLOT)!==normalizeKey(slot.key,CATALOGUE_KEY)&&this.#statsFor(fitted)?.exclusionGroup===module.exclusionGroup);if(conflict){throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${module.exclusionGroup} is limited to one per ship (already fitted in ${truncate(conflict.Slot)})`,"duplicateExclusiveModule",{exclusionGroup:module.exclusionGroup,slot:slot.key,symbol:module.symbol,previousSlot:conflict.Slot,previousSymbol:conflict.Item})}}const limitProblem=this.#moduleLimitRegression(slot.key,module);if(limitProblem!==null){throw new LoadoutEditError(`ShipLoadout.setModule: ${truncate(module.symbol)} → ${truncate(slotKey)}: ${limitProblem.group} would have ${limitProblem.count} modules but the ship allows ${limitProblem.limit}`,"moduleLimitExceeded",{group:limitProblem.group,count:limitProblem.count,limit:limitProblem.limit,slot:slot.key,symbol:module.symbol})}const key=this.#fittedKey(slotKey)??slot.key;this.#replaceModule(key,{Slot:key,Item:module.symbol},module);return this}removeModule(slotKey){const wanted=normalizeKey(slotKey,SLOT_KEY);if(wanted==="cargohatch"){throw new LoadoutEditError("ShipLoadout.removeModule: the cargoHatch slot cannot be changed","immutableSlot",{slot:"CargoHatch"})}const parsed=parseSlotName(slotKey);const slot=this.#layout().find(candidate=>normalizeKey(candidate.key,CATALOGUE_KEY)===wanted);if(parsed!==null&&fixedSlotReason(parsed)==="requiredSlot"){const fittedKey=this.#fittedKey(slotKey);const key2=slot?.key??fittedKey??slotKey;throw new LoadoutEditError(`ShipLoadout.removeModule: the ${truncate(key2)} slot is required and cannot be emptied`,"requiredSlot",{slot:key2})}const key=this.#fittedKey(slotKey);if(key!==null){const limitProblem=this.#moduleLimitRegression(key,null);if(limitProblem!==null){const fitted=this.#modules.get(key);throw new LoadoutEditError(`ShipLoadout.removeModule: ${truncate(slotKey)}: ${limitProblem.group} would have ${limitProblem.count} modules but the ship allows ${limitProblem.limit}`,"moduleLimitExceeded",{group:limitProblem.group,count:limitProblem.count,limit:limitProblem.limit,slot:key,...fitted===void 0?{}:{symbol:fitted.Item}})}this.#replaceModule(key,null)}return this}applyBlueprint(slotKey,blueprintSymbol,options){requireString(blueprintSymbol,"ShipLoadout.applyBlueprint: blueprintSymbol");if(options===null||typeof options!=="object"){throw new TypeError(`ShipLoadout.applyBlueprint: options must be an object with a grade, received ${describeValue(options)}`)}const wantedGrade=options.grade;const wantedQuality=options.quality;let wantedExperimental=options.experimentalEffectSymbol??void 0;requireStringIfPresent(wantedExperimental,"ShipLoadout.applyBlueprint: options.experimentalEffectSymbol");const module=this.#fittedModuleFor(slotKey);if(!module){throw new RangeError(`ShipLoadout.applyBlueprint: slot "${truncate(slotKey)}" is empty`)}const fittedStats=this.#statsFor(module);if(!fittedStats){throw new TypeError(`ShipLoadout.applyBlueprint: no stats for module "${truncate(module.Item)}"`)}const recipe=resolveBlueprintForModule(module.Item,blueprintSymbol);const named=recipe===blueprintSymbol?`"${truncate(blueprintSymbol)}"`:`"${truncate(blueprintSymbol)}" (${truncate(recipe)} on this module)`;const written=blueprintSymbol.trim().toLowerCase();const resolved=recipe.trim().toLowerCase();const mercenaryHardpoint=fittedStats.category==="hardpoint"?getPreEngineeredVariants(module.Item).find(variant=>variant.acquisition==="mercenary"&&(variant.blueprintSymbol.toLowerCase()===written||variant.blueprintSymbol.toLowerCase()===resolved)):void 0;if(mercenaryHardpoint){const locked=mercenaryHardpoint.experimentalEffectSymbol;if(wantedExperimental!==void 0&&(locked===void 0||locked.trim().toLowerCase()!==wantedExperimental.trim().toLowerCase())){throw new TypeError(`ShipLoadout.applyBlueprint: Mercenary hardpoint "${truncate(module.Item)}" keeps its purchased experimental effect`)}wantedExperimental=locked}if(getPreEngineeredVariants(module.Item).some(variant=>variant.acquisition==="eventReward"&&(variant.blueprintSymbol.toLowerCase()===written||variant.blueprintSymbol.toLowerCase()===resolved))){throw new TypeError(`ShipLoadout.applyBlueprint: ${named} is a fixed pre-engineered identity, not a craftable blueprint; use setPreEngineeredVariant to fit its fixed article`)}if(!Number.isInteger(wantedGrade)||wantedGrade<1||wantedGrade>5){throw new RangeError(`ShipLoadout.applyBlueprint: no blueprint ${named} grade ${truncate(wantedGrade)}`)}const grade=getBlueprintGrade(recipe,wantedGrade);if(!grade){throw new RangeError(`ShipLoadout.applyBlueprint: no blueprint ${named} grade ${truncate(wantedGrade)}`)}let experimental;if(wantedExperimental!==void 0){experimental=getExperimentalEffect(wantedExperimental);if(!experimental){throw new RangeError(`ShipLoadout.applyBlueprint: unknown experimental effect "${truncate(wantedExperimental)}"`)}}const quality=wantedQuality??1;if(!Number.isFinite(quality)||quality<0||quality>1){throw new RangeError(`ShipLoadout.applyBlueprint: quality must be a finite number in [0, 1]`)}if(fittedStats.engineeringLocked){throw new TypeError(`ShipLoadout.applyBlueprint: module "${truncate(module.Item)}" is a final pre-engineered article and accepts no further engineering`)}if(!blueprintAvailableFor(module.Item,blueprintSymbol)){const offered=[...blueprintRoutesFor(module.Item)].map(([blueprint,route])=>`${blueprint} (${route})`);throw new TypeError(offered.length>0?`ShipLoadout.applyBlueprint: module "${truncate(module.Item)}" is not offered blueprint ${named}; available candidates are ${offered.join(", ")}`:`ShipLoadout.applyBlueprint: no registry lists an engineering menu for module "${truncate(module.Item)}"`)}if(wantedExperimental!==void 0&&!experimentalAvailableFor(module.Item,wantedExperimental)&&mercenaryHardpoint===void 0){const offered=getExperimentalsForModule(module.Item);throw new TypeError(`ShipLoadout.applyBlueprint: module "${truncate(module.Item)}" is not offered experimental effect "${truncate(wantedExperimental)}"; it takes ${offered.length>0?offered.join(", "):"no experimental effect"}`)}const stats=this.#engineeringBaseStats(module)??fittedStats;const base=baseStats(stats);const canonical=primitiveEngineeringInputsFor(stats,grade,experimental);const missing=missingBaseLabels(stats,base,canonical.grade.features,canonical.experimental?.modifiers);if(missing.length>0){throw new TypeError(`ShipLoadout.applyBlueprint: cannot compute ${named} for module "${truncate(module.Item)}"; missing base stats for ${missing.join(", ")}`)}const damageDistribution=experimental?.damageDistribution??grade.damageDistribution;const primitiveModifiers=computeModifiers(base,canonical.grade,quality,canonical.experimental);const modifiers=journalModifiersFor(stats,primitiveModifiers);if(damageDistribution){for(const type of["kinetic","thermal","explosive","absolute"]){const value=damageDistribution[type];if(value===void 0)continue;const label=labelsForDamageType(type)[0];if(label===void 0)continue;const damageModifier={Label:label,Value:value*scaleForLabel(label),OriginalValue:(stats.damageDistribution?.[type]??0)*scaleForLabel(label)};modifiers.push(damageModifier);primitiveModifiers.push(damageModifier)}}const engineering={BlueprintName:blueprintSymbol,Level:wantedGrade,Quality:quality,...wantedExperimental!==void 0?{ExperimentalEffect:wantedExperimental}:{},Modifiers:modifiers};this.#replaceModule(module.Slot,{...module,Engineering:engineering},stats,primitiveModifiers);return this}setExperimentalEffect(slotKey,experimental){if(experimental!==null){requireString(experimental,"ShipLoadout.setExperimentalEffect: experimental")}const wanted=experimental;const module=this.#fittedModuleFor(slotKey);if(!module)return experimentalEffectUnsupported("emptySlot",{slot:slotKey});const stats=this.#statsFor(module);if(!stats){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const engineering=module.Engineering;if(!engineering){return experimentalEffectUnsupported("notEngineered",{slot:module.Slot,symbol:module.Item})}if(stats.engineeringLocked){return experimentalEffectUnsupported("finalArticle",{slot:module.Slot,symbol:module.Item})}const previous=engineering.ExperimentalEffect??null;if(previous===null&&wanted===null||previous!==null&&wanted!==null&&previous.trim().toLowerCase()===wanted.trim().toLowerCase()){return deepFreeze({kind:"unchanged",experimentalEffectSymbol:previous})}const variant=preEngineeredVariantFor(module);if(stats.category==="hardpoint"&&variant?.acquisition==="mercenary"){return experimentalEffectUnsupported("unsupportedExperimentalEffect",{slot:module.Slot,symbol:module.Item,...wanted===null?{}:{experimental:wanted}})}let effect;if(wanted!==null){effect=getExperimentalEffect(wanted);if(!effect){return experimentalEffectUnsupported("unknownExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:wanted})}const restoresBakedEffect=variant?.experimentalEffectSymbol!==void 0&&variant.acquisition!=="mercenary"&&variant.experimentalEffectSymbol.trim().toLowerCase()===wanted.trim().toLowerCase();if(!experimentalAvailableFor(module.Item,wanted)&&!restoresBakedEffect){return experimentalEffectUnsupported("unsupportedExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:wanted})}}if(variant&&variant.acquisition!=="mercenary"){const stock=this.#engineeringBaseStats(module);if(!stock){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const missing=missingBaseLabels(stock,baseStats(stock),[],effect?.modifiers);if(missing.length>0){return experimentalEffectUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}const{experimentalEffectSymbol:originalEffect,...withoutEffect}=variant;const adjusted=wanted===null?withoutEffect:{...withoutEffect,experimentalEffectSymbol:wanted};const resolved=getPreEngineeredStats(withoutEffect);if(!resolved){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const replacement={BlueprintName:engineering.BlueprintName,Level:engineering.Level,Quality:engineering.Quality,...wanted===null?{}:{ExperimentalEffect:wanted},Modifiers:getPreEngineeredJournalModifiers(adjusted)};this.#replaceModule(module.Slot,{...module,Engineering:replacement},cloneModuleStats(resolved),getPreEngineeredModifiers(adjusted))}else{const blueprint=engineering.BlueprintName;const grade=engineering.Level;const quality=engineering.Quality;if(typeof blueprint!=="string"||!Number.isInteger(grade)||grade<1||grade>5){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const currentEffect=previous===null?void 0:getExperimentalEffect(previous)??null;if(ordinaryEngineeringProof(module.Item,engineering,currentEffect)==="unproven"){return experimentalEffectUnsupported("unidentifiedPreEngineeredVariant",{slot:module.Slot,symbol:module.Item,blueprint:blueprint})}const recipe=resolveBlueprintForModule(module.Item,blueprint);const blueprintGrade=getBlueprintGrade(recipe,grade);if(!blueprintGrade||!blueprintAvailableFor(module.Item,blueprint)||!Number.isFinite(quality)||quality<0||quality>1){return experimentalEffectUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item,blueprint:blueprint,grade:grade})}const base=this.#engineeringBaseStats(module)??stats;const canonical=primitiveEngineeringInputsFor(base,blueprintGrade,effect);const missing=missingBaseLabels(base,baseStats(base),canonical.grade.features,canonical.experimental?.modifiers);if(missing.length>0){return experimentalEffectUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}this.applyBlueprint(module.Slot,blueprint,{grade:grade,quality:quality,...wanted===null?{}:{experimentalEffectSymbol:wanted}})}return deepFreeze({kind:"updated",previousExperimentalEffectSymbol:previous,experimentalEffectSymbol:wanted})}completeEngineeringGrade(slotKey){const module=this.#fittedModuleFor(slotKey);if(!module)return engineeringNormalizationUnsupported("emptySlot",{slot:slotKey});const stats=this.#statsFor(module);if(!stats){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const engineering=module.Engineering;if(!engineering){return engineeringNormalizationUnsupported("notEngineered",{slot:module.Slot,symbol:module.Item})}if(stats.engineeringLocked){return engineeringNormalizationUnsupported("finalArticle",{slot:module.Slot,symbol:module.Item})}if(engineering.Quality===1&&engineering.Modifiers!==void 0){return deepFreeze({kind:"unchanged"})}const previousQuality=engineering.Quality;if(!Number.isFinite(previousQuality)||previousQuality<0||previousQuality>1){return engineeringNormalizationUnsupported("invalidQuality",{slot:module.Slot,symbol:module.Item})}const experimental=engineering.ExperimentalEffect??null;const effect=experimental===null?void 0:getExperimentalEffect(experimental)??void 0;if(experimental!==null&&!effect){return engineeringNormalizationUnsupported("unknownExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:experimental})}const blueprint=engineering.BlueprintName;const grade=engineering.Level;if(typeof blueprint!=="string"||!Number.isInteger(grade)||grade<1||grade>5){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const variant=preEngineeredVariantFor(module);const restoresBakedEffect=variant?.experimentalEffectSymbol!==void 0&&(variant.acquisition!=="mercenary"||stats.category==="hardpoint")&&variant.experimentalEffectSymbol.trim().toLowerCase()===experimental?.trim().toLowerCase();if(experimental!==null&&!experimentalAvailableFor(module.Item,experimental)&&!restoresBakedEffect){return engineeringNormalizationUnsupported("unsupportedExperimentalEffect",{slot:module.Slot,symbol:module.Item,experimental:experimental})}if(variant&&variant.acquisition!=="mercenary"){const stock=this.#engineeringBaseStats(module);if(!stock){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const missing=missingBaseLabels(stock,baseStats(stock),[],effect?.modifiers);if(missing.length>0){return engineeringNormalizationUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}const{experimentalEffectSymbol:originalEffect,...withoutEffect}=variant;const adjusted=experimental===null?withoutEffect:{...withoutEffect,experimentalEffectSymbol:experimental};const resolved=getPreEngineeredStats(withoutEffect);if(!resolved){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item})}const replacement={BlueprintName:engineering.BlueprintName,Level:engineering.Level,Quality:1,...experimental===null?{}:{ExperimentalEffect:experimental},Modifiers:getPreEngineeredJournalModifiers(adjusted)};this.#replaceModule(module.Slot,{...module,Engineering:replacement},cloneModuleStats(resolved),getPreEngineeredModifiers(adjusted))}else{const proof=ordinaryEngineeringProof(module.Item,engineering,effect);if(proof==="unproven"||proof==="proven"&&!blueprintAvailableFor(module.Item,blueprint)){return engineeringNormalizationUnsupported("unidentifiedPreEngineeredVariant",{slot:module.Slot,symbol:module.Item,blueprint:blueprint})}const recipe=resolveBlueprintForModule(module.Item,blueprint);const blueprintGrade=getBlueprintGrade(recipe,grade);if(!blueprintGrade||!blueprintAvailableFor(module.Item,blueprint)){return engineeringNormalizationUnsupported("unsupportedEngineering",{slot:module.Slot,symbol:module.Item,blueprint:blueprint,grade:grade})}const base=this.#engineeringBaseStats(module)??stats;const canonical=primitiveEngineeringInputsFor(base,blueprintGrade,effect);const missing=missingBaseLabels(base,baseStats(base),canonical.grade.features,canonical.experimental?.modifiers);if(missing.length>0){return engineeringNormalizationUnsupported("unresolvedModifiers",{slot:module.Slot,symbol:module.Item,labels:missing})}this.applyBlueprint(module.Slot,blueprint,{grade:grade,quality:1,...experimental===null?{}:{experimentalEffectSymbol:experimental}})}return deepFreeze({kind:"normalized",previousQuality:previousQuality,quality:1})}setPreEngineeredVariant(slotKey,variant){if(variant===null||typeof variant!=="object"){throw new TypeError(`ShipLoadout.setPreEngineeredVariant: variant must be a pre-engineered variant, received ${describeValue(variant)}`)}requireString(variant.symbol,"ShipLoadout.setPreEngineeredVariant: variant.symbol");requireString(variant.blueprintSymbol,"ShipLoadout.setPreEngineeredVariant: variant.blueprintSymbol");requireString(variant.acquisition,"ShipLoadout.setPreEngineeredVariant: variant.acquisition");requireStringIfPresent(variant.experimentalEffectSymbol,"ShipLoadout.setPreEngineeredVariant: variant.experimentalEffectSymbol");const known=getPreEngineeredVariants(variant.symbol).find(candidate=>candidate.blueprintSymbol.toLowerCase()===variant.blueprintSymbol.toLowerCase()&&candidate.grade===variant.grade&&(candidate.experimentalEffectSymbol?.toLowerCase()??"")===(variant.experimentalEffectSymbol?.toLowerCase()??"")&&candidate.acquisition===variant.acquisition);if(!known){throw new RangeError(`ShipLoadout.setPreEngineeredVariant: no catalogued variant "${truncate(variant.blueprintSymbol)}" for module "${truncate(variant.symbol)}"`)}const stats=getPreEngineeredStats(known);const unresolved=unresolvedModifiers(known);if(unresolved.length>0){throw new TypeError(`ShipLoadout.setPreEngineeredVariant: cannot resolve "${truncate(variant.blueprintSymbol)}" for module "${truncate(variant.symbol)}"; missing base stats for ${unresolved.join(", ")}`)}this.setModule(slotKey,stats);const module=this.#fittedModuleFor(slotKey);const journalModifiers=getPreEngineeredJournalModifiers(known);const engineering={BlueprintName:known.blueprintSymbol,Level:known.grade,Quality:1,...known.experimentalEffectSymbol===void 0?{}:{ExperimentalEffect:known.experimentalEffectSymbol},...journalModifiers.length>0?{Modifiers:journalModifiers}:{}};this.#replaceModule(module.Slot,{...module,Engineering:engineering},cloneModuleStats(stats),getPreEngineeredModifiers(known));return this}clearEngineering(slotKey){const module=this.#fittedModuleFor(slotKey);if(module&&this.#statsFor(module)?.engineeringLocked){throw new TypeError(`ShipLoadout.clearEngineering: module "${truncate(module.Item)}" is a final pre-engineered article and its engineering cannot be removed`)}if(module?.Engineering){const baseStats2=this.#engineeringBaseStats(module);const bare={Slot:module.Slot,Item:module.Item};if(module.On!==void 0)bare.On=module.On;if(module.Priority!==void 0){bare.Priority=module.Priority}if(module.Health!==void 0)bare.Health=module.Health;if(module.Value!==void 0)bare.Value=module.Value;this.#replaceModule(module.Slot,bare,baseStats2??void 0)}return this}setModuleEnabled(slotKey,on){this.#patchModule(slotKey,{On:on});return this}setModulePriority(slotKey,priority){if(!Number.isInteger(priority)||priority<0||priority>4){throw new RangeError(`ShipLoadout: power priority must be an integer 0-4, got ${truncate(priority)}`)}this.#patchModule(slotKey,{Priority:priority});return this}#patchModule(slotKey,patch){const module=this.#fittedModuleFor(slotKey);if(!module){throw new RangeError(`ShipLoadout: slot "${truncate(slotKey)}" is empty`)}this.#modules.set(module.Slot,cloneLoadoutModule({...module,...patch}));this.#slotCache.clear()}toLoadoutEvent(options={}){const unladenMass=this.#computedUnladenMass();const cargoCapacity=this.#computedCargoCapacity();const fuel=this.#computedFuelCapacity();const maxJumpRange=this.#exportableJumpRange(unladenMass);return exportLoadoutEvent({shipSymbol:this.#shipSymbol,...this.#top.ShipName===void 0?{}:{shipName:this.#top.ShipName},...this.#top.ShipIdent===void 0?{}:{shipIdent:this.#top.ShipIdent},modules:this.#modules,layout:this.#layout(),sourcePurchase:this.#sourcePurchase,retailHullValue:this.#ship.hullCost,unladenMass:unladenMass,cargoCapacity:cargoCapacity,fuelCapacity:fuel,maxJumpRange:maxJumpRange,sourceTotalsVoided:this.#importOutcomes.some(outcome=>{if(outcome.sourceSymbol!==null)return false;const parsed=parseSlotName(outcome.slot);return parsed!==null&&stockedMountKind(parsed)==="core"}),statsFor:module=>this.#statsFor(module)},options)}toSlef(options){return toSlef(this.toLoadoutEvent(options),options.header)}toSlefString(options){return stringifySlef(this.toSlef(options),{indent:options.indent??0})}#exportableJumpRange(unladenMass){let drive;try{drive=this.#resolveDrive()}catch{return null}if(drive===null)return null;const tank=this.#computedFuelCapacity();return singleJumpRange(unladenMass,Math.min(tank.main,drive.maxFuel),drive)}#layout(){if(this.#layoutCache===void 0){this.#layoutCache=Object.freeze(enumerateSlots(this.#ship))}return this.#layoutCache}#requireSlot(slotKey){const wanted=normalizeKey(slotKey,SLOT_KEY);const slot=this.#layout().find(s=>normalizeKey(s.key,CATALOGUE_KEY)===wanted);if(!slot){throw new RangeError(`ShipLoadout: hull "${truncate(this.#shipSymbol)}" has no slot "${truncate(slotKey)}"`)}return slot}#fittedKey(slotKey){return matchingKeyIn(this.#modules,normalizeKey(slotKey,SLOT_KEY))}#fittedModuleFor(slotKey){const key=this.#fittedKey(slotKey);return key===null?void 0:this.#modules.get(key)}#calculationModules(){return[...this.#modules.values()].map(module=>({mass:this.#moduleMass(module),cargoCapacity:this.#moduleCapacity(module,"CargoCapacity","cargoCapacity"),cabinCapacity:this.#moduleCapacity(module,"CabinCapacity","cabinCapacity"),fuelCapacity:this.#moduleCapacity(module,"FuelCapacity","fuelCapacity")}))}#moduleLimits(){const entries=[...this.#modules.values()].flatMap(module=>{const stats=this.#statsFor(module);return stats===null?[]:[stats]});return calculateModuleLimits(entries)}#moduleStatsAt(slotKey){const fitted=this.#fittedModuleFor(slotKey);return fitted===void 0?null:this.#statsFor(fitted)}#engineeringBaseStats(module){const fitted=this.#statsFor(module);if(!module.Engineering||preEngineeredVariantFor(module)===null)return fitted;const stock=builtInModuleBySymbol(module.Item,FITTED_ITEM);if(!stock)return fitted;return fitted?.engineeringLocked?cloneModuleStats({...stock,engineeringLocked:true}):stock}#moduleForEffectiveStats(module){const modifiers=this.#primitiveModifiers.get(module.Slot);if(modifiers===void 0||module.Engineering===void 0)return module;return{...module,Engineering:{...module.Engineering,Modifiers:modifiers}}}#modulesForEffectiveStats(){return[...this.#modules.values()].map(module=>this.#moduleForEffectiveStats(module))}#moduleLimitRegression(slotKey,replacement,current=this.#moduleLimits(),previous=this.#moduleStatsAt(slotKey)){if(previous?.limitGroup===void 0&&previous?.limitIncrease===void 0&&replacement?.limitGroup===void 0&&replacement?.limitIncrease===void 0){return null}for(const usage of current){const count=usage.count-Number(previous?.limitGroup===usage.group)+Number(replacement?.limitGroup===usage.group);const increase=usage.increase-(previous?.limitIncrease?.group===usage.group?previous.limitIncrease.amount:0)+(replacement?.limitIncrease?.group===usage.group?replacement.limitIncrease.amount:0);const limit=usage.baseLimit+increase;const excess=Math.max(0,count-limit);if(excess>usage.excess){return{...usage,increase:increase,limit:limit,count:count,excess:excess}}}return null}#replaceModule(slotKey,replacement,replacementStats,primitiveModifiers){const previous=this.#modules.get(slotKey)??null;this.#adjustImportedFigures(previous,replacement,replacementStats);if(replacement===null){this.#modules.delete(slotKey);this.#moduleStats.delete(slotKey);this.#primitiveModifiers.delete(slotKey)}else{this.#modules.set(slotKey,cloneLoadoutModule(replacement));if(replacementStats!==void 0)this.#moduleStats.set(slotKey,replacementStats);if(primitiveModifiers===void 0)this.#primitiveModifiers.delete(slotKey);else this.#primitiveModifiers.set(slotKey,primitiveModifiers)}this.#slotCache.clear()}#adjustImportedFigures(previous,next,nextStats){if(this.#top.UnladenMass!==void 0){this.#top.UnladenMass+=this.#moduleMass(next,nextStats)-this.#moduleMass(previous)}if(this.#top.CargoCapacity!==void 0){this.#top.CargoCapacity+=this.#moduleCapacity(next,"CargoCapacity","cargoCapacity",nextStats)-this.#moduleCapacity(previous,"CargoCapacity","cargoCapacity")}if(this.#top.FuelCapacity?.Main!==void 0){const reserve=this.#top.FuelCapacity.Reserve;this.#top.FuelCapacity={Main:this.#top.FuelCapacity.Main+this.#moduleCapacity(next,"FuelCapacity","fuelCapacity",nextStats)-this.#moduleCapacity(previous,"FuelCapacity","fuelCapacity"),...reserve===void 0?{}:{Reserve:reserve}}}if(normalizeKey(previous?.Item,FITTED_ITEM)===normalizeKey(next?.Item,FITTED_ITEM)){return}if(previous!==null&&isCargoHatchSlot(previous.Slot)||next!==null&&isCargoHatchSlot(next.Slot)){return}delete this.#top.ModulesValue;delete this.#top.Rebuy}#moduleMass(module,statsOverride){if(module===null)return 0;if(isCargoHatchSlot(module.Slot))return 0;const modified=getLoadoutModifier(module,"Mass");if(modified!==null)return modified;return(statsOverride??this.#statsFor(module))?.mass??0}#moduleCapacity(module,modifierLabel,field,statsOverride){if(module===null)return 0;if(isCargoHatchSlot(module.Slot))return 0;const modified=getLoadoutModifier(module,modifierLabel);if(modified!==null)return modified;return(statsOverride??this.#statsFor(module))?.[field]??0}#frameShiftDrive(){for(const m of this.#modules.values()){const stats=this.#statsFor(m);if(stats?.slot==="frameShiftDrive")return{module:m,stats:stats}}return void 0}#resolveDrive(){const fsd=this.#frameShiftDrive();if(!fsd)return null;const{module:fsdModule,stats:base}=fsd;if(base.fuelMul===void 0||base.fuelPower===void 0){throw new TypeError(`ShipLoadout: the fitted record for frame shift drive "${truncate(fsdModule.Item)}" has no jump constants`)}const optMass=getLoadoutModifier(fsdModule,"FSDOptimalMass")??base.optMass;const maxFuel=getLoadoutModifier(fsdModule,"MaxFuelPerJump")??base.maxFuel;if(optMass===void 0||maxFuel===void 0){const missing=[...optMass===void 0?["optMass"]:[],...maxFuel===void 0?["maxFuel"]:[]];throw new TypeError(`ShipLoadout: the fitted record for frame shift drive "${truncate(fsdModule.Item)}" has no ${missing.join(" or ")}`)}return{optMass:optMass,maxFuel:maxFuel,fuelMul:base.fuelMul,fuelPower:base.fuelPower,jumpBoost:this.#resolveJumpBoost()}}#resolveJumpBoost(){for(const m of this.#modules.values()){const stats=this.#statsFor(m);if(stats?.engineeringGroup!=="fsdBoosters"&&(stats?.jumpBoost===void 0||stats.jumpBoost===0)){continue}if(m.On===false)continue;if(stats?.jumpBoost===void 0){throw new TypeError(`ShipLoadout: the fitted record for FSD booster "${truncate(m.Item)}" has no jumpBoost`)}return stats.jumpBoost}return 0}#statsFor(module){if(module===null)return null;const stats=this.#moduleStats.get(module.Slot)??builtInModuleBySymbol(module.Item,FITTED_ITEM);if(stats)return stats;return isBuiltInHullModule(module)?builtInModuleBySymbol(BUILT_IN_HULL_SYMBOL,"ShipLoadout: built-in module"):null}};export{LoadoutEditError,ShipLoadout};//# sourceMappingURL=chunk-55R4MYWV.js.map
@@ -1 +1 @@
1
- import{CORE_MODULES}from"./chunk-ZZTDEDXJ.js";import{HARDPOINT_MODULES}from"./chunk-4T3TTYUT.js";import{INTERNAL_MODULES}from"./chunk-7Y5EK2VO.js";import{UTILITY_MODULES}from"./chunk-PKKBYBL4.js";var ALL_MODULES=Object.freeze([...CORE_MODULES,...INTERNAL_MODULES,...HARDPOINT_MODULES,...UTILITY_MODULES]);export{ALL_MODULES};//# sourceMappingURL=chunk-UVX7RCMP.js.map
1
+ import{CORE_MODULES}from"./chunk-ZZTDEDXJ.js";import{HARDPOINT_MODULES}from"./chunk-P3DGQUID.js";import{INTERNAL_MODULES}from"./chunk-7Y5EK2VO.js";import{UTILITY_MODULES}from"./chunk-PKKBYBL4.js";var ALL_MODULES=Object.freeze([...CORE_MODULES,...INTERNAL_MODULES,...HARDPOINT_MODULES,...UTILITY_MODULES]);export{ALL_MODULES};//# sourceMappingURL=chunk-BI3EFLQ7.js.map
@@ -0,0 +1 @@
1
+ import{builtInModuleBySymbol,getModuleBySymbol}from"./chunk-2GVJNKFW.js";import{getPreEngineeredVariants}from"./chunk-EXHZ4CFB.js";import{ALL_MODULES}from"./chunk-BI3EFLQ7.js";import{getBlueprintGrade,getBlueprint,BLUEPRINTS}from"./chunk-WDAYRHXR.js";import{EXPERIMENTAL_EFFECTS,getExperimentalEffect}from"./chunk-77I24V6B.js";import{fieldForLabel,damageTypeForLabel,capabilityValueForLabel,baseStats,computeModifiers,labelsForDamageType,scaleForLabel}from"./chunk-U73MBQ45.js";import{round6,burstPartOrOne,float32FiringCycle,float32RateOfFire,preciseModifierValue,BURST_PATTERN_LABELS,journalRateOfFire,preciseValueFor}from"./chunk-EFQOUATZ.js";import{resolveBlueprintForModule}from"./chunk-2J6NNI3Y.js";import{getBlueprintsForModule,getExperimentalsForModule,getEngineeringGroup}from"./chunk-M4STXLXO.js";import{normalizeKey}from"./chunk-BKWLI44T.js";import{requireStringIfPresent}from"./chunk-PKWVG2JY.js";import{deepFreeze}from"./chunk-DURKO7JU.js";function scaleDamageComponents(components,baseDamage,effectiveDamage){const scale=baseDamage!==void 0&&baseDamage!==0&&effectiveDamage!==void 0?effectiveDamage/baseDamage:1;return{...components.kinetic===void 0?{}:{kinetic:components.kinetic*scale},...components.thermal===void 0?{}:{thermal:components.thermal*scale},...components.explosive===void 0?{}:{explosive:components.explosive*scale},...components.caustic===void 0?{}:{caustic:components.caustic*scale},...components.absolute===void 0?{}:{absolute:components.absolute*scale},...components.antiXeno===void 0?{}:{antiXeno:components.antiXeno*scale},...components.unclassified===void 0?{}:{unclassified:components.unclassified.map(value=>value*scale)}}}function fixedModifierFeatures(modifiers){return modifiers.map(modifier=>({label:modifier.label,method:modifier.method,min:modifier.value,max:modifier.value}))}var FITTED_ITEM="ShipLoadout: fitted module Item";function isNonOutfittingSlot(slotKey){return/^(paintjob|shipname\d+|shipid\d+|bobble\d+|decal\d+|shipkit.+|weaponcolour|enginecolour|vesselvoice|shipcockpit|stringlights)$/i.test(slotKey)}function isCargoHatchSlot(slotKey){return slotKey.toLowerCase()==="cargohatch"}var BUILT_IN_HULL_SYMBOL="ModularCargoBayDoor";function isBuiltInHullSymbol(symbol){return symbol.toLowerCase().startsWith(BUILT_IN_HULL_SYMBOL.toLowerCase())}function isBuiltInHullModule(module){return isCargoHatchSlot(module.Slot)&&isBuiltInHullSymbol(module.Item)}function cloneLoadoutModule(module){return{Slot:module.Slot,Item:module.Item,...module.On===void 0?{}:{On:module.On},...module.Priority===void 0?{}:{Priority:module.Priority},...module.Health===void 0?{}:{Health:module.Health},...module.Value===void 0?{}:{Value:module.Value},...module.Engineering===void 0?{}:{Engineering:{BlueprintName:module.Engineering.BlueprintName,Level:module.Engineering.Level,Quality:module.Engineering.Quality,...module.Engineering.ExperimentalEffect===void 0?{}:{ExperimentalEffect:module.Engineering.ExperimentalEffect},...module.Engineering.ExperimentalEffect_Localised===void 0?{}:{ExperimentalEffect_Localised:module.Engineering.ExperimentalEffect_Localised},...module.Engineering.Modifiers===void 0?{}:{Modifiers:module.Engineering.Modifiers.map(modifier=>({...modifier}))}}}}}function matchingKeyIn(keyed,slotKey){if(keyed.has(slotKey))return slotKey;const wanted=slotKey.toLowerCase();for(const key of keyed.keys()){if(key.toLowerCase()===wanted)return key}return null}function ownKeyIn(keyed,canonicalKey){return matchingKeyIn(keyed,canonicalKey)??(keyed.size>0&&[...keyed.keys()].every(key=>key===key.toLowerCase())?canonicalKey.toLowerCase():canonicalKey)}function orderBySlotLayout(values,layout,slotOf){const order=new Map(layout.map((slot,index)=>[slot.key.toLowerCase(),index]));return[...values].sort((left,right)=>(order.get(slotOf(left).toLowerCase())??Number.MAX_SAFE_INTEGER)-(order.get(slotOf(right).toLowerCase())??Number.MAX_SAFE_INTEGER))}function cloneModuleStats(module){try{return deepFreeze(structuredClone(module))}catch(error){if(!(error instanceof Error&&error.name==="DataCloneError"))throw error;return deepFreeze({...module,...module.restrictedToShips===void 0?{}:{restrictedToShips:[...module.restrictedToShips]},...module.limitIncrease===void 0?{}:{limitIncrease:{...module.limitIncrease}},...module.damageDistribution===void 0?{}:{damageDistribution:{...module.damageDistribution}},...module.damageComponents===void 0?{}:{damageComponents:{...module.damageComponents,...module.damageComponents.unclassified===void 0?{}:{unclassified:[...module.damageComponents.unclassified]}}},...module.projectileRange===void 0?{}:{projectileRange:{...module.projectileRange}}})}}var GUARDIAN_WEAPON_GROUPS=/* @__PURE__ */new Set(["guardianGauss","guardianPlasma","guardianShard"]);function missingBaseLabels(stats,base,features,experimental){const contributions=[...features,...experimental??[]];return[...new Set(contributions.map(contribution=>contribution.label).filter(label=>{if(base[label]!==void 0)return false;return fieldForLabel(label,stats)===null}))]}function recipeSignature(blueprintSymbol){const blueprint=getBlueprint(blueprintSymbol);if(!blueprint)return null;const grades=Object.entries(blueprint.grades).map(([grade,{features:features}])=>`${grade}:${features.map(feature=>`${feature.label}/${feature.method??""}`).sort().join(",")}`).sort().join(";");return`${blueprint.name.toLowerCase()}|${grades}`}var isGenericSpelling=blueprintSymbol=>blueprintSymbol.toLowerCase().startsWith("misc_");function isSoldWithBlueprint(item,wanted){return getPreEngineeredVariants(item).some(variant=>variant.acquisition==="mercenary"&&variant.blueprintSymbol.toLowerCase()===wanted)}function blueprintRoutesFor(item){const routes=/* @__PURE__ */new Map;for(const blueprintSymbol of getBlueprintsForModule(item))routes.set(blueprintSymbol,"ordinary");for(const variant of getPreEngineeredVariants(item)){if(variant.acquisition==="mercenary"&&!routes.has(variant.blueprintSymbol)){routes.set(variant.blueprintSymbol,"mercenary")}}return routes}function blueprintAvailableFor(item,blueprintSymbol){const offered=getBlueprintsForModule(item);const asWritten=normalizeKey(blueprintSymbol,"ShipLoadout.applyBlueprint: blueprintSymbol");const resolved=resolveBlueprintForModule(item,blueprintSymbol).trim();const wanted=resolved.toLowerCase();if(offered.some(id=>id.toLowerCase()===wanted))return true;if(isSoldWithBlueprint(item,wanted)||isSoldWithBlueprint(item,asWritten))return true;if(!isGenericSpelling(wanted))return false;const signature=recipeSignature(resolved);if(signature===null)return false;return offered.some(id=>recipeSignature(id)===signature&&!isGenericSpelling(id))}function experimentalAvailableFor(item,experimentalEffectSymbol){const wanted=normalizeKey(experimentalEffectSymbol,"ShipLoadout.applyBlueprint: options.experimentalEffectSymbol");return getExperimentalsForModule(item).some(id=>id.toLowerCase()===wanted)}function primitiveLabelFor(stats,label){if(label==="MaximumRange"&&stats.maximumRange!==void 0)return"Range";if(label==="DamageFalloffRange"&&stats.falloffRange!==void 0){return"FalloffRange"}if(label==="Range"&&stats.scannerRange!==void 0)return"ScannerRange";if(label==="DSS_PatchRadius")return"ProbeRadius";if(label==="FuelScoopRate")return"RefuelRate";if(label==="EnergyPerRegen"&&stats.shieldRegenRate!==void 0){return"DistributorDraw"}return label}function primitiveEngineeringInputsFor(stats,grade,experimental){const canonicalGrade={...grade,features:grade.features.map(feature=>{const label=primitiveLabelFor(stats,feature.label);return label===feature.label?feature:{...feature,label:label}})};if(!experimental)return{grade:canonicalGrade};return{grade:canonicalGrade,experimental:{...experimental,modifiers:experimental.modifiers.map(modifier=>{const label=primitiveLabelFor(stats,modifier.label);return label===modifier.label?modifier:{...modifier,label:label}})}}}function matchesCalculatedModifiers(captured,calculated){if(!captured||captured.length!==calculated.length)return false;const byLabel=new Map(captured.map(modifier=>[modifier.Label.trim().toLowerCase(),modifier]));if(byLabel.size!==captured.length)return false;return calculated.every(expected=>{const actual=byLabel.get(expected.Label.trim().toLowerCase());if(!actual)return false;if(expected.Value!==void 0){return actual.Value!==void 0&&Math.abs(actual.Value-expected.Value)<=1e-5*Math.max(1,Math.abs(expected.Value))}return actual.ValueStr===expected.ValueStr})}function identityArticles(item,engineering){if(engineering.Modifiers!==void 0||typeof engineering.BlueprintName!=="string"){return[]}const wanted=engineering.BlueprintName.trim().toLowerCase();const experimental=engineering.ExperimentalEffect?.trim().toLowerCase();return getPreEngineeredVariants(item).filter(candidate=>candidate.blueprintSymbol.trim().toLowerCase()===wanted&&candidate.grade===engineering.Level&&(candidate.experimentalEffectSymbol===void 0?experimental===void 0&&engineering.ExperimentalEffect_Localised===void 0:candidate.experimentalEffectSymbol.trim().toLowerCase()===experimental))}function unrollableFixedArticle(item,engineering){const matches=identityArticles(item,engineering).filter(candidate=>!blueprintAvailableFor(item,candidate.blueprintSymbol));return matches.length===1?matches[0]:null}function rolledOverFixedArticle(item,engineering){const matches=identityArticles(item,engineering).filter(candidate=>blueprintAvailableFor(item,candidate.blueprintSymbol));return matches.length===1?matches[0]:null}function statesInertModifiers(stats,modifiers){return modifiers.every(modifier=>{if(damageTypeForLabel(modifier.Label)!==null||capabilityValueForLabel(modifier.Label)!==null){return false}const field=fieldForLabel(modifier.Label,stats);return field===null||typeof stats[field]!=="number"})}function ordinaryEngineeringProof(item,engineering,experimental){const recipe=resolveBlueprintForModule(item,engineering.BlueprintName);const fixedCandidate=getPreEngineeredVariants(item).some(candidate=>candidate.acquisition!=="mercenary"&&candidate.blueprintSymbol.trim().toLowerCase()===recipe.trim().toLowerCase());if(!fixedCandidate)return"notFixedCandidate";const grade=getBlueprintGrade(recipe,engineering.Level);const quality=engineering.Quality;const stock=builtInModuleBySymbol(item,FITTED_ITEM);if(!stock||!grade||experimental===null||!Number.isFinite(quality)||quality<0||quality>1){return"unproven"}const current=primitiveEngineeringInputsFor(stock,grade,experimental);if(missingBaseLabels(stock,baseStats(stock),current.grade.features,current.experimental?.modifiers).length>0){return"unproven"}const calculated=journalModifiersFor(stock,computeModifiers(baseStats(stock),current.grade,quality,current.experimental));const damageDistribution=current.experimental?.damageDistribution??current.grade.damageDistribution;if(damageDistribution){for(const type of["kinetic","thermal","explosive","absolute"]){const value=damageDistribution[type];if(value===void 0)continue;const label=labelsForDamageType(type)[0];if(label===void 0)continue;calculated.push({Label:label,Value:value*scaleForLabel(label),OriginalValue:(stock.damageDistribution?.[type]??0)*scaleForLabel(label)})}}return matchesCalculatedModifiers(engineering.Modifiers,calculated)?"proven":"unproven"}function float32DamagePerSecond(damage,rounds,rate,burstRounds,cycle){if(cycle!==void 0&&(rounds!==1||burstRounds!==1)){const damagePerCycle=Math.fround(Math.fround(Math.fround(damage)*Math.fround(rounds))*Math.fround(burstRounds));return Math.fround(damagePerCycle/cycle)}return Math.fround(Math.fround(Math.fround(damage)*Math.fround(rounds))*Math.fround(rate))}var JOURNAL_MODIFIER_ORDER=["CargoCapacity","GuardianModuleResistance","Mass","Integrity","PowerDraw","BootTime","PowerCapacity","HeatEfficiency","FSDOptimalMass","MaxFuelPerJump","FSDHeatRate","EngineOptimalMass","EngineOptPerformance","EngineHeatRate","ShieldGenOptimalMass","ShieldGenStrength","DamagePerSecond","Damage","DistributorDraw","ThermalLoad","ArmourPenetration","MaximumRange","ShotSpeed","RateOfFire","DamageType","$Kinetic;","$Thermal;","$Explosive;","$Absolute;","AmmoClipSize","AmmoMaximum","ReloadTime","Jitter","DamageFalloffRange","DefenceModifierShieldMultiplier","DefenceModifierHealthMultiplier","DefenceModifierHealthAddition","DefenceModifierShieldAddition","RegenRate","BrokenRegenRate","EnergyPerRegen","KineticResistance","ThermicResistance","ExplosiveResistance","CausticResistance","DamageProtection","ModuleDefenceAbsorption","WeaponsCapacity","WeaponsRecharge","EnginesCapacity","EnginesRecharge","SystemsCapacity","SystemsRecharge","ShieldBankSpinUp","ShieldBankDuration","ShieldBankReinforcement","ShieldBankHeat","FSDInterdictorRange","FSDInterdictorFacingLimit","SensorTargetScanAngle","MaxAngle","ScannerTimeToScan","Range","DSS_PatchRadius","FuelScoopRate","FuelCapacity"];var JOURNAL_MODIFIER_RANK=new Map(JOURNAL_MODIFIER_ORDER.map((label,index)=>[label,index]));function sortJournalModifiers(modifiers){return modifiers.map((modifier,index)=>({modifier:modifier,index:index})).sort((a,b)=>(JOURNAL_MODIFIER_RANK.get(a.modifier.Label)??JOURNAL_MODIFIER_ORDER.length)-(JOURNAL_MODIFIER_RANK.get(b.modifier.Label)??JOURNAL_MODIFIER_ORDER.length)||a.index-b.index).map(({modifier:modifier})=>modifier)}function journalModifiersFor(stats,modifiers){const weapon=stats.damage!==void 0;const valueFor=(label,fallback)=>{const modifier=modifiers.find(candidate=>candidate.Label===label);return(modifier&&preciseModifierValue(modifier))??Math.fround(fallback)};const burstTouched=["BurstInterval","BurstSize","BurstRateOfFire"].some(label=>modifiers.some(modifier=>modifier.Label===label));const damageTouched=modifiers.some(modifier=>modifier.Label==="Damage");const rateTouched=burstTouched||modifiers.some(modifier=>modifier.Label==="RateOfFire");let damagePerSecond;let derivedRate;if(weapon&&(damageTouched||rateTouched)){const continuous=stats.burstInterval===void 0&&stats.rateOfFire===void 0;const baseDamage=Math.fround(stats.damage);const effectiveDamage=valueFor("Damage",stats.damage);if(continuous){damagePerSecond={Label:"DamagePerSecond",Value:round6(effectiveDamage),OriginalValue:round6(baseDamage)}}else{const burstRounds=burstPartOrOne(valueFor("BurstSize",stats.burstRounds??1));const burstRate=burstPartOrOne(valueFor("BurstRateOfFire",stats.burstRateOfFire??1));const baseBurstRounds=Math.fround(burstPartOrOne(stats.burstRounds));const baseBurstRate=Math.fround(burstPartOrOne(stats.burstRateOfFire));const baseInterval=stats.burstInterval===void 0?void 0:Math.fround(stats.burstInterval);const baseCycle=baseInterval===void 0?void 0:float32FiringCycle(baseInterval,baseBurstRounds,baseBurstRate);const baseRate=baseInterval!==void 0?float32RateOfFire(baseInterval,baseBurstRounds,baseBurstRate):stats.rateOfFire===void 0?void 0:Math.fround(stats.rateOfFire);const rateModifier=modifiers.find(modifier=>modifier.Label==="RateOfFire");const effectiveRate=rateModifier&&preciseModifierValue(rateModifier);const effectiveInterval=valueFor("BurstInterval",stats.burstInterval??0);const effectiveCycle=effectiveRate===void 0?float32FiringCycle(effectiveInterval,burstRounds,burstRate):void 0;const rate=effectiveRate??(effectiveCycle===void 0?void 0:Math.fround(Math.fround(burstRounds)/effectiveCycle));if(baseRate!==void 0&&rate!==void 0){const stockRounds=Math.fround(stats.roundsPerShot??1);const effectiveRounds=Math.fround(modifiers.find(modifier=>modifier.Label==="Rounds"||modifier.Label==="RoundsPerShot")?.Value??stockRounds);damagePerSecond={Label:"DamagePerSecond",Value:round6(float32DamagePerSecond(effectiveDamage,effectiveRounds,rate,burstRounds,effectiveCycle)),OriginalValue:round6(float32DamagePerSecond(baseDamage,stockRounds,baseRate,baseBurstRounds,baseCycle))};if(burstTouched){derivedRate={Label:"RateOfFire",Value:round6(rate),OriginalValue:round6(baseRate)}}}}}const result=[];for(const modifier of modifiers){const label=modifier.Label;if(weapon&&["BurstInterval","BurstSize","BurstRateOfFire"].includes(label))continue;if(weapon&&label==="Damage"&&stats.rateOfFire===void 0)continue;let journalLabel=label;if(label==="Range"&&stats.maximumRange!==void 0)journalLabel="MaximumRange";else if(label==="FalloffRange"&&stats.falloffRange!==void 0){journalLabel="DamageFalloffRange"}else if(label==="ScannerRange"&&stats.scannerRange!==void 0){journalLabel="Range"}else if(label==="ProbeRadius")journalLabel="DSS_PatchRadius";else if(label==="RefuelRate")journalLabel="FuelScoopRate";else if(label==="DistributorDraw"&&stats.shieldRegenRate!==void 0){journalLabel="EnergyPerRegen"}result.push(journalLabel===label?modifier:{...modifier,Label:journalLabel})}if(damagePerSecond)result.push(damagePerSecond);if(derivedRate){const direct=result.findIndex(modifier=>modifier.Label==="RateOfFire");if(direct>=0)result[direct]=derivedRate;else result.push(derivedRate)}return sortJournalModifiers(result)}function isFinalGuardianWeaponEngineering(item,blueprint){const group=getEngineeringGroup(item);if(group===null||!GUARDIAN_WEAPON_GROUPS.has(group))return false;const resolved=resolveBlueprintForModule(item,blueprint);return getBlueprint(resolved)!==null&&!blueprintAvailableFor(item,blueprint)}function engineerableBase(item,statsOverride){const stats=statsOverride??builtInModuleBySymbol(item,FITTED_ITEM);if(!stats||stats.engineeringLocked)return null;return{stats:stats,base:baseStats(stats)}}function availableBlueprintsFor(item,statsOverride){const engineerable=engineerableBase(item,statsOverride);if(!engineerable)return[];const{stats:stats,base:base}=engineerable;const available=[];for(const[blueprintSymbol,route]of blueprintRoutesFor(item)){const blueprint=BLUEPRINTS[blueprintSymbol];if(!blueprint)continue;const grades=Object.entries(blueprint.grades).filter(([,grade])=>missingBaseLabels(stats,base,grade.features).length===0).map(([grade])=>Number(grade)).filter(Number.isFinite).sort((a,b)=>a-b);if(grades.length>0)available.push({blueprintSymbol:blueprintSymbol,grades:grades,route:route})}return available}function availableExperimentalsFor(item,statsOverride){const engineerable=engineerableBase(item,statsOverride);if(!engineerable)return[];const{stats:stats,base:base}=engineerable;return getExperimentalsForModule(item).filter(experimentalEffectSymbol=>{const effect=EXPERIMENTAL_EFFECTS[experimentalEffectSymbol];return effect!==void 0&&missingBaseLabels(stats,base,effect.modifiers).length===0})}var MAX_ENGINEERING_GRADE=5;function modifiersWithExperimental(variant,experimental){const module=getModuleBySymbol(variant.symbol,ALL_MODULES);const effectName=experimental===void 0?variant.experimentalEffectSymbol:experimental;if(!module||!variant.modifiers?.length&&effectName==null)return null;const effect=effectName==null?void 0:getExperimentalEffect(effectName);if(effectName!==null&&effectName!==void 0&&!effect)return null;return computeModifiers(baseStats(module),fixedModifierFeatures(variant.modifiers??[]),1,effect??void 0)}function getPreEngineeredModifiers(variant){return modifiersWithExperimental(variant)??[]}function journalModifiersWithExperimental(variant,experimental){const module=getModuleBySymbol(variant.symbol,ALL_MODULES);if(!module)return[];const modifiers=journalModifiersFor(module,modifiersWithExperimental(variant,experimental)??[]);const effectName=experimental===void 0?variant.experimentalEffectSymbol:experimental;const damageDistribution=(effectName?getExperimentalEffect(effectName)?.damageDistribution:void 0)??variant.damageDistribution;if(!damageDistribution)return modifiers;for(const type of["kinetic","thermal","explosive","absolute"]){const value=damageDistribution[type];const label=labelsForDamageType(type)[0];if(value===void 0||label===void 0)continue;modifiers.push({Label:label,Value:value*scaleForLabel(label),OriginalValue:(module.damageDistribution?.[type]??0)*scaleForLabel(label)})}return modifiers}function getPreEngineeredJournalModifiers(variant){return journalModifiersWithExperimental(variant)}function sameJournalNumber(actual,expected,base){return Math.abs(actual-expected)<=Math.max(1e-5,Math.abs(base)*1e-4,Math.abs(expected)*1e-6)}function modifierKey(modifier,module){return fieldForLabel(modifier.Label,module)??`label:${normalizeKey(modifier.Label,"identifyPreEngineeredVariant: module.Engineering.Modifiers[].Label")}`}function sameModifier(actual,expected){if(expected.Value!==void 0){return actual.Value!==void 0&&sameJournalNumber(actual.Value,expected.Value,expected.OriginalValue??expected.Value)}return expected.ValueStr!==void 0&&actual.ValueStr!==void 0}function matchesModifierSignature(actualByKey,expected,module){let matched=0;for(const predicted of expected){const actual=actualByKey.get(modifierKey(predicted,module));if(!actual)continue;if(!sameModifier(actual,predicted))return false;matched++}return matched>=Math.max(1,expected.length-1)}function identifyPreEngineeredVariant(module){const engineering=module.Engineering;if(!engineering)return null;requireStringIfPresent(module.Item,"identifyPreEngineeredVariant: module.Item");const stock=getModuleBySymbol(module.Item,ALL_MODULES);if(!stock)return null;const capturedBlueprint=normalizeKey(engineering.BlueprintName,"identifyPreEngineeredVariant: module.Engineering.BlueprintName");const variants=getPreEngineeredVariants(module.Item);const blueprintMatches=variants.filter(candidate=>candidate.blueprintSymbol.toLowerCase()===capturedBlueprint);const blueprintMatch=blueprintMatches.length===1?blueprintMatches[0]:null;const capturedGrade=engineering.Level;if(blueprintMatch?.acquisition==="mercenary"&&Number.isInteger(capturedGrade)&&capturedGrade>=blueprintMatch.grade&&capturedGrade<=MAX_ENGINEERING_GRADE){return blueprintMatch}if(engineering.Modifiers===void 0){const capturedExperimental=normalizeKey(engineering.ExperimentalEffect,"identifyPreEngineeredVariant: module.Engineering.ExperimentalEffect");const identityMatches=blueprintMatches.filter(candidate=>candidate.engineeringLocked===true&&candidate.grade===capturedGrade&&(candidate.experimentalEffectSymbol===void 0?capturedExperimental===void 0&&engineering.ExperimentalEffect_Localised===void 0:candidate.experimentalEffectSymbol.toLowerCase()===capturedExperimental));return identityMatches.length===1?identityMatches[0]:null}if(!engineering.Modifiers?.length)return null;const actualByKey=/* @__PURE__ */new Map;for(const modifier of engineering.Modifiers){actualByKey.set(modifierKey(modifier,stock),modifier)}requireStringIfPresent(engineering.ExperimentalEffect,"identifyPreEngineeredVariant: module.Engineering.ExperimentalEffect");const matches=[];for(const candidate of variants){if(!candidate.modifiers?.length)continue;if(candidate.grade!==engineering.Level)continue;if(candidate.acquisition==="eventReward"&&(engineering.ExperimentalEffect!==void 0||engineering.ExperimentalEffect_Localised!==void 0||capturedBlueprint!==candidate.blueprintSymbol.toLowerCase())){continue}const primitive=modifiersWithExperimental(candidate,engineering.ExperimentalEffect??null);if(!primitive?.length)continue;const matched=matchesModifierSignature(actualByKey,primitive,stock)||matchesModifierSignature(actualByKey,journalModifiersWithExperimental(candidate,engineering.ExperimentalEffect??null),stock);if(matched)matches.push(candidate)}return matches.length===1?matches[0]:null}function unresolvedModifiers(variant){const resolved=new Set(getPreEngineeredModifiers(variant).map(modifier=>modifier.Label));return(variant.modifiers??[]).map(modifier=>modifier.label).filter(label=>!resolved.has(label))}function getPreEngineeredStats(variant){const module=getModuleBySymbol(variant.symbol,ALL_MODULES);if(!module)return null;if(!variant.modifiers?.length&&!variant.engineeringLocked&&variant.experimentalEffectSymbol===void 0)return{...module};const applied=getPreEngineeredModifiers(variant);const resolved={...module,...variant.engineeringLocked?{engineeringLocked:true}:{}};for(const{Label:Label,Value:Value,ValueStr:ValueStr}of applied){const field=fieldForLabel(Label,module);if(field&&field!=="damageDistribution"&&Value!==void 0){Object.assign(resolved,{[field]:Value/scaleForLabel(Label)})}else if(field&&ValueStr!==void 0&&capabilityValueForLabel(Label)!==null){Object.assign(resolved,{[field]:true})}}const fixedDamageDistribution=(variant.experimentalEffectSymbol?getExperimentalEffect(variant.experimentalEffectSymbol)?.damageDistribution:void 0)??variant.damageDistribution;if(fixedDamageDistribution){resolved.damageDistribution={...fixedDamageDistribution};delete resolved.damageComponents}if(resolved.rateOfFire!==void 0&&!applied.some(m=>m.Label==="RateOfFire")&&applied.some(m=>BURST_PATTERN_LABELS.some(label=>label===m.Label))){const rate=journalRateOfFire(preciseValueFor(applied,"BurstInterval")??resolved.burstInterval,preciseValueFor(applied,"BurstSize")??resolved.burstRounds,preciseValueFor(applied,"BurstRateOfFire")??resolved.burstRateOfFire);if(rate!==void 0)resolved.rateOfFire=rate}if(module.damageComponents&&!fixedDamageDistribution){resolved.damageComponents=scaleDamageComponents(module.damageComponents,module.damage,resolved.damage)}return resolved}export{BUILT_IN_HULL_SYMBOL,FITTED_ITEM,availableBlueprintsFor,availableExperimentalsFor,blueprintAvailableFor,blueprintRoutesFor,cloneLoadoutModule,cloneModuleStats,experimentalAvailableFor,getPreEngineeredJournalModifiers,getPreEngineeredModifiers,getPreEngineeredStats,identifyPreEngineeredVariant,isBuiltInHullModule,isBuiltInHullSymbol,isCargoHatchSlot,isFinalGuardianWeaponEngineering,isNonOutfittingSlot,journalModifiersFor,matchingKeyIn,missingBaseLabels,orderBySlotLayout,ordinaryEngineeringProof,ownKeyIn,primitiveEngineeringInputsFor,rolledOverFixedArticle,scaleDamageComponents,statesInertModifiers,unresolvedModifiers,unrollableFixedArticle};//# sourceMappingURL=chunk-HE4XE3WR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ships/internal/damage-components.ts","../src/ships/internal/fixed-modifier-features.ts","../src/ships/internal/loadout-state.ts","../src/ships/internal/loadout-engineering.ts","../src/ships/pre-engineered-stats.ts"],"names":["builtInModuleBySymbol","getModuleBySymbol","getPreEngineeredVariants","ALL_MODULES","getBlueprintGrade","getBlueprint","BLUEPRINTS","EXPERIMENTAL_EFFECTS","getExperimentalEffect","fieldForLabel","damageTypeForLabel","capabilityValueForLabel","baseStats","computeModifiers","labelsForDamageType","scaleForLabel","round6","burstPartOrOne","float32FiringCycle","float32RateOfFire","preciseModifierValue","BURST_PATTERN_LABELS","journalRateOfFire","preciseValueFor","resolveBlueprintForModule","getBlueprintsForModule","getExperimentalsForModule","getEngineeringGroup","normalizeKey","requireStringIfPresent","deepFreeze","scaleDamageComponents","components","baseDamage","effectiveDamage","scale","kinetic","thermal","explosive","caustic","absolute","antiXeno","unclassified","map","value","fixedModifierFeatures","modifiers","modifier","label","method","min","max","FITTED_ITEM","isNonOutfittingSlot","slotKey","test","isCargoHatchSlot","toLowerCase","BUILT_IN_HULL_SYMBOL","isBuiltInHullSymbol","symbol","startsWith","isBuiltInHullModule","module","Slot","Item","cloneLoadoutModule","On","Priority","Health","Value","Engineering","BlueprintName","Level","Quality","ExperimentalEffect","ExperimentalEffect_Localised","Modifiers","matchingKeyIn","keyed","has","wanted","key","keys","ownKeyIn","canonicalKey","size","every","orderBySlotLayout","values","layout","slotOf","order","Map","slot","index","sort","left","right","get","Number","MAX_SAFE_INTEGER","cloneModuleStats","structuredClone","error","Error","name","restrictedToShips","limitIncrease","damageDistribution","damageComponents","projectileRange","GUARDIAN_WEAPON_GROUPS","Set","missingBaseLabels","stats","base","features","experimental","contributions","contribution","filter","recipeSignature","blueprintSymbol","blueprint","grades","Object","entries","grade","feature","join","isGenericSpelling","isSoldWithBlueprint","item","some","variant","acquisition","blueprintRoutesFor","routes","set","blueprintAvailableFor","offered","asWritten","resolved","trim","id","signature","experimentalAvailableFor","experimentalEffectSymbol","primitiveLabelFor","maximumRange","falloffRange","scannerRange","shieldRegenRate","primitiveEngineeringInputsFor","canonicalGrade","matchesCalculatedModifiers","captured","calculated","length","byLabel","Label","expected","actual","Math","abs","ValueStr","identityArticles","engineering","candidate","unrollableFixedArticle","matches","rolledOverFixedArticle","statesInertModifiers","field","ordinaryEngineeringProof","recipe","fixedCandidate","quality","stock","isFinite","current","journalModifiersFor","type","push","OriginalValue","float32DamagePerSecond","damage","rounds","rate","burstRounds","cycle","damagePerCycle","fround","JOURNAL_MODIFIER_ORDER","JOURNAL_MODIFIER_RANK","sortJournalModifiers","a","b","weapon","valueFor","fallback","find","burstTouched","damageTouched","rateTouched","damagePerSecond","derivedRate","continuous","burstInterval","rateOfFire","burstRate","burstRateOfFire","baseBurstRounds","baseBurstRate","baseInterval","baseCycle","baseRate","rateModifier","effectiveRate","effectiveInterval","effectiveCycle","stockRounds","roundsPerShot","effectiveRounds","result","includes","journalLabel","direct","findIndex","isFinalGuardianWeaponEngineering","group","engineerableBase","statsOverride","engineeringLocked","availableBlueprintsFor","engineerable","available","route","availableExperimentalsFor","effect","MAX_ENGINEERING_GRADE","modifiersWithExperimental","effectName","getPreEngineeredModifiers","journalModifiersWithExperimental","getPreEngineeredJournalModifiers","sameJournalNumber","modifierKey","sameModifier","matchesModifierSignature","actualByKey","matched","predicted","identifyPreEngineeredVariant","capturedBlueprint","variants","blueprintMatches","blueprintMatch","capturedGrade","isInteger","capturedExperimental","identityMatches","primitive","unresolvedModifiers","getPreEngineeredStats","applied","assign","fixedDamageDistribution","m"],"mappings":"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"}
@@ -1 +1 @@
1
- import{capacitorRechargeAtPips}from"./chunk-JOTAOI5T.js";import{systemsResistance,mapDamageTypes,effectiveHitPoints}from"./chunk-F44QX47A.js";import{requirePips,requireFiniteNonNegative}from"./chunk-65FZECUX.js";var DAMAGE_TYPES=["kinetic","thermal","explosive","caustic"];function shieldCapacitorMetrics(input){const scope="shieldCapacitorMetrics";const systemsPips=input.systemsPips??4;requirePips(scope,"systemsPips",systemsPips);for(const field of["strength","systemsCapacity","systemsRecharge"]){requireFiniteNonNegative(scope,field,input[field])}const resistances=input.resistances;if(typeof resistances!=="object"||resistances===null){throw new TypeError(`${scope}: resistances must carry the four damage types`)}for(const type of DAMAGE_TYPES){if(!Number.isFinite(input.resistances[type])){throw new RangeError(`${scope}: resistances.${type} must be a finite number`)}}const sysResistance=systemsResistance(systemsPips);const effectiveResistances=Object.freeze(mapDamageTypes(type=>1-(1-input.resistances[type])*(1-sysResistance)));return Object.freeze({systemsPips:systemsPips,capacity:input.systemsCapacity,rechargeRate:capacitorRechargeAtPips(input.systemsRecharge,systemsPips),systemsResistance:sysResistance,effectiveResistances:effectiveResistances,effectiveHitPoints:Object.freeze(effectiveHitPoints(input.strength,effectiveResistances))})}export{shieldCapacitorMetrics};//# sourceMappingURL=chunk-XQJERZUS.js.map
1
+ import{capacitorRechargeAtPips}from"./chunk-JOTAOI5T.js";import{systemsResistance,mapDamageTypes,effectiveHitPoints}from"./chunk-Q75JSMU6.js";import{requirePips,requireFiniteNonNegative}from"./chunk-65FZECUX.js";var DAMAGE_TYPES=["kinetic","thermal","explosive","caustic"];function shieldCapacitorMetrics(input){const scope="shieldCapacitorMetrics";const systemsPips=input.systemsPips??4;requirePips(scope,"systemsPips",systemsPips);for(const field of["strength","systemsCapacity","systemsRecharge"]){requireFiniteNonNegative(scope,field,input[field])}const resistances=input.resistances;if(typeof resistances!=="object"||resistances===null){throw new TypeError(`${scope}: resistances must carry the four damage types`)}for(const type of DAMAGE_TYPES){if(!Number.isFinite(input.resistances[type])){throw new RangeError(`${scope}: resistances.${type} must be a finite number`)}}const sysResistance=systemsResistance(systemsPips);const effectiveResistances=Object.freeze(mapDamageTypes(type=>1-(1-input.resistances[type])*(1-sysResistance)));return Object.freeze({systemsPips:systemsPips,capacity:input.systemsCapacity,rechargeRate:capacitorRechargeAtPips(input.systemsRecharge,systemsPips),systemsResistance:sysResistance,effectiveResistances:effectiveResistances,effectiveHitPoints:Object.freeze(effectiveHitPoints(input.strength,effectiveResistances))})}export{shieldCapacitorMetrics};//# sourceMappingURL=chunk-HWOP7QWK.js.map
@@ -1 +1 @@
1
- import{loadoutInternals,fittedThrusterParamsFor,preEngineeredVariantFor,powerConsumerFor,powerAvailable,heatInputResultFor,completeResult,cellBankInputsFor,armourInputFor,weaponStatsFor,weaponsCapacitorInputFor,mobilityInputResultFor,shieldInputResultFor,shieldCapacitorInputResultFor,shieldRecoveryInputResultFor,distributorInputResultFor,incompleteResult}from"./chunk-BUQLUEQS.js";import{weaponsCapacitorMetrics}from"./chunk-M4FZRDAH.js";import{weaponMetrics,sumWeaponMetrics}from"./chunk-AAU7OM47.js";import{powerBudget}from"./chunk-GGQMIQPC.js";import{isNonOutfittingSlot,isBuiltInHullModule,orderBySlotLayout}from"./chunk-P6HCQ2YE.js";import{shieldCapacitorMetrics}from"./chunk-XQJERZUS.js";import{cellBankSummary,shieldRecovery}from"./chunk-JMAXSXXQ.js";import{shieldMetrics}from"./chunk-DBJKLXLS.js";import{heatMetrics}from"./chunk-6HA2YIKW.js";import{frameShiftDriveMassFactor,singleJumpRange,fuelPerJump,totalRange}from"./chunk-VTMCSCXV.js";import{calculateUnladenMass}from"./chunk-C3LLPLLD.js";import{mobilityCapacitorMetrics}from"./chunk-VEEBJFJ7.js";import{mobilityMetrics}from"./chunk-A4QKXXZD.js";import{distributorMetrics}from"./chunk-M2TCZKRT.js";import{getExperimentalEffectCost}from"./chunk-CJK2IBI2.js";import{ammunitionCapacity}from"./chunk-AA3K5XUE.js";import{armourMetrics}from"./chunk-Q5ALV3DI.js";import{requirePips,requireFiniteNonNegative}from"./chunk-65FZECUX.js";import{getBlueprintCost}from"./chunk-ARG6ESYB.js";import{sumMaterials}from"./chunk-U73MBQ45.js";import{deepFreeze}from"./chunk-DURKO7JU.js";var FACADE="BuildMetrics";function requireLoadOptions(scope,options){for(const field of["fuel","cargo"]){const value=options[field];if(value!==void 0)requireFiniteNonNegative(scope,field,value)}}var BuildMetrics=class _BuildMetrics{#build;#state;constructor(build,state){this.#build=build;this.#state=state}static of(build){return new _BuildMetrics(build,loadoutInternals(build,`${FACADE}.of: build`))}loadout(){return this.#build}frameShiftDrive(){const drive=this.#state.resolveDrive();if(drive===null){throw new TypeError(`${FACADE}: build has no frame shift drive`)}return drive}thrusters(){return fittedThrusterParamsFor(this.#state.modules(),this.#state.statsFor)}frameShiftDriveMassFactor(options={}){requireLoadOptions(`${FACADE}.frameShiftDriveMassFactor`,options);return frameShiftDriveMassFactor(this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}maxJumpRange(){const fsd=this.frameShiftDrive();return singleJumpRange(this.#loadedMass(0),this.#maxJumpFuel(fsd),fsd)}jumpRange(options={}){requireLoadOptions(`${FACADE}.jumpRange`,options);return singleJumpRange(this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}ladenJumpRange(){return this.jumpRange({cargo:this.#build.cargoCapacity})}fuelPerJump(distance,options={}){requireLoadOptions(`${FACADE}.fuelPerJump`,options);return fuelPerJump(distance,this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}totalRange(options={}){requireLoadOptions(`${FACADE}.totalRange`,options);return totalRange(this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}standardLoadResult(load){return this.#standardLoad(load)}jumpRangeSummary(){const maximum=this.#require(this.standardLoadResult("maximum"),"maximum load");const unladen=this.#require(this.standardLoadResult("unladen"),"unladen load");const laden=this.#require(this.standardLoadResult("laden"),"laden load");return{max:this.jumpRange(maximum),unladen:this.jumpRange(unladen),laden:this.jumpRange(laden),totalMax:this.totalRange(maximum),totalUnladen:this.totalRange(unladen),totalLaden:this.totalRange(laden)}}buildMass(options={}){requireLoadOptions(`${FACADE}.buildMass`,options);const unladen=this.#build.unladenMass;const fuel=options.fuel??this.#build.fuelCapacity.main;const cargo=options.cargo??0;return Object.freeze({hull:this.#state.ship.hullMass,modules:calculateUnladenMass(0,this.#state.calculationModules()),unladen:unladen,fuel:fuel,cargo:cargo,total:unladen+fuel+cargo})}buildCost(){const hull=this.#state.ship.hullCost;let modules=0;let mercCoins=0;const unpriced=[];const materials=[];for(const module of this.#state.modules()){const stats=this.#state.statsFor(module);if(stats?.cost!==void 0){modules+=stats.cost}else if(stats!==null||!isNonOutfittingSlot(module.Slot)&&!isBuiltInHullModule(module)){unpriced.push({slot:module.Slot,symbol:module.Item})}const variant=preEngineeredVariantFor(module);mercCoins+=variant?.mercCoinCost??0;const engineering=module.Engineering;if(!engineering)continue;const grade=engineering.Level;const bought=variant?.grade??0;if(Number.isInteger(grade)&&grade>bought&&grade<=5){const climb=getBlueprintCost(engineering.BlueprintName,grade,bought);if(climb){materials.push(climb.materials);mercCoins+=climb.mercCoins}}const experimental=engineering.ExperimentalEffect;if(experimental!==void 0&&experimental.toLowerCase()!==variant?.experimentalEffectSymbol?.toLowerCase()){const cost=getExperimentalEffectCost(experimental);if(cost)materials.push(cost)}}return deepFreeze({credits:{total:hull+modules,hull:hull,modules:modules,rebuy:Math.trunc((hull+modules)*.05),unpriced:unpriced},mercCoins:mercCoins,materials:sumMaterials(...materials)})}powerBudget(){const modules=this.#state.modules();const consumers=[];for(const module of modules){const consumer=powerConsumerFor(module,this.#state.statsFor(module));if(consumer)consumers.push(consumer)}return powerBudget(powerAvailable(modules,this.#state.statsFor),consumers)}heatMetricsResult(){const input=heatInputResultFor(this.#state.ship,this.#state.effectiveModules(),this.powerBudget(),this.#state.statsFor);return input.complete?completeResult(heatMetrics(input.value)):input}mobilityMetricsResult(options={}){return this.#mobility(options)}mobilityCapacitorMetricsResult(options={}){return this.#mobilityCapacitor(options)}shieldMetricsResult(){return this.#shields()}shieldCapacitorMetricsResult(options={}){return this.#shieldCapacitor(options)}shieldRecoveryResult(options={}){return this.#recovery(options)}cellBanks(){return cellBankSummary(orderBySlotLayout(cellBankInputsFor(this.#state.modules(),this.powerBudget(),this.#state.statsFor),this.#state.layout(),bank=>bank.slot))}armourMetrics(){return armourMetrics(armourInputFor(this.#state.ship,this.#state.modules(),this.#state.statsFor))}weaponMetrics(){const weapons=[];for(const module of this.#state.modules()){const record=this.#state.statsFor(module);const stats=weaponStatsFor(this.#state.effectiveModule(module),record);if(!stats)continue;weapons.push({slot:module.Slot,symbol:module.Item,name:record?.name??module.Item,enabled:module.On!==false,metrics:weaponMetrics(stats),ammunition:ammunitionCapacity(stats),...stats.maximumRange===void 0?{}:{maximumRange:stats.maximumRange},...stats.falloffRange===void 0?{}:{falloffRange:stats.falloffRange},...stats.projectileRange===void 0?{}:{projectileRange:{...stats.projectileRange}},...stats.armourPiercing===void 0?{}:{armourPiercing:stats.armourPiercing}})}const orderedWeapons=orderBySlotLayout(weapons,this.#state.layout(),weapon=>weapon.slot);return{weapons:orderedWeapons,total:sumWeaponMetrics(orderedWeapons.filter(weapon=>weapon.enabled).map(weapon=>weapon.metrics))}}weaponsCapacitorMetrics(options={}){const weaponsPips=requirePips(`${FACADE}.weaponsCapacitorMetrics`,"weaponsPips",options.weaponsPips??4);return weaponsCapacitorMetrics(weaponsCapacitorInputFor(this.#state.effectiveModules(),weaponsPips,this.powerBudget(),this.#state.statsFor))}distributorMetricsResult(options={}){return this.#distributor(options)}#mobility(options){const input=this.#mobilityInput(`${FACADE}.mobilityMetricsResult`,options);return input.complete?completeResult(mobilityMetrics(input.value)):input}#mobilityCapacitor(options){const scope=`${FACADE}.mobilityCapacitorMetricsResult`;const enginesPips=requirePips(scope,"enginesPips",options.enginesPips??4);const input=this.#mobilityInput(scope,options);return input.complete?completeResult(mobilityCapacitorMetrics({...input.value,enginesPips:enginesPips})):input}#mobilityInput(scope,options){requireLoadOptions(scope,options);return mobilityInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),()=>this.#loadedMass(options.cargo??0)+(options.fuel??this.#state.statedMainFuel()??this.#build.fuelCapacity.main),this.#state.statsFor)}#shields(){const input=shieldInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),this.#state.statsFor);return input.complete?completeResult(shieldMetrics(input.value)):input}#shieldCapacitor(options){const systemsPips=requirePips(`${FACADE}.shieldCapacitorMetricsResult`,"systemsPips",options.systemsPips??4);const input=shieldCapacitorInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),systemsPips,this.#state.statsFor);return input.complete?completeResult(shieldCapacitorMetrics(input.value)):input}#recovery(options){const systemsPips=requirePips(`${FACADE}.shieldRecoveryResult`,"systemsPips",options.systemsPips??4);const input=shieldRecoveryInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),systemsPips,this.#state.statsFor);return input.complete?completeResult(shieldRecovery(input.value)):input}#distributor(options){const scope=`${FACADE}.distributorMetricsResult`;const pips={systemsPips:requirePips(scope,"systemsPips",options.systemsPips??4),enginesPips:requirePips(scope,"enginesPips",options.enginesPips??4),weaponsPips:requirePips(scope,"weaponsPips",options.weaponsPips??4)};const input=distributorInputResultFor(this.#state.effectiveModules(),pips,this.powerBudget(),this.#state.statsFor);return input.complete?completeResult(distributorMetrics(input.value)):input}#standardLoad(load){if(load!=="maximum"&&load!=="unladen"&&load!=="laden"){throw new RangeError(`${FACADE}.standardLoadResult: load must be 'maximum', 'unladen', or 'laden'`)}const fuel=this.#build.fuelCapacity;const cargo=load==="laden"?this.#build.cargoCapacity:0;const mass=load==="maximum"?this.#build.unladenMass:0;let drive=null;let maximumFuel=null;if(load==="maximum"){const fitted=this.#state.frameShiftDriveModule();let driveError=null;try{drive=this.#state.resolveDrive();maximumFuel=drive?.maxFuel??null}catch(error){if(!(error instanceof Error))throw error;driveError=error}if(maximumFuel===null){return incompleteResult([{field:"frameShiftDrive",reason:fitted?"unresolved":"missing",slot:fitted?.Slot??"FrameShiftDrive",...fitted?{symbol:fitted.Item}:{},message:driveError?.message??"FrameShiftDrive: no frame shift drive is fitted",params:fitted?{field:"frameShiftDrive",reason:"unresolved",slot:fitted.Slot,symbol:fitted.Item}:{field:"frameShiftDrive",reason:"missing",slot:"FrameShiftDrive"}}])}}const carriedFuel=load==="maximum"?Math.min(fuel.main,maximumFuel):fuel.main;const value=Object.freeze({fuel:carriedFuel,cargo:cargo,mass:this.#build.unladenMass+carriedFuel+cargo});if(load==="maximum"){try{this.jumpRange(value)}catch(error){if(!(error instanceof RangeError))throw error;const fitted=this.#state.frameShiftDriveModule();const field=drive!==null&&(!Number.isFinite(drive.maxFuel)||drive.maxFuel<0)?"frameShiftDrive":!Number.isFinite(value.fuel)||value.fuel<0?"fuelCapacity":!Number.isFinite(mass)||mass<0?"mass":"frameShiftDrive";const driveParams=field==="frameShiftDrive"&&fitted?{slot:fitted.Slot,symbol:fitted.Item}:{};return incompleteResult([{field:field,reason:"invalid",...driveParams,message:error.message,params:{field:field,reason:"invalid",...driveParams}}])}}return completeResult(value)}#require(result,what){if(result.value===null){throw new TypeError(`${FACADE}: cannot determine ${what} (${result.issues.map(issue=>issue.message).join("; ")})`)}return result.value}#loadedMass(cargo){return this.#build.unladenMass+cargo}#maxJumpFuel(fsd){return Math.min(this.#build.fuelCapacity.main,fsd.maxFuel)}};export{BuildMetrics};//# sourceMappingURL=chunk-DEY44PHF.js.map
1
+ import{loadoutInternals,fittedThrusterParamsFor,preEngineeredVariantFor,powerConsumerFor,powerAvailable,heatInputResultFor,completeResult,cellBankInputsFor,armourInputFor,weaponStatsFor,weaponsCapacitorInputFor,mobilityInputResultFor,shieldInputResultFor,shieldCapacitorInputResultFor,shieldRecoveryInputResultFor,distributorInputResultFor,incompleteResult}from"./chunk-ZBB7Q3OZ.js";import{weaponsCapacitorMetrics}from"./chunk-M4FZRDAH.js";import{weaponMetrics,sumWeaponMetrics}from"./chunk-QQFZEOPB.js";import{powerBudget}from"./chunk-GGQMIQPC.js";import{isNonOutfittingSlot,isBuiltInHullModule,orderBySlotLayout}from"./chunk-HE4XE3WR.js";import{shieldCapacitorMetrics}from"./chunk-HWOP7QWK.js";import{cellBankSummary,shieldRecovery}from"./chunk-JMAXSXXQ.js";import{shieldMetrics}from"./chunk-SRPCHXW2.js";import{heatMetrics}from"./chunk-6HA2YIKW.js";import{frameShiftDriveMassFactor,singleJumpRange,fuelPerJump,totalRange}from"./chunk-VTMCSCXV.js";import{calculateUnladenMass}from"./chunk-C3LLPLLD.js";import{mobilityCapacitorMetrics}from"./chunk-VEEBJFJ7.js";import{mobilityMetrics}from"./chunk-A4QKXXZD.js";import{distributorMetrics}from"./chunk-M2TCZKRT.js";import{getExperimentalEffectCost}from"./chunk-CJK2IBI2.js";import{ammunitionCapacity}from"./chunk-AA3K5XUE.js";import{armourMetrics}from"./chunk-3I2I5KG4.js";import{requirePips,requireFiniteNonNegative}from"./chunk-65FZECUX.js";import{getBlueprintCost}from"./chunk-ARG6ESYB.js";import{sumMaterials}from"./chunk-U73MBQ45.js";import{deepFreeze}from"./chunk-DURKO7JU.js";var FACADE="BuildMetrics";function requireLoadOptions(scope,options){for(const field of["fuel","cargo"]){const value=options[field];if(value!==void 0)requireFiniteNonNegative(scope,field,value)}}var BuildMetrics=class _BuildMetrics{#build;#state;constructor(build,state){this.#build=build;this.#state=state}static of(build){return new _BuildMetrics(build,loadoutInternals(build,`${FACADE}.of: build`))}loadout(){return this.#build}frameShiftDrive(){const drive=this.#state.resolveDrive();if(drive===null){throw new TypeError(`${FACADE}: build has no frame shift drive`)}return drive}thrusters(){return fittedThrusterParamsFor(this.#state.modules(),this.#state.statsFor)}frameShiftDriveMassFactor(options={}){requireLoadOptions(`${FACADE}.frameShiftDriveMassFactor`,options);return frameShiftDriveMassFactor(this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}maxJumpRange(){const fsd=this.frameShiftDrive();return singleJumpRange(this.#loadedMass(0),this.#maxJumpFuel(fsd),fsd)}jumpRange(options={}){requireLoadOptions(`${FACADE}.jumpRange`,options);return singleJumpRange(this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}ladenJumpRange(){return this.jumpRange({cargo:this.#build.cargoCapacity})}fuelPerJump(distance,options={}){requireLoadOptions(`${FACADE}.fuelPerJump`,options);return fuelPerJump(distance,this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}totalRange(options={}){requireLoadOptions(`${FACADE}.totalRange`,options);return totalRange(this.#loadedMass(options.cargo??0),options.fuel??this.#build.fuelCapacity.main,this.frameShiftDrive())}standardLoadResult(load){return this.#standardLoad(load)}jumpRangeSummary(){const maximum=this.#require(this.standardLoadResult("maximum"),"maximum load");const unladen=this.#require(this.standardLoadResult("unladen"),"unladen load");const laden=this.#require(this.standardLoadResult("laden"),"laden load");return{max:this.jumpRange(maximum),unladen:this.jumpRange(unladen),laden:this.jumpRange(laden),totalMax:this.totalRange(maximum),totalUnladen:this.totalRange(unladen),totalLaden:this.totalRange(laden)}}buildMass(options={}){requireLoadOptions(`${FACADE}.buildMass`,options);const unladen=this.#build.unladenMass;const fuel=options.fuel??this.#build.fuelCapacity.main;const cargo=options.cargo??0;return Object.freeze({hull:this.#state.ship.hullMass,modules:calculateUnladenMass(0,this.#state.calculationModules()),unladen:unladen,fuel:fuel,cargo:cargo,total:unladen+fuel+cargo})}buildCost(){const hull=this.#state.ship.hullCost;let modules=0;let mercCoins=0;const unpriced=[];const materials=[];for(const module of this.#state.modules()){const stats=this.#state.statsFor(module);if(stats?.cost!==void 0){modules+=stats.cost}else if(stats!==null||!isNonOutfittingSlot(module.Slot)&&!isBuiltInHullModule(module)){unpriced.push({slot:module.Slot,symbol:module.Item})}const variant=preEngineeredVariantFor(module);mercCoins+=variant?.mercCoinCost??0;const engineering=module.Engineering;if(!engineering)continue;const grade=engineering.Level;const bought=variant?.grade??0;if(Number.isInteger(grade)&&grade>bought&&grade<=5){const climb=getBlueprintCost(engineering.BlueprintName,grade,bought);if(climb){materials.push(climb.materials);mercCoins+=climb.mercCoins}}const experimental=engineering.ExperimentalEffect;if(experimental!==void 0&&experimental.toLowerCase()!==variant?.experimentalEffectSymbol?.toLowerCase()){const cost=getExperimentalEffectCost(experimental);if(cost)materials.push(cost)}}return deepFreeze({credits:{total:hull+modules,hull:hull,modules:modules,rebuy:Math.trunc((hull+modules)*.05),unpriced:unpriced},mercCoins:mercCoins,materials:sumMaterials(...materials)})}powerBudget(){const modules=this.#state.modules();const consumers=[];for(const module of modules){const consumer=powerConsumerFor(module,this.#state.statsFor(module));if(consumer)consumers.push(consumer)}return powerBudget(powerAvailable(modules,this.#state.statsFor),consumers)}heatMetricsResult(){const input=heatInputResultFor(this.#state.ship,this.#state.effectiveModules(),this.powerBudget(),this.#state.statsFor);return input.complete?completeResult(heatMetrics(input.value)):input}mobilityMetricsResult(options={}){return this.#mobility(options)}mobilityCapacitorMetricsResult(options={}){return this.#mobilityCapacitor(options)}shieldMetricsResult(){return this.#shields()}shieldCapacitorMetricsResult(options={}){return this.#shieldCapacitor(options)}shieldRecoveryResult(options={}){return this.#recovery(options)}cellBanks(){return cellBankSummary(orderBySlotLayout(cellBankInputsFor(this.#state.modules(),this.powerBudget(),this.#state.statsFor),this.#state.layout(),bank=>bank.slot))}armourMetrics(){return armourMetrics(armourInputFor(this.#state.ship,this.#state.modules(),this.#state.statsFor))}weaponMetrics(){const weapons=[];for(const module of this.#state.modules()){const record=this.#state.statsFor(module);const stats=weaponStatsFor(this.#state.effectiveModule(module),record);if(!stats)continue;weapons.push({slot:module.Slot,symbol:module.Item,name:record?.name??module.Item,enabled:module.On!==false,metrics:weaponMetrics(stats),ammunition:ammunitionCapacity(stats),...stats.maximumRange===void 0?{}:{maximumRange:stats.maximumRange},...stats.falloffRange===void 0?{}:{falloffRange:stats.falloffRange},...stats.projectileRange===void 0?{}:{projectileRange:{...stats.projectileRange}},...stats.armourPiercing===void 0?{}:{armourPiercing:stats.armourPiercing}})}const orderedWeapons=orderBySlotLayout(weapons,this.#state.layout(),weapon=>weapon.slot);return{weapons:orderedWeapons,total:sumWeaponMetrics(orderedWeapons.filter(weapon=>weapon.enabled).map(weapon=>weapon.metrics))}}weaponsCapacitorMetrics(options={}){const weaponsPips=requirePips(`${FACADE}.weaponsCapacitorMetrics`,"weaponsPips",options.weaponsPips??4);return weaponsCapacitorMetrics(weaponsCapacitorInputFor(this.#state.effectiveModules(),weaponsPips,this.powerBudget(),this.#state.statsFor))}distributorMetricsResult(options={}){return this.#distributor(options)}#mobility(options){const input=this.#mobilityInput(`${FACADE}.mobilityMetricsResult`,options);return input.complete?completeResult(mobilityMetrics(input.value)):input}#mobilityCapacitor(options){const scope=`${FACADE}.mobilityCapacitorMetricsResult`;const enginesPips=requirePips(scope,"enginesPips",options.enginesPips??4);const input=this.#mobilityInput(scope,options);return input.complete?completeResult(mobilityCapacitorMetrics({...input.value,enginesPips:enginesPips})):input}#mobilityInput(scope,options){requireLoadOptions(scope,options);return mobilityInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),()=>this.#loadedMass(options.cargo??0)+(options.fuel??this.#state.statedMainFuel()??this.#build.fuelCapacity.main),this.#state.statsFor)}#shields(){const input=shieldInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),this.#state.statsFor);return input.complete?completeResult(shieldMetrics(input.value)):input}#shieldCapacitor(options){const systemsPips=requirePips(`${FACADE}.shieldCapacitorMetricsResult`,"systemsPips",options.systemsPips??4);const input=shieldCapacitorInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),systemsPips,this.#state.statsFor);return input.complete?completeResult(shieldCapacitorMetrics(input.value)):input}#recovery(options){const systemsPips=requirePips(`${FACADE}.shieldRecoveryResult`,"systemsPips",options.systemsPips??4);const input=shieldRecoveryInputResultFor(this.#state.ship,this.#state.modules(),()=>this.powerBudget(),systemsPips,this.#state.statsFor);return input.complete?completeResult(shieldRecovery(input.value)):input}#distributor(options){const scope=`${FACADE}.distributorMetricsResult`;const pips={systemsPips:requirePips(scope,"systemsPips",options.systemsPips??4),enginesPips:requirePips(scope,"enginesPips",options.enginesPips??4),weaponsPips:requirePips(scope,"weaponsPips",options.weaponsPips??4)};const input=distributorInputResultFor(this.#state.effectiveModules(),pips,this.powerBudget(),this.#state.statsFor);return input.complete?completeResult(distributorMetrics(input.value)):input}#standardLoad(load){if(load!=="maximum"&&load!=="unladen"&&load!=="laden"){throw new RangeError(`${FACADE}.standardLoadResult: load must be 'maximum', 'unladen', or 'laden'`)}const fuel=this.#build.fuelCapacity;const cargo=load==="laden"?this.#build.cargoCapacity:0;const mass=load==="maximum"?this.#build.unladenMass:0;let drive=null;let maximumFuel=null;if(load==="maximum"){const fitted=this.#state.frameShiftDriveModule();let driveError=null;try{drive=this.#state.resolveDrive();maximumFuel=drive?.maxFuel??null}catch(error){if(!(error instanceof Error))throw error;driveError=error}if(maximumFuel===null){return incompleteResult([{field:"frameShiftDrive",reason:fitted?"unresolved":"missing",slot:fitted?.Slot??"FrameShiftDrive",...fitted?{symbol:fitted.Item}:{},message:driveError?.message??"FrameShiftDrive: no frame shift drive is fitted",params:fitted?{field:"frameShiftDrive",reason:"unresolved",slot:fitted.Slot,symbol:fitted.Item}:{field:"frameShiftDrive",reason:"missing",slot:"FrameShiftDrive"}}])}}const carriedFuel=load==="maximum"?Math.min(fuel.main,maximumFuel):fuel.main;const value=Object.freeze({fuel:carriedFuel,cargo:cargo,mass:this.#build.unladenMass+carriedFuel+cargo});if(load==="maximum"){try{this.jumpRange(value)}catch(error){if(!(error instanceof RangeError))throw error;const fitted=this.#state.frameShiftDriveModule();const field=drive!==null&&(!Number.isFinite(drive.maxFuel)||drive.maxFuel<0)?"frameShiftDrive":!Number.isFinite(value.fuel)||value.fuel<0?"fuelCapacity":!Number.isFinite(mass)||mass<0?"mass":"frameShiftDrive";const driveParams=field==="frameShiftDrive"&&fitted?{slot:fitted.Slot,symbol:fitted.Item}:{};return incompleteResult([{field:field,reason:"invalid",...driveParams,message:error.message,params:{field:field,reason:"invalid",...driveParams}}])}}return completeResult(value)}#require(result,what){if(result.value===null){throw new TypeError(`${FACADE}: cannot determine ${what} (${result.issues.map(issue=>issue.message).join("; ")})`)}return result.value}#loadedMass(cargo){return this.#build.unladenMass+cargo}#maxJumpFuel(fsd){return Math.min(this.#build.fuelCapacity.main,fsd.maxFuel)}};export{BuildMetrics};//# sourceMappingURL=chunk-JEHKGTP2.js.map