@alpaca-software/40kdc-data 0.1.1 → 0.1.3
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/README.md +2 -0
- package/dist/abilities-resolver/index.d.ts +9 -0
- package/dist/abilities-resolver/index.d.ts.map +1 -0
- package/dist/abilities-resolver/index.js +9 -0
- package/dist/abilities-resolver/index.js.map +1 -0
- package/dist/abilities-resolver/resolver.d.ts +73 -0
- package/dist/abilities-resolver/resolver.d.ts.map +1 -0
- package/dist/abilities-resolver/resolver.js +142 -0
- package/dist/abilities-resolver/resolver.js.map +1 -0
- package/dist/audit-coverage.d.ts +78 -0
- package/dist/audit-coverage.d.ts.map +1 -0
- package/dist/audit-coverage.js +341 -0
- package/dist/audit-coverage.js.map +1 -0
- package/dist/author-batch.d.ts +147 -0
- package/dist/author-batch.d.ts.map +1 -0
- package/dist/author-batch.js +675 -0
- package/dist/author-batch.js.map +1 -0
- package/dist/author-input.d.ts +37 -0
- package/dist/author-input.d.ts.map +1 -0
- package/dist/author-input.js +162 -0
- package/dist/author-input.js.map +1 -0
- package/dist/bundle-schemas.d.ts +1 -0
- package/dist/bundle-schemas.d.ts.map +1 -0
- package/dist/bundle-schemas.js +1 -0
- package/dist/bundle-schemas.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -0
- package/dist/codegen-data.d.ts +1 -0
- package/dist/codegen-data.d.ts.map +1 -0
- package/dist/codegen-data.js +2 -0
- package/dist/codegen-data.js.map +1 -0
- package/dist/commands/import.d.ts +1 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +1 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/translate.d.ts +1 -0
- package/dist/commands/translate.d.ts.map +1 -0
- package/dist/commands/translate.js +10 -4
- package/dist/commands/translate.js.map +1 -0
- package/dist/commands/validate-all.d.ts +1 -0
- package/dist/commands/validate-all.d.ts.map +1 -0
- package/dist/commands/validate-all.js +1 -0
- package/dist/commands/validate-all.js.map +1 -0
- package/dist/commands/validate-core.d.ts +1 -0
- package/dist/commands/validate-core.d.ts.map +1 -0
- package/dist/commands/validate-core.js +1 -0
- package/dist/commands/validate-core.js.map +1 -0
- package/dist/commands/validate-enrichment.d.ts +1 -0
- package/dist/commands/validate-enrichment.d.ts.map +1 -0
- package/dist/commands/validate-enrichment.js +1 -0
- package/dist/commands/validate-enrichment.js.map +1 -0
- package/dist/convert-faction.d.ts +1 -0
- package/dist/convert-faction.d.ts.map +1 -0
- package/dist/convert-faction.js +1 -0
- package/dist/convert-faction.js.map +1 -0
- package/dist/converters/configs/adepta-sororitas.d.ts +1 -0
- package/dist/converters/configs/adepta-sororitas.d.ts.map +1 -0
- package/dist/converters/configs/adepta-sororitas.js +1 -0
- package/dist/converters/configs/adepta-sororitas.js.map +1 -0
- package/dist/converters/configs/adeptus-astartes.d.ts +1 -0
- package/dist/converters/configs/adeptus-astartes.d.ts.map +1 -0
- package/dist/converters/configs/adeptus-astartes.js +1 -0
- package/dist/converters/configs/adeptus-astartes.js.map +1 -0
- package/dist/converters/configs/adeptus-custodes.d.ts +1 -0
- package/dist/converters/configs/adeptus-custodes.d.ts.map +1 -0
- package/dist/converters/configs/adeptus-custodes.js +1 -0
- package/dist/converters/configs/adeptus-custodes.js.map +1 -0
- package/dist/converters/configs/adeptus-mechanicus.d.ts +1 -0
- package/dist/converters/configs/adeptus-mechanicus.d.ts.map +1 -0
- package/dist/converters/configs/adeptus-mechanicus.js +1 -0
- package/dist/converters/configs/adeptus-mechanicus.js.map +1 -0
- package/dist/converters/configs/aeldari.d.ts +1 -0
- package/dist/converters/configs/aeldari.d.ts.map +1 -0
- package/dist/converters/configs/aeldari.js +1 -0
- package/dist/converters/configs/aeldari.js.map +1 -0
- package/dist/converters/configs/agents-of-the-imperium.d.ts +1 -0
- package/dist/converters/configs/agents-of-the-imperium.d.ts.map +1 -0
- package/dist/converters/configs/agents-of-the-imperium.js +1 -0
- package/dist/converters/configs/agents-of-the-imperium.js.map +1 -0
- package/dist/converters/configs/astra-militarum.d.ts +1 -0
- package/dist/converters/configs/astra-militarum.d.ts.map +1 -0
- package/dist/converters/configs/astra-militarum.js +1 -0
- package/dist/converters/configs/astra-militarum.js.map +1 -0
- package/dist/converters/configs/black-templars.d.ts +1 -0
- package/dist/converters/configs/black-templars.d.ts.map +1 -0
- package/dist/converters/configs/black-templars.js +1 -0
- package/dist/converters/configs/black-templars.js.map +1 -0
- package/dist/converters/configs/blood-angels.d.ts +1 -0
- package/dist/converters/configs/blood-angels.d.ts.map +1 -0
- package/dist/converters/configs/blood-angels.js +1 -0
- package/dist/converters/configs/blood-angels.js.map +1 -0
- package/dist/converters/configs/chaos-daemons.d.ts +1 -0
- package/dist/converters/configs/chaos-daemons.d.ts.map +1 -0
- package/dist/converters/configs/chaos-daemons.js +1 -0
- package/dist/converters/configs/chaos-daemons.js.map +1 -0
- package/dist/converters/configs/chaos-knights.d.ts +1 -0
- package/dist/converters/configs/chaos-knights.d.ts.map +1 -0
- package/dist/converters/configs/chaos-knights.js +1 -0
- package/dist/converters/configs/chaos-knights.js.map +1 -0
- package/dist/converters/configs/chaos-space-marines.d.ts +1 -0
- package/dist/converters/configs/chaos-space-marines.d.ts.map +1 -0
- package/dist/converters/configs/chaos-space-marines.js +1 -0
- package/dist/converters/configs/chaos-space-marines.js.map +1 -0
- package/dist/converters/configs/crimson-fists.d.ts +1 -0
- package/dist/converters/configs/crimson-fists.d.ts.map +1 -0
- package/dist/converters/configs/crimson-fists.js +1 -0
- package/dist/converters/configs/crimson-fists.js.map +1 -0
- package/dist/converters/configs/dark-angels.d.ts +1 -0
- package/dist/converters/configs/dark-angels.d.ts.map +1 -0
- package/dist/converters/configs/dark-angels.js +1 -0
- package/dist/converters/configs/dark-angels.js.map +1 -0
- package/dist/converters/configs/death-guard.d.ts +1 -0
- package/dist/converters/configs/death-guard.d.ts.map +1 -0
- package/dist/converters/configs/death-guard.js +1 -0
- package/dist/converters/configs/death-guard.js.map +1 -0
- package/dist/converters/configs/deathwatch.d.ts +1 -0
- package/dist/converters/configs/deathwatch.d.ts.map +1 -0
- package/dist/converters/configs/deathwatch.js +1 -0
- package/dist/converters/configs/deathwatch.js.map +1 -0
- package/dist/converters/configs/drukhari.d.ts +1 -0
- package/dist/converters/configs/drukhari.d.ts.map +1 -0
- package/dist/converters/configs/drukhari.js +1 -0
- package/dist/converters/configs/drukhari.js.map +1 -0
- package/dist/converters/configs/emperors-children.d.ts +1 -0
- package/dist/converters/configs/emperors-children.d.ts.map +1 -0
- package/dist/converters/configs/emperors-children.js +1 -0
- package/dist/converters/configs/emperors-children.js.map +1 -0
- package/dist/converters/configs/genestealer-cults.d.ts +1 -0
- package/dist/converters/configs/genestealer-cults.d.ts.map +1 -0
- package/dist/converters/configs/genestealer-cults.js +1 -0
- package/dist/converters/configs/genestealer-cults.js.map +1 -0
- package/dist/converters/configs/grey-knights.d.ts +1 -0
- package/dist/converters/configs/grey-knights.d.ts.map +1 -0
- package/dist/converters/configs/grey-knights.js +1 -0
- package/dist/converters/configs/grey-knights.js.map +1 -0
- package/dist/converters/configs/imperial-fists.d.ts +1 -0
- package/dist/converters/configs/imperial-fists.d.ts.map +1 -0
- package/dist/converters/configs/imperial-fists.js +1 -0
- package/dist/converters/configs/imperial-fists.js.map +1 -0
- package/dist/converters/configs/imperial-knights.d.ts +1 -0
- package/dist/converters/configs/imperial-knights.d.ts.map +1 -0
- package/dist/converters/configs/imperial-knights.js +1 -0
- package/dist/converters/configs/imperial-knights.js.map +1 -0
- package/dist/converters/configs/iron-hands.d.ts +1 -0
- package/dist/converters/configs/iron-hands.d.ts.map +1 -0
- package/dist/converters/configs/iron-hands.js +1 -0
- package/dist/converters/configs/iron-hands.js.map +1 -0
- package/dist/converters/configs/leagues-of-votann.d.ts +1 -0
- package/dist/converters/configs/leagues-of-votann.d.ts.map +1 -0
- package/dist/converters/configs/leagues-of-votann.js +1 -0
- package/dist/converters/configs/leagues-of-votann.js.map +1 -0
- package/dist/converters/configs/necrons.d.ts +1 -0
- package/dist/converters/configs/necrons.d.ts.map +1 -0
- package/dist/converters/configs/necrons.js +1 -0
- package/dist/converters/configs/necrons.js.map +1 -0
- package/dist/converters/configs/orks.d.ts +1 -0
- package/dist/converters/configs/orks.d.ts.map +1 -0
- package/dist/converters/configs/orks.js +1 -0
- package/dist/converters/configs/orks.js.map +1 -0
- package/dist/converters/configs/raven-guard.d.ts +1 -0
- package/dist/converters/configs/raven-guard.d.ts.map +1 -0
- package/dist/converters/configs/raven-guard.js +1 -0
- package/dist/converters/configs/raven-guard.js.map +1 -0
- package/dist/converters/configs/salamanders.d.ts +1 -0
- package/dist/converters/configs/salamanders.d.ts.map +1 -0
- package/dist/converters/configs/salamanders.js +1 -0
- package/dist/converters/configs/salamanders.js.map +1 -0
- package/dist/converters/configs/space-wolves.d.ts +1 -0
- package/dist/converters/configs/space-wolves.d.ts.map +1 -0
- package/dist/converters/configs/space-wolves.js +1 -0
- package/dist/converters/configs/space-wolves.js.map +1 -0
- package/dist/converters/configs/tau-empire.d.ts +1 -0
- package/dist/converters/configs/tau-empire.d.ts.map +1 -0
- package/dist/converters/configs/tau-empire.js +1 -0
- package/dist/converters/configs/tau-empire.js.map +1 -0
- package/dist/converters/configs/thousand-sons.d.ts +1 -0
- package/dist/converters/configs/thousand-sons.d.ts.map +1 -0
- package/dist/converters/configs/thousand-sons.js +1 -0
- package/dist/converters/configs/thousand-sons.js.map +1 -0
- package/dist/converters/configs/tyranids.d.ts +1 -0
- package/dist/converters/configs/tyranids.d.ts.map +1 -0
- package/dist/converters/configs/tyranids.js +1 -0
- package/dist/converters/configs/tyranids.js.map +1 -0
- package/dist/converters/configs/ultramarines.d.ts +1 -0
- package/dist/converters/configs/ultramarines.d.ts.map +1 -0
- package/dist/converters/configs/ultramarines.js +1 -0
- package/dist/converters/configs/ultramarines.js.map +1 -0
- package/dist/converters/configs/white-scars.d.ts +1 -0
- package/dist/converters/configs/white-scars.d.ts.map +1 -0
- package/dist/converters/configs/white-scars.js +1 -0
- package/dist/converters/configs/white-scars.js.map +1 -0
- package/dist/converters/configs/world-eaters.d.ts +1 -0
- package/dist/converters/configs/world-eaters.d.ts.map +1 -0
- package/dist/converters/configs/world-eaters.js +1 -0
- package/dist/converters/configs/world-eaters.js.map +1 -0
- package/dist/converters/faction-config.d.ts +1 -0
- package/dist/converters/faction-config.d.ts.map +1 -0
- package/dist/converters/faction-config.js +1 -0
- package/dist/converters/faction-config.js.map +1 -0
- package/dist/converters/id-generator.d.ts +1 -0
- package/dist/converters/id-generator.d.ts.map +1 -0
- package/dist/converters/id-generator.js +1 -0
- package/dist/converters/id-generator.js.map +1 -0
- package/dist/converters/keyword-filter.d.ts +1 -0
- package/dist/converters/keyword-filter.d.ts.map +1 -0
- package/dist/converters/keyword-filter.js +1 -0
- package/dist/converters/keyword-filter.js.map +1 -0
- package/dist/converters/stat-parser.d.ts +1 -0
- package/dist/converters/stat-parser.d.ts.map +1 -0
- package/dist/converters/stat-parser.js +1 -0
- package/dist/converters/stat-parser.js.map +1 -0
- package/dist/converters/view-selector.d.ts +1 -0
- package/dist/converters/view-selector.d.ts.map +1 -0
- package/dist/converters/view-selector.js +1 -0
- package/dist/converters/view-selector.js.map +1 -0
- package/dist/converters/weapon-dedup.d.ts +1 -0
- package/dist/converters/weapon-dedup.d.ts.map +1 -0
- package/dist/converters/weapon-dedup.js +1 -0
- package/dist/converters/weapon-dedup.js.map +1 -0
- package/dist/cruncher/attribution.d.ts +66 -0
- package/dist/cruncher/attribution.d.ts.map +1 -0
- package/dist/cruncher/attribution.js +88 -0
- package/dist/cruncher/attribution.js.map +1 -0
- package/dist/cruncher/buffs.d.ts +206 -0
- package/dist/cruncher/buffs.d.ts.map +1 -0
- package/dist/cruncher/buffs.js +150 -0
- package/dist/cruncher/buffs.js.map +1 -0
- package/dist/cruncher/engine.d.ts +50 -0
- package/dist/cruncher/engine.d.ts.map +1 -0
- package/dist/cruncher/engine.js +312 -0
- package/dist/cruncher/engine.js.map +1 -0
- package/dist/cruncher/from-dsl.d.ts +101 -0
- package/dist/cruncher/from-dsl.d.ts.map +1 -0
- package/dist/cruncher/from-dsl.js +968 -0
- package/dist/cruncher/from-dsl.js.map +1 -0
- package/dist/cruncher/from-keyword.d.ts +35 -0
- package/dist/cruncher/from-keyword.d.ts.map +1 -0
- package/dist/cruncher/from-keyword.js +159 -0
- package/dist/cruncher/from-keyword.js.map +1 -0
- package/dist/cruncher/get-buffs.d.ts +12 -0
- package/dist/cruncher/get-buffs.d.ts.map +1 -0
- package/dist/cruncher/get-buffs.js +7 -0
- package/dist/cruncher/get-buffs.js.map +1 -0
- package/dist/cruncher/index.d.ts +12 -0
- package/dist/cruncher/index.d.ts.map +1 -0
- package/dist/cruncher/index.js +12 -0
- package/dist/cruncher/index.js.map +1 -0
- package/dist/data/bundle.generated.d.ts +1 -0
- package/dist/data/bundle.generated.d.ts.map +1 -0
- package/dist/data/bundle.generated.js +2 -1
- package/dist/data/bundle.generated.js.map +1 -0
- package/dist/data/collection.d.ts +10 -0
- package/dist/data/collection.d.ts.map +1 -0
- package/dist/data/collection.js +15 -0
- package/dist/data/collection.js.map +1 -0
- package/dist/data/dataset.d.ts +132 -2
- package/dist/data/dataset.d.ts.map +1 -0
- package/dist/data/dataset.js +248 -1
- package/dist/data/dataset.js.map +1 -0
- package/dist/data/entities.d.ts +67 -2
- package/dist/data/entities.d.ts.map +1 -0
- package/dist/data/entities.js +122 -0
- package/dist/data/entities.js.map +1 -0
- package/dist/data/index.d.ts +10 -1
- package/dist/data/index.d.ts.map +1 -0
- package/dist/data/index.js +14 -1
- package/dist/data/index.js.map +1 -0
- package/dist/data/normalize.d.ts +1 -0
- package/dist/data/normalize.d.ts.map +1 -0
- package/dist/data/normalize.js +1 -0
- package/dist/data/normalize.js.map +1 -0
- package/dist/data/roster-resolve.d.ts +58 -0
- package/dist/data/roster-resolve.d.ts.map +1 -0
- package/dist/data/roster-resolve.js +82 -0
- package/dist/data/roster-resolve.js.map +1 -0
- package/dist/data/types.d.ts +4 -1
- package/dist/data/types.d.ts.map +1 -0
- package/dist/data/types.js +2 -0
- package/dist/data/types.js.map +1 -0
- package/dist/export/helpers.d.ts +33 -0
- package/dist/export/helpers.d.ts.map +1 -0
- package/dist/export/helpers.js +57 -0
- package/dist/export/helpers.js.map +1 -0
- package/dist/export/index.d.ts +22 -0
- package/dist/export/index.d.ts.map +1 -0
- package/dist/export/index.js +28 -0
- package/dist/export/index.js.map +1 -0
- package/dist/export/newrecruit-json.d.ts +3 -0
- package/dist/export/newrecruit-json.d.ts.map +1 -0
- package/dist/export/newrecruit-json.js +140 -0
- package/dist/export/newrecruit-json.js.map +1 -0
- package/dist/export/newrecruit-simple.d.ts +3 -0
- package/dist/export/newrecruit-simple.d.ts.map +1 -0
- package/dist/export/newrecruit-simple.js +76 -0
- package/dist/export/newrecruit-simple.js.map +1 -0
- package/dist/export/newrecruit-wtc.d.ts +4 -0
- package/dist/export/newrecruit-wtc.d.ts.map +1 -0
- package/dist/export/newrecruit-wtc.js +142 -0
- package/dist/export/newrecruit-wtc.js.map +1 -0
- package/dist/export/roster-json.d.ts +3 -0
- package/dist/export/roster-json.d.ts.map +1 -0
- package/dist/export/roster-json.js +8 -0
- package/dist/export/roster-json.js.map +1 -0
- package/dist/export/rosterizer.d.ts +3 -0
- package/dist/export/rosterizer.d.ts.map +1 -0
- package/dist/export/rosterizer.js +144 -0
- package/dist/export/rosterizer.js.map +1 -0
- package/dist/export/serializer.d.ts +27 -0
- package/dist/export/serializer.d.ts.map +1 -0
- package/dist/export/serializer.js +2 -0
- package/dist/export/serializer.js.map +1 -0
- package/dist/gen-conformance.d.ts +1 -0
- package/dist/gen-conformance.d.ts.map +1 -0
- package/dist/gen-conformance.js +274 -12
- package/dist/gen-conformance.js.map +1 -0
- package/dist/generated.d.ts +194 -118
- package/dist/generated.d.ts.map +1 -0
- package/dist/generated.js +1 -0
- package/dist/generated.js.map +1 -0
- package/dist/import/adapter.d.ts +4 -3
- package/dist/import/adapter.d.ts.map +1 -0
- package/dist/import/adapter.js +1 -0
- package/dist/import/adapter.js.map +1 -0
- package/dist/import/decode.d.ts +1 -0
- package/dist/import/decode.d.ts.map +1 -0
- package/dist/import/decode.js +1 -0
- package/dist/import/decode.js.map +1 -0
- package/dist/import/gw.d.ts +69 -0
- package/dist/import/gw.d.ts.map +1 -0
- package/dist/import/gw.js +245 -0
- package/dist/import/gw.js.map +1 -0
- package/dist/import/import-roster.d.ts +84 -0
- package/dist/import/import-roster.d.ts.map +1 -0
- package/dist/import/import-roster.js +207 -0
- package/dist/import/import-roster.js.map +1 -0
- package/dist/import/index.d.ts +7 -3
- package/dist/import/index.d.ts.map +1 -0
- package/dist/import/index.js +5 -1
- package/dist/import/index.js.map +1 -0
- package/dist/import/listforge.d.ts +1 -0
- package/dist/import/listforge.d.ts.map +1 -0
- package/dist/import/listforge.js +22 -2
- package/dist/import/listforge.js.map +1 -0
- package/dist/import/newrecruit-json.d.ts +31 -0
- package/dist/import/newrecruit-json.d.ts.map +1 -0
- package/dist/import/newrecruit-json.js +224 -0
- package/dist/import/newrecruit-json.js.map +1 -0
- package/dist/import/newrecruit-simple.d.ts +29 -0
- package/dist/import/newrecruit-simple.d.ts.map +1 -0
- package/dist/import/newrecruit-simple.js +200 -0
- package/dist/import/newrecruit-simple.js.map +1 -0
- package/dist/import/newrecruit-text.d.ts +51 -0
- package/dist/import/newrecruit-text.d.ts.map +1 -0
- package/dist/import/newrecruit-text.js +102 -0
- package/dist/import/newrecruit-text.js.map +1 -0
- package/dist/import/newrecruit-wtc.d.ts +36 -0
- package/dist/import/newrecruit-wtc.d.ts.map +1 -0
- package/dist/import/newrecruit-wtc.js +337 -0
- package/dist/import/newrecruit-wtc.js.map +1 -0
- package/dist/import/resolve.d.ts +3 -2
- package/dist/import/resolve.d.ts.map +1 -0
- package/dist/import/resolve.js +5 -2
- package/dist/import/resolve.js.map +1 -0
- package/dist/import/rosterizer.d.ts +70 -0
- package/dist/import/rosterizer.d.ts.map +1 -0
- package/dist/import/rosterizer.js +348 -0
- package/dist/import/rosterizer.js.map +1 -0
- package/dist/import/types.d.ts +11 -1
- package/dist/import/types.d.ts.map +1 -0
- package/dist/import/types.js +1 -0
- package/dist/import/types.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -0
- package/dist/known-support-10e.d.ts +1 -0
- package/dist/known-support-10e.d.ts.map +1 -0
- package/dist/known-support-10e.js +1 -0
- package/dist/known-support-10e.js.map +1 -0
- package/dist/link-abilities.d.ts +41 -0
- package/dist/link-abilities.d.ts.map +1 -0
- package/dist/link-abilities.js +159 -0
- package/dist/link-abilities.js.map +1 -0
- package/dist/migrations/2026-weapon-keywords.d.ts +2 -0
- package/dist/migrations/2026-weapon-keywords.d.ts.map +1 -0
- package/dist/migrations/2026-weapon-keywords.js +247 -0
- package/dist/migrations/2026-weapon-keywords.js.map +1 -0
- package/dist/port-10e-faction.d.ts +1 -0
- package/dist/port-10e-faction.d.ts.map +1 -0
- package/dist/port-10e-faction.js +1 -0
- package/dist/port-10e-faction.js.map +1 -0
- package/dist/report.d.ts +1 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +1 -0
- package/dist/report.js.map +1 -0
- package/dist/rube-goldberg.d.ts +3 -0
- package/dist/rube-goldberg.d.ts.map +1 -0
- package/dist/rube-goldberg.js +109 -0
- package/dist/rube-goldberg.js.map +1 -0
- package/dist/runner.d.ts +38 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +492 -0
- package/dist/runner.js.map +1 -0
- package/dist/schema-loader.d.ts +1 -0
- package/dist/schema-loader.d.ts.map +1 -0
- package/dist/schema-loader.js +1 -0
- package/dist/schema-loader.js.map +1 -0
- package/dist/scrub-ip.d.ts +14 -0
- package/dist/scrub-ip.d.ts.map +1 -0
- package/dist/scrub-ip.js +88 -0
- package/dist/scrub-ip.js.map +1 -0
- package/dist/validate.d.ts +1 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +2 -0
- package/dist/validate.js.map +1 -0
- package/package.json +15 -3
- package/schemas/core/roster.schema.json +19 -4
- package/schemas/core/weapon-keyword.schema.json +31 -0
- package/schemas/core/weapon.schema.json +22 -1
- package/schemas/enrichment/ability-dsl/effect.schema.json +23 -1
- package/dist/import/import-listforge.d.ts +0 -23
- package/dist/import/import-listforge.js +0 -32
package/dist/data/entities.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Linked views over the
|
|
2
|
+
* Linked views over the richly-connected entity types. Each wraps a raw
|
|
3
3
|
* generated record and resolves its relationships lazily against the owning
|
|
4
4
|
* {@link Dataset}; the full underlying record is always available via `.raw`.
|
|
5
5
|
*
|
|
6
6
|
* @packageDocumentation
|
|
7
7
|
*/
|
|
8
|
-
import type { AbilityDSLEntry, Faction, Phase, Unit, Weapon } from "../generated.js";
|
|
8
|
+
import type { AbilityDSLEntry, Faction, Phase, Unit, Weapon, WeaponKeyword } from "../generated.js";
|
|
9
|
+
import type { Buff, BuffSource, EngineContext } from "../cruncher/buffs.js";
|
|
10
|
+
import { type EffectTranslation, type TranslationPerspective } from "../cruncher/from-dsl.js";
|
|
9
11
|
import type { Dataset } from "./dataset.js";
|
|
10
12
|
/** A unit, linked to its faction, weapons, and abilities. */
|
|
11
13
|
export declare class UnitView {
|
|
@@ -23,6 +25,12 @@ export declare class UnitView {
|
|
|
23
25
|
get weapons(): WeaponView[];
|
|
24
26
|
/** Abilities referenced by `ability_ids`; unresolved ids are skipped. */
|
|
25
27
|
get abilities(): AbilityView[];
|
|
28
|
+
/**
|
|
29
|
+
* The stat profile at index `i` (default 0). Returns the schema-generated
|
|
30
|
+
* profile object directly so callers can feed it straight to the engine
|
|
31
|
+
* without an intermediate wrapper.
|
|
32
|
+
*/
|
|
33
|
+
profileAt(i?: number): Unit["profiles"][number];
|
|
26
34
|
}
|
|
27
35
|
/**
|
|
28
36
|
* An ability, linked to the phases it acts in and the units that have it.
|
|
@@ -47,6 +55,22 @@ export declare class AbilityView {
|
|
|
47
55
|
get phases(): Phase[];
|
|
48
56
|
/** Units that list this ability in their `ability_ids`. */
|
|
49
57
|
get units(): UnitView[];
|
|
58
|
+
/**
|
|
59
|
+
* Buff stack this ability contributes against `context`, with provenance
|
|
60
|
+
* tagged via `source` (the caller knows whether this ability is being read
|
|
61
|
+
* as army, detachment, unit, leader, etc.). DSL branches the buff layer
|
|
62
|
+
* can't auto-apply are dropped here; call {@link describeBuffs} if you
|
|
63
|
+
* also want the diagnostics. `perspective` defaults to `"attacker"`; pass
|
|
64
|
+
* `"target"` to translate the ability as a defensive buff (FNP, T/Sv
|
|
65
|
+
* stat-mods, save rerolls, incoming hit penalties).
|
|
66
|
+
*/
|
|
67
|
+
getBuffs(source: BuffSource, context?: EngineContext, perspective?: TranslationPerspective): Buff[];
|
|
68
|
+
/**
|
|
69
|
+
* Full DSL→Buff translation, including the `unsupported` list of effect
|
|
70
|
+
* fragments the buff layer can't model. The SPA renders these as warnings
|
|
71
|
+
* so users see which abilities have effects that need a manual toggle.
|
|
72
|
+
*/
|
|
73
|
+
describeBuffs(source: BuffSource, context?: EngineContext, perspective?: TranslationPerspective): EffectTranslation;
|
|
50
74
|
}
|
|
51
75
|
/** A weapon, linked to the units that carry it. */
|
|
52
76
|
export declare class WeaponView {
|
|
@@ -60,6 +84,46 @@ export declare class WeaponView {
|
|
|
60
84
|
get name(): string;
|
|
61
85
|
/** Units that list this weapon in their `weapon_ids`. */
|
|
62
86
|
get units(): UnitView[];
|
|
87
|
+
/** The stat profile at index `i` (default 0). */
|
|
88
|
+
profileAt(i?: number): Weapon["profiles"][number];
|
|
89
|
+
/**
|
|
90
|
+
* Catalog views for each keyword referenced by profile `i`, paired with the
|
|
91
|
+
* reference-site parameters. Unresolved keyword ids are skipped.
|
|
92
|
+
*/
|
|
93
|
+
keywordsAt(i?: number): {
|
|
94
|
+
keyword: WeaponKeywordView;
|
|
95
|
+
parameters: Record<string, unknown> | undefined;
|
|
96
|
+
}[];
|
|
97
|
+
/**
|
|
98
|
+
* Buffs contributed by profile `i`'s intrinsic keywords against `context` —
|
|
99
|
+
* the natural "what does this profile bring on its own?" call the engine
|
|
100
|
+
* makes automatically before adding ability/manual buffs.
|
|
101
|
+
*/
|
|
102
|
+
profileBuffs(i: number | undefined, context: EngineContext): Buff[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* A weapon-keyword catalog entry, linked to the weapons whose profiles
|
|
106
|
+
* reference it. Exposes the keyword's mechanical effect as a buff stack
|
|
107
|
+
* via {@link getBuffs}.
|
|
108
|
+
*/
|
|
109
|
+
export declare class WeaponKeywordView {
|
|
110
|
+
/** The full generated `WeaponKeyword` record. */
|
|
111
|
+
readonly raw: WeaponKeyword;
|
|
112
|
+
private readonly ds;
|
|
113
|
+
constructor(
|
|
114
|
+
/** The full generated `WeaponKeyword` record. */
|
|
115
|
+
raw: WeaponKeyword, ds: Dataset);
|
|
116
|
+
get id(): string;
|
|
117
|
+
get name(): string;
|
|
118
|
+
/** Weapons whose profiles reference this keyword id. */
|
|
119
|
+
get weapons(): WeaponView[];
|
|
120
|
+
/**
|
|
121
|
+
* Buff contributions from this catalog entry, for one reference site:
|
|
122
|
+
* pass the keyword's `parameters` (e.g. `{ value: 1 }` for Sustained Hits 1)
|
|
123
|
+
* along with the `weaponId` that's carrying it (used as the buff source)
|
|
124
|
+
* and the engine `context` (e.g. attacker stationary?).
|
|
125
|
+
*/
|
|
126
|
+
getBuffs(parameters: Record<string, unknown> | undefined, weaponId: string, context: EngineContext): Buff[];
|
|
63
127
|
}
|
|
64
128
|
/** A faction, linked to its units and the records scoped to it. */
|
|
65
129
|
export declare class FactionView {
|
|
@@ -78,3 +142,4 @@ export declare class FactionView {
|
|
|
78
142
|
/** Distinct weapons carried by this faction's units. */
|
|
79
143
|
get weapons(): WeaponView[];
|
|
80
144
|
}
|
|
145
|
+
//# sourceMappingURL=entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/data/entities.ts"],"names":[],"mappings":"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"}
|
package/dist/data/entities.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { buffsFromKeyword } from "../cruncher/from-keyword.js";
|
|
2
|
+
import { effectToBuffs, } from "../cruncher/from-dsl.js";
|
|
1
3
|
/** A unit, linked to its faction, weapons, and abilities. */
|
|
2
4
|
export class UnitView {
|
|
3
5
|
raw;
|
|
@@ -26,6 +28,18 @@ export class UnitView {
|
|
|
26
28
|
get abilities() {
|
|
27
29
|
return resolveAll(this.raw.ability_ids, (id) => this.ds.abilities.get(id));
|
|
28
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* The stat profile at index `i` (default 0). Returns the schema-generated
|
|
33
|
+
* profile object directly so callers can feed it straight to the engine
|
|
34
|
+
* without an intermediate wrapper.
|
|
35
|
+
*/
|
|
36
|
+
profileAt(i = 0) {
|
|
37
|
+
const profile = this.raw.profiles[i];
|
|
38
|
+
if (profile === undefined) {
|
|
39
|
+
throw new RangeError(`UnitView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`);
|
|
40
|
+
}
|
|
41
|
+
return profile;
|
|
42
|
+
}
|
|
29
43
|
}
|
|
30
44
|
/**
|
|
31
45
|
* An ability, linked to the phases it acts in and the units that have it.
|
|
@@ -60,6 +74,27 @@ export class AbilityView {
|
|
|
60
74
|
get units() {
|
|
61
75
|
return this.ds.unitsWithAbility(this.raw.ability_id);
|
|
62
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Buff stack this ability contributes against `context`, with provenance
|
|
79
|
+
* tagged via `source` (the caller knows whether this ability is being read
|
|
80
|
+
* as army, detachment, unit, leader, etc.). DSL branches the buff layer
|
|
81
|
+
* can't auto-apply are dropped here; call {@link describeBuffs} if you
|
|
82
|
+
* also want the diagnostics. `perspective` defaults to `"attacker"`; pass
|
|
83
|
+
* `"target"` to translate the ability as a defensive buff (FNP, T/Sv
|
|
84
|
+
* stat-mods, save rerolls, incoming hit penalties).
|
|
85
|
+
*/
|
|
86
|
+
getBuffs(source, context, perspective = "attacker") {
|
|
87
|
+
return this.describeBuffs(source, context, perspective).applied;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Full DSL→Buff translation, including the `unsupported` list of effect
|
|
91
|
+
* fragments the buff layer can't model. The SPA renders these as warnings
|
|
92
|
+
* so users see which abilities have effects that need a manual toggle.
|
|
93
|
+
*/
|
|
94
|
+
describeBuffs(source, context, perspective = "attacker") {
|
|
95
|
+
const ctx = context ?? { phase: "shooting" };
|
|
96
|
+
return effectToBuffs(this.raw.effect, source, ctx, perspective);
|
|
97
|
+
}
|
|
63
98
|
}
|
|
64
99
|
/** A weapon, linked to the units that carry it. */
|
|
65
100
|
export class WeaponView {
|
|
@@ -81,6 +116,92 @@ export class WeaponView {
|
|
|
81
116
|
get units() {
|
|
82
117
|
return this.ds.unitsWithWeapon(this.raw.id);
|
|
83
118
|
}
|
|
119
|
+
/** The stat profile at index `i` (default 0). */
|
|
120
|
+
profileAt(i = 0) {
|
|
121
|
+
const profile = this.raw.profiles[i];
|
|
122
|
+
if (profile === undefined) {
|
|
123
|
+
throw new RangeError(`WeaponView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`);
|
|
124
|
+
}
|
|
125
|
+
return profile;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Catalog views for each keyword referenced by profile `i`, paired with the
|
|
129
|
+
* reference-site parameters. Unresolved keyword ids are skipped.
|
|
130
|
+
*/
|
|
131
|
+
keywordsAt(i = 0) {
|
|
132
|
+
const profile = this.profileAt(i);
|
|
133
|
+
const refs = profile.keywords ?? [];
|
|
134
|
+
const out = [];
|
|
135
|
+
for (const ref of refs) {
|
|
136
|
+
const view = this.ds.weaponKeywords.get(ref.keyword_id);
|
|
137
|
+
if (!view)
|
|
138
|
+
continue;
|
|
139
|
+
out.push({
|
|
140
|
+
keyword: view,
|
|
141
|
+
parameters: ref.parameters,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Buffs contributed by profile `i`'s intrinsic keywords against `context` —
|
|
148
|
+
* the natural "what does this profile bring on its own?" call the engine
|
|
149
|
+
* makes automatically before adding ability/manual buffs.
|
|
150
|
+
*/
|
|
151
|
+
profileBuffs(i, context) {
|
|
152
|
+
const index = i ?? 0;
|
|
153
|
+
const out = [];
|
|
154
|
+
for (const { keyword, parameters } of this.keywordsAt(index)) {
|
|
155
|
+
out.push(...buffsFromKeyword({
|
|
156
|
+
keywordId: keyword.id,
|
|
157
|
+
weaponId: this.raw.id,
|
|
158
|
+
effect: keyword.raw.effect,
|
|
159
|
+
...(parameters !== undefined ? { parameters } : {}),
|
|
160
|
+
context,
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* A weapon-keyword catalog entry, linked to the weapons whose profiles
|
|
168
|
+
* reference it. Exposes the keyword's mechanical effect as a buff stack
|
|
169
|
+
* via {@link getBuffs}.
|
|
170
|
+
*/
|
|
171
|
+
export class WeaponKeywordView {
|
|
172
|
+
raw;
|
|
173
|
+
ds;
|
|
174
|
+
constructor(
|
|
175
|
+
/** The full generated `WeaponKeyword` record. */
|
|
176
|
+
raw, ds) {
|
|
177
|
+
this.raw = raw;
|
|
178
|
+
this.ds = ds;
|
|
179
|
+
}
|
|
180
|
+
get id() {
|
|
181
|
+
return this.raw.id;
|
|
182
|
+
}
|
|
183
|
+
get name() {
|
|
184
|
+
return this.raw.name;
|
|
185
|
+
}
|
|
186
|
+
/** Weapons whose profiles reference this keyword id. */
|
|
187
|
+
get weapons() {
|
|
188
|
+
return this.ds.weaponsWithKeyword(this.raw.id);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Buff contributions from this catalog entry, for one reference site:
|
|
192
|
+
* pass the keyword's `parameters` (e.g. `{ value: 1 }` for Sustained Hits 1)
|
|
193
|
+
* along with the `weaponId` that's carrying it (used as the buff source)
|
|
194
|
+
* and the engine `context` (e.g. attacker stationary?).
|
|
195
|
+
*/
|
|
196
|
+
getBuffs(parameters, weaponId, context) {
|
|
197
|
+
return buffsFromKeyword({
|
|
198
|
+
keywordId: this.raw.id,
|
|
199
|
+
weaponId,
|
|
200
|
+
effect: this.raw.effect,
|
|
201
|
+
...(parameters !== undefined ? { parameters } : {}),
|
|
202
|
+
context,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
84
205
|
}
|
|
85
206
|
/** A faction, linked to its units and the records scoped to it. */
|
|
86
207
|
export class FactionView {
|
|
@@ -131,3 +252,4 @@ function resolveAll(ids, get) {
|
|
|
131
252
|
}
|
|
132
253
|
return out;
|
|
133
254
|
}
|
|
255
|
+
//# sourceMappingURL=entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/data/entities.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Linked views over the richly-connected entity types. Each wraps a raw\n * generated record and resolves its relationships lazily against the owning\n * {@link Dataset}; the full underlying record is always available via `.raw`.\n *\n * @packageDocumentation\n */\nimport type {\n AbilityDSLEntry,\n Faction,\n Phase,\n Unit,\n Weapon,\n WeaponKeyword,\n} from \"../generated.js\";\nimport type { Buff, BuffSource, EngineContext } from \"../cruncher/buffs.js\";\nimport { buffsFromKeyword } from \"../cruncher/from-keyword.js\";\nimport {\n effectToBuffs,\n type EffectTranslation,\n type TranslationPerspective,\n} from \"../cruncher/from-dsl.js\";\nimport type { Dataset } from \"./dataset.js\";\n\n/** A unit, linked to its faction, weapons, and abilities. */\nexport class UnitView {\n constructor(\n /** The full generated `Unit` record. */\n readonly raw: Unit,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** The unit's faction, or `undefined` if its `faction_id` is unknown. */\n get faction(): FactionView | undefined {\n return this.ds.factions.get(this.raw.faction_id);\n }\n\n /** Weapons referenced by `weapon_ids`; unresolved ids are skipped. */\n get weapons(): WeaponView[] {\n return resolveAll(this.raw.weapon_ids, (id) => this.ds.weapons.get(id));\n }\n\n /** Abilities referenced by `ability_ids`; unresolved ids are skipped. */\n get abilities(): AbilityView[] {\n return resolveAll(this.raw.ability_ids, (id) => this.ds.abilities.get(id));\n }\n\n /**\n * The stat profile at index `i` (default 0). Returns the schema-generated\n * profile object directly so callers can feed it straight to the engine\n * without an intermediate wrapper.\n */\n profileAt(i = 0): Unit[\"profiles\"][number] {\n const profile = this.raw.profiles[i];\n if (profile === undefined) {\n throw new RangeError(\n `UnitView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`,\n );\n }\n return profile;\n }\n}\n\n/**\n * An ability, linked to the phases it acts in and the units that have it.\n *\n * Phases are not stored on the ability — they live in `phase-mappings` records.\n *\n * @example\n * units.find(\"Kharn\")!.abilities\n * .filter(a => a.phases.includes(\"shooting\"));\n */\nexport class AbilityView {\n constructor(\n /** The full generated ability record. */\n readonly raw: AbilityDSLEntry,\n private readonly ds: Dataset,\n ) {}\n\n /** The ability's id (`ability_id` in the raw record). */\n get id(): string {\n return this.raw.ability_id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Game phases this ability acts in, unioned across its phase-mappings. */\n get phases(): Phase[] {\n return this.ds.phasesFor(\"ability\", this.raw.ability_id);\n }\n\n /** Units that list this ability in their `ability_ids`. */\n get units(): UnitView[] {\n return this.ds.unitsWithAbility(this.raw.ability_id);\n }\n\n /**\n * Buff stack this ability contributes against `context`, with provenance\n * tagged via `source` (the caller knows whether this ability is being read\n * as army, detachment, unit, leader, etc.). DSL branches the buff layer\n * can't auto-apply are dropped here; call {@link describeBuffs} if you\n * also want the diagnostics. `perspective` defaults to `\"attacker\"`; pass\n * `\"target\"` to translate the ability as a defensive buff (FNP, T/Sv\n * stat-mods, save rerolls, incoming hit penalties).\n */\n getBuffs(\n source: BuffSource,\n context?: EngineContext,\n perspective: TranslationPerspective = \"attacker\",\n ): Buff[] {\n return this.describeBuffs(source, context, perspective).applied;\n }\n\n /**\n * Full DSL→Buff translation, including the `unsupported` list of effect\n * fragments the buff layer can't model. The SPA renders these as warnings\n * so users see which abilities have effects that need a manual toggle.\n */\n describeBuffs(\n source: BuffSource,\n context?: EngineContext,\n perspective: TranslationPerspective = \"attacker\",\n ): EffectTranslation {\n const ctx: EngineContext = context ?? { phase: \"shooting\" };\n return effectToBuffs(this.raw.effect, source, ctx, perspective);\n }\n}\n\n/** A weapon, linked to the units that carry it. */\nexport class WeaponView {\n constructor(\n /** The full generated `Weapon` record. */\n readonly raw: Weapon,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Units that list this weapon in their `weapon_ids`. */\n get units(): UnitView[] {\n return this.ds.unitsWithWeapon(this.raw.id);\n }\n\n /** The stat profile at index `i` (default 0). */\n profileAt(i = 0): Weapon[\"profiles\"][number] {\n const profile = this.raw.profiles[i];\n if (profile === undefined) {\n throw new RangeError(\n `WeaponView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`,\n );\n }\n return profile;\n }\n\n /**\n * Catalog views for each keyword referenced by profile `i`, paired with the\n * reference-site parameters. Unresolved keyword ids are skipped.\n */\n keywordsAt(\n i = 0,\n ): { keyword: WeaponKeywordView; parameters: Record<string, unknown> | undefined }[] {\n const profile = this.profileAt(i);\n const refs = profile.keywords ?? [];\n const out: { keyword: WeaponKeywordView; parameters: Record<string, unknown> | undefined }[] = [];\n for (const ref of refs) {\n const view = this.ds.weaponKeywords.get(ref.keyword_id);\n if (!view) continue;\n out.push({\n keyword: view,\n parameters: ref.parameters as Record<string, unknown> | undefined,\n });\n }\n return out;\n }\n\n /**\n * Buffs contributed by profile `i`'s intrinsic keywords against `context` —\n * the natural \"what does this profile bring on its own?\" call the engine\n * makes automatically before adding ability/manual buffs.\n */\n profileBuffs(i: number | undefined, context: EngineContext): Buff[] {\n const index = i ?? 0;\n const out: Buff[] = [];\n for (const { keyword, parameters } of this.keywordsAt(index)) {\n out.push(\n ...buffsFromKeyword({\n keywordId: keyword.id,\n weaponId: this.raw.id,\n effect: keyword.raw.effect,\n ...(parameters !== undefined ? { parameters } : {}),\n context,\n }),\n );\n }\n return out;\n }\n}\n\n/**\n * A weapon-keyword catalog entry, linked to the weapons whose profiles\n * reference it. Exposes the keyword's mechanical effect as a buff stack\n * via {@link getBuffs}.\n */\nexport class WeaponKeywordView {\n constructor(\n /** The full generated `WeaponKeyword` record. */\n readonly raw: WeaponKeyword,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Weapons whose profiles reference this keyword id. */\n get weapons(): WeaponView[] {\n return this.ds.weaponsWithKeyword(this.raw.id);\n }\n\n /**\n * Buff contributions from this catalog entry, for one reference site:\n * pass the keyword's `parameters` (e.g. `{ value: 1 }` for Sustained Hits 1)\n * along with the `weaponId` that's carrying it (used as the buff source)\n * and the engine `context` (e.g. attacker stationary?).\n */\n getBuffs(\n parameters: Record<string, unknown> | undefined,\n weaponId: string,\n context: EngineContext,\n ): Buff[] {\n return buffsFromKeyword({\n keywordId: this.raw.id,\n weaponId,\n effect: this.raw.effect,\n ...(parameters !== undefined ? { parameters } : {}),\n context,\n });\n }\n}\n\n/** A faction, linked to its units and the records scoped to it. */\nexport class FactionView {\n constructor(\n /** The full generated `Faction` record. */\n readonly raw: Faction,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Units whose `faction_id` is this faction (may be empty for successors). */\n get units(): UnitView[] {\n return this.ds.units.byFaction(this.raw.id);\n }\n\n /** Faction-scoped abilities (abilities whose `faction_id` is this faction). */\n get abilities(): AbilityView[] {\n return this.ds.abilities.byFaction(this.raw.id);\n }\n\n /** Distinct weapons carried by this faction's units. */\n get weapons(): WeaponView[] {\n const seen = new Set<string>();\n const out: WeaponView[] = [];\n for (const unit of this.units) {\n for (const weapon of unit.weapons) {\n if (seen.has(weapon.id)) continue;\n seen.add(weapon.id);\n out.push(weapon);\n }\n }\n return out;\n }\n}\n\n/** Resolve a list of ids, dropping any that don't resolve. */\nfunction resolveAll<V>(ids: string[] | undefined, get: (id: string) => V | undefined): V[] {\n const out: V[] = [];\n for (const id of ids ?? []) {\n const v = get(id);\n if (v !== undefined) out.push(v);\n }\n return out;\n}\n"]}
|
package/dist/data/index.d.ts
CHANGED
|
@@ -20,12 +20,18 @@
|
|
|
20
20
|
* factions.find("World Eaters")!.units.length;
|
|
21
21
|
*/
|
|
22
22
|
export { Dataset } from "./dataset.js";
|
|
23
|
+
export type { StackableBuff, StackableBuffGroup } from "./dataset.js";
|
|
23
24
|
export { Collection } from "./collection.js";
|
|
24
25
|
export type { CollectionConfig } from "./collection.js";
|
|
25
|
-
export { UnitView, AbilityView, WeaponView, FactionView } from "./entities.js";
|
|
26
|
+
export { UnitView, AbilityView, WeaponView, WeaponKeywordView, FactionView, } from "./entities.js";
|
|
26
27
|
export { normalizeName } from "./normalize.js";
|
|
27
28
|
export { emptyRawData } from "./types.js";
|
|
28
29
|
export type { RawData } from "./types.js";
|
|
30
|
+
export * from "../cruncher/index.js";
|
|
31
|
+
export { effectToBuffs, parseKeywordGrant } from "../cruncher/from-dsl.js";
|
|
32
|
+
export type { ActivatableBuff, ActivatableGroupRef, EffectTranslation, TranslationPerspective, UnsupportedFragment, } from "../cruncher/from-dsl.js";
|
|
33
|
+
export * from "../abilities-resolver/index.js";
|
|
34
|
+
export { resolveRosterUnit, resolveRosterWargear, resolveAttachedLeader, resolveAttachmentPartners, } from "./roster-resolve.js";
|
|
29
35
|
import { Dataset } from "./dataset.js";
|
|
30
36
|
/** The dataset built from this package's embedded data. */
|
|
31
37
|
export declare const dataset: Dataset;
|
|
@@ -33,6 +39,8 @@ export declare const dataset: Dataset;
|
|
|
33
39
|
export declare const units: import("./collection.js").Collection<import("../generated.js").Unit, import("./entities.js").UnitView>;
|
|
34
40
|
/** All weapons, linked to the units that carry them. */
|
|
35
41
|
export declare const weapons: import("./collection.js").Collection<import("../generated.js").Weapon, import("./entities.js").WeaponView>;
|
|
42
|
+
/** Catalog of weapon keywords (Lethal Hits, Sustained Hits N, Anti-X N+, ...). */
|
|
43
|
+
export declare const weaponKeywords: import("./collection.js").Collection<import("../generated.js").WeaponKeyword, import("./entities.js").WeaponKeywordView>;
|
|
36
44
|
/** All factions, linked to their units, abilities, and weapons. */
|
|
37
45
|
export declare const factions: import("./collection.js").Collection<import("../generated.js").Faction, import("./entities.js").FactionView>;
|
|
38
46
|
/** All abilities, linked to their phases and the units that have them. */
|
|
@@ -57,3 +65,4 @@ export declare const deploymentPatterns: import("./collection.js").Collection<im
|
|
|
57
65
|
export declare const forceDispositions: import("./collection.js").Collection<import("../generated.js").ForceDisposition, import("../generated.js").ForceDisposition>;
|
|
58
66
|
/** All resource pools. */
|
|
59
67
|
export declare const resourcePools: import("./collection.js").Collection<import("../generated.js").ResourcePool, import("../generated.js").ResourcePool>;
|
|
68
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAK1C,cAAc,sBAAsB,CAAC;AAGrC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AAGjC,cAAc,gCAAgC,CAAC;AAG/C,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,2DAA2D;AAC3D,eAAO,MAAM,OAAO,SAAqB,CAAC;AAE1C,kEAAkE;AAClE,eAAO,MAAM,KAAK,wGAAgB,CAAC;AACnC,wDAAwD;AACxD,eAAO,MAAM,OAAO,4GAAkB,CAAC;AACvC,kFAAkF;AAClF,eAAO,MAAM,cAAc,0HAAyB,CAAC;AACrD,mEAAmE;AACnE,eAAO,MAAM,QAAQ,8GAAmB,CAAC;AACzC,0EAA0E;AAC1E,eAAO,MAAM,SAAS,sHAAoB,CAAC;AAC3C,uBAAuB;AACvB,eAAO,MAAM,WAAW,kHAAsB,CAAC;AAC/C,wBAAwB;AACxB,eAAO,MAAM,YAAY,oHAAuB,CAAC;AACjD,sBAAsB;AACtB,eAAO,MAAM,UAAU,gHAAqB,CAAC;AAC7C,2BAA2B;AAC3B,eAAO,MAAM,cAAc,wHAAyB,CAAC;AACrD,oBAAoB;AACpB,eAAO,MAAM,QAAQ,4GAAmB,CAAC;AACzC,4BAA4B;AAC5B,eAAO,MAAM,eAAe,0HAA0B,CAAC;AACvD,mCAAmC;AACnC,eAAO,MAAM,cAAc,wHAAyB,CAAC;AACrD,+BAA+B;AAC/B,eAAO,MAAM,kBAAkB,gIAA6B,CAAC;AAC7D,8BAA8B;AAC9B,eAAO,MAAM,iBAAiB,8HAA4B,CAAC;AAC3D,0BAA0B;AAC1B,eAAO,MAAM,aAAa,sHAAwB,CAAC"}
|
package/dist/data/index.js
CHANGED
|
@@ -21,9 +21,19 @@
|
|
|
21
21
|
*/
|
|
22
22
|
export { Dataset } from "./dataset.js";
|
|
23
23
|
export { Collection } from "./collection.js";
|
|
24
|
-
export { UnitView, AbilityView, WeaponView, FactionView } from "./entities.js";
|
|
24
|
+
export { UnitView, AbilityView, WeaponView, WeaponKeywordView, FactionView, } from "./entities.js";
|
|
25
25
|
export { normalizeName } from "./normalize.js";
|
|
26
26
|
export { emptyRawData } from "./types.js";
|
|
27
|
+
// The cruncher surface — buff types + the engine — re-exported from the data
|
|
28
|
+
// package so downstream callers can import their whole 40kdc API from
|
|
29
|
+
// `@alpaca-software/40kdc-data` without reaching into subpaths.
|
|
30
|
+
export * from "../cruncher/index.js";
|
|
31
|
+
// The DSL→Buff translator that powers AbilityView.getBuffs / describeBuffs.
|
|
32
|
+
export { effectToBuffs, parseKeywordGrant } from "../cruncher/from-dsl.js";
|
|
33
|
+
// The eligible-abilities resolver (also reachable as Dataset.eligibleAbilities).
|
|
34
|
+
export * from "../abilities-resolver/index.js";
|
|
35
|
+
// Bridge helpers from the importer's RosterUnit → linked views.
|
|
36
|
+
export { resolveRosterUnit, resolveRosterWargear, resolveAttachedLeader, resolveAttachmentPartners, } from "./roster-resolve.js";
|
|
27
37
|
import { Dataset } from "./dataset.js";
|
|
28
38
|
/** The dataset built from this package's embedded data. */
|
|
29
39
|
export const dataset = Dataset.embedded();
|
|
@@ -31,6 +41,8 @@ export const dataset = Dataset.embedded();
|
|
|
31
41
|
export const units = dataset.units;
|
|
32
42
|
/** All weapons, linked to the units that carry them. */
|
|
33
43
|
export const weapons = dataset.weapons;
|
|
44
|
+
/** Catalog of weapon keywords (Lethal Hits, Sustained Hits N, Anti-X N+, ...). */
|
|
45
|
+
export const weaponKeywords = dataset.weaponKeywords;
|
|
34
46
|
/** All factions, linked to their units, abilities, and weapons. */
|
|
35
47
|
export const factions = dataset.factions;
|
|
36
48
|
/** All abilities, linked to their phases and the units that have them. */
|
|
@@ -55,3 +67,4 @@ export const deploymentPatterns = dataset.deploymentPatterns;
|
|
|
55
67
|
export const forceDispositions = dataset.forceDispositions;
|
|
56
68
|
/** All resource pools. */
|
|
57
69
|
export const resourcePools = dataset.resourcePools;
|
|
70
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EACL,QAAQ,EACR,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,6EAA6E;AAC7E,sEAAsE;AACtE,gEAAgE;AAChE,cAAc,sBAAsB,CAAC;AAErC,4EAA4E;AAC5E,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAS3E,iFAAiF;AACjF,cAAc,gCAAgC,CAAC;AAE/C,gEAAgE;AAChE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,2DAA2D;AAC3D,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;AAE1C,kEAAkE;AAClE,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;AACnC,wDAAwD;AACxD,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;AACvC,kFAAkF;AAClF,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;AACrD,mEAAmE;AACnE,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;AACzC,0EAA0E;AAC1E,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;AAC3C,uBAAuB;AACvB,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;AAC/C,wBAAwB;AACxB,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;AACjD,sBAAsB;AACtB,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;AAC7C,2BAA2B;AAC3B,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;AACrD,oBAAoB;AACpB,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;AACzC,4BAA4B;AAC5B,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;AACvD,mCAAmC;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;AACrD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;AAC7D,8BAA8B;AAC9B,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;AAC3D,0BAA0B;AAC1B,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC","sourcesContent":["/**\n * The linked, typed 40kdc dataset.\n *\n * The default {@link dataset} is built once from the data embedded in this\n * package; the top-level collections below are its accessors, re-exported for\n * the ergonomic one-liner form.\n *\n * @packageDocumentation\n *\n * @example\n * import { units } from \"@alpaca-software/40kdc-data\";\n *\n * units.find(\"Kharn\")!.abilities\n * .filter(a => a.phases.includes(\"shooting\"))\n * .map(a => a.id); // [\"berzerker-frenzy\"]\n *\n * @example\n * import { factions } from \"@alpaca-software/40kdc-data\";\n *\n * factions.find(\"World Eaters\")!.units.length;\n */\nexport { Dataset } from \"./dataset.js\";\nexport type { StackableBuff, StackableBuffGroup } from \"./dataset.js\";\nexport { Collection } from \"./collection.js\";\nexport type { CollectionConfig } from \"./collection.js\";\nexport {\n UnitView,\n AbilityView,\n WeaponView,\n WeaponKeywordView,\n FactionView,\n} from \"./entities.js\";\nexport { normalizeName } from \"./normalize.js\";\nexport { emptyRawData } from \"./types.js\";\nexport type { RawData } from \"./types.js\";\n\n// The cruncher surface — buff types + the engine — re-exported from the data\n// package so downstream callers can import their whole 40kdc API from\n// `@alpaca-software/40kdc-data` without reaching into subpaths.\nexport * from \"../cruncher/index.js\";\n\n// The DSL→Buff translator that powers AbilityView.getBuffs / describeBuffs.\nexport { effectToBuffs, parseKeywordGrant } from \"../cruncher/from-dsl.js\";\nexport type {\n ActivatableBuff,\n ActivatableGroupRef,\n EffectTranslation,\n TranslationPerspective,\n UnsupportedFragment,\n} from \"../cruncher/from-dsl.js\";\n\n// The eligible-abilities resolver (also reachable as Dataset.eligibleAbilities).\nexport * from \"../abilities-resolver/index.js\";\n\n// Bridge helpers from the importer's RosterUnit → linked views.\nexport {\n resolveRosterUnit,\n resolveRosterWargear,\n resolveAttachedLeader,\n resolveAttachmentPartners,\n} from \"./roster-resolve.js\";\n\nimport { Dataset } from \"./dataset.js\";\n\n/** The dataset built from this package's embedded data. */\nexport const dataset = Dataset.embedded();\n\n/** All units, linked to their faction, weapons, and abilities. */\nexport const units = dataset.units;\n/** All weapons, linked to the units that carry them. */\nexport const weapons = dataset.weapons;\n/** Catalog of weapon keywords (Lethal Hits, Sustained Hits N, Anti-X N+, ...). */\nexport const weaponKeywords = dataset.weaponKeywords;\n/** All factions, linked to their units, abilities, and weapons. */\nexport const factions = dataset.factions;\n/** All abilities, linked to their phases and the units that have them. */\nexport const abilities = dataset.abilities;\n/** All detachments. */\nexport const detachments = dataset.detachments;\n/** All enhancements. */\nexport const enhancements = dataset.enhancements;\n/** All stratagems. */\nexport const stratagems = dataset.stratagems;\n/** All wargear options. */\nexport const wargearOptions = dataset.wargearOptions;\n/** All missions. */\nexport const missions = dataset.missions;\n/** All mission matchups. */\nexport const missionMatchups = dataset.missionMatchups;\n/** All secondary mission cards. */\nexport const secondaryCards = dataset.secondaryCards;\n/** All deployment patterns. */\nexport const deploymentPatterns = dataset.deploymentPatterns;\n/** All force dispositions. */\nexport const forceDispositions = dataset.forceDispositions;\n/** All resource pools. */\nexport const resourcePools = dataset.resourcePools;\n"]}
|
package/dist/data/normalize.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/data/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQnD"}
|
package/dist/data/normalize.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/data/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK;SACT,SAAS,CAAC,KAAK,CAAC;SAChB,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC;SAC9B,WAAW,EAAE;SACb,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,IAAI,EAAE,CAAC;AACZ,CAAC","sourcesContent":["/**\n * Name normalization for diacritic- and punctuation-insensitive lookup.\n *\n * Warhammer 40,000 is played globally and many entity names carry diacritics or\n * punctuation — \"Khârn the Betrayer\", \"T'au\", \"Be'lakor\". A user typing the\n * plain-ASCII form of a name must still find the entity. Every name comparison\n * in this package routes through {@link normalizeName} so the matching rule is\n * defined in exactly one place; consumers can import it to reproduce the same\n * behaviour in their own search UIs.\n *\n * @packageDocumentation\n */\n\n/**\n * Reduce a display name to a canonical lookup key.\n *\n * The transform, in order:\n * 1. Unicode NFD-decompose, then strip combining marks — `Khârn` → `Kharn`.\n * 2. Casefold to lower case.\n * 3. Remove apostrophe and quote variants (`' ’ ‘ \\` \" “ ”`) — `T'au` → `Tau`.\n * 4. Collapse any run of whitespace or hyphens to a single space, then trim —\n * `Be'lakor` → `belakor`, `the betrayer` → `the betrayer`.\n *\n * The result is intended only for comparison; it is not a display value.\n *\n * @example\n * normalizeName(\"Khârn the Betrayer\"); // \"kharn the betrayer\"\n * normalizeName(\"T'au\"); // \"tau\"\n */\nexport function normalizeName(input: string): string {\n return input\n .normalize(\"NFD\")\n .replace(/\\p{Diacritic}/gu, \"\")\n .toLowerCase()\n .replace(/['’‘`\"“”]/g, \"\")\n .replace(/[\\s-]+/g, \" \")\n .trim();\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge helpers between the importer's flat-data {@link Roster} types and
|
|
3
|
+
* the linked {@link UnitView} the cruncher consumes. The importer ships
|
|
4
|
+
* unit entries as plain interfaces (`RosterUnit` is data, not behaviour),
|
|
5
|
+
* so the lookup is a free function rather than a method.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import type { Roster, RosterUnit, RosterWargear } from "../import/types.js";
|
|
10
|
+
import type { Dataset } from "./dataset.js";
|
|
11
|
+
import type { UnitView, WeaponView } from "./entities.js";
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a roster's unit entry against the dataset, returning the linked
|
|
14
|
+
* {@link UnitView}. Returns `undefined` when:
|
|
15
|
+
* - the roster's `ref.id` is `null` (the importer couldn't match the unit), or
|
|
16
|
+
* - the id doesn't appear in the dataset (e.g. the roster was authored
|
|
17
|
+
* against an older dataslate than the bundled one).
|
|
18
|
+
*
|
|
19
|
+
* Doesn't surface diagnostics — the caller already has them on the roster's
|
|
20
|
+
* own `diagnostics` field.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveRosterUnit(rosterUnit: RosterUnit, dataset: Dataset): UnitView | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve every wargear entry on a roster unit to a {@link WeaponView},
|
|
25
|
+
* keeping each entry's count alongside. Unresolved entries are dropped
|
|
26
|
+
* silently (matching {@link resolveRosterUnit}). Useful when the SPA
|
|
27
|
+
* needs to enumerate firing options after the user picks a roster unit.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveRosterWargear(wargear: RosterWargear[], dataset: Dataset): {
|
|
30
|
+
weapon: WeaponView;
|
|
31
|
+
count: number;
|
|
32
|
+
}[];
|
|
33
|
+
/**
|
|
34
|
+
* The roster's leader entry attached to `bodyguardUnitId`, if any. Import
|
|
35
|
+
* stores the inferred (always-provisional) attachment on the *leader's*
|
|
36
|
+
* {@link RosterUnit}, pointing down to its bodyguard via
|
|
37
|
+
* `leader_attachment.bodyguard_ref`. Selection UIs start from the body unit,
|
|
38
|
+
* so this scans for the leader whose `bodyguard_ref.id` matches. Returns
|
|
39
|
+
* `undefined` when no leader in the roster is attached to that unit (the
|
|
40
|
+
* common case — attachments are optional at game start).
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveAttachedLeader(roster: Roster, bodyguardUnitId: string): RosterUnit | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Every roster unit attached to `unitId`, resolved from *either* end of the
|
|
45
|
+
* attachment. A leader+bodyguard are one combined unit, so a selection UI may
|
|
46
|
+
* start from either half:
|
|
47
|
+
* - `unitId` is the **bodyguard** → the leader(s) whose
|
|
48
|
+
* `leader_attachment.bodyguard_ref.id` points at it (body-first, the
|
|
49
|
+
* {@link resolveAttachedLeader} direction), and
|
|
50
|
+
* - `unitId` is the **leader** → the bodyguard its own `leader_attachment`
|
|
51
|
+
* points to.
|
|
52
|
+
* Returns the partner {@link RosterUnit}s (deduped, source order). Empty when
|
|
53
|
+
* the unit has no attachment in this roster — the common case, since
|
|
54
|
+
* attachments are optional at game start. Shaped as a list to carry 11th
|
|
55
|
+
* edition's multi-member attachments without an API change.
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveAttachmentPartners(roster: Roster, unitId: string): RosterUnit[];
|
|
58
|
+
//# sourceMappingURL=roster-resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster-resolve.d.ts","sourceRoot":"","sources":["../../src/data/roster-resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE1D;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,GACf,QAAQ,GAAG,SAAS,CAItB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EAAE,EACxB,OAAO,EAAE,OAAO,GACf;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAUzC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GACtB,UAAU,GAAG,SAAS,CAIxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,UAAU,EAAE,CAkBd"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a roster's unit entry against the dataset, returning the linked
|
|
3
|
+
* {@link UnitView}. Returns `undefined` when:
|
|
4
|
+
* - the roster's `ref.id` is `null` (the importer couldn't match the unit), or
|
|
5
|
+
* - the id doesn't appear in the dataset (e.g. the roster was authored
|
|
6
|
+
* against an older dataslate than the bundled one).
|
|
7
|
+
*
|
|
8
|
+
* Doesn't surface diagnostics — the caller already has them on the roster's
|
|
9
|
+
* own `diagnostics` field.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveRosterUnit(rosterUnit, dataset) {
|
|
12
|
+
const id = rosterUnit.ref.id;
|
|
13
|
+
if (id === null)
|
|
14
|
+
return undefined;
|
|
15
|
+
return dataset.units.get(id);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolve every wargear entry on a roster unit to a {@link WeaponView},
|
|
19
|
+
* keeping each entry's count alongside. Unresolved entries are dropped
|
|
20
|
+
* silently (matching {@link resolveRosterUnit}). Useful when the SPA
|
|
21
|
+
* needs to enumerate firing options after the user picks a roster unit.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveRosterWargear(wargear, dataset) {
|
|
24
|
+
const out = [];
|
|
25
|
+
for (const w of wargear) {
|
|
26
|
+
const id = w.ref.id;
|
|
27
|
+
if (id === null)
|
|
28
|
+
continue;
|
|
29
|
+
const weapon = dataset.weapons.get(id);
|
|
30
|
+
if (!weapon)
|
|
31
|
+
continue;
|
|
32
|
+
out.push({ weapon, count: w.count });
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The roster's leader entry attached to `bodyguardUnitId`, if any. Import
|
|
38
|
+
* stores the inferred (always-provisional) attachment on the *leader's*
|
|
39
|
+
* {@link RosterUnit}, pointing down to its bodyguard via
|
|
40
|
+
* `leader_attachment.bodyguard_ref`. Selection UIs start from the body unit,
|
|
41
|
+
* so this scans for the leader whose `bodyguard_ref.id` matches. Returns
|
|
42
|
+
* `undefined` when no leader in the roster is attached to that unit (the
|
|
43
|
+
* common case — attachments are optional at game start).
|
|
44
|
+
*/
|
|
45
|
+
export function resolveAttachedLeader(roster, bodyguardUnitId) {
|
|
46
|
+
return roster.units.find((u) => u.leader_attachment?.bodyguard_ref.id === bodyguardUnitId);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Every roster unit attached to `unitId`, resolved from *either* end of the
|
|
50
|
+
* attachment. A leader+bodyguard are one combined unit, so a selection UI may
|
|
51
|
+
* start from either half:
|
|
52
|
+
* - `unitId` is the **bodyguard** → the leader(s) whose
|
|
53
|
+
* `leader_attachment.bodyguard_ref.id` points at it (body-first, the
|
|
54
|
+
* {@link resolveAttachedLeader} direction), and
|
|
55
|
+
* - `unitId` is the **leader** → the bodyguard its own `leader_attachment`
|
|
56
|
+
* points to.
|
|
57
|
+
* Returns the partner {@link RosterUnit}s (deduped, source order). Empty when
|
|
58
|
+
* the unit has no attachment in this roster — the common case, since
|
|
59
|
+
* attachments are optional at game start. Shaped as a list to carry 11th
|
|
60
|
+
* edition's multi-member attachments without an API change.
|
|
61
|
+
*/
|
|
62
|
+
export function resolveAttachmentPartners(roster, unitId) {
|
|
63
|
+
const seen = new Set();
|
|
64
|
+
const out = [];
|
|
65
|
+
const add = (u) => {
|
|
66
|
+
if (!u || seen.has(u))
|
|
67
|
+
return;
|
|
68
|
+
seen.add(u);
|
|
69
|
+
out.push(u);
|
|
70
|
+
};
|
|
71
|
+
for (const u of roster.units) {
|
|
72
|
+
// Body-first: leaders pointing down at `unitId`.
|
|
73
|
+
if (u.leader_attachment?.bodyguard_ref.id === unitId)
|
|
74
|
+
add(u);
|
|
75
|
+
// Leader-first: `unitId`'s own entry points down at a bodyguard.
|
|
76
|
+
if (u.ref.id === unitId && u.leader_attachment) {
|
|
77
|
+
add(roster.units.find((b) => b.ref.id === u.leader_attachment.bodyguard_ref.id));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=roster-resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster-resolve.js","sourceRoot":"","sources":["../../src/data/roster-resolve.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAsB,EACtB,OAAgB;IAEhB,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7B,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClC,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAwB,EACxB,OAAgB;IAEhB,MAAM,GAAG,GAA4C,EAAE,CAAC;IACxD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,IAAI,EAAE,KAAK,IAAI;YAAE,SAAS;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAc,EACd,eAAuB;IAEvB,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE,aAAa,CAAC,EAAE,KAAK,eAAe,CACjE,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAc,EACd,MAAc;IAEd,MAAM,IAAI,GAAG,IAAI,GAAG,EAAc,CAAC;IACnC,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,CAAC,CAAyB,EAAE,EAAE;QACxC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO;QAC9B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACZ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,iDAAiD;QACjD,IAAI,CAAC,CAAC,iBAAiB,EAAE,aAAa,CAAC,EAAE,KAAK,MAAM;YAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC7D,iEAAiE;QACjE,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;YAC/C,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,iBAAkB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["/**\n * Bridge helpers between the importer's flat-data {@link Roster} types and\n * the linked {@link UnitView} the cruncher consumes. The importer ships\n * unit entries as plain interfaces (`RosterUnit` is data, not behaviour),\n * so the lookup is a free function rather than a method.\n *\n * @packageDocumentation\n */\nimport type { Roster, RosterUnit, RosterWargear } from \"../import/types.js\";\nimport type { Dataset } from \"./dataset.js\";\nimport type { UnitView, WeaponView } from \"./entities.js\";\n\n/**\n * Resolve a roster's unit entry against the dataset, returning the linked\n * {@link UnitView}. Returns `undefined` when:\n * - the roster's `ref.id` is `null` (the importer couldn't match the unit), or\n * - the id doesn't appear in the dataset (e.g. the roster was authored\n * against an older dataslate than the bundled one).\n *\n * Doesn't surface diagnostics — the caller already has them on the roster's\n * own `diagnostics` field.\n */\nexport function resolveRosterUnit(\n rosterUnit: RosterUnit,\n dataset: Dataset,\n): UnitView | undefined {\n const id = rosterUnit.ref.id;\n if (id === null) return undefined;\n return dataset.units.get(id);\n}\n\n/**\n * Resolve every wargear entry on a roster unit to a {@link WeaponView},\n * keeping each entry's count alongside. Unresolved entries are dropped\n * silently (matching {@link resolveRosterUnit}). Useful when the SPA\n * needs to enumerate firing options after the user picks a roster unit.\n */\nexport function resolveRosterWargear(\n wargear: RosterWargear[],\n dataset: Dataset,\n): { weapon: WeaponView; count: number }[] {\n const out: { weapon: WeaponView; count: number }[] = [];\n for (const w of wargear) {\n const id = w.ref.id;\n if (id === null) continue;\n const weapon = dataset.weapons.get(id);\n if (!weapon) continue;\n out.push({ weapon, count: w.count });\n }\n return out;\n}\n\n/**\n * The roster's leader entry attached to `bodyguardUnitId`, if any. Import\n * stores the inferred (always-provisional) attachment on the *leader's*\n * {@link RosterUnit}, pointing down to its bodyguard via\n * `leader_attachment.bodyguard_ref`. Selection UIs start from the body unit,\n * so this scans for the leader whose `bodyguard_ref.id` matches. Returns\n * `undefined` when no leader in the roster is attached to that unit (the\n * common case — attachments are optional at game start).\n */\nexport function resolveAttachedLeader(\n roster: Roster,\n bodyguardUnitId: string,\n): RosterUnit | undefined {\n return roster.units.find(\n (u) => u.leader_attachment?.bodyguard_ref.id === bodyguardUnitId,\n );\n}\n\n/**\n * Every roster unit attached to `unitId`, resolved from *either* end of the\n * attachment. A leader+bodyguard are one combined unit, so a selection UI may\n * start from either half:\n * - `unitId` is the **bodyguard** → the leader(s) whose\n * `leader_attachment.bodyguard_ref.id` points at it (body-first, the\n * {@link resolveAttachedLeader} direction), and\n * - `unitId` is the **leader** → the bodyguard its own `leader_attachment`\n * points to.\n * Returns the partner {@link RosterUnit}s (deduped, source order). Empty when\n * the unit has no attachment in this roster — the common case, since\n * attachments are optional at game start. Shaped as a list to carry 11th\n * edition's multi-member attachments without an API change.\n */\nexport function resolveAttachmentPartners(\n roster: Roster,\n unitId: string,\n): RosterUnit[] {\n const seen = new Set<RosterUnit>();\n const out: RosterUnit[] = [];\n const add = (u: RosterUnit | undefined) => {\n if (!u || seen.has(u)) return;\n seen.add(u);\n out.push(u);\n };\n\n for (const u of roster.units) {\n // Body-first: leaders pointing down at `unitId`.\n if (u.leader_attachment?.bodyguard_ref.id === unitId) add(u);\n // Leader-first: `unitId`'s own entry points down at a bodyguard.\n if (u.ref.id === unitId && u.leader_attachment) {\n add(roster.units.find((b) => b.ref.id === u.leader_attachment!.bodyguard_ref.id));\n }\n }\n return out;\n}\n"]}
|
package/dist/data/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @packageDocumentation
|
|
9
9
|
*/
|
|
10
|
-
import type { AbilityDSLEntry, DeploymentPattern, Detachment, Enhancement, Faction, ForceDisposition, GameVersion, InteractionFlag, LeaderAttachment, Mission, MissionMatchup, PhaseMapping, ResourcePool, SecondaryCard, Stratagem, TimingFlag, Unit, UnitComposition, WargearOption, Weapon } from "../generated.js";
|
|
10
|
+
import type { AbilityDSLEntry, DeploymentPattern, Detachment, Enhancement, Faction, ForceDisposition, GameVersion, InteractionFlag, LeaderAttachment, Mission, MissionMatchup, PhaseMapping, ResourcePool, SecondaryCard, Stratagem, TimingFlag, Unit, UnitComposition, WargearOption, Weapon, WeaponKeyword } from "../generated.js";
|
|
11
11
|
/**
|
|
12
12
|
* Every entity collection in the dataset, keyed by camelCase collection name.
|
|
13
13
|
*
|
|
@@ -18,6 +18,8 @@ import type { AbilityDSLEntry, DeploymentPattern, Detachment, Enhancement, Facti
|
|
|
18
18
|
export interface RawData {
|
|
19
19
|
units: Unit[];
|
|
20
20
|
weapons: Weapon[];
|
|
21
|
+
/** Catalog of weapon keywords (Lethal Hits, Sustained Hits N, Anti-X N+, ...). */
|
|
22
|
+
weaponKeywords: WeaponKeyword[];
|
|
21
23
|
factions: Faction[];
|
|
22
24
|
/** Community-authored ability mechanics (key is `ability_id`, not `id`). */
|
|
23
25
|
abilities: AbilityDSLEntry[];
|
|
@@ -41,3 +43,4 @@ export interface RawData {
|
|
|
41
43
|
}
|
|
42
44
|
/** A `RawData` with every collection initialised to an empty array. */
|
|
43
45
|
export declare function emptyRawData(): RawData;
|
|
46
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,SAAS,EACT,UAAU,EACV,IAAI,EACJ,eAAe,EACf,aAAa,EACb,MAAM,EACN,aAAa,EACd,MAAM,iBAAiB,CAAC;AAEzB;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kFAAkF;IAClF,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,4EAA4E;IAC5E,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,8EAA8E;IAC9E,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;IACxC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,gBAAgB,EAAE,eAAe,EAAE,CAAC;CACrC;AAED,uEAAuE;AACvE,wBAAgB,YAAY,IAAI,OAAO,CAwBtC"}
|
package/dist/data/types.js
CHANGED
|
@@ -3,6 +3,7 @@ export function emptyRawData() {
|
|
|
3
3
|
return {
|
|
4
4
|
units: [],
|
|
5
5
|
weapons: [],
|
|
6
|
+
weaponKeywords: [],
|
|
6
7
|
factions: [],
|
|
7
8
|
abilities: [],
|
|
8
9
|
phaseMappings: [],
|
|
@@ -23,3 +24,4 @@ export function emptyRawData() {
|
|
|
23
24
|
interactionFlags: [],
|
|
24
25
|
};
|
|
25
26
|
}
|
|
27
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/data/types.ts"],"names":[],"mappings":"AAmEA,uEAAuE;AACvE,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE;QACX,cAAc,EAAE,EAAE;QAClB,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,EAAE;QACb,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,EAAE;QACf,UAAU,EAAE,EAAE;QACd,YAAY,EAAE,EAAE;QAChB,iBAAiB,EAAE,EAAE;QACrB,gBAAgB,EAAE,EAAE;QACpB,cAAc,EAAE,EAAE;QAClB,YAAY,EAAE,EAAE;QAChB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,EAAE;QACnB,cAAc,EAAE,EAAE;QAClB,kBAAkB,EAAE,EAAE;QACtB,iBAAiB,EAAE,EAAE;QACrB,aAAa,EAAE,EAAE;QACjB,WAAW,EAAE,EAAE;QACf,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The shape of the embedded data bundle: one named array per entity collection.\n *\n * `RawData` is the boundary between the generated JSON-Schema types and the\n * linked view layer. The codegen ({@link file://../codegen-data.ts}) emits a\n * `RAW_DATA: RawData` constant; {@link Dataset} wraps it with linked accessors.\n *\n * @packageDocumentation\n */\nimport type {\n AbilityDSLEntry,\n DeploymentPattern,\n Detachment,\n Enhancement,\n Faction,\n ForceDisposition,\n GameVersion,\n InteractionFlag,\n LeaderAttachment,\n Mission,\n MissionMatchup,\n PhaseMapping,\n ResourcePool,\n SecondaryCard,\n Stratagem,\n TimingFlag,\n Unit,\n UnitComposition,\n WargearOption,\n Weapon,\n WeaponKeyword,\n} from \"../generated.js\";\n\n/**\n * Every entity collection in the dataset, keyed by camelCase collection name.\n *\n * Collections with no authored data yet (e.g. `interactionFlags`) are present\n * as empty arrays so the API surface is stable and new data flows through\n * automatically once authored.\n */\nexport interface RawData {\n units: Unit[];\n weapons: Weapon[];\n /** Catalog of weapon keywords (Lethal Hits, Sustained Hits N, Anti-X N+, ...). */\n weaponKeywords: WeaponKeyword[];\n factions: Faction[];\n /** Community-authored ability mechanics (key is `ability_id`, not `id`). */\n abilities: AbilityDSLEntry[];\n /** Phase assignments, joined to abilities/stratagems/etc. via `source_id`. */\n phaseMappings: PhaseMapping[];\n detachments: Detachment[];\n stratagems: Stratagem[];\n enhancements: Enhancement[];\n leaderAttachments: LeaderAttachment[];\n unitCompositions: UnitComposition[];\n wargearOptions: WargearOption[];\n gameVersions: GameVersion[];\n missions: Mission[];\n missionMatchups: MissionMatchup[];\n secondaryCards: SecondaryCard[];\n deploymentPatterns: DeploymentPattern[];\n forceDispositions: ForceDisposition[];\n resourcePools: ResourcePool[];\n timingFlags: TimingFlag[];\n interactionFlags: InteractionFlag[];\n}\n\n/** A `RawData` with every collection initialised to an empty array. */\nexport function emptyRawData(): RawData {\n return {\n units: [],\n weapons: [],\n weaponKeywords: [],\n factions: [],\n abilities: [],\n phaseMappings: [],\n detachments: [],\n stratagems: [],\n enhancements: [],\n leaderAttachments: [],\n unitCompositions: [],\n wargearOptions: [],\n gameVersions: [],\n missions: [],\n missionMatchups: [],\n secondaryCards: [],\n deploymentPatterns: [],\n forceDispositions: [],\n resourcePools: [],\n timingFlags: [],\n interactionFlags: [],\n };\n}\n"]}
|