@elite-dangerous-almanac/core 0.2.7 → 0.2.8

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 (101) hide show
  1. package/PROVENANCE/equipment/SOURCES.md +149 -27
  2. package/PROVENANCE/i18n/SOURCES.md +176 -27
  3. package/PROVENANCE/ships/SOURCES.md +10 -18
  4. package/README.md +20 -5
  5. package/THIRD_PARTY_NOTICES.md +4 -1
  6. package/dist/{chunk-AAU7OM47.js → chunk-2OBUSQA7.js} +1 -1
  7. package/dist/{chunk-AAU7OM47.js.map → chunk-2OBUSQA7.js.map} +1 -1
  8. package/dist/{chunk-MVBVXK3G.js → chunk-3GNYPM6J.js} +1 -1
  9. package/dist/{chunk-MVBVXK3G.js.map → chunk-3GNYPM6J.js.map} +1 -1
  10. package/dist/{chunk-A6OINYNP.js → chunk-3WGXGBW5.js} +1 -1
  11. package/dist/{chunk-NZXSIHAW.js → chunk-5YEHJM6V.js} +1 -1
  12. package/dist/{chunk-NZXSIHAW.js.map → chunk-5YEHJM6V.js.map} +1 -1
  13. package/dist/{chunk-7S7ZTZZY.js → chunk-7EWZGDWY.js} +1 -1
  14. package/dist/chunk-DAQ3PJ4R.js +1 -0
  15. package/dist/chunk-DAQ3PJ4R.js.map +1 -0
  16. package/dist/chunk-DHACRCLI.js +1 -0
  17. package/dist/chunk-DHACRCLI.js.map +1 -0
  18. package/dist/chunk-FJIWJYKO.js +1 -0
  19. package/dist/chunk-FJIWJYKO.js.map +1 -0
  20. package/dist/chunk-GIGRBFIJ.js +1 -0
  21. package/dist/{chunk-MGRDB2BZ.js.map → chunk-GIGRBFIJ.js.map} +1 -1
  22. package/dist/{chunk-FMA36V6A.js → chunk-IMNOEFUE.js} +1 -1
  23. package/dist/{chunk-FMA36V6A.js.map → chunk-IMNOEFUE.js.map} +1 -1
  24. package/dist/chunk-IN36YSS4.js +1 -0
  25. package/dist/chunk-IN36YSS4.js.map +1 -0
  26. package/dist/chunk-IUSMAX5T.js +1 -0
  27. package/dist/{chunk-6GJHUWMO.js.map → chunk-IUSMAX5T.js.map} +1 -1
  28. package/dist/{chunk-XQJERZUS.js → chunk-JCYOE3C4.js} +1 -1
  29. package/dist/{chunk-XQJERZUS.js.map → chunk-JCYOE3C4.js.map} +1 -1
  30. package/dist/chunk-LWNBWRKL.js +1 -0
  31. package/dist/{chunk-B7EYTZRK.js.map → chunk-LWNBWRKL.js.map} +1 -1
  32. package/dist/chunk-MT5AHPNP.js +1 -0
  33. package/dist/{chunk-ZEN5K3GE.js.map → chunk-MT5AHPNP.js.map} +1 -1
  34. package/dist/chunk-OLKOWR7S.js +1 -0
  35. package/dist/chunk-OLKOWR7S.js.map +1 -0
  36. package/dist/chunk-SC4MEHVY.js +1 -0
  37. package/dist/chunk-SC4MEHVY.js.map +1 -0
  38. package/dist/chunk-W5ULI75F.js +1 -0
  39. package/dist/chunk-W5ULI75F.js.map +1 -0
  40. package/dist/chunk-WV7QCDL5.js +1 -0
  41. package/dist/chunk-WV7QCDL5.js.map +1 -0
  42. package/dist/{chunk-F7VWRDSL.js → chunk-YJAH6DFY.js} +1 -1
  43. package/dist/chunk-YJAH6DFY.js.map +1 -0
  44. package/dist/equipment/engineering.d.ts +53 -1
  45. package/dist/equipment/engineering.js +1 -1
  46. package/dist/equipment/index.d.ts +13 -2
  47. package/dist/equipment/index.js +1 -1
  48. package/dist/equipment/modification-journal.js +1 -1
  49. package/dist/equipment/modifications.d.ts +32 -9
  50. package/dist/equipment/modifications.js +1 -1
  51. package/dist/equipment/suits.d.ts +32 -2
  52. package/dist/equipment/suits.js +1 -1
  53. package/dist/equipment/upgrade-costs.js +1 -1
  54. package/dist/equipment/weapons.d.ts +16 -2
  55. package/dist/equipment/weapons.js +1 -1
  56. package/dist/i18n/index.d.ts +76 -0
  57. package/dist/i18n/index.js +1 -1
  58. package/dist/i18n/personal-modifications.d.ts +68 -0
  59. package/dist/i18n/personal-modifications.js +1 -0
  60. package/dist/i18n/personal-modifications.js.map +1 -0
  61. package/dist/i18n/personal-weapons.d.ts +33 -0
  62. package/dist/i18n/personal-weapons.js +1 -0
  63. package/dist/i18n/personal-weapons.js.map +1 -0
  64. package/dist/i18n/suits.d.ts +59 -0
  65. package/dist/i18n/suits.js +1 -0
  66. package/dist/i18n/suits.js.map +1 -0
  67. package/dist/materials/index.js +1 -1
  68. package/dist/materials/micro-resources-all.js +1 -1
  69. package/dist/materials/micro-resources.js +1 -1
  70. package/dist/ships/build-metrics.js +1 -1
  71. package/dist/ships/index.js +1 -1
  72. package/dist/ships/loadout-validation.d.ts +7 -2
  73. package/dist/ships/loadout-validation.js +1 -1
  74. package/dist/ships/modules-all.js +1 -1
  75. package/dist/ships/modules-internal.d.ts +17 -6
  76. package/dist/ships/modules-internal.js +1 -1
  77. package/dist/ships/modules.d.ts +5 -1
  78. package/dist/ships/modules.js +1 -1
  79. package/dist/ships/pre-engineered-stats.js +1 -1
  80. package/dist/ships/shield-capacitor.js +1 -1
  81. package/dist/ships/ship-loadout.d.ts +6 -0
  82. package/dist/ships/ship-loadout.js +1 -1
  83. package/dist/ships/weapons.js +1 -1
  84. package/package.json +13 -1
  85. package/dist/chunk-4U7KYQGK.js +0 -1
  86. package/dist/chunk-4U7KYQGK.js.map +0 -1
  87. package/dist/chunk-6GJHUWMO.js +0 -1
  88. package/dist/chunk-B7EYTZRK.js +0 -1
  89. package/dist/chunk-C5HG4GJI.js +0 -1
  90. package/dist/chunk-C5HG4GJI.js.map +0 -1
  91. package/dist/chunk-F7VWRDSL.js.map +0 -1
  92. package/dist/chunk-KLC5XT6F.js +0 -1
  93. package/dist/chunk-KLC5XT6F.js.map +0 -1
  94. package/dist/chunk-MGRDB2BZ.js +0 -1
  95. package/dist/chunk-TSEDU73T.js +0 -1
  96. package/dist/chunk-TSEDU73T.js.map +0 -1
  97. package/dist/chunk-XRGECU7S.js +0 -1
  98. package/dist/chunk-XRGECU7S.js.map +0 -1
  99. package/dist/chunk-ZEN5K3GE.js +0 -1
  100. /package/dist/{chunk-A6OINYNP.js.map → chunk-3WGXGBW5.js.map} +0 -0
  101. /package/dist/{chunk-7S7ZTZZY.js.map → chunk-7EWZGDWY.js.map} +0 -0
@@ -1,33 +1,38 @@
1
1
  # Data sources — `data/equipment/`
2
2
 
3
+ ## Upstream snapshots this domain is pinned to
4
+
5
+ Referred to throughout by source name; the pin is here, once.
6
+
7
+ | Source | Pin | Acquired |
8
+ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
9
+ | Odyssey Materials Helper | commit `2e6d4c3e767d2b714ffddc5c9386831d66812916` (2026-08-09), the last revision before the project extracted its core data into a separately distributed dependency | 2026-08-13 UTC |
10
+ | Frontier Elite Dangerous Gamestore | no immutable revision; the displayed weapon names were read on the acquisition date | 2026-08-13 UTC |
11
+ | Elite Dangerous in-game observation | no game version recorded; direct reading of the suit and weapon stats panels, the sight magnification they show, and the on-foot engineering options | 2026-08-31 UTC |
12
+
13
+ **Where a source and the game disagree, the in-game reading governs.** Odyssey Materials Helper
14
+ supplies the identities, the slot and grade structure, the engineer availability and
15
+ every material shopping list; the stat values are the ones the game itself shows.
16
+
3
17
  ## Personal suits, handheld weapons and engineering
4
18
 
5
19
  - **Files:** `suits.jsonc`, `weapons.jsonc`, `upgrade-costs.jsonc`,
6
20
  `modifications.jsonc`, `modification-costs.jsonc`,
7
21
  `modification-journal-names.jsonc`.
8
- - **Acquired:** 2026-08-13.
9
- - **Source:** Odyssey Materials Helper.
10
- - **Upstream revisions:**
11
- - Odyssey Materials Helper commit `2e6d4c3e767d2b714ffddc5c9386831d66812916`
12
- (2026-08-09), the last revision before the project extracted its core data into a
13
- separately distributed dependency.
14
- - Frontier Elite Dangerous Gamestore product pages have no immutable revision; their
15
- displayed weapon names were read on the acquisition date above.
16
22
  - **Derivation:**
17
23
  - `Suit.java` supplies the four suit families, journal symbols, weapon-slot counts and
18
- grade-dependent shield strength, shield regeneration, resistances and modification
19
- slots. English suit display names come from
24
+ the grade-dependent modification slots, shield strength and shield regeneration.
25
+ English suit display names come from
20
26
  `application/src/main/resources/locale/loadout/equipment.csv`. `family` removes
21
27
  `_class{grade}` from the grade-specific Frontier `symbol`; the exact symbol remains
22
28
  on every grade. Shield strength is in shield points, shield regeneration in shield
23
- points per second. The source's resistance percentage points are divided by 100 into
24
- fractions, matching the resistance convention used by the ships domain (`0.5` means
25
- 50% resisted).
29
+ points per second.
26
30
  - `Weapon.java` supplies the eleven handheld weapons, their exact journal symbols,
27
- class, slot, damage type, fire mode and combat stats. English weapon display names
28
- come from `application/src/main/resources/locale/loadout/equipment.csv`. Damage is
29
- per projectile or pellet, rate of fire is shots per second, effective range is
30
- metres, and the source's headshot percentages are divided by 100 into multipliers.
31
+ class, slot, damage type, fire mode, magazine size, headshot multiplier and effective
32
+ range. English weapon display names come from
33
+ `application/src/main/resources/locale/loadout/equipment.csv`. Damage is per
34
+ projectile or pellet, rate of fire is shots per second, effective range is metres,
35
+ and the source's headshot percentages are divided by 100 into multipliers.
31
36
  - `OdysseyBlueprintConstants.java` supplies each one-step suit and manufacturer-family
32
37
  weapon upgrade recipe, all engineer-applied modification recipes, and the engineers
33
38
  who offer them. Enum names are joined to the lower-case Frontier micro-resource
@@ -36,17 +41,134 @@
36
41
  the source's `karma`, `takada` and `manticore` identities; `engineeringType` separately
37
42
  records the `kinetic`, `laser` or `plasma` suffix used by modification recipes.
38
43
  - `SuitModification.java` and `WeaponModification.java` supply the journal symbols.
39
- English modification display names come from
40
- `application/src/main/resources/locale/loadout/modification.csv`; English engineer
41
- names come from `application/src/main/resources/locale/engineer/names.csv`. A recipe
42
- is keyed by its symbol rather than by a derived library id. Greater Range, Headshot
43
- Damage and Higher Accuracy retain their nine distinct Kinetic, Laser and Plasma
44
+ English engineer names come from
45
+ `application/src/main/resources/locale/engineer/names.csv`. A recipe is keyed by its
46
+ symbol rather than by a derived library id. Greater Range, Headshot Damage and
47
+ Improved Hip Fire Accuracy retain their nine distinct Kinetic, Laser and Plasma
44
48
  recipe symbols. The journal writes only three unsuffixed symbols, so
45
49
  `modification-journal-names.jsonc` records that collision once for resolution against
46
50
  the weapon. `modification-costs.jsonc` is split from recipe metadata so an identity
47
51
  lookup does not bundle every shopping list, matching the ships engineering boundary.
48
- - **Manual corrections:** Odyssey Materials Helper's English locale calls the four Karma
49
- weapons “Kinematic” and expands the three TK weapon names to “Takada”. The Frontier
50
- Elite Dangerous Gamestore confirms the in-game prefixes are `Karma` and `TK`, which are
51
- stored here. Frontier's misspelled `surveilleancelogs` symbol is kept verbatim so it
52
- joins to journal inventory data and the micro-resource catalogue.
52
+ - **In-game observation supplies every stat value** described in the three sections
53
+ below: the suit-wide component stats and the four resistances, the weapon combat
54
+ stats and damage, and the multipliers each modification applies.
55
+
56
+ - **Manual corrections:**
57
+ - Odyssey Materials Helper's English locale calls the four Karma weapons “Kinematic”
58
+ and expands the three TK weapon names to “Takada”. The Frontier Elite Dangerous
59
+ Gamestore confirms the in-game prefixes are `Karma` and `TK`, which are stored here.
60
+ - Frontier's misspelled `surveilleancelogs` symbol is kept verbatim so it joins to
61
+ journal inventory data and the micro-resource catalogue.
62
+ - Three modification display names are the in-game text rather than the source's:
63
+ `Faster Shield Regeneration`→`Faster Shield Regen`,
64
+ `Higher Accuracy`→`Improved Hip Fire Accuracy`, and `Stowed Reloading`→
65
+ `Stowed reloading`. The last keeps Frontier's own lower-case second word; it reads
66
+ like a typo and is not one, so do not "fix" it back.
67
+
68
+ ### Suit stats read in-game
69
+
70
+ The suit stats panel is read per suit family and per grade.
71
+
72
+ - **Suit-wide, identical at all five grades**, so they are stored once per family rather
73
+ than per grade: `health` (30 on every suit), `mass` (100 kg on every suit),
74
+ `batteryCapacity` in energy units, `oxygenTime` in seconds of emergency air,
75
+ `boostAcceleration` for the jump assist, the three backpack capacities
76
+ (`goodsCapacity`, `assetsCapacity`, `dataCapacity`), `footstepAudibleRange` as a
77
+ multiplier of the base audible range (1 on every suit), `losAnalysisRange` in metres
78
+ (50 on every suit) and `losAnalysisTime` in seconds (1 on every suit). The constant
79
+ ones are stored anyway: a suit-stats view reads them like any other field, and a value
80
+ that is the same everywhere is still the value.
81
+ - **Resistances are stored as fractions** (`0.5` means half the damage taken),
82
+ matching the ships domain. The panel's own figure is the same fraction as a
83
+ percentage, so a negative resistance is a weakness. Every resistance is now the
84
+ panel's, which corrects nine grade rows against Odyssey Materials Helper:
85
+
86
+ | Suit and grade | Field → stored value |
87
+ | ------------------- | ------------------------------------------------------------------------- |
88
+ | Artemis 1 | `thermalResistance` 0.39→0.4 |
89
+ | Artemis 2 | `kineticResistance` -0.42→-0.43; `plasmaResistance` 0→-0.01 |
90
+ | Artemis 3 | `plasmaResistance` 0.14→0.15 |
91
+ | Artemis 5 | `kineticResistance` 0.14→0.15; `plasmaResistance` 0.39→0.4 |
92
+ | Flight Suit | `thermalResistance` 0.39→0.4 |
93
+ | Dominator 4 | `kineticResistance` 0.19→0.11; `thermalResistance` 0.78→0.76; `plasmaResistance` 0.46→0.41; `explosiveResistance` 0.46→0.41 |
94
+ | Maverick 2 | `plasmaResistance` 0.07→0.08 |
95
+ | Maverick 3 | `kineticResistance` -0.13→-0.14 |
96
+ | Maverick 5 | `kineticResistance` 0.19→0.2 |
97
+
98
+ - **Shield strength and shield regeneration are unchanged.** Every stored value already
99
+ matches the panel, which is also why the resistance disagreements are read as source
100
+ rounding rather than as a different snapshot of the game.
101
+ - **A grade changes the armour, the shield generator, the modification slots and the
102
+ item symbol.** Nothing else on a suit moves with the grade, which is what makes the
103
+ suit-wide fields safe to store once per family.
104
+
105
+ ### Weapon stats read in-game
106
+
107
+ - **Rate of fire** is the panel's, correcting `Karma AR-50` 9.5→9.52,
108
+ `TK Aphelion` 5.7→5.71, `Manticore Oppressor` 6.7→6.67, `Manticore Intimidator`
109
+ 1.3→1.25, `Manticore Tormentor` 1.7→1.67, `Manticore Executioner` 0.8→0.833 and
110
+ `TK Zenith` 5.7→2.78. The Zenith is the one large disagreement and it is not a
111
+ rounding difference: it fires bursts, and 2.78 is the rate the panel shows.
112
+ - **Reserve ammunition** is the panel's, correcting `Karma P-15` 120→240,
113
+ `Karma AR-50` 200→250, `TK Eclipse` 280→315 and `TK Zenith` 90→180. It is the reserve
114
+ a stock suit carries, before the Extra Ammo Capacity modification.
115
+ - **Magazine size, effective range, class, slot, damage type and headshot multiplier**
116
+ are unchanged: every one already matches the panel.
117
+ - **Damage** is the grade-1 figure read in-game, times the grade multiplier the game
118
+ applies to it — `1`, `1.31`, `1.73`, `2.27`, `2.98` for grades 1 to 5. Each product is
119
+ taken in double-precision floating point and rounded to three decimals, as
120
+ `Number(x.toFixed(3))` does it; that reproduces all 55 stored figures exactly. The
121
+ rounding rule has to be stated rather than assumed, because twelve products land on a
122
+ half and are therefore broken in both directions, and because scaling before rounding
123
+ (`Math.round(x * 1000) / 1000`) re-introduces error and misses eight of the 55.
124
+ - **The multipliers are what Odyssey Materials Helper's own figures follow.** On the four
125
+ weapons whose grade-1 damage needed no correction — `Karma L-6`,
126
+ `Manticore Executioner`, `Manticore Tormentor` and `Manticore Oppressor` — its grades 2
127
+ to 5 sit within 0.05 of the same progression on 15 of those 16 rows, which is half of
128
+ one decimal — the most a figure rounded to one decimal can move. The exception is `Karma L-6` grade 4: 90.8 here, and
129
+ 90 in that source alone.
130
+ - **Every weapon's damage therefore changes**, and by more than rounding wherever the
131
+ grade-1 figure itself had been rounded: `Karma C-44` 0.6→0.65, `Karma AR-50` 1→0.95,
132
+ `TK Eclipse` 0.9→0.85, `Karma P-15` 1.4→1.38, `TK Aphelion` 1.6→1.572, `TK Zenith`
133
+ 1.7→1.668 and `Manticore Intimidator` 1.8→1.75. Damage is stored at the precision the
134
+ game reports it, which is why two of those grade-1 figures carry three decimals where
135
+ the panel shows one.
136
+ - **`scopeMagnification` is new**: the aim-down-sights magnification the panel shows with
137
+ the sight the weapon ships with, and with the sight the Scope modification fits, both
138
+ to two decimals. Scope stores no modifier of its own because its magnitude is this
139
+ pair, and it differs per weapon — `Manticore Executioner` gains 1.61x→3.75x where
140
+ `Manticore Intimidator` gains 1.08x→1.25x.
141
+
142
+ ### Modification magnitudes
143
+
144
+ Each recipe carries `modifiers`, the stat multipliers it applies. A modification is
145
+ applied in one step and has no grade or quality roll, so a modifier is a single factor
146
+ rather than the `[min, max]` band a ship blueprint feature carries, and `1` — a factor
147
+ that changes nothing — is never stored.
148
+
149
+ - **Enhanced Tracking effectively removes the analysis delay** rather than shortening
150
+ it proportionally: its factor on `losAnalysisTime` is `0.001`, which takes the 1 second
151
+ every suit needs down to a thousandth of one. It is recorded as the factor it applies,
152
+ like every other modifier.
153
+ - **A resistance factor multiplies the damage taken**, not the stored resistance
154
+ fraction. Damage Resistance is `×0.9` on damage taken, so a `0.5` resistance becomes
155
+ `0.55`. This is the same convention the ships domain uses for resistances.
156
+ - **`roundUp` marks the one result the game rounds up**: Magazine Size multiplies by 1.5
157
+ and rounds the magazine up to a whole number, so 45 rounds become 68 rather than 67.5.
158
+ - **Six recipes name a stat no catalogue field carries**, because the panel shows no
159
+ base for it: the melee damage, sprint duration and tool energy drain multipliers, the
160
+ reload speed, and the pressurised and unpressurised firing audible ranges. The factor
161
+ is recorded against the stat it moves; the base has to come from the panel.
162
+ - **Ten recipes carry an empty modifier list**, for two different reasons, and both are
163
+ a statement rather than a gap:
164
+ - Night Vision, Scope, Stowed reloading and Combat Movement Speed apply no factor to
165
+ any stat. Night Vision and Stowed reloading switch a capability on, Scope's whole
166
+ numeric effect is the weapon's own `scopeMagnification`, and Combat Movement Speed
167
+ changes how a suit moves while aiming without moving a displayed stat.
168
+ - Faster Handling, Improved Hip Fire Accuracy, Stability and Improved Jump Assist do
169
+ change stats, but ones the panel puts no number on — weapon handling, hip-fire
170
+ jitter and recoil, and the jump assist's boost drain and recharge. Improved Jump
171
+ Assist notably leaves the panel's Jump Assist Boost Acceleration exactly where it
172
+ was, so recording it against that field would be wrong.
173
+ - **Extra Ammo Capacity multiplies a weapon's `reserveAmmo`**, which is why the reserve
174
+ stored on a weapon is the stock figure and not an engineered one.
@@ -1,7 +1,9 @@
1
1
  # Localized game-name catalogues
2
2
 
3
- These catalogues keep the canonical English display names already published by the
4
- ships data domain and add only localized values carried explicitly by accepted sources.
3
+ These catalogues keep the canonical English display names already published by the ships
4
+ and equipment data domains and add only localized values carried explicitly by accepted
5
+ sources. Where a catalogue holds display prose rather than a name, the owning domain
6
+ publishes no English for it and all six values are the source's own.
5
7
  They are deliberately sparse: absence means that no accepted source carried a value, and
6
8
  the lookup API returns `null` for that locale rather than treating English as a
7
9
  translation.
@@ -46,13 +48,12 @@ tag follows the rule above, so `pt-PT` resolves to Brazilian Portuguese.
46
48
  after that is not a name and is rejected.
47
49
  - **The `(Free)` vessel-hangar grants have no name of their own** — theirs is a
48
50
  template wrapping the base hangar's. Their canonical English is already the base
49
- module's, so they share its record, exactly as they did before.
50
- - **This table replaces the EDDI and EDSY joins the catalogue previously used**, and wins
51
- where they disagree, as in-game values do everywhere in this repository. It fills the
52
- 349 values those joins left empty and restyles 3,135 they carried, across 324 distinct
53
- record-and-locale pairs: 73 differ only in letter case, 10 only in punctuation or
54
- accents, and 241 in wording. Many of the last are the game being specific where the
55
- registries were general — Russian `Двигатели` becomes `Маневровые двигатели`, Brazilian
51
+ module's, so they share its record.
52
+ - **The in-game table is authoritative over the EDDI and EDSY joins.** It carries 349
53
+ values absent from those registries and differs from them in 3,135 cells across 324
54
+ distinct record-and-locale pairs: 73 differ only in letter case, 10 only in punctuation
55
+ or accents, and 241 in wording. Many of the last are the game being specific where the
56
+ registries are general Russian `Двигатели` is `Маневровые двигатели`, Brazilian
56
57
  Portuguese `Propulsores` becomes `Propulsores de desempenho melhorado`.
57
58
  - **The least abbreviated spelling is the one stored**, as it is in
58
59
  `material-names.jsonc`. The outfitting panel shortens a label that will not fit, and
@@ -121,10 +122,9 @@ tag follows the rule above, so `pt-PT` resolves to Brazilian Portuguese.
121
122
  - **Derivation:** each of the 86 current keys and its English name comes from
122
123
  `data/ships/experimental-effects.jsonc`, which stays authoritative for canonical
123
124
  English. The Frontier symbol joins to the in-game experimental-effect name table,
124
- which supplies every locale for all 86. The table replaces the EDSY join this
125
- catalogue previously used: where the two disagree the in-game value is kept, as
126
- everywhere else in this repository. It supplies six values EDSY did not carry — all
127
- five non-English `special_super_penetrator` names and the German
125
+ which supplies every locale for all 86. Where it and EDSY disagree, the in-game value
126
+ is kept, as everywhere else in this repository. It supplies six values EDSY does not
127
+ carry all five non-English `special_super_penetrator` names and the German
128
128
  `special_weapon_rateoffire` — and changes two EDSY already carried: German
129
129
  `special_regeneration_sequence` is "Regenerationssequenz" (EDSY
130
130
  "Regenerierungssequenz") and Brazilian Portuguese `special_lock_breaker` is "Quebra da
@@ -300,39 +300,188 @@ tag follows the rule above, so `pt-PT` resolves to Brazilian Portuguese.
300
300
  own localized name.
301
301
 
302
302
  Replace any of the twelve with a source-backed value the moment one is published.
303
- - **Coverage:** English covers every variant, and Brazilian Portuguese and Russian now do
304
- too. Ordinary names inherit the explicit localized values available for their base
303
+ - **Coverage:** English, Brazilian Portuguese and Russian cover every variant. Ordinary
304
+ names inherit the explicit localized values available for their base
305
305
  module; the Merc-shop names carry all six locales. The German, Spanish and French gaps
306
306
  that remain are their base modules' own — the SCO drive and the Enhanced AX
307
307
  Multi-Cannon carry no value in those locales for composition to build on.
308
308
  - **Manual corrections:** none.
309
309
 
310
+ ## `suit-names.jsonc`
311
+
312
+ - **Acquired:** 2026-09-01 UTC.
313
+ - **In-game localisation revision:** none published; the game ships no immutable
314
+ identifier for its localisation tables. The acquired table is the evidence.
315
+ - **Derivation:** the four suit families and their canonical English names come from
316
+ `data/equipment/suits.jsonc`, which stays authoritative for canonical English. Each
317
+ family's grade symbols join case-insensitively to the in-game suit localisation
318
+ identity, which carries a `name`, a `longname` and an `info` string per locale. The
319
+ join is exact and total: all 16 grade symbols resolve.
320
+ - **`name` is the value taken.** It is the suit's own name and equals the canonical
321
+ English on all four families.
322
+ - **The manufacturer is not part of the name.** `longname` prefixes one —
323
+ `Remlok Maverick Suit`, `Supratech Artemis Suit`, `Manticore Dominator Suit` — which
324
+ names a Pioneer Supplies listing rather than the suit, so it is rejected the way a
325
+ rendered capacity is in `module-names.jsonc`. The brand is a proper noun the game
326
+ leaves in English in every locale, so composing it back on costs nothing but the
327
+ name it would displace.
328
+ - **A suit is named per family, not per grade.** Every grade of a family carries
329
+ byte-identical values in all six locales, so one record is stored per family and
330
+ `nameKeys` maps the family id and every grade symbol onto it. Both forms a consumer
331
+ holds therefore resolve: `Suit.family` and the `utilitysuit_class3` a journal line
332
+ writes. The flight suit has a single grade whose symbol *is* the family id, so the four
333
+ families and 16 grade symbols make 19 distinct identifiers rather than 20.
334
+ - **Coverage:** complete. All 19 identifiers carry all six locales.
335
+ - **Two suits are not stored**, because `data/equipment/suits.jsonc` does not carry them:
336
+ the five `specialistsuit_class{1..5}` grades, which the source does name
337
+ (`Specialist Suit`, listed as `Remlok Paragon Specialist Suit`), and `hyperspacesuit`,
338
+ which carries no text at all. Storing a name for equipment no catalogue owns would
339
+ leave a lookup answering for something the library cannot otherwise describe.
340
+ - **Manual corrections:** none.
341
+
342
+ ## `suit-descriptions.jsonc`
343
+
344
+ - **Acquired:** 2026-09-01 UTC.
345
+ - **In-game localisation revision:** none published; the game ships no immutable
346
+ identifier for its localisation tables. The acquired table is the evidence.
347
+ - **Derivation:** the same four families and the same identifier set as
348
+ `suit-names.jsonc`, joined to the `info` string of the in-game suit localisation
349
+ identity. All six values, English included, are the source's verbatim: the owning
350
+ catalogue publishes no description for a suit, so there is no canonical English here
351
+ to be authoritative for.
352
+ - **This is display prose, not the suit's stats.** `data/equipment/suits.jsonc` answers
353
+ what a suit does — shield strength, battery capacity, the four resistances — and the
354
+ description answers what it is for, naming no figure at all. Neither is projected onto
355
+ the other.
356
+ - **Coverage:** complete. All 19 identifiers carry all six locales, and every grade of a
357
+ family shares its record exactly as in `suit-names.jsonc`.
358
+ - **The Specialist Suit grades carry no description at all**, which is a second reason
359
+ they are absent here beyond the owning catalogue not carrying them.
360
+ - **Manual corrections:** none. The English keeps the source's own mixed apostrophes
361
+ (`Manticore's`, `a user’s`); they are the game's prose and are stored as published.
362
+
363
+ ## `personal-weapon-descriptions.jsonc`
364
+
365
+ - **Acquired:** 2026-09-01 UTC.
366
+ - **In-game localisation revision:** none published; the game ships no immutable
367
+ identifier for its localisation tables. The acquired table is the evidence.
368
+ - **Derivation:** all 11 current weapon symbols come from `data/equipment/weapons.jsonc`.
369
+ Each joins case-insensitively to the in-game weapon localisation identity and takes its
370
+ `info` string; the join is exact and total. All six values, English included, are the
371
+ source's verbatim, because the owning catalogue publishes no weapon description.
372
+ - **No sibling name catalogue exists**, and that is a decision rather than a gap — see
373
+ §Names this repository deliberately does not localize.
374
+ - **Coverage:** complete. All 11 weapons carry all six locales.
375
+ - **Two entries the source carries are not stored:** `wpn_h_launcher_rocket_sauto`
376
+ (`Karma HL-9`), the heavy rocket launcher no current catalogue owns, and
377
+ `wpn_m_submachinegun_kinetic_burst`, which the table lists with no text at all.
378
+ - **Manual corrections:** none.
379
+
380
+ ## `personal-modification-names.jsonc`
381
+
382
+ - **Acquired:** 2026-09-01 UTC.
383
+ - **In-game localisation revision:** none published; the game ships no immutable
384
+ identifier for its localisation tables. The acquired table is the evidence.
385
+ - **Derivation:** all 31 recipe symbols and their canonical English names come from
386
+ `data/equipment/modifications.jsonc`, which stays authoritative for canonical English.
387
+ A symbol joins case-insensitively to the in-game modification identity as
388
+ `humanoidmod_<symbol>`, which carries a `name` and a `description` per locale.
389
+ - **The nine technology-specific recipes share the entry the game publishes.** Greater
390
+ Range, Headshot Damage and Improved Hip Fire Accuracy are one engineering option each
391
+ in game; this repository keys the Kinetic, Laser and Plasma recipes separately because
392
+ their material costs differ (§`data/equipment/SOURCES.md`). The `_kinetic`, `_laser`
393
+ and `_plasma` suffix is dropped before the join, so each of the three takes its generic
394
+ entry's locales — exactly as a shadowing blueprint id takes its generic's in
395
+ `blueprint-names.jsonc`. 25 distinct source entries therefore cover all 31 recipes, and
396
+ the catalogue stores them once each: `nameKeys` maps a recipe symbol onto the entry the
397
+ game publishes, as `module-names.jsonc` maps a module symbol onto a shared name.
398
+ - **That shape is about visibility, not bytes.** Storing each shared entry three times
399
+ instead costs about the same, because the six duplicate name records weigh roughly what
400
+ the 31-entry `nameKeys` map does; the descriptions save about a fifteenth. What the
401
+ deduplicated form buys is that the sharing is stated in the data, rather than sitting in
402
+ six duplicate records a later edit could silently pull apart.
403
+ - **`Headshot Damage` is the one English value the game spells differently.** The in-game
404
+ menu reads `Headshot damage`; the owning catalogue's canonical `Headshot Damage` is
405
+ kept, as canonical English is kept everywhere in this directory. The lower-case
406
+ `Stowed reloading` the owning catalogue already carries *is* the game's own spelling
407
+ and agrees with it.
408
+ - **Coverage:** complete. All 31 recipes carry all six locales.
409
+ - **One in-game modification is not stored:** `humanoidmod_suit_headshotresistance`
410
+ (`Increased Helmet Protection`), which `data/equipment/modifications.jsonc` does not
411
+ carry as a recipe.
412
+ - **Manual corrections:** two German names are the engineering panel's own layout rather
413
+ than translations. `Kampf-Bewegungs-geschwindigkeit` and `Geräusch-unterdrückung` break
414
+ a compound word mid-noun, leaving a lower-case second half no German spelling has. The
415
+ whole word is kept in each, as it is for the wrapped consumables in
416
+ `micro-resource-names.jsonc`: `Kampfbewegungsgeschwindigkeit` and
417
+ `Geräuschunterdrückung`.
418
+
419
+ ## `personal-modification-descriptions.jsonc`
420
+
421
+ - **Acquired:** 2026-09-01 UTC.
422
+ - **In-game localisation revision:** none published; the game ships no immutable
423
+ identifier for its localisation tables. The acquired table is the evidence.
424
+ - **Derivation:** the same 31 recipe symbols as `personal-modification-names.jsonc`,
425
+ joined the same way and sharing the generic entry across the nine technology-specific
426
+ recipes for the same reason. Each takes the identity's `description` string. All six
427
+ values, English included, are the source's verbatim.
428
+ - **This is display prose, not the recipe's magnitudes.** The game says a modification
429
+ "allows more ammo to be carried for each weapon" and never how much more; the
430
+ `modifiers` list in `data/equipment/modifications.jsonc` is what states the multiplier,
431
+ and the two are deliberately different strings. It is also the only account of the ten
432
+ recipes whose `modifiers` list is empty — some switch a capability on, the rest move a
433
+ stat the panel puts no number on (§`data/equipment/SOURCES.md`).
434
+ - **Coverage:** complete. All 31 recipes carry all six locales.
435
+ - **Manual corrections:** none. The French
436
+ `weapon_backpackreloading` description keeps the non-breaking space the source sets
437
+ between a figure and its unit (`5 secondes`), which is French typography rather than
438
+ layout.
439
+
310
440
  ## Names this repository deliberately does not localize
311
441
 
312
- Three catalogues were removed rather than completed, because the game does not translate
313
- what they held and storing English under five more keys said otherwise.
442
+ No catalogues are stored for the following names, either because the game does not
443
+ translate them storing English under five more keys would say otherwise — or because no
444
+ record in this repository is keyed by them.
314
445
 
315
446
  - **Ship names and manufacturers.** Odyssey Materials Helper and EDSY each publish a
316
447
  per-locale ship column, and every value either one publishes is byte-for-byte the
317
448
  canonical English name: a hull name is a proper noun the game leaves alone, and so is
318
- a manufacturer's. No source publishes a localized manufacturer label at all. A lookup
319
- that can only ever answer in English is not a translation lookup, so `getShipName` and
320
- `getShipManufacturer` are gone; `data/ships/ships.jsonc` carries both strings and stays
321
- the one place to read them.
449
+ a manufacturer's. No source publishes a localized manufacturer label at all.
450
+ `data/ships/ships.jsonc` is the one place to read both strings.
322
451
  - **Engineering-group labels.** An engineering group is this repository's own partition
323
452
  of the modules that share one menu; the game heads that menu with the module's
324
- outfitting family and publishes no group label of its own. The EDSY `mtype-*` values
325
- previously stored here were outfitting labels reached by a name join, which is why they
326
- disagreed with `module-family-names.jsonc` in 22 places on wording. A group therefore
453
+ outfitting family and publishes no group label of its own. EDSY's `mtype-*` values are
454
+ outfitting labels reached by a name join and disagree with
455
+ `module-family-names.jsonc` in 22 places on wording. A group therefore
327
456
  carries no name at all — see the header of `data/ships/engineering-options.jsonc` — and
328
457
  a consumer names one by joining a module's `familyId` to `module-family-names.jsonc`.
458
+ - **Handheld personal-weapon names.** The in-game weapon localisation table publishes all
459
+ six locales for every one of the eleven weapons, and each of the 55 non-English values
460
+ is byte-for-byte the English: `Karma P-15`, `TK Aphelion` and `Manticore Executioner`
461
+ are product names the game leaves alone, exactly as it does a hull's. `PersonalWeapon`
462
+ in `data/equipment/weapons.jsonc` is the one place to read the name; the weapons'
463
+ *descriptions* are prose and are localized, in `personal-weapon-descriptions.jsonc`.
464
+ - **Personal-equipment manufacturers.** `Supratech`, `Remlok`, `Manticore` and
465
+ `Kinematic Armaments` are byte-for-byte identical in all six locales wherever the game
466
+ names them, which is why `suit-names.jsonc` stores a suit's own name and not the
467
+ outfitting list's manufacturer-prefixed listing.
468
+ - **Suit and weapon stat labels, the on-foot loadout panel's row labels, and engineer
469
+ dialogue.** These are the second reason rather than the first: the game does publish all
470
+ six locales for each, and none of them names a record in any catalogue here. A stat
471
+ label names a field of `Suit` or `PersonalWeapon`, a row label names a line of the
472
+ on-foot loadout panel, and an engineer's line is spoken flavour attached to an offer.
473
+ Storing them would mean inventing keys this repository does not otherwise own, so a
474
+ consumer that needs a field label supplies its own. **This is not the ship slot and
475
+ restriction gap of [#320](https://github.com/DarkSession/Elite-Dangerous-Almanac/issues/320)**,
476
+ which is about labels no source translates at all.
329
477
 
330
478
  ## Known gaps
331
479
 
332
480
  Localized coverage follows the accepted sources and is not complete for every catalogue or
333
- stored locale. A language absent from all eight catalogues is the locale decision
481
+ stored locale. A language absent from all thirteen catalogues is the locale decision
334
482
  recorded above rather than a gap. The accepted sources carry only canonical English for
335
483
  19 of the 77 outfitting-family labels, slot and restriction labels, fixed reward names,
336
- and structured loadout, calculation, SLEF and edit messages. Missing source-backed
337
- translations remain tracked by
484
+ and structured loadout, calculation, SLEF and edit messages. Personal equipment carries
485
+ no gap: every suit, handheld weapon and modification the owning catalogues hold is
486
+ complete in all six locales. Missing source-backed translations remain tracked by
338
487
  [#320](https://github.com/DarkSession/Elite-Dangerous-Almanac/issues/320).
@@ -489,8 +489,7 @@ FDevIDs, stats from coriolis-data and EDSY, joined on `symbol`.
489
489
  `Manifest Scanners`, `Torpedo Pylons` is `Torpedoes` and `Mine Launchers` is `Mines`.
490
490
  The remaining 19 keep the Almanac's own descriptive name, because the outfitting
491
491
  screen does not name them separately. Each id is the camelCase form of its English
492
- name with punctuation removed, which `modules.test.ts` asserts, so an id and its
493
- label cannot drift apart.
492
+ name with punctuation removed.
494
493
  - **Merged families.** Where the game lists several Almanac families under one category,
495
494
  they are one family here: the operations, rescue, universal and xeno multi-limpet
496
495
  controllers are `multiLimpetControllers`; mining volley repeaters and seismic charge
@@ -856,8 +855,7 @@ damage for the small 1D cannon and **38.5** for the medium 2B cannon. Those read
856
855
  settle the registry disagreement in favour of coriolis-data's 22 / 38.5 rather than
857
856
  EDSY's 40 / 70. The catalogue stores the displayed values without further derivation and
858
857
  applies the same correction to their exact thermal and anti-xeno components. The two
859
- records are pinned in `fixtures/ships/module-stats.jsonc`. A panel reading has no upstream
860
- immutable revision.
858
+ panel readings have no upstream immutable revision.
861
859
 
862
860
  **Values that look wrong and are not.** Three records break the pattern their family
863
861
  follows and are confirmed outright by EDSY. Recorded so the "breaks its family's curve"
@@ -951,8 +949,8 @@ and bulkhead name because those records carry no symbol upstream.
951
949
  where both registries publish a multiple of 10 still differ by 10
952
950
  (`Int_FighterBay_Size{6,7}_Class1`, `Int_PassengerCabin_Size6_Class1`), which no
953
951
  rounding explains: whatever the real price is, at least one of the two registries is
954
- wrong about it by five credits or more, and neither says which. Two of the three are
955
- now settled by in-game readings, and coriolis is exactly right in both:
952
+ wrong about it by five credits or more, and neither says which. In-game readings
953
+ settle two of the three, with coriolis exactly right in both:
956
954
  `Int_FighterBay_Size7_Class1` is 2 369 320 and `Int_FighterBay_Size6_Class1` is
957
955
  1 869 340, so EDSY's 2 369 330 is the wrong member of that pair (see "Prices read from
958
956
  an in-game purchase capture" below). So treat 12 560 as
@@ -1073,7 +1071,7 @@ and size-6 racks): here the discount is stated rather than solved for.
1073
1071
  - **The size-8 SCO drives are priced identically to their size-7 siblings.** All four
1074
1072
  distinct readings land exactly on coriolis's size-7 figures (6 838 548, 20 515 645,
1075
1073
  61 546 935), and EDSY's size-8 numbers are those same figures rounded to 10. The
1076
- catalogue previously carried the EDSY rounding; it now carries the readings.
1074
+ catalogue carries the exact readings rather than EDSY's rounded figures.
1077
1075
  - **A known residual.** `Int_CorrosionProofCargoRack_Size4_Class1` at 94 330 predicts
1078
1076
  82 775 under this rule where `journal-the-deep-black.jsonc` reads **82 774**. It is one
1079
1077
  of a minority of records whose catalogue list price appears to sit a credit or two above
@@ -1234,9 +1232,8 @@ Records not in coriolis-data / FDevIDs at the acquired revisions:
1234
1232
  modules checked numerically, and "every FSD field 72/72" — figures that could not have
1235
1233
  been true of five records the game does not offer. The corrected accounting is 1188
1236
1234
  identity matches, 947 non-armour modules and 67/67 FSD fields, with
1237
- `registryOnlyIdentities` unchanged at 6; `fixtures/ships/module-stats.jsonc` carries
1238
- the same numbers. This is a manual correction to previously published provenance, not
1239
- a re-derivation from a new capture.
1235
+ `registryOnlyIdentities` at 6. Those are the standing audit figures; the source
1236
+ capture itself has not changed.
1240
1237
  - **1B Shield Generator** (`Int_ShieldGenerator_Size1_Class4`) — a gap in FDevIDs, not
1241
1238
  in the game: every other shield-generator size carries all five ratings, and size 1
1242
1239
  ran E/D/C/A with **B missing**. The module is real, so the record is carried with the
@@ -1638,9 +1635,9 @@ up straight through with no disambiguation at all. Both paths are evidence that
1638
1635
  `blueprints` and `experimentals` it offers.
1639
1636
  - **A group carries no display name.** The grouping is this repository's own partition of
1640
1637
  the modules sharing one menu; the game publishes no engineering-group label, heading
1641
- each menu with the module's outfitting family instead. EDSY's `mtype-*` strings, which
1642
- this file previously stored as group names, are outfitting labels reached by a name
1643
- join — which is why they disagreed with `module-families.jsonc` in 22 places on wording
1638
+ each menu with the module's outfitting family instead. EDSY's `mtype-*` strings are
1639
+ outfitting labels reached by a name join and disagree with `module-families.jsonc` in
1640
+ 22 places on wording
1644
1641
  (`cannons` Russian "Пушки" against the family's "Орудия", `moduleReinforcements`
1645
1642
  Brazilian Portuguese title case against the family's sentence case). Consumers name a
1646
1643
  group by joining a module's `familyId` to `module-families.jsonc`. The two partitions
@@ -1919,11 +1916,6 @@ whose thermal-cascade tech-broker row is a Seeker Missile Rack V1 while its thre
1919
1916
  community-goal rows are plain. Two tech-broker rows carry no marker at all and keep their
1920
1917
  base module's name: the Mining Laser and the size-5 Frame Shift Drive.
1921
1918
 
1922
- This repository's own fixtures already described several of these under the corrected
1923
- names — `pre-engineered.jsonc` calls one row "the tech-broker 'Modified Guardian Shard
1924
- Cannon'" and another "a V1 FSD" — while `name` carried the plain module's. The data now
1925
- agrees with the prose.
1926
-
1927
1919
  ### Festive variants
1928
1920
 
1929
1921
  - **File:** `pre-engineered.jsonc`. Three grade-5 records pair
package/README.md CHANGED
@@ -141,11 +141,12 @@ data-free leaf modules under `ships/jump-range`, `ships/power`, `ships/shields`,
141
141
 
142
142
  `build.validation()` reports validity and operational completeness. `cargoCapacity`,
143
143
  `passengerCapacity`, `fuelCapacity` and `unladenMass` always have an answer, because no
144
- article the catalogue cannot weigh reaches a build; the eight metrics that depend on
145
- build state (`mobilityMetrics`, `mobilityCapacitorMetrics`, `shieldMetrics`,
146
- `shieldCapacitorMetrics`, `shieldRecovery`, `heatMetrics`, `distributorMetrics` and
147
- `standardLoad`) are nullable and each has a `…Result` counterpart naming what is
148
- missing, switched off, shed or unpowered. `parseSlef`
144
+ article the catalogue cannot weigh reaches a build. The eight build-state methods
145
+ (`mobilityMetricsResult`, `mobilityCapacitorMetricsResult`, `shieldMetricsResult`,
146
+ `shieldCapacitorMetricsResult`, `shieldRecoveryResult`, `heatMetricsResult`,
147
+ `distributorMetricsResult` and `standardLoadResult`) return a diagnostic result whose
148
+ value is either complete or `null`, with issues naming what is missing, unresolved,
149
+ switched off, shed or invalid. `parseSlef`
149
150
  is strict; `inspectSlef` is the tolerant importer for mixed files and returns indexed
150
151
  diagnostics instead of silently dropping entries.
151
152
 
@@ -172,16 +173,30 @@ import {
172
173
  getMicroResourceName,
173
174
  getModuleName,
174
175
  getOutfittingFamilyName,
176
+ getPersonalModificationName,
177
+ getSuitName,
175
178
  } from '@elite-dangerous-almanac/core/i18n';
176
179
 
177
180
  getModuleName('Int_Hyperdrive_Size6_Class5', 'de-DE'); // -> "Frameshiftantrieb"
178
181
  getBlueprintName('FSD_LongRange', 'fr-FR'); // -> "Portée FSD améliorée"
179
182
  getMaterialName('GridResistors', 'de'); // -> "Gitterwiderstände"
180
183
  getMicroResourceName('graphene', 'fr'); // -> "Graphène"
184
+ getSuitName('explorationsuit_class3', 'de'); // -> "Artemis-Anzug"
185
+ getPersonalModificationName('suit_nightvision', 'fr'); // -> "Vision nocturne"
181
186
  getOutfittingFamilyName('shieldGenerators', 'de'); // -> "Schildgeneratoren"
182
187
  getOutfittingFamilyName('xenoScanners', 'de'); // -> null
183
188
  ```
184
189
 
190
+ Display prose the game shows a player — a suit's or a handheld weapon's blurb, what an
191
+ experimental effect or an engineer's modification does — has its own lookups in the same
192
+ `i18n` area, each on its own subpath, complete in all six locales:
193
+
194
+ ```ts
195
+ import { getSuitDescription } from '@elite-dangerous-almanac/core/i18n/suits';
196
+
197
+ getSuitDescription('utilitysuit', 'en')?.slice(0, 20); // -> "The Maverick suit is"
198
+ ```
199
+
185
200
  The functions return an explicit source value verbatim, so a source-backed spelling may
186
201
  happen to equal English; the library itself never supplies an English fallback. The
187
202
  catalogues carry English, French, German, Portuguese, Russian and Spanish, each stored
@@ -161,7 +161,10 @@ a verbatim copy produced at build time — edit this file, never the copy.
161
161
  with its [announcement](https://x.com/EliteDangerous/status/1812792503776489745).
162
162
  Frontier's own **in-game localisation** supplies the outfitting category labels behind
163
163
  the module families and their German, Spanish, French, Brazilian Portuguese and Russian
164
- display text, and the engineering modification names in the six stored locales.
164
+ display text, the engineering modification names in the six stored locales, and the
165
+ personal-equipment display text in `data/i18n/`: the suit names and descriptions, the
166
+ handheld-weapon descriptions, and the names and descriptions of the engineer-applied
167
+ suit and weapon modifications.
165
168
  Values read directly from the running game are Frontier's too — see the notice below.
166
169
  - **A [community description](https://www.reddit.com/r/EliteDangerous/comments/1uk2zhp/plasma_laser_theorycrafting_following_new/)
167
170
  by u/Techno3020** — linked only as corroboration that the Operations Plasma conversion's