@shipload/sdk 1.0.0-next.3 → 1.0.0-next.4

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.
package/lib/shipload.js CHANGED
@@ -3184,10 +3184,6 @@ var recipes = [
3184
3184
  },
3185
3185
  {
3186
3186
  sources: [
3187
- {
3188
- inputIndex: 1,
3189
- statIndex: 1
3190
- }
3191
3187
  ]
3192
3188
  },
3193
3189
  {
@@ -3227,8 +3223,8 @@ var recipes = [
3227
3223
  {
3228
3224
  sources: [
3229
3225
  {
3230
- inputIndex: 0,
3231
- statIndex: 0
3226
+ inputIndex: 1,
3227
+ statIndex: 1
3232
3228
  }
3233
3229
  ]
3234
3230
  },
@@ -3346,7 +3342,7 @@ var recipes = [
3346
3342
  sources: [
3347
3343
  {
3348
3344
  inputIndex: 0,
3349
- statIndex: 0
3345
+ statIndex: 1
3350
3346
  }
3351
3347
  ]
3352
3348
  },
@@ -3362,16 +3358,12 @@ var recipes = [
3362
3358
  sources: [
3363
3359
  {
3364
3360
  inputIndex: 0,
3365
- statIndex: 1
3361
+ statIndex: 0
3366
3362
  }
3367
3363
  ]
3368
3364
  },
3369
3365
  {
3370
3366
  sources: [
3371
- {
3372
- inputIndex: 1,
3373
- statIndex: 1
3374
- }
3375
3367
  ]
3376
3368
  }
3377
3369
  ],
@@ -8499,10 +8491,10 @@ function moduleSlotTypeToCode(slotType) {
8499
8491
  }
8500
8492
 
8501
8493
  function computeShipHullCapabilities(stats) {
8502
- const density = stats.density ?? 500;
8503
- const strength = stats.strength ?? 500;
8504
- const hardness = stats.hardness ?? 500;
8505
- const saturation = stats.saturation ?? 500;
8494
+ const density = stats.density;
8495
+ const strength = stats.strength;
8496
+ const hardness = stats.hardness;
8497
+ const saturation = stats.saturation;
8506
8498
  const hullmass = 25000 + 75 * density;
8507
8499
  const statSum = strength + hardness + saturation;
8508
8500
  const exponent = statSum / 2997.0;
@@ -8510,26 +8502,26 @@ function computeShipHullCapabilities(stats) {
8510
8502
  return { hullmass, capacity };
8511
8503
  }
8512
8504
  function computeEngineCapabilities(stats) {
8513
- const vol = stats.volatility ?? 500;
8514
- const thm = stats.thermal ?? 500;
8505
+ const vol = stats.volatility;
8506
+ const thm = stats.thermal;
8515
8507
  return {
8516
8508
  thrust: 400 + Math.floor((vol * 3) / 4),
8517
8509
  drain: Math.max(30, 50 - Math.floor(thm / 70)),
8518
8510
  };
8519
8511
  }
8520
8512
  function computeGeneratorCapabilities(stats) {
8521
- const res = stats.resonance ?? 500;
8522
- const ref = stats.reflectivity ?? 500;
8513
+ const com = stats.composition;
8514
+ const fin = stats.fineness;
8523
8515
  return {
8524
- capacity: 300 + Math.floor(res / 6),
8525
- recharge: 1 + Math.floor((ref * 3) / 1000),
8516
+ capacity: 300 + Math.floor(com / 6),
8517
+ recharge: 1 + Math.floor((fin * 3) / 1000),
8526
8518
  };
8527
8519
  }
8528
8520
  function computeGathererCapabilities(stats) {
8529
- const str = stats.strength ?? 500;
8530
- const con = stats.conductivity ?? 500;
8531
- const ref = stats.reflectivity ?? 500;
8532
- const tol = stats.tolerance ?? 500;
8521
+ const str = stats.strength;
8522
+ const con = stats.conductivity;
8523
+ const ref = stats.reflectivity;
8524
+ const tol = stats.tolerance;
8533
8525
  return {
8534
8526
  yield: 200 + str,
8535
8527
  drain: Math.max(250, 1250 - Math.floor((con * 25) / 20)),
@@ -8538,45 +8530,46 @@ function computeGathererCapabilities(stats) {
8538
8530
  };
8539
8531
  }
8540
8532
  function computeLoaderCapabilities(stats) {
8541
- const hrd = stats.hardness ?? 500;
8542
- const pla = stats.plasticity ?? 500;
8533
+ const insulation = stats.insulation;
8534
+ const plasticity = stats.plasticity;
8543
8535
  return {
8544
- mass: Math.max(200, 2000 - Math.floor(hrd * 2)),
8545
- thrust: 1 + Math.floor(pla / 500),
8536
+ mass: Math.max(200, 2000 - Math.floor(insulation * 2)),
8537
+ thrust: 1 + Math.floor(plasticity / 500),
8546
8538
  quantity: 1,
8547
8539
  };
8548
8540
  }
8549
8541
  function computeCrafterCapabilities(stats) {
8550
- const rea = stats.reactivity ?? 500;
8551
- const com = stats.composition ?? 500;
8542
+ const rea = stats.reactivity;
8543
+ const fin = stats.fineness;
8552
8544
  return {
8553
8545
  speed: 100 + Math.floor((rea * 4) / 5),
8554
- drain: Math.max(5, 30 - Math.floor(com / 33)),
8546
+ drain: Math.max(5, 30 - Math.floor(fin / 33)),
8555
8547
  };
8556
8548
  }
8557
8549
  function computeHaulerCapabilities(stats) {
8558
- const res = stats.resonance ?? 500;
8559
- const con = stats.conductivity ?? 500;
8560
- const ref = stats.reflectivity ?? 500;
8550
+ const fineness = stats.fineness;
8551
+ const conductivity = stats.conductivity;
8552
+ const composition = stats.composition;
8561
8553
  return {
8562
- capacity: Math.max(1, 1 + Math.floor(res / 400)),
8563
- efficiency: 2000 + con * 6,
8564
- drain: Math.max(3, 15 - Math.floor(ref / 80)),
8554
+ capacity: Math.max(1, 1 + Math.floor(fineness / 400)),
8555
+ efficiency: 2000 + conductivity * 6,
8556
+ drain: Math.max(3, 15 - Math.floor(composition / 80)),
8565
8557
  };
8566
8558
  }
8567
8559
  function computeStorageCapabilities(stats, baseCapacity) {
8568
- const strength = stats.strength ?? 500;
8569
- const hardness = stats.hardness ?? 500;
8570
- const saturation = stats.saturation ?? 500;
8571
- const statSum = strength + hardness + saturation;
8560
+ const strength = stats.strength;
8561
+ const density = stats.density;
8562
+ const hardness = stats.hardness;
8563
+ const saturation = stats.saturation;
8564
+ const statSum = strength + density + hardness + saturation;
8572
8565
  const capacityBonus = Math.floor((baseCapacity * (10 + Math.floor((statSum * 10) / 2997))) / 100);
8573
8566
  return { capacityBonus };
8574
8567
  }
8575
8568
  function computeWarehouseHullCapabilities(stats) {
8576
- const density = stats.density ?? 500;
8577
- const strength = stats.strength ?? 500;
8578
- const hardness = stats.hardness ?? 500;
8579
- const saturation = stats.saturation ?? 500;
8569
+ const density = stats.density;
8570
+ const strength = stats.strength;
8571
+ const hardness = stats.hardness;
8572
+ const saturation = stats.saturation;
8580
8573
  const hullmass = 25000 + 75 * density;
8581
8574
  const statSum = strength + hardness + saturation;
8582
8575
  const exponent = statSum / 2997.0;
@@ -8779,10 +8772,10 @@ class Container extends exports.ServerTypes.entity_info {
8779
8772
  }
8780
8773
  }
8781
8774
  function computeContainerCapabilities(stats) {
8782
- const density = stats['density'] ?? 500;
8783
- const strength = stats['strength'] ?? 500;
8784
- const hardness = stats['hardness'] ?? 500;
8785
- const saturation = stats['saturation'] ?? 500;
8775
+ const density = stats.density;
8776
+ const strength = stats.strength;
8777
+ const hardness = stats.hardness;
8778
+ const saturation = stats.saturation;
8786
8779
  const hullmass = 25000 + 75 * density;
8787
8780
  const statSum = strength + hardness + saturation;
8788
8781
  const exponent = statSum / 2997;
@@ -8790,10 +8783,10 @@ function computeContainerCapabilities(stats) {
8790
8783
  return { hullmass, capacity };
8791
8784
  }
8792
8785
  function computeContainerT2Capabilities(stats) {
8793
- const strength = stats['strength'] ?? 0;
8794
- const density = stats['density'] ?? 0;
8795
- const hardness = stats['hardness'] ?? 0;
8796
- const saturation = stats['saturation'] ?? 0;
8786
+ const strength = stats.strength;
8787
+ const density = stats.density;
8788
+ const hardness = stats.hardness;
8789
+ const saturation = stats.saturation;
8797
8790
  const hullmass = 20000 + 50 * density;
8798
8791
  const statSum = strength + hardness + saturation;
8799
8792
  const exponent = statSum / 2500;
@@ -10130,6 +10123,11 @@ const capabilityNames = [
10130
10123
  const capabilityAttributes = [
10131
10124
  { capability: 'Hull', attribute: 'mass', description: 'Total mass of the hull' },
10132
10125
  { capability: 'Storage', attribute: 'capacity', description: 'Maximum mass that can be stored' },
10126
+ {
10127
+ capability: 'Storage',
10128
+ attribute: 'bonus',
10129
+ description: 'Capacity bonus added by an installed Storage module',
10130
+ },
10133
10131
  { capability: 'Movement', attribute: 'thrust', description: 'Propulsion force' },
10134
10132
  { capability: 'Movement', attribute: 'drain', description: 'Energy consumed per movement' },
10135
10133
  { capability: 'Energy', attribute: 'capacity', description: 'Maximum energy storage' },
@@ -10167,338 +10165,149 @@ const capabilityAttributes = [
10167
10165
  description: 'Energy consumed per target during haul-beam operation',
10168
10166
  },
10169
10167
  ];
10170
- const statMappings = [
10171
- {
10172
- stat: 'Strength',
10173
- capability: 'Gathering',
10174
- attribute: 'yield',
10175
- rationale: 'Raw mechanical force drives faster gathering',
10176
- },
10177
- {
10178
- stat: 'Strength',
10179
- capability: 'Storage',
10180
- attribute: 'capacity',
10181
- rationale: 'Stronger walls hold more capacity per mass',
10182
- },
10183
- {
10184
- stat: 'Strength',
10185
- capability: 'Launch',
10186
- attribute: 'capacity',
10187
- rationale: 'Stronger housing handles larger launch loads',
10188
- },
10189
- {
10190
- stat: 'Tolerance',
10191
- capability: 'Movement',
10192
- attribute: 'thrust',
10193
- rationale: 'Engine components that tolerate more can push harder',
10194
- },
10195
- {
10196
- stat: 'Tolerance',
10197
- capability: 'Energy',
10198
- attribute: 'recharge',
10199
- rationale: 'Generator housing withstands stress for faster recharge',
10200
- },
10201
- {
10202
- stat: 'Tolerance',
10203
- capability: 'Gathering',
10204
- attribute: 'depth',
10205
- rationale: 'Housing withstands pressure/heat at extreme depths',
10206
- },
10207
- {
10208
- stat: 'Tolerance',
10209
- capability: 'Warp',
10210
- attribute: 'range',
10211
- rationale: 'Warp drive housing withstands extreme forces',
10212
- },
10213
- {
10214
- stat: 'Density',
10215
- capability: 'Hull',
10216
- attribute: 'mass',
10217
- rationale: 'Lighter metal = lighter hull',
10218
- },
10219
- {
10220
- stat: 'Density',
10221
- capability: 'Loader',
10222
- attribute: 'mass',
10223
- rationale: 'Lighter metal = lighter loader units',
10224
- },
10225
- {
10226
- stat: 'Density',
10227
- capability: 'Movement',
10228
- attribute: 'drain',
10229
- rationale: 'Lighter components require less energy to move',
10230
- },
10231
- {
10232
- stat: 'Conductivity',
10233
- capability: 'Movement',
10234
- attribute: 'drain',
10235
- rationale: 'Efficient energy transfer reduces movement energy cost',
10236
- },
10237
- {
10238
- stat: 'Conductivity',
10239
- capability: 'Gathering',
10240
- attribute: 'drain',
10241
- rationale: 'Efficient energy transfer reduces gathering energy cost',
10242
- },
10243
- {
10244
- stat: 'Conductivity',
10245
- capability: 'Crafter',
10246
- attribute: 'drain',
10247
- rationale: 'Efficient energy transfer reduces crafting energy cost',
10248
- },
10249
- {
10250
- stat: 'Conductivity',
10251
- capability: 'Energy',
10252
- attribute: 'recharge',
10253
- rationale: 'Better conductivity speeds energy flow during recharge',
10254
- },
10255
- {
10256
- stat: 'Ductility',
10257
- capability: 'Crafter',
10258
- attribute: 'quality',
10259
- rationale: 'Precise shaping enables tighter crafting tolerances',
10260
- },
10261
- {
10262
- stat: 'Ductility',
10263
- capability: 'Gathering',
10264
- attribute: 'yield',
10265
- rationale: 'Precisely shaped conduit components gather faster',
10266
- },
10267
- {
10268
- stat: 'Ductility',
10269
- capability: 'Storage',
10270
- attribute: 'capacity',
10271
- rationale: 'Precision-formed container walls maximize volume',
10272
- },
10273
- {
10274
- stat: 'Ductility',
10275
- capability: 'Loader',
10276
- attribute: 'mass',
10277
- rationale: 'Precision-formed precious metal reduces loader unit mass',
10278
- },
10279
- {
10280
- stat: 'Reflectivity',
10281
- capability: 'Gathering',
10282
- attribute: 'depth',
10283
- rationale: 'Reflective heat shielding protects equipment at depth',
10284
- },
10285
- {
10286
- stat: 'Reflectivity',
10287
- capability: 'Launch',
10288
- attribute: 'range',
10289
- rationale: 'Reflective surfaces focus electromagnetic launch energy',
10290
- },
10291
- {
10292
- stat: 'Volatility',
10293
- capability: 'Gathering',
10294
- attribute: 'yield',
10295
- rationale: 'Energy release powers faster gathering',
10296
- },
10297
- {
10298
- stat: 'Volatility',
10299
- capability: 'Movement',
10300
- attribute: 'thrust',
10301
- rationale: 'Energy release drives propulsion force',
10302
- },
10303
- {
10304
- stat: 'Volatility',
10305
- capability: 'Loader',
10306
- attribute: 'thrust',
10307
- rationale: 'Energy release powers loader motors',
10308
- },
10309
- {
10310
- stat: 'Volatility',
10311
- capability: 'Launch',
10312
- attribute: 'capacity',
10313
- rationale: 'Energy release enables launching heavier payloads',
10314
- },
10315
- {
10316
- stat: 'Reactivity',
10317
- capability: 'Crafter',
10318
- attribute: 'speed',
10319
- rationale: 'Reactive gases accelerate chemical/thermal processing',
10320
- },
10321
- {
10322
- stat: 'Reactivity',
10323
- capability: 'Gathering',
10324
- attribute: 'speed',
10325
- rationale: 'Reactive gases manage heat/friction during gathering',
10326
- },
10327
- {
10328
- stat: 'Reactivity',
10329
- capability: 'Launch',
10330
- attribute: 'drain',
10331
- rationale: 'Reactive gas medium reduces electromagnetic resistance',
10332
- },
10333
- {
10334
- stat: 'Thermal',
10335
- capability: 'Crafter',
10336
- attribute: 'quality',
10337
- rationale: 'Precise thermal control during fabrication',
10338
- },
10339
- {
10340
- stat: 'Thermal',
10341
- capability: 'Gathering',
10342
- attribute: 'drain',
10343
- rationale: 'Thermal management reduces energy waste during gathering',
10344
- },
10345
- {
10346
- stat: 'Thermal',
10347
- capability: 'Energy',
10348
- attribute: 'capacity',
10349
- rationale: 'Thermal management enables denser energy storage',
10350
- },
10351
- {
10352
- stat: 'Resonance',
10353
- capability: 'Energy',
10354
- attribute: 'capacity',
10355
- rationale: 'Resonating crystals store energy in fields',
10356
- },
10357
- {
10358
- stat: 'Resonance',
10359
- capability: 'Warp',
10360
- attribute: 'range',
10361
- rationale: 'Resonant crystals amplify warp field projection',
10362
- },
10363
- {
10364
- stat: 'Resonance',
10365
- capability: 'Launch',
10366
- attribute: 'range',
10367
- rationale: 'Resonant crystals focus electromagnetic launch field',
10368
- },
10369
- {
10370
- stat: 'Resonance',
10371
- capability: 'Launch',
10372
- attribute: 'capacity',
10373
- rationale: 'Stronger resonant field launches heavier payloads',
10374
- },
10375
- {
10376
- stat: 'Hardness',
10377
- capability: 'Crafter',
10378
- attribute: 'speed',
10379
- rationale: 'Hard tooling surfaces cut and shape materials faster',
10380
- },
10381
- {
10382
- stat: 'Hardness',
10383
- capability: 'Launch',
10384
- attribute: 'drain',
10385
- rationale: 'Hard rail surfaces reduce friction, less energy wasted',
10386
- },
10387
- {
10388
- stat: 'Clarity',
10389
- capability: 'Energy',
10390
- attribute: 'recharge',
10391
- rationale: 'Flawless crystals enable smoother energy flow during recharge',
10392
- },
10393
- {
10394
- stat: 'Clarity',
10395
- capability: 'Crafter',
10396
- attribute: 'quality',
10397
- rationale: 'Precision optics for calibration during fabrication',
10398
- },
10399
- {
10400
- stat: 'Clarity',
10401
- capability: 'Crafter',
10402
- attribute: 'drain',
10403
- rationale: 'Precision computing optimizes energy routing in factory',
10404
- },
10405
- {
10406
- stat: 'Plasticity',
10407
- capability: 'Crafter',
10408
- attribute: 'speed',
10409
- rationale: 'Easily reshaped materials speed up processing',
10410
- },
10411
- {
10412
- stat: 'Plasticity',
10413
- capability: 'Movement',
10414
- attribute: 'thrust',
10415
- rationale: 'Flexible polymer seals reduce friction in propulsion',
10416
- },
10417
- {
10418
- stat: 'Plasticity',
10419
- capability: 'Loader',
10420
- attribute: 'thrust',
10421
- rationale: 'Flexible joints improve loader force transfer',
10422
- },
10423
- {
10424
- stat: 'Insulation',
10425
- capability: 'Movement',
10426
- attribute: 'drain',
10427
- rationale: 'Better insulation reduces energy loss during movement',
10428
- },
10429
- {
10430
- stat: 'Insulation',
10431
- capability: 'Gathering',
10432
- attribute: 'drain',
10433
- rationale: 'Better insulation reduces energy loss during gathering',
10434
- },
10435
- {
10436
- stat: 'Insulation',
10437
- capability: 'Crafter',
10438
- attribute: 'drain',
10439
- rationale: 'Better insulation reduces energy loss during crafting',
10168
+ const invertedAttributes = new Set(['drain', 'mass']);
10169
+ function isInvertedAttribute(attribute) {
10170
+ return invertedAttributes.has(attribute);
10171
+ }
10172
+ function getCapabilityAttributes(capability) {
10173
+ if (capability) {
10174
+ return capabilityAttributes.filter((a) => a.capability === capability);
10175
+ }
10176
+ return capabilityAttributes;
10177
+ }
10178
+
10179
+ const ENTITY_HULL_SLOTS = {
10180
+ 0: { capability: 'Storage', attribute: 'capacity' },
10181
+ 1: { capability: 'Hull', attribute: 'mass' },
10182
+ 2: { capability: 'Storage', attribute: 'capacity' },
10183
+ 3: { capability: 'Storage', attribute: 'capacity' },
10184
+ };
10185
+ const SLOT_FORMULAS = {
10186
+ engine: {
10187
+ 0: { capability: 'Movement', attribute: 'thrust' },
10188
+ 1: { capability: 'Movement', attribute: 'drain' },
10440
10189
  },
10441
- {
10442
- stat: 'Insulation',
10443
- capability: 'Launch',
10444
- attribute: 'drain',
10445
- rationale: 'Better insulation reduces energy loss during launch',
10190
+ generator: {
10191
+ 0: { capability: 'Energy', attribute: 'capacity' },
10192
+ 1: { capability: 'Energy', attribute: 'recharge' },
10446
10193
  },
10447
- {
10448
- stat: 'Purity',
10449
- capability: 'Storage',
10450
- attribute: 'capacity',
10451
- rationale: 'Purer composites make better containers',
10194
+ gatherer: {
10195
+ 0: { capability: 'Gathering', attribute: 'yield' },
10196
+ 1: { capability: 'Gathering', attribute: 'depth' },
10197
+ 3: { capability: 'Gathering', attribute: 'drain' },
10198
+ 4: { capability: 'Gathering', attribute: 'speed' },
10452
10199
  },
10453
- {
10454
- stat: 'Purity',
10455
- capability: 'Gathering',
10456
- attribute: 'speed',
10457
- rationale: 'Purer bio-lubricants reduce friction during gathering',
10200
+ loader: {
10201
+ 0: { capability: 'Loader', attribute: 'mass' },
10202
+ 1: { capability: 'Loader', attribute: 'thrust' },
10458
10203
  },
10459
- {
10460
- stat: 'Purity',
10461
- capability: 'Energy',
10462
- attribute: 'capacity',
10463
- rationale: 'Purer organic electrolytes store more charge',
10204
+ crafter: {
10205
+ 0: { capability: 'Crafter', attribute: 'speed' },
10206
+ 1: { capability: 'Crafter', attribute: 'drain' },
10464
10207
  },
10465
- {
10466
- stat: 'Resonance',
10467
- capability: 'Hauler',
10468
- attribute: 'capacity',
10469
- rationale: 'Resonant field strength determines how many targets the haul beam can lock onto simultaneously.',
10208
+ storage: {
10209
+ 0: { capability: 'Storage', attribute: 'bonus' },
10210
+ 1: { capability: 'Storage', attribute: 'bonus' },
10211
+ 2: { capability: 'Storage', attribute: 'bonus' },
10212
+ 3: { capability: 'Storage', attribute: 'bonus' },
10470
10213
  },
10471
- {
10472
- stat: 'Conductivity',
10473
- capability: 'Hauler',
10474
- attribute: 'efficiency',
10475
- rationale: 'Energy-transfer efficiency reduces the thrust penalty from each hauled target.',
10214
+ hauler: {
10215
+ 0: { capability: 'Hauler', attribute: 'capacity' },
10216
+ 1: { capability: 'Hauler', attribute: 'efficiency' },
10217
+ 2: { capability: 'Hauler', attribute: 'drain' },
10476
10218
  },
10477
- {
10478
- stat: 'Clarity',
10479
- capability: 'Hauler',
10480
- attribute: 'drain',
10481
- rationale: 'Clarity-focused energy routing reduces per-target drain during haul-beam operation.',
10219
+ warp: {
10220
+ 0: { capability: 'Warp', attribute: 'range' },
10482
10221
  },
10483
- ];
10484
- const invertedAttributes = new Set(['drain', 'mass']);
10485
- function isInvertedAttribute(attribute) {
10486
- return invertedAttributes.has(attribute);
10222
+ 'ship-t1': ENTITY_HULL_SLOTS,
10223
+ 'container-t1': ENTITY_HULL_SLOTS,
10224
+ 'warehouse-t1': ENTITY_HULL_SLOTS,
10225
+ 'container-t2': ENTITY_HULL_SLOTS,
10226
+ };
10227
+
10228
+ const KIND_TO_ITEM_ID = {
10229
+ engine: ITEM_ENGINE_T1,
10230
+ generator: ITEM_GENERATOR_T1,
10231
+ gatherer: ITEM_GATHERER_T1,
10232
+ loader: ITEM_LOADER_T1,
10233
+ crafter: ITEM_CRAFTER_T1,
10234
+ storage: ITEM_STORAGE_T1,
10235
+ hauler: ITEM_HAULER_T1,
10236
+ warp: ITEM_WARP_T1,
10237
+ 'ship-t1': ITEM_SHIP_T1_PACKED,
10238
+ 'container-t1': ITEM_CONTAINER_T1_PACKED,
10239
+ 'warehouse-t1': ITEM_WAREHOUSE_T1_PACKED,
10240
+ 'container-t2': ITEM_CONTAINER_T2_PACKED,
10241
+ };
10242
+ function isCategoryInput(input) {
10243
+ return 'category' in input;
10487
10244
  }
10488
- function getCapabilityAttributes(capability) {
10489
- if (capability) {
10490
- return capabilityAttributes.filter((a) => a.capability === capability);
10245
+ function traceToRawCategoryStat(recipe, source, visited = new Set()) {
10246
+ const input = recipe.inputs[source.inputIndex];
10247
+ if (!input)
10248
+ return undefined;
10249
+ if (isCategoryInput(input)) {
10250
+ const defs = getStatDefinitions(input.category);
10251
+ return defs[source.statIndex];
10491
10252
  }
10492
- return capabilityAttributes;
10253
+ if (visited.has(input.itemId))
10254
+ return undefined;
10255
+ const subRecipe = getRecipe(input.itemId);
10256
+ if (!subRecipe)
10257
+ return undefined;
10258
+ const subSlot = subRecipe.statSlots[source.statIndex];
10259
+ if (!subSlot)
10260
+ return undefined;
10261
+ const subSource = subSlot.sources[0];
10262
+ if (!subSource)
10263
+ return undefined;
10264
+ const nextVisited = new Set(visited);
10265
+ nextVisited.add(input.itemId);
10266
+ return traceToRawCategoryStat(subRecipe, subSource, nextVisited);
10267
+ }
10268
+ let cached;
10269
+ function deriveStatMappings() {
10270
+ if (cached)
10271
+ return cached;
10272
+ const out = [];
10273
+ const seen = new Set();
10274
+ for (const [kind, slots] of Object.entries(SLOT_FORMULAS)) {
10275
+ const itemId = KIND_TO_ITEM_ID[kind];
10276
+ const recipe = getRecipe(itemId);
10277
+ if (!recipe)
10278
+ continue;
10279
+ for (const [slotIdxStr, consumer] of Object.entries(slots)) {
10280
+ const slotIdx = Number(slotIdxStr);
10281
+ const slot = recipe.statSlots[slotIdx];
10282
+ if (!slot)
10283
+ continue;
10284
+ for (const source of slot.sources) {
10285
+ const stat = traceToRawCategoryStat(recipe, source);
10286
+ if (!stat)
10287
+ continue;
10288
+ const key = `${stat.label}|${consumer.capability}|${consumer.attribute}`;
10289
+ if (seen.has(key))
10290
+ continue;
10291
+ seen.add(key);
10292
+ out.push({
10293
+ stat: stat.label,
10294
+ capability: consumer.capability,
10295
+ attribute: consumer.attribute,
10296
+ });
10297
+ }
10298
+ }
10299
+ }
10300
+ cached = out;
10301
+ return out;
10493
10302
  }
10494
10303
  function getStatMappings() {
10495
- return statMappings;
10304
+ return deriveStatMappings();
10496
10305
  }
10497
10306
  function getStatMappingsForStat(stat) {
10498
- return statMappings.filter((m) => m.stat === stat);
10307
+ return deriveStatMappings().filter((m) => m.stat === stat);
10499
10308
  }
10500
10309
  function getStatMappingsForCapability(capability) {
10501
- return statMappings.filter((m) => m.capability === capability);
10310
+ return deriveStatMappings().filter((m) => m.capability === capability);
10502
10311
  }
10503
10312
 
10504
10313
  function toNum(v) {
@@ -10637,10 +10446,11 @@ function computeCapabilityGroup(moduleType, stats) {
10637
10446
  };
10638
10447
  }
10639
10448
  case MODULE_STORAGE: {
10640
- const str = stats.strength ?? 500;
10641
- const hrd = stats.hardness ?? 500;
10642
- const sat = stats.saturation ?? 500;
10643
- const statSum = str + hrd + sat;
10449
+ const str = stats.strength;
10450
+ const den = stats.density;
10451
+ const hrd = stats.hardness;
10452
+ const sat = stats.saturation;
10453
+ const statSum = str + den + hrd + sat;
10644
10454
  const pct = 10 + Math.floor((statSum * 10) / 2997);
10645
10455
  return { capability: 'Storage', attributes: [{ label: 'Capacity Bonus', value: pct }] };
10646
10456
  }
@@ -10945,16 +10755,16 @@ function computeBaseCapacityWarehouse(stats) {
10945
10755
  }
10946
10756
  const computeEngineThrust = (vol) => 400 + idiv(vol * 3, 4);
10947
10757
  const computeEngineDrain = (thm) => Math.max(30, 50 - idiv(thm, 70));
10948
- const computeGeneratorCap = (res) => 300 + idiv(res, 6);
10949
- const computeGeneratorRech = (ref) => 1 + idiv(ref * 3, 1000);
10758
+ const computeGeneratorCap = (com) => 300 + idiv(com, 6);
10759
+ const computeGeneratorRech = (fin) => 1 + idiv(fin * 3, 1000);
10950
10760
  const computeGathererYield = (str) => 200 + str;
10951
10761
  const computeGathererDrain = (con) => Math.max(250, 1250 - idiv(con * 25, 20));
10952
10762
  const computeGathererDepth = (tol) => 200 + idiv(tol * 3, 2);
10953
10763
  const computeGathererSpeed = (ref) => 100 + idiv(ref * 4, 5);
10954
- const computeLoaderMass = (fin) => Math.max(200, 2000 - fin * 2);
10764
+ const computeLoaderMass = (ins) => Math.max(200, 2000 - ins * 2);
10955
10765
  const computeLoaderThrust = (pla) => 1 + idiv(pla, 500);
10956
10766
  const computeCrafterSpeed = (rea) => 100 + idiv(rea * 4, 5);
10957
- const computeCrafterDrain = (com) => Math.max(5, 30 - idiv(com, 33));
10767
+ const computeCrafterDrain = (fin) => Math.max(5, 30 - idiv(fin, 33));
10958
10768
  const computeWarpRange = (stat) => 100 + stat * 3;
10959
10769
  function entityDisplayName(itemId) {
10960
10770
  switch (itemId) {
@@ -11339,6 +11149,7 @@ exports.SHIP_NOT_IDLE = SHIP_NOT_IDLE;
11339
11149
  exports.SHIP_NOT_OWNED = SHIP_NOT_OWNED;
11340
11150
  exports.SHIP_NO_COMPLETED_TASKS = SHIP_NO_COMPLETED_TASKS;
11341
11151
  exports.SHIP_NO_TASKS_TO_CANCEL = SHIP_NO_TASKS_TO_CANCEL;
11152
+ exports.SLOT_FORMULAS = SLOT_FORMULAS;
11342
11153
  exports.STARTER_ALREADY_CLAIMED = STARTER_ALREADY_CLAIMED;
11343
11154
  exports.ScheduleAccessor = ScheduleAccessor;
11344
11155
  exports.ServerContract = server;
@@ -11444,6 +11255,7 @@ exports.computeShipHullCapabilities = computeShipHullCapabilities;
11444
11255
  exports.computeStorageCapabilities = computeStorageCapabilities;
11445
11256
  exports.computeWarehouseCapabilities = computeWarehouseCapabilities;
11446
11257
  exports.computeWarehouseHullCapabilities = computeWarehouseHullCapabilities;
11258
+ exports.computeWarpRange = computeWarpRange;
11447
11259
  exports.coordsToLocationId = coordsToLocationId;
11448
11260
  exports.createInventoryAccessor = createInventoryAccessor;
11449
11261
  exports.createProjectedEntity = createProjectedEntity;
@@ -11457,6 +11269,7 @@ exports.deriveLocationEpoch = deriveLocationEpoch;
11457
11269
  exports.deriveLocationSize = deriveLocationSize;
11458
11270
  exports.deriveLocationStatic = deriveLocationStatic;
11459
11271
  exports.deriveResourceStats = deriveResourceStats;
11272
+ exports.deriveStatMappings = deriveStatMappings;
11460
11273
  exports.deriveStrata = deriveStrata;
11461
11274
  exports.deriveStratum = deriveStratum;
11462
11275
  exports.describeItem = describeItem;
@@ -11571,7 +11384,6 @@ exports.setSubscriptionsDebug = setSubscriptionsDebug;
11571
11384
  exports.stackKey = stackKey;
11572
11385
  exports.stackToCargoItem = stackToCargoItem;
11573
11386
  exports.stacksEqual = stacksEqual;
11574
- exports.statMappings = statMappings;
11575
11387
  exports.tierColors = tierColors;
11576
11388
  exports.tierLabel = tierLabel;
11577
11389
  exports.tierLabels = tierLabels;