rpg-engine 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +101 -2
- package/dist/campaign/create-campaign.d.ts +6 -0
- package/dist/campaign/create-campaign.js +71 -0
- package/dist/campaign/find-campaign.d.ts +8 -0
- package/dist/campaign/find-campaign.js +28 -0
- package/dist/campaign/host-files.d.ts +16 -0
- package/dist/campaign/host-files.js +134 -0
- package/dist/campaign/index.d.ts +5 -0
- package/dist/campaign/index.js +6 -0
- package/dist/campaign/settings.d.ts +185 -0
- package/dist/campaign/settings.js +399 -0
- package/dist/campaign/state.d.ts +15 -0
- package/dist/campaign/state.js +52 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +19 -0
- package/dist/command-line.d.ts +7 -0
- package/dist/command-line.js +140 -0
- package/dist/commands/advance.d.ts +7 -0
- package/dist/commands/advance.js +80 -0
- package/dist/commands/ask.d.ts +33 -0
- package/dist/commands/ask.js +280 -0
- package/dist/commands/change.d.ts +69 -0
- package/dist/commands/change.js +604 -0
- package/dist/commands/config.d.ts +59 -0
- package/dist/commands/config.js +512 -0
- package/dist/commands/effect-layer.d.ts +22 -0
- package/dist/commands/effect-layer.js +84 -0
- package/dist/commands/effect.d.ts +27 -0
- package/dist/commands/effect.js +369 -0
- package/dist/commands/find.d.ts +34 -0
- package/dist/commands/find.js +64 -0
- package/dist/commands/game-advance.d.ts +50 -0
- package/dist/commands/game-advance.js +103 -0
- package/dist/commands/game-effects.d.ts +68 -0
- package/dist/commands/game-effects.js +196 -0
- package/dist/commands/game-environment.d.ts +16 -0
- package/dist/commands/game-environment.js +24 -0
- package/dist/commands/game-events.d.ts +84 -0
- package/dist/commands/game-events.js +325 -0
- package/dist/commands/game-experience.d.ts +57 -0
- package/dist/commands/game-experience.js +119 -0
- package/dist/commands/game-grid-moves.d.ts +33 -0
- package/dist/commands/game-grid-moves.js +94 -0
- package/dist/commands/game-grids.d.ts +52 -0
- package/dist/commands/game-grids.js +162 -0
- package/dist/commands/game-here.d.ts +40 -0
- package/dist/commands/game-here.js +100 -0
- package/dist/commands/game-images.d.ts +31 -0
- package/dist/commands/game-images.js +87 -0
- package/dist/commands/game-journey.d.ts +62 -0
- package/dist/commands/game-journey.js +163 -0
- package/dist/commands/game-knowledge.d.ts +32 -0
- package/dist/commands/game-knowledge.js +120 -0
- package/dist/commands/game-maps.d.ts +20 -0
- package/dist/commands/game-maps.js +51 -0
- package/dist/commands/game-mode.d.ts +31 -0
- package/dist/commands/game-mode.js +128 -0
- package/dist/commands/game-money.d.ts +17 -0
- package/dist/commands/game-money.js +55 -0
- package/dist/commands/game-moods.d.ts +22 -0
- package/dist/commands/game-moods.js +32 -0
- package/dist/commands/game-moves.d.ts +14 -0
- package/dist/commands/game-moves.js +43 -0
- package/dist/commands/game-open.d.ts +18 -0
- package/dist/commands/game-open.js +47 -0
- package/dist/commands/game-outside.d.ts +14 -0
- package/dist/commands/game-outside.js +151 -0
- package/dist/commands/game-positions.d.ts +52 -0
- package/dist/commands/game-positions.js +244 -0
- package/dist/commands/game-quests.d.ts +46 -0
- package/dist/commands/game-quests.js +97 -0
- package/dist/commands/game-recipes.d.ts +34 -0
- package/dist/commands/game-recipes.js +109 -0
- package/dist/commands/game-reminders.d.ts +22 -0
- package/dist/commands/game-reminders.js +74 -0
- package/dist/commands/game-roads.d.ts +90 -0
- package/dist/commands/game-roads.js +284 -0
- package/dist/commands/game-rules.d.ts +17 -0
- package/dist/commands/game-rules.js +30 -0
- package/dist/commands/game-saves.d.ts +59 -0
- package/dist/commands/game-saves.js +249 -0
- package/dist/commands/game-scene.d.ts +69 -0
- package/dist/commands/game-scene.js +285 -0
- package/dist/commands/game-thresholds.d.ts +13 -0
- package/dist/commands/game-thresholds.js +41 -0
- package/dist/commands/game-time.d.ts +17 -0
- package/dist/commands/game-time.js +42 -0
- package/dist/commands/game-view-journal.d.ts +145 -0
- package/dist/commands/game-view-journal.js +129 -0
- package/dist/commands/game-view-map.d.ts +78 -0
- package/dist/commands/game-view-map.js +266 -0
- package/dist/commands/game-view-place.d.ts +160 -0
- package/dist/commands/game-view-place.js +388 -0
- package/dist/commands/game-world.d.ts +60 -0
- package/dist/commands/game-world.js +204 -0
- package/dist/commands/image.d.ts +19 -0
- package/dist/commands/image.js +185 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +57 -0
- package/dist/commands/init.d.ts +23 -0
- package/dist/commands/init.js +44 -0
- package/dist/commands/install.d.ts +23 -0
- package/dist/commands/install.js +68 -0
- package/dist/commands/instructions.d.ts +4 -0
- package/dist/commands/instructions.js +97 -0
- package/dist/commands/mode.d.ts +23 -0
- package/dist/commands/mode.js +84 -0
- package/dist/commands/mood.d.ts +34 -0
- package/dist/commands/mood.js +113 -0
- package/dist/commands/move.d.ts +34 -0
- package/dist/commands/move.js +274 -0
- package/dist/commands/notes.d.ts +10 -0
- package/dist/commands/notes.js +37 -0
- package/dist/commands/page-counters.d.ts +24 -0
- package/dist/commands/page-counters.js +84 -0
- package/dist/commands/parts.d.ts +16 -0
- package/dist/commands/parts.js +49 -0
- package/dist/commands/problems.d.ts +5 -0
- package/dist/commands/problems.js +47 -0
- package/dist/commands/progression.d.ts +68 -0
- package/dist/commands/progression.js +206 -0
- package/dist/commands/rename.d.ts +16 -0
- package/dist/commands/rename.js +116 -0
- package/dist/commands/reveal.d.ts +25 -0
- package/dist/commands/reveal.js +193 -0
- package/dist/commands/roll.d.ts +56 -0
- package/dist/commands/roll.js +302 -0
- package/dist/commands/route.d.ts +19 -0
- package/dist/commands/route.js +110 -0
- package/dist/commands/rules.d.ts +48 -0
- package/dist/commands/rules.js +194 -0
- package/dist/commands/save.d.ts +68 -0
- package/dist/commands/save.js +141 -0
- package/dist/commands/scene.d.ts +105 -0
- package/dist/commands/scene.js +741 -0
- package/dist/commands/sheet.d.ts +136 -0
- package/dist/commands/sheet.js +445 -0
- package/dist/commands/show.d.ts +76 -0
- package/dist/commands/show.js +216 -0
- package/dist/commands/status.d.ts +54 -0
- package/dist/commands/status.js +291 -0
- package/dist/commands/translate.d.ts +23 -0
- package/dist/commands/translate.js +108 -0
- package/dist/commands/travel.d.ts +47 -0
- package/dist/commands/travel.js +457 -0
- package/dist/commands/validate.d.ts +4 -0
- package/dist/commands/validate.js +25 -0
- package/dist/commands/view.d.ts +272 -0
- package/dist/commands/view.js +623 -0
- package/dist/commands/worked-out.d.ts +116 -0
- package/dist/commands/worked-out.js +704 -0
- package/dist/commands/write.d.ts +51 -0
- package/dist/commands/write.js +1017 -0
- package/dist/core/command-reference.d.ts +6 -0
- package/dist/core/command-reference.js +47 -0
- package/dist/core/context.d.ts +140 -0
- package/dist/core/context.js +28 -0
- package/dist/core/field-kind.d.ts +6 -0
- package/dist/core/field-kind.js +5 -0
- package/dist/core/files.d.ts +4 -0
- package/dist/core/files.js +30 -0
- package/dist/core/formula.d.ts +164 -0
- package/dist/core/formula.js +590 -0
- package/dist/core/frozen.d.ts +2 -0
- package/dist/core/frozen.js +11 -0
- package/dist/core/length.d.ts +27 -0
- package/dist/core/length.js +49 -0
- package/dist/core/log.d.ts +27 -0
- package/dist/core/log.js +38 -0
- package/dist/core/memo.d.ts +2 -0
- package/dist/core/memo.js +17 -0
- package/dist/core/mood.d.ts +6 -0
- package/dist/core/mood.js +11 -0
- package/dist/core/problem.d.ts +6 -0
- package/dist/core/problem.js +1 -0
- package/dist/core/progression-rule.d.ts +21 -0
- package/dist/core/progression-rule.js +2 -0
- package/dist/core/registry.d.ts +31 -0
- package/dist/core/registry.js +25 -0
- package/dist/core/session-store.d.ts +90 -0
- package/dist/core/session-store.js +289 -0
- package/dist/core/store.d.ts +83 -0
- package/dist/core/store.js +224 -0
- package/dist/core/text.d.ts +12 -0
- package/dist/core/text.js +32 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.js +6 -0
- package/dist/core/yaml-file.d.ts +10 -0
- package/dist/core/yaml-file.js +42 -0
- package/dist/counters/counter.d.ts +36 -0
- package/dist/counters/counter.js +59 -0
- package/dist/counters/index.d.ts +1 -0
- package/dist/counters/index.js +2 -0
- package/dist/dashboard/address.js +43 -0
- package/dist/dashboard/api.js +185 -0
- package/dist/dashboard/app.js +217 -0
- package/dist/dashboard/asked.js +132 -0
- package/dist/dashboard/assets/dice/dice-sharp.glb +0 -0
- package/dist/dashboard/assets/dice/dice.glb +0 -0
- package/dist/dashboard/assets/dice/dice.json +1 -0
- package/dist/dashboard/assets/dice/textures/ash.jpg +0 -0
- package/dist/dashboard/assets/dice/textures/granite.jpg +0 -0
- package/dist/dashboard/assets/dice/textures/marble.jpg +0 -0
- package/dist/dashboard/assets/dice/textures/onyx.jpg +0 -0
- package/dist/dashboard/assets/dice/textures/walnut.jpg +0 -0
- package/dist/dashboard/assets/favicon.svg +7 -0
- package/dist/dashboard/assets/icon-180.png +0 -0
- package/dist/dashboard/assets/icon-32.png +0 -0
- package/dist/dashboard/assets/master.svg +71 -0
- package/dist/dashboard/assets/sounds/dice-collision.wav +0 -0
- package/dist/dashboard/assets/sounds/dice-touch.wav +0 -0
- package/dist/dashboard/card.js +61 -0
- package/dist/dashboard/columns.js +37 -0
- package/dist/dashboard/combat.js +72 -0
- package/dist/dashboard/data.js +3 -0
- package/dist/dashboard/dice/burn.js +200 -0
- package/dist/dashboard/dice/celebration.js +199 -0
- package/dist/dashboard/dice/floor-cracks.js +149 -0
- package/dist/dashboard/dice/frost.js +51 -0
- package/dist/dashboard/dice/load.js +66 -0
- package/dist/dashboard/dice/models.js +138 -0
- package/dist/dashboard/dice/pool.js +49 -0
- package/dist/dashboard/dice/roller.js +101 -0
- package/dist/dashboard/dice/sets.js +49 -0
- package/dist/dashboard/dice/sounds.js +102 -0
- package/dist/dashboard/dice/stage.js +355 -0
- package/dist/dashboard/dice/throw.js +242 -0
- package/dist/dashboard/dice/tray.js +365 -0
- package/dist/dashboard/faces.js +16 -0
- package/dist/dashboard/footer.js +17 -0
- package/dist/dashboard/free-rolls.js +41 -0
- package/dist/dashboard/game-words.js +164 -0
- package/dist/dashboard/glass.js +12 -0
- package/dist/dashboard/guide/ar.md +308 -0
- package/dist/dashboard/guide/cs.md +308 -0
- package/dist/dashboard/guide/da.md +308 -0
- package/dist/dashboard/guide/de.md +308 -0
- package/dist/dashboard/guide/el.md +308 -0
- package/dist/dashboard/guide/en.md +307 -0
- package/dist/dashboard/guide/es.md +308 -0
- package/dist/dashboard/guide/fi.md +308 -0
- package/dist/dashboard/guide/fr.md +308 -0
- package/dist/dashboard/guide/he.md +308 -0
- package/dist/dashboard/guide/hi.md +308 -0
- package/dist/dashboard/guide/hu.md +308 -0
- package/dist/dashboard/guide/is.md +308 -0
- package/dist/dashboard/guide/it.md +308 -0
- package/dist/dashboard/guide/ja.md +308 -0
- package/dist/dashboard/guide/ko.md +308 -0
- package/dist/dashboard/guide/nb.md +308 -0
- package/dist/dashboard/guide/nl.md +308 -0
- package/dist/dashboard/guide/pl.md +308 -0
- package/dist/dashboard/guide/pt.md +308 -0
- package/dist/dashboard/guide/ro.md +308 -0
- package/dist/dashboard/guide/ru.md +308 -0
- package/dist/dashboard/guide/sv.md +308 -0
- package/dist/dashboard/guide/tr.md +308 -0
- package/dist/dashboard/guide/uk.md +308 -0
- package/dist/dashboard/guide/zh.md +308 -0
- package/dist/dashboard/guide-blocks.js +72 -0
- package/dist/dashboard/guide-markdown.js +63 -0
- package/dist/dashboard/help.js +92 -0
- package/dist/dashboard/i18n/ar.json +670 -0
- package/dist/dashboard/i18n/cs.json +670 -0
- package/dist/dashboard/i18n/da.json +670 -0
- package/dist/dashboard/i18n/de.json +670 -0
- package/dist/dashboard/i18n/el.json +670 -0
- package/dist/dashboard/i18n/es.json +670 -0
- package/dist/dashboard/i18n/fi.json +670 -0
- package/dist/dashboard/i18n/fr.json +670 -0
- package/dist/dashboard/i18n/he.json +670 -0
- package/dist/dashboard/i18n/hi.json +670 -0
- package/dist/dashboard/i18n/hu.json +670 -0
- package/dist/dashboard/i18n/is.json +670 -0
- package/dist/dashboard/i18n/it.json +670 -0
- package/dist/dashboard/i18n/ja.json +670 -0
- package/dist/dashboard/i18n/ko.json +670 -0
- package/dist/dashboard/i18n/nb.json +670 -0
- package/dist/dashboard/i18n/nl.json +670 -0
- package/dist/dashboard/i18n/pl.json +670 -0
- package/dist/dashboard/i18n/pt.json +670 -0
- package/dist/dashboard/i18n/ro.json +670 -0
- package/dist/dashboard/i18n/ru.json +670 -0
- package/dist/dashboard/i18n/sv.json +670 -0
- package/dist/dashboard/i18n/tr.json +670 -0
- package/dist/dashboard/i18n/uk.json +670 -0
- package/dist/dashboard/i18n/zh.json +670 -0
- package/dist/dashboard/icons.js +123 -0
- package/dist/dashboard/journal.js +188 -0
- package/dist/dashboard/labels.js +226 -0
- package/dist/dashboard/language-choice.js +83 -0
- package/dist/dashboard/languages.js +144 -0
- package/dist/dashboard/layout.js +93 -0
- package/dist/dashboard/map-sheet.js +32 -0
- package/dist/dashboard/map-symbols.js +79 -0
- package/dist/dashboard/markdown.js +72 -0
- package/dist/dashboard/master.js +69 -0
- package/dist/dashboard/mood-faces.js +16 -0
- package/dist/dashboard/mood.js +27 -0
- package/dist/dashboard/notes.js +203 -0
- package/dist/dashboard/notices.js +24 -0
- package/dist/dashboard/pages.js +32 -0
- package/dist/dashboard/party.js +65 -0
- package/dist/dashboard/place-map-view.js +362 -0
- package/dist/dashboard/place-map.js +204 -0
- package/dist/dashboard/prefs.js +97 -0
- package/dist/dashboard/reactions.js +28 -0
- package/dist/dashboard/requested.js +32 -0
- package/dist/dashboard/rolls.js +240 -0
- package/dist/dashboard/saves.js +154 -0
- package/dist/dashboard/scene.js +63 -0
- package/dist/dashboard/settings.js +362 -0
- package/dist/dashboard/setup.js +195 -0
- package/dist/dashboard/sheet.js +180 -0
- package/dist/dashboard/status.js +42 -0
- package/dist/dashboard/story.js +51 -0
- package/dist/dashboard/style.css +9355 -0
- package/dist/dashboard/text.js +158 -0
- package/dist/dashboard/theme.js +32 -0
- package/dist/dashboard/top.js +156 -0
- package/dist/dashboard/widgets.js +69 -0
- package/dist/dashboard/world-map.js +523 -0
- package/dist/dashboard/world.js +357 -0
- package/dist/dashboard-server.d.ts +38 -0
- package/dist/dashboard-server.js +818 -0
- package/dist/dice/evaluate.d.ts +30 -0
- package/dist/dice/evaluate.js +90 -0
- package/dist/dice/format.d.ts +3 -0
- package/dist/dice/format.js +26 -0
- package/dist/dice/index.d.ts +4 -0
- package/dist/dice/index.js +5 -0
- package/dist/dice/notation.d.ts +43 -0
- package/dist/dice/notation.js +132 -0
- package/dist/dice/proof.d.ts +4 -0
- package/dist/dice/proof.js +12 -0
- package/dist/dice/roll-dice.d.ts +29 -0
- package/dist/dice/roll-dice.js +43 -0
- package/dist/dice/words.d.ts +12 -0
- package/dist/dice/words.js +21 -0
- package/dist/effects/effect.d.ts +57 -0
- package/dist/effects/effect.js +123 -0
- package/dist/effects/index.d.ts +1 -0
- package/dist/effects/index.js +2 -0
- package/dist/grid/grid.d.ts +53 -0
- package/dist/grid/grid.js +151 -0
- package/dist/grid/index.d.ts +2 -0
- package/dist/grid/index.js +2 -0
- package/dist/grid/paths.d.ts +27 -0
- package/dist/grid/paths.js +128 -0
- package/dist/images/images.d.ts +26 -0
- package/dist/images/images.js +74 -0
- package/dist/images/index.d.ts +1 -0
- package/dist/images/index.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/instructions/index.d.ts +17 -0
- package/dist/instructions/index.js +48 -0
- package/dist/map/geometry.d.ts +22 -0
- package/dist/map/geometry.js +66 -0
- package/dist/map/index.d.ts +3 -0
- package/dist/map/index.js +5 -0
- package/dist/map/looks.d.ts +9 -0
- package/dist/map/looks.js +57 -0
- package/dist/map/ways.d.ts +36 -0
- package/dist/map/ways.js +78 -0
- package/dist/mcp-server.d.ts +22 -0
- package/dist/mcp-server.js +289 -0
- package/dist/money/index.d.ts +1 -0
- package/dist/money/index.js +2 -0
- package/dist/money/money.d.ts +48 -0
- package/dist/money/money.js +218 -0
- package/dist/page-words.d.ts +46 -0
- package/dist/page-words.js +221 -0
- package/dist/pages/check.d.ts +9 -0
- package/dist/pages/check.js +345 -0
- package/dist/pages/containers.d.ts +34 -0
- package/dist/pages/containers.js +181 -0
- package/dist/pages/environment.d.ts +26 -0
- package/dist/pages/environment.js +118 -0
- package/dist/pages/index.d.ts +15 -0
- package/dist/pages/index.js +16 -0
- package/dist/pages/inheritance.d.ts +80 -0
- package/dist/pages/inheritance.js +260 -0
- package/dist/pages/maps.d.ts +11 -0
- package/dist/pages/maps.js +14 -0
- package/dist/pages/markdown.d.ts +59 -0
- package/dist/pages/markdown.js +271 -0
- package/dist/pages/page-file.d.ts +26 -0
- package/dist/pages/page-file.js +166 -0
- package/dist/pages/page-types.d.ts +17 -0
- package/dist/pages/page-types.js +18 -0
- package/dist/pages/positions.d.ts +11 -0
- package/dist/pages/positions.js +23 -0
- package/dist/pages/rename-page.d.ts +39 -0
- package/dist/pages/rename-page.js +109 -0
- package/dist/pages/roads.d.ts +11 -0
- package/dist/pages/roads.js +40 -0
- package/dist/pages/standard-fields.d.ts +31 -0
- package/dist/pages/standard-fields.js +142 -0
- package/dist/pages/system-pages.d.ts +35 -0
- package/dist/pages/system-pages.js +98 -0
- package/dist/pages/world.d.ts +174 -0
- package/dist/pages/world.js +349 -0
- package/dist/pages/write-page.d.ts +27 -0
- package/dist/pages/write-page.js +311 -0
- package/dist/pictures/briefs.d.ts +25 -0
- package/dist/pictures/briefs.js +145 -0
- package/dist/pictures/chosen.d.ts +5 -0
- package/dist/pictures/chosen.js +21 -0
- package/dist/pictures/claude.d.ts +14 -0
- package/dist/pictures/claude.js +129 -0
- package/dist/pictures/codex.d.ts +20 -0
- package/dist/pictures/codex.js +154 -0
- package/dist/pictures/helpers.d.ts +26 -0
- package/dist/pictures/helpers.js +219 -0
- package/dist/pictures/index.d.ts +6 -0
- package/dist/pictures/index.js +8 -0
- package/dist/pictures/stop.d.ts +3 -0
- package/dist/pictures/stop.js +10 -0
- package/dist/pictures/svg.d.ts +4 -0
- package/dist/pictures/svg.js +129 -0
- package/dist/player-notes/index.d.ts +1 -0
- package/dist/player-notes/index.js +2 -0
- package/dist/player-notes/notes.d.ts +21 -0
- package/dist/player-notes/notes.js +50 -0
- package/dist/progression/index.d.ts +1 -0
- package/dist/progression/index.js +1 -0
- package/dist/progression/level-table.d.ts +41 -0
- package/dist/progression/level-table.js +123 -0
- package/dist/rules/index.d.ts +3 -0
- package/dist/rules/index.js +4 -0
- package/dist/rules/rule-book.d.ts +31 -0
- package/dist/rules/rule-book.js +157 -0
- package/dist/rules/search.d.ts +18 -0
- package/dist/rules/search.js +101 -0
- package/dist/rules/shown.d.ts +19 -0
- package/dist/rules/shown.js +44 -0
- package/dist/saves/index.d.ts +1 -0
- package/dist/saves/index.js +2 -0
- package/dist/saves/saves.d.ts +14 -0
- package/dist/saves/saves.js +27 -0
- package/dist/scene/index.d.ts +1 -0
- package/dist/scene/index.js +2 -0
- package/dist/scene/scene.d.ts +46 -0
- package/dist/scene/scene.js +44 -0
- package/dist/systems/game-system.d.ts +236 -0
- package/dist/systems/game-system.js +593 -0
- package/dist/systems/index.d.ts +2 -0
- package/dist/systems/index.js +3 -0
- package/dist/systems/words.d.ts +9 -0
- package/dist/systems/words.js +23 -0
- package/dist/time/game-date.d.ts +20 -0
- package/dist/time/game-date.js +59 -0
- package/dist/time/index.d.ts +1 -0
- package/dist/time/index.js +2 -0
- package/dist/triggers/index.d.ts +1 -0
- package/dist/triggers/index.js +2 -0
- package/dist/triggers/trigger.d.ts +43 -0
- package/dist/triggers/trigger.js +98 -0
- package/instructions/author.md +1 -0
- package/instructions/buttons-physical-dice.md +1 -0
- package/instructions/buttons.md +1 -0
- package/instructions/combat.md +3 -0
- package/instructions/core.md +54 -0
- package/instructions/dashboard.md +7 -0
- package/instructions/mentor-hints.md +1 -0
- package/instructions/mentor-tutorial.md +1 -0
- package/instructions/new-day.md +1 -0
- package/instructions/play.md +23 -0
- package/instructions/prose-literary.md +1 -0
- package/instructions/prose-pulp.md +1 -0
- package/instructions/prose-wry.md +1 -0
- package/instructions/session-zero.md +3 -0
- package/instructions/setup.md +3 -0
- package/instructions/start.md +1 -0
- package/instructions/story-arcs.md +1 -0
- package/instructions/story-episodes.md +1 -0
- package/instructions/story-mystery.md +1 -0
- package/instructions/style.md +1 -0
- package/package.json +85 -4
- package/systems/5e/LICENSE.md +25 -0
- package/systems/5e/images/acid-blob.svg +1 -0
- package/systems/5e/images/angel-outfit.svg +1 -0
- package/systems/5e/images/angler-fish.svg +1 -0
- package/systems/5e/images/angular-spider.svg +1 -0
- package/systems/5e/images/animal-skull.svg +1 -0
- package/systems/5e/images/bad-gnome.svg +1 -0
- package/systems/5e/images/badger.svg +1 -0
- package/systems/5e/images/bandit.svg +1 -0
- package/systems/5e/images/barn-owl.svg +1 -0
- package/systems/5e/images/basset-hound-head.svg +1 -0
- package/systems/5e/images/bat.svg +1 -0
- package/systems/5e/images/bear-face.svg +1 -0
- package/systems/5e/images/bear-head.svg +1 -0
- package/systems/5e/images/beetle-shell.svg +1 -0
- package/systems/5e/images/berry-bush.svg +1 -0
- package/systems/5e/images/bestial-fangs.svg +1 -0
- package/systems/5e/images/big-wave.svg +1 -0
- package/systems/5e/images/black-knight-helm.svg +1 -0
- package/systems/5e/images/boar-tusks.svg +1 -0
- package/systems/5e/images/boar.svg +1 -0
- package/systems/5e/images/bone-gnawer.svg +1 -0
- package/systems/5e/images/breastplate.svg +1 -0
- package/systems/5e/images/brute.svg +1 -0
- package/systems/5e/images/camel-head.svg +1 -0
- package/systems/5e/images/carnivore-mouth.svg +1 -0
- package/systems/5e/images/cassowary-head.svg +1 -0
- package/systems/5e/images/cat.svg +1 -0
- package/systems/5e/images/centaur.svg +1 -0
- package/systems/5e/images/centipede.svg +1 -0
- package/systems/5e/images/charging-bull.svg +1 -0
- package/systems/5e/images/closed-barbute.svg +1 -0
- package/systems/5e/images/cobra.svg +1 -0
- package/systems/5e/images/condor-emblem.svg +1 -0
- package/systems/5e/images/cowled.svg +1 -0
- package/systems/5e/images/crab-claw.svg +1 -0
- package/systems/5e/images/crab.svg +1 -0
- package/systems/5e/images/croc-jaws.svg +1 -0
- package/systems/5e/images/crow-dive.svg +1 -0
- package/systems/5e/images/crown.svg +1 -0
- package/systems/5e/images/crowned-skull.svg +1 -0
- package/systems/5e/images/cube.svg +1 -0
- package/systems/5e/images/cultist-lorc.svg +1 -0
- package/systems/5e/images/cultist-skoll.svg +1 -0
- package/systems/5e/images/curled-tentacle.svg +1 -0
- package/systems/5e/images/daemon-skull.svg +1 -0
- package/systems/5e/images/deer-head.svg +1 -0
- package/systems/5e/images/desert-skull.svg +1 -0
- package/systems/5e/images/devil-mask.svg +1 -0
- package/systems/5e/images/diablo-skull.svg +1 -0
- package/systems/5e/images/dinosaur-rex.svg +1 -0
- package/systems/5e/images/direwolf.svg +1 -0
- package/systems/5e/images/djinn.svg +1 -0
- package/systems/5e/images/donkey.svg +1 -0
- package/systems/5e/images/dragon-head-faithtoken.svg +1 -0
- package/systems/5e/images/dragon-head-lorc.svg +1 -0
- package/systems/5e/images/dragon-shield.svg +1 -0
- package/systems/5e/images/dragon-spiral.svg +1 -0
- package/systems/5e/images/dread-skull.svg +1 -0
- package/systems/5e/images/duality-mask.svg +1 -0
- package/systems/5e/images/dust-cloud.svg +1 -0
- package/systems/5e/images/dwarf-face.svg +1 -0
- package/systems/5e/images/dwarf-helmet.svg +1 -0
- package/systems/5e/images/eagle-emblem.svg +1 -0
- package/systems/5e/images/eagle-head.svg +1 -0
- package/systems/5e/images/egyptian-sphinx.svg +1 -0
- package/systems/5e/images/elephant-head.svg +1 -0
- package/systems/5e/images/elf-ear.svg +1 -0
- package/systems/5e/images/elf-helmet.svg +1 -0
- package/systems/5e/images/ent-mouth.svg +1 -0
- package/systems/5e/images/ermine.svg +1 -0
- package/systems/5e/images/eruption.svg +1 -0
- package/systems/5e/images/evil-bat.svg +1 -0
- package/systems/5e/images/evil-minion.svg +1 -0
- package/systems/5e/images/evil-tree.svg +1 -0
- package/systems/5e/images/evil-wings.svg +1 -0
- package/systems/5e/images/eyestalk.svg +1 -0
- package/systems/5e/images/fairy.svg +1 -0
- package/systems/5e/images/farmer.svg +1 -0
- package/systems/5e/images/feline.svg +1 -0
- package/systems/5e/images/fire-silhouette.svg +1 -0
- package/systems/5e/images/fish-monster.svg +1 -0
- package/systems/5e/images/fleshy-mass.svg +1 -0
- package/systems/5e/images/fluffy-flame.svg +1 -0
- package/systems/5e/images/fly.svg +1 -0
- package/systems/5e/images/fox-head.svg +1 -0
- package/systems/5e/images/frankenstein-creature.svg +1 -0
- package/systems/5e/images/frog.svg +1 -0
- package/systems/5e/images/gargoyle.svg +1 -0
- package/systems/5e/images/gecko.svg +1 -0
- package/systems/5e/images/ghost.svg +1 -0
- package/systems/5e/images/giant.svg +1 -0
- package/systems/5e/images/goat.svg +1 -0
- package/systems/5e/images/goblin-head.svg +1 -0
- package/systems/5e/images/goblin.svg +1 -0
- package/systems/5e/images/golem-head.svg +1 -0
- package/systems/5e/images/gooey-daemon.svg +1 -0
- package/systems/5e/images/gorilla.svg +1 -0
- package/systems/5e/images/greek-sphinx.svg +1 -0
- package/systems/5e/images/griffin-symbol.svg +1 -0
- package/systems/5e/images/grim-reaper.svg +1 -0
- package/systems/5e/images/hanging-spider.svg +1 -0
- package/systems/5e/images/harpy.svg +1 -0
- package/systems/5e/images/hawk-emblem.svg +1 -0
- package/systems/5e/images/hooded-assassin.svg +1 -0
- package/systems/5e/images/horned-reptile.svg +1 -0
- package/systems/5e/images/horse-head-delapouite.svg +1 -0
- package/systems/5e/images/horse-head-lorc.svg +1 -0
- package/systems/5e/images/hound.svg +1 -0
- package/systems/5e/images/hydra.svg +1 -0
- package/systems/5e/images/hyena-head.svg +1 -0
- package/systems/5e/images/icicles-aura.svg +1 -0
- package/systems/5e/images/ifrit.svg +1 -0
- package/systems/5e/images/imp-laugh.svg +1 -0
- package/systems/5e/images/imp.svg +1 -0
- package/systems/5e/images/insect-jaws.svg +1 -0
- package/systems/5e/images/invisible-face.svg +1 -0
- package/systems/5e/images/jumping-dog.svg +1 -0
- package/systems/5e/images/kraken-tentacle.svg +1 -0
- package/systems/5e/images/labrador-head.svg +1 -0
- package/systems/5e/images/lion.svg +1 -0
- package/systems/5e/images/lizard-tongue.svg +1 -0
- package/systems/5e/images/lizardman.svg +1 -0
- package/systems/5e/images/long-antennae-bug.svg +1 -0
- package/systems/5e/images/long-legged-spider.svg +1 -0
- package/systems/5e/images/mammoth.svg +1 -0
- package/systems/5e/images/mandrill-head.svg +1 -0
- package/systems/5e/images/manta-ray.svg +1 -0
- package/systems/5e/images/masked-spider.svg +1 -0
- package/systems/5e/images/medusa-head.svg +1 -0
- package/systems/5e/images/mermaid.svg +1 -0
- package/systems/5e/images/metal-golem-head.svg +1 -0
- package/systems/5e/images/mimic-chest.svg +1 -0
- package/systems/5e/images/minotaur.svg +1 -0
- package/systems/5e/images/monk-face.svg +1 -0
- package/systems/5e/images/moon-bats.svg +1 -0
- package/systems/5e/images/mucous-pillar.svg +1 -0
- package/systems/5e/images/mummy-head.svg +1 -0
- package/systems/5e/images/mushrooms-cluster.svg +1 -0
- package/systems/5e/images/octopus.svg +1 -0
- package/systems/5e/images/ogre.svg +1 -0
- package/systems/5e/images/oni.svg +1 -0
- package/systems/5e/images/orc-head.svg +1 -0
- package/systems/5e/images/owl.svg +1 -0
- package/systems/5e/images/pan-flute.svg +1 -0
- package/systems/5e/images/pegasus.svg +1 -0
- package/systems/5e/images/person.svg +1 -0
- package/systems/5e/images/piranha.svg +1 -0
- package/systems/5e/images/plesiosaurus.svg +1 -0
- package/systems/5e/images/pointy-hat.svg +1 -0
- package/systems/5e/images/polar-bear.svg +1 -0
- package/systems/5e/images/rat.svg +1 -0
- package/systems/5e/images/rattlesnake.svg +1 -0
- package/systems/5e/images/raven.svg +1 -0
- package/systems/5e/images/rhinoceros-horn.svg +1 -0
- package/systems/5e/images/robber.svg +1 -0
- package/systems/5e/images/robin-hood-hat.svg +1 -0
- package/systems/5e/images/robot-golem.svg +1 -0
- package/systems/5e/images/rock-golem.svg +1 -0
- package/systems/5e/images/rolled-cloth.svg +1 -0
- package/systems/5e/images/rooster.svg +1 -0
- package/systems/5e/images/saber-toothed-cat-head.svg +1 -0
- package/systems/5e/images/salamander.svg +1 -0
- package/systems/5e/images/school-of-fish.svg +1 -0
- package/systems/5e/images/scorpion.svg +1 -0
- package/systems/5e/images/sea-serpent.svg +1 -0
- package/systems/5e/images/seahorse.svg +1 -0
- package/systems/5e/images/seated-mouse.svg +1 -0
- package/systems/5e/images/sensuousness.svg +1 -0
- package/systems/5e/images/shadow-follower.svg +1 -0
- package/systems/5e/images/shambling-mound.svg +1 -0
- package/systems/5e/images/shambling-zombie.svg +1 -0
- package/systems/5e/images/shark-fin.svg +1 -0
- package/systems/5e/images/shark-jaws.svg +1 -0
- package/systems/5e/images/skeleton.svg +1 -0
- package/systems/5e/images/slime.svg +1 -0
- package/systems/5e/images/small-fire.svg +1 -0
- package/systems/5e/images/snake-spiral.svg +1 -0
- package/systems/5e/images/snake-tongue.svg +1 -0
- package/systems/5e/images/snake-totem.svg +1 -0
- package/systems/5e/images/snake.svg +1 -0
- package/systems/5e/images/spark-spirit.svg +1 -0
- package/systems/5e/images/spartan.svg +1 -0
- package/systems/5e/images/spectre.svg +1 -0
- package/systems/5e/images/sperm-whale.svg +1 -0
- package/systems/5e/images/spider-alt.svg +1 -0
- package/systems/5e/images/spiked-dragon-head.svg +1 -0
- package/systems/5e/images/spiked-tail.svg +1 -0
- package/systems/5e/images/spotted-mushroom.svg +1 -0
- package/systems/5e/images/spy.svg +1 -0
- package/systems/5e/images/squid.svg +1 -0
- package/systems/5e/images/stag-head.svg +1 -0
- package/systems/5e/images/steam.svg +1 -0
- package/systems/5e/images/sun-priest.svg +1 -0
- package/systems/5e/images/tick.svg +1 -0
- package/systems/5e/images/tiger-head.svg +1 -0
- package/systems/5e/images/tiger.svg +1 -0
- package/systems/5e/images/toad-teeth.svg +1 -0
- package/systems/5e/images/tornado.svg +1 -0
- package/systems/5e/images/transparent-slime.svg +1 -0
- package/systems/5e/images/tree-face.svg +1 -0
- package/systems/5e/images/tribal-mask.svg +1 -0
- package/systems/5e/images/triceratops-head.svg +1 -0
- package/systems/5e/images/triton-head.svg +1 -0
- package/systems/5e/images/troglodyte.svg +1 -0
- package/systems/5e/images/troll.svg +1 -0
- package/systems/5e/images/turtle.svg +1 -0
- package/systems/5e/images/unicorn.svg +1 -0
- package/systems/5e/images/vampire-dracula.svg +1 -0
- package/systems/5e/images/viking-head.svg +1 -0
- package/systems/5e/images/visored-helm.svg +1 -0
- package/systems/5e/images/vulture.svg +1 -0
- package/systems/5e/images/warlord-helmet.svg +1 -0
- package/systems/5e/images/wasp-sting.svg +1 -0
- package/systems/5e/images/werewolf.svg +1 -0
- package/systems/5e/images/winged-sword.svg +1 -0
- package/systems/5e/images/witch-face.svg +1 -0
- package/systems/5e/images/wizard-face.svg +1 -0
- package/systems/5e/images/wolf-head.svg +1 -0
- package/systems/5e/images/wolf-howl.svg +1 -0
- package/systems/5e/images/woman-elf-face.svg +1 -0
- package/systems/5e/images/worm-mouth.svg +1 -0
- package/systems/5e/images/wyvern.svg +1 -0
- package/systems/5e/instructions/level-up.md +1 -0
- package/systems/5e/instructions/mentor-tutorial.md +1 -0
- package/systems/5e/instructions/play.md +5 -0
- package/systems/5e/instructions/quest-ends.md +1 -0
- package/systems/5e/instructions/session-zero.md +1 -0
- package/systems/5e/rules/Adventuring.md +228 -0
- package/systems/5e/rules/Beyond 1st Level.md +241 -0
- package/systems/5e/rules/Combat.md +504 -0
- package/systems/5e/rules/Conditions.md +110 -0
- package/systems/5e/rules/Diseases.md +41 -0
- package/systems/5e/rules/Equipment.md +731 -0
- package/systems/5e/rules/Fantasy-Historical Pantheons.md +112 -0
- package/systems/5e/rules/Madness.md +72 -0
- package/systems/5e/rules/Magic Items.md +142 -0
- package/systems/5e/rules/Monsters.md +403 -0
- package/systems/5e/rules/Nonplayer Characters.md +15 -0
- package/systems/5e/rules/Objects.md +40 -0
- package/systems/5e/rules/Poisons.md +64 -0
- package/systems/5e/rules/Races.md +33 -0
- package/systems/5e/rules/Spellcasting.md +225 -0
- package/systems/5e/rules/The Planes of Existence.md +59 -0
- package/systems/5e/rules/Traps.md +170 -0
- package/systems/5e/rules/Using Ability Scores.md +394 -0
- package/systems/5e/system.yaml +602 -0
- package/systems/5e/words/ar.yaml +421 -0
- package/systems/5e/words/cs.yaml +421 -0
- package/systems/5e/words/da.yaml +421 -0
- package/systems/5e/words/de.yaml +421 -0
- package/systems/5e/words/el.yaml +421 -0
- package/systems/5e/words/es.yaml +421 -0
- package/systems/5e/words/fi.yaml +421 -0
- package/systems/5e/words/fr.yaml +421 -0
- package/systems/5e/words/he.yaml +421 -0
- package/systems/5e/words/hi.yaml +421 -0
- package/systems/5e/words/hu.yaml +421 -0
- package/systems/5e/words/is.yaml +421 -0
- package/systems/5e/words/it.yaml +453 -0
- package/systems/5e/words/ja.yaml +421 -0
- package/systems/5e/words/ko.yaml +421 -0
- package/systems/5e/words/nb.yaml +421 -0
- package/systems/5e/words/nl.yaml +421 -0
- package/systems/5e/words/pl.yaml +421 -0
- package/systems/5e/words/pt.yaml +421 -0
- package/systems/5e/words/ro.yaml +421 -0
- package/systems/5e/words/ru.yaml +421 -0
- package/systems/5e/words/sv.yaml +421 -0
- package/systems/5e/words/tr.yaml +421 -0
- package/systems/5e/words/uk.yaml +421 -0
- package/systems/5e/words/zh.yaml +421 -0
- package/systems/5e/world/creatures/Aboleth.md +65 -0
- package/systems/5e/world/creatures/Acolyte.md +37 -0
- package/systems/5e/world/creatures/Adult Black Dragon.md +69 -0
- package/systems/5e/world/creatures/Adult Blue Dragon.md +66 -0
- package/systems/5e/world/creatures/Adult Brass Dragon.md +70 -0
- package/systems/5e/world/creatures/Adult Bronze Dragon.md +78 -0
- package/systems/5e/world/creatures/Adult Copper Dragon.md +70 -0
- package/systems/5e/world/creatures/Adult Gold Dragon.md +78 -0
- package/systems/5e/world/creatures/Adult Green Dragon.md +70 -0
- package/systems/5e/world/creatures/Adult Red Dragon.md +66 -0
- package/systems/5e/world/creatures/Adult Silver Dragon.md +74 -0
- package/systems/5e/world/creatures/Adult White Dragon.md +70 -0
- package/systems/5e/world/creatures/Air Elemental.md +43 -0
- package/systems/5e/world/creatures/Ancient Black Dragon.md +69 -0
- package/systems/5e/world/creatures/Ancient Blue Dragon.md +66 -0
- package/systems/5e/world/creatures/Ancient Brass Dragon.md +75 -0
- package/systems/5e/world/creatures/Ancient Bronze Dragon.md +78 -0
- package/systems/5e/world/creatures/Ancient Copper Dragon.md +75 -0
- package/systems/5e/world/creatures/Ancient Gold Dragon.md +78 -0
- package/systems/5e/world/creatures/Ancient Green Dragon.md +70 -0
- package/systems/5e/world/creatures/Ancient Red Dragon.md +66 -0
- package/systems/5e/world/creatures/Ancient Silver Dragon.md +74 -0
- package/systems/5e/world/creatures/Ancient White Dragon.md +70 -0
- package/systems/5e/world/creatures/Androsphinx.md +82 -0
- package/systems/5e/world/creatures/Animated Armor.md +39 -0
- package/systems/5e/world/creatures/Ankheg.md +31 -0
- package/systems/5e/world/creatures/Ape.md +32 -0
- package/systems/5e/world/creatures/Archmage.md +63 -0
- package/systems/5e/world/creatures/Assassin.md +48 -0
- package/systems/5e/world/creatures/Awakened Shrub.md +34 -0
- package/systems/5e/world/creatures/Awakened Tree.md +35 -0
- package/systems/5e/world/creatures/Axe Beak.md +26 -0
- package/systems/5e/world/creatures/Azer.md +40 -0
- package/systems/5e/world/creatures/Baboon.md +30 -0
- package/systems/5e/world/creatures/Badger.md +31 -0
- package/systems/5e/world/creatures/Balor.md +55 -0
- package/systems/5e/world/creatures/Bandit Captain.md +45 -0
- package/systems/5e/world/creatures/Bandit.md +33 -0
- package/systems/5e/world/creatures/Barbed Devil.md +52 -0
- package/systems/5e/world/creatures/Basilisk.md +35 -0
- package/systems/5e/world/creatures/Bat.md +34 -0
- package/systems/5e/world/creatures/Bearded Devil.md +48 -0
- package/systems/5e/world/creatures/Behir.md +44 -0
- package/systems/5e/world/creatures/Berserker.md +33 -0
- package/systems/5e/world/creatures/Black Bear.md +38 -0
- package/systems/5e/world/creatures/Black Dragon Wyrmling.md +41 -0
- package/systems/5e/world/creatures/Black Pudding.md +46 -0
- package/systems/5e/world/creatures/Blink Dog.md +36 -0
- package/systems/5e/world/creatures/Blood Hawk.md +36 -0
- package/systems/5e/world/creatures/Blue Dragon Wyrmling.md +36 -0
- package/systems/5e/world/creatures/Boar.md +33 -0
- package/systems/5e/world/creatures/Bone Devil.md +47 -0
- package/systems/5e/world/creatures/Brass Dragon Wyrmling.md +40 -0
- package/systems/5e/world/creatures/Bronze Dragon Wyrmling.md +45 -0
- package/systems/5e/world/creatures/Brown Bear.md +38 -0
- package/systems/5e/world/creatures/Bugbear.md +39 -0
- package/systems/5e/world/creatures/Bulette.md +37 -0
- package/systems/5e/world/creatures/Camel.md +24 -0
- package/systems/5e/world/creatures/Cat.md +31 -0
- package/systems/5e/world/creatures/Centaur.md +40 -0
- package/systems/5e/world/creatures/Chain Devil.md +52 -0
- package/systems/5e/world/creatures/Chimera.md +41 -0
- package/systems/5e/world/creatures/Chuul.md +45 -0
- package/systems/5e/world/creatures/Clay Golem.md +52 -0
- package/systems/5e/world/creatures/Cloaker.md +56 -0
- package/systems/5e/world/creatures/Cloud Giant.md +46 -0
- package/systems/5e/world/creatures/Cockatrice.md +26 -0
- package/systems/5e/world/creatures/Commoner.md +27 -0
- package/systems/5e/world/creatures/Constrictor Snake.md +29 -0
- package/systems/5e/world/creatures/Copper Dragon Wyrmling.md +40 -0
- package/systems/5e/world/creatures/Couatl.md +54 -0
- package/systems/5e/world/creatures/Crab.md +33 -0
- package/systems/5e/world/creatures/Crocodile.md +32 -0
- package/systems/5e/world/creatures/Cult Fanatic.md +46 -0
- package/systems/5e/world/creatures/Cultist.md +34 -0
- package/systems/5e/world/creatures/Darkmantle.md +42 -0
- package/systems/5e/world/creatures/Death Dog.md +36 -0
- package/systems/5e/world/creatures/Deep Gnome (Svirfneblin).md +46 -0
- package/systems/5e/world/creatures/Deer.md +24 -0
- package/systems/5e/world/creatures/Deva.md +57 -0
- package/systems/5e/world/creatures/Dire Wolf.md +34 -0
- package/systems/5e/world/creatures/Djinni.md +50 -0
- package/systems/5e/world/creatures/Doppelganger.md +45 -0
- package/systems/5e/world/creatures/Draft Horse.md +24 -0
- package/systems/5e/world/creatures/Dragon Turtle.md +47 -0
- package/systems/5e/world/creatures/Dragonborn.md +58 -0
- package/systems/5e/world/creatures/Dretch.md +39 -0
- package/systems/5e/world/creatures/Drider.md +58 -0
- package/systems/5e/world/creatures/Drow Elf.md +46 -0
- package/systems/5e/world/creatures/Druid (creature).md +41 -0
- package/systems/5e/world/creatures/Dryad.md +53 -0
- package/systems/5e/world/creatures/Duergar.md +45 -0
- package/systems/5e/world/creatures/Dust Mephit.md +42 -0
- package/systems/5e/world/creatures/Dwarf.md +48 -0
- package/systems/5e/world/creatures/Eagle.md +31 -0
- package/systems/5e/world/creatures/Earth Elemental.md +44 -0
- package/systems/5e/world/creatures/Efreeti.md +48 -0
- package/systems/5e/world/creatures/Elephant.md +33 -0
- package/systems/5e/world/creatures/Elf.md +44 -0
- package/systems/5e/world/creatures/Elk.md +32 -0
- package/systems/5e/world/creatures/Erinyes.md +51 -0
- package/systems/5e/world/creatures/Ettercap.md +48 -0
- package/systems/5e/world/creatures/Ettin.md +42 -0
- package/systems/5e/world/creatures/Fire Elemental.md +43 -0
- package/systems/5e/world/creatures/Fire Giant.md +35 -0
- package/systems/5e/world/creatures/Flesh Golem.md +53 -0
- package/systems/5e/world/creatures/Flying Snake.md +34 -0
- package/systems/5e/world/creatures/Flying Sword.md +38 -0
- package/systems/5e/world/creatures/Frog.md +32 -0
- package/systems/5e/world/creatures/Frost Giant.md +35 -0
- package/systems/5e/world/creatures/Gargoyle.md +42 -0
- package/systems/5e/world/creatures/Gelatinous Cube.md +49 -0
- package/systems/5e/world/creatures/Ghast.md +40 -0
- package/systems/5e/world/creatures/Ghost.md +49 -0
- package/systems/5e/world/creatures/Ghoul.md +31 -0
- package/systems/5e/world/creatures/Giant Ape.md +32 -0
- package/systems/5e/world/creatures/Giant Badger.md +37 -0
- package/systems/5e/world/creatures/Giant Bat.md +34 -0
- package/systems/5e/world/creatures/Giant Boar.md +33 -0
- package/systems/5e/world/creatures/Giant Centipede.md +27 -0
- package/systems/5e/world/creatures/Giant Constrictor Snake.md +30 -0
- package/systems/5e/world/creatures/Giant Crab.md +33 -0
- package/systems/5e/world/creatures/Giant Crocodile.md +38 -0
- package/systems/5e/world/creatures/Giant Eagle.md +40 -0
- package/systems/5e/world/creatures/Giant Elk.md +37 -0
- package/systems/5e/world/creatures/Giant Fire Beetle.md +33 -0
- package/systems/5e/world/creatures/Giant Frog.md +40 -0
- package/systems/5e/world/creatures/Giant Goat.md +33 -0
- package/systems/5e/world/creatures/Giant Hyena.md +30 -0
- package/systems/5e/world/creatures/Giant Lizard.md +29 -0
- package/systems/5e/world/creatures/Giant Octopus.md +41 -0
- package/systems/5e/world/creatures/Giant Owl.md +38 -0
- package/systems/5e/world/creatures/Giant Poisonous Snake.md +27 -0
- package/systems/5e/world/creatures/Giant Rat.md +39 -0
- package/systems/5e/world/creatures/Giant Scorpion.md +32 -0
- package/systems/5e/world/creatures/Giant Sea Horse.md +36 -0
- package/systems/5e/world/creatures/Giant Shark.md +38 -0
- package/systems/5e/world/creatures/Giant Spider.md +45 -0
- package/systems/5e/world/creatures/Giant Toad.md +39 -0
- package/systems/5e/world/creatures/Giant Vulture.md +43 -0
- package/systems/5e/world/creatures/Giant Wasp.md +25 -0
- package/systems/5e/world/creatures/Giant Weasel.md +31 -0
- package/systems/5e/world/creatures/Giant Wolf Spider.md +41 -0
- package/systems/5e/world/creatures/Gibbering Mouther.md +41 -0
- package/systems/5e/world/creatures/Glabrezu.md +48 -0
- package/systems/5e/world/creatures/Gladiator.md +49 -0
- package/systems/5e/world/creatures/Gnoll.md +38 -0
- package/systems/5e/world/creatures/Gnome.md +37 -0
- package/systems/5e/world/creatures/Goat.md +32 -0
- package/systems/5e/world/creatures/Goblin.md +36 -0
- package/systems/5e/world/creatures/Gold Dragon Wyrmling.md +45 -0
- package/systems/5e/world/creatures/Gorgon.md +39 -0
- package/systems/5e/world/creatures/Gray Ooze.md +42 -0
- package/systems/5e/world/creatures/Green Dragon Wyrmling.md +42 -0
- package/systems/5e/world/creatures/Green Hag.md +49 -0
- package/systems/5e/world/creatures/Grick.md +39 -0
- package/systems/5e/world/creatures/Griffon.md +38 -0
- package/systems/5e/world/creatures/Grimlock.md +39 -0
- package/systems/5e/world/creatures/Guard.md +29 -0
- package/systems/5e/world/creatures/Guardian Naga.md +55 -0
- package/systems/5e/world/creatures/Gynosphinx.md +71 -0
- package/systems/5e/world/creatures/Half-Elf.md +40 -0
- package/systems/5e/world/creatures/Half-Orc.md +44 -0
- package/systems/5e/world/creatures/Half-Red Dragon Veteran.md +42 -0
- package/systems/5e/world/creatures/Halfling.md +39 -0
- package/systems/5e/world/creatures/Harpy.md +39 -0
- package/systems/5e/world/creatures/Hawk.md +31 -0
- package/systems/5e/world/creatures/Hell Hound.md +40 -0
- package/systems/5e/world/creatures/Hezrou.md +45 -0
- package/systems/5e/world/creatures/High Elf.md +22 -0
- package/systems/5e/world/creatures/Hill Dwarf.md +16 -0
- package/systems/5e/world/creatures/Hill Giant.md +33 -0
- package/systems/5e/world/creatures/Hippogriff.md +37 -0
- package/systems/5e/world/creatures/Hobgoblin.md +35 -0
- package/systems/5e/world/creatures/Homunculus.md +35 -0
- package/systems/5e/world/creatures/Horned Devil.md +49 -0
- package/systems/5e/world/creatures/Human.md +29 -0
- package/systems/5e/world/creatures/Hunter Shark.md +38 -0
- package/systems/5e/world/creatures/Hydra.md +49 -0
- package/systems/5e/world/creatures/Hyena.md +30 -0
- package/systems/5e/world/creatures/Ice Devil.md +56 -0
- package/systems/5e/world/creatures/Ice Mephit.md +45 -0
- package/systems/5e/world/creatures/Imp.md +45 -0
- package/systems/5e/world/creatures/Invisible Stalker.md +42 -0
- package/systems/5e/world/creatures/Iron Golem.md +52 -0
- package/systems/5e/world/creatures/Jackal.md +33 -0
- package/systems/5e/world/creatures/Killer Whale.md +39 -0
- package/systems/5e/world/creatures/Knight.md +48 -0
- package/systems/5e/world/creatures/Kobold.md +37 -0
- package/systems/5e/world/creatures/Kraken.md +69 -0
- package/systems/5e/world/creatures/Lamia.md +46 -0
- package/systems/5e/world/creatures/Lemure.md +37 -0
- package/systems/5e/world/creatures/Lich.md +82 -0
- package/systems/5e/world/creatures/Lightfoot Halfling.md +18 -0
- package/systems/5e/world/creatures/Lion.md +42 -0
- package/systems/5e/world/creatures/Lizard.md +26 -0
- package/systems/5e/world/creatures/Lizardfolk.md +45 -0
- package/systems/5e/world/creatures/Mage.md +47 -0
- package/systems/5e/world/creatures/Magma Mephit.md +45 -0
- package/systems/5e/world/creatures/Magmin.md +37 -0
- package/systems/5e/world/creatures/Mammoth.md +35 -0
- package/systems/5e/world/creatures/Manticore.md +42 -0
- package/systems/5e/world/creatures/Marilith.md +56 -0
- package/systems/5e/world/creatures/Mastiff.md +32 -0
- package/systems/5e/world/creatures/Medusa.md +46 -0
- package/systems/5e/world/creatures/Merfolk.md +32 -0
- package/systems/5e/world/creatures/Merrow.md +42 -0
- package/systems/5e/world/creatures/Mimic.md +46 -0
- package/systems/5e/world/creatures/Minotaur Skeleton.md +38 -0
- package/systems/5e/world/creatures/Minotaur.md +42 -0
- package/systems/5e/world/creatures/Mule.md +32 -0
- package/systems/5e/world/creatures/Mummy Lord.md +82 -0
- package/systems/5e/world/creatures/Mummy.md +38 -0
- package/systems/5e/world/creatures/Nalfeshnee.md +49 -0
- package/systems/5e/world/creatures/Night Hag.md +50 -0
- package/systems/5e/world/creatures/Nightmare.md +39 -0
- package/systems/5e/world/creatures/Noble.md +36 -0
- package/systems/5e/world/creatures/Ochre Jelly.md +42 -0
- package/systems/5e/world/creatures/Octopus.md +41 -0
- package/systems/5e/world/creatures/Ogre Zombie.md +34 -0
- package/systems/5e/world/creatures/Ogre.md +30 -0
- package/systems/5e/world/creatures/Oni.md +53 -0
- package/systems/5e/world/creatures/Orc.md +36 -0
- package/systems/5e/world/creatures/Otyugh.md +42 -0
- package/systems/5e/world/creatures/Owl.md +35 -0
- package/systems/5e/world/creatures/Owlbear.md +38 -0
- package/systems/5e/world/creatures/Panther.md +37 -0
- package/systems/5e/world/creatures/Pegasus.md +28 -0
- package/systems/5e/world/creatures/Phase Spider.md +41 -0
- package/systems/5e/world/creatures/Pit Fiend.md +61 -0
- package/systems/5e/world/creatures/Planetar.md +56 -0
- package/systems/5e/world/creatures/Plesiosaurus.md +32 -0
- package/systems/5e/world/creatures/Poisonous Snake.md +26 -0
- package/systems/5e/world/creatures/Polar Bear.md +38 -0
- package/systems/5e/world/creatures/Pony.md +24 -0
- package/systems/5e/world/creatures/Priest.md +47 -0
- package/systems/5e/world/creatures/Pseudodragon.md +44 -0
- package/systems/5e/world/creatures/Purple Worm.md +42 -0
- package/systems/5e/world/creatures/Quasit.md +44 -0
- package/systems/5e/world/creatures/Quipper.md +36 -0
- package/systems/5e/world/creatures/Rakshasa.md +45 -0
- package/systems/5e/world/creatures/Rat.md +30 -0
- package/systems/5e/world/creatures/Raven.md +31 -0
- package/systems/5e/world/creatures/Red Dragon Wyrmling.md +36 -0
- package/systems/5e/world/creatures/Reef Shark.md +38 -0
- package/systems/5e/world/creatures/Remorhaz.md +39 -0
- package/systems/5e/world/creatures/Rhinoceros.md +30 -0
- package/systems/5e/world/creatures/Riding Horse.md +24 -0
- package/systems/5e/world/creatures/Roc.md +39 -0
- package/systems/5e/world/creatures/Rock Gnome.md +27 -0
- package/systems/5e/world/creatures/Roper.md +48 -0
- package/systems/5e/world/creatures/Rug of Smothering.md +38 -0
- package/systems/5e/world/creatures/Rust Monster.md +39 -0
- package/systems/5e/world/creatures/Saber-Toothed Tiger.md +36 -0
- package/systems/5e/world/creatures/Sahuagin.md +49 -0
- package/systems/5e/world/creatures/Salamander.md +44 -0
- package/systems/5e/world/creatures/Satyr.md +38 -0
- package/systems/5e/world/creatures/Scorpion.md +26 -0
- package/systems/5e/world/creatures/Scout.md +40 -0
- package/systems/5e/world/creatures/Sea Hag.md +46 -0
- package/systems/5e/world/creatures/Sea Horse.md +25 -0
- package/systems/5e/world/creatures/Shadow.md +45 -0
- package/systems/5e/world/creatures/Shambling Mound.md +42 -0
- package/systems/5e/world/creatures/Shield Guardian.md +49 -0
- package/systems/5e/world/creatures/Shrieker.md +31 -0
- package/systems/5e/world/creatures/Silver Dragon Wyrmling.md +39 -0
- package/systems/5e/world/creatures/Skeleton.md +33 -0
- package/systems/5e/world/creatures/Solar.md +76 -0
- package/systems/5e/world/creatures/Specter.md +38 -0
- package/systems/5e/world/creatures/Spider.md +38 -0
- package/systems/5e/world/creatures/Spirit Naga.md +50 -0
- package/systems/5e/world/creatures/Sprite.md +37 -0
- package/systems/5e/world/creatures/Spy.md +42 -0
- package/systems/5e/world/creatures/Steam Mephit.md +40 -0
- package/systems/5e/world/creatures/Stirge.md +29 -0
- package/systems/5e/world/creatures/Stone Giant.md +45 -0
- package/systems/5e/world/creatures/Stone Golem.md +46 -0
- package/systems/5e/world/creatures/Storm Giant.md +51 -0
- package/systems/5e/world/creatures/Succubus-Incubus.md +50 -0
- package/systems/5e/world/creatures/Swarm of Bats.md +39 -0
- package/systems/5e/world/creatures/Swarm of Insects.md +52 -0
- package/systems/5e/world/creatures/Swarm of Poisonous Snakes.md +33 -0
- package/systems/5e/world/creatures/Swarm of Quippers.md +39 -0
- package/systems/5e/world/creatures/Swarm of Rats.md +35 -0
- package/systems/5e/world/creatures/Swarm of Ravens.md +33 -0
- package/systems/5e/world/creatures/Tarrasque.md +76 -0
- package/systems/5e/world/creatures/Thug.md +40 -0
- package/systems/5e/world/creatures/Tiefling.md +40 -0
- package/systems/5e/world/creatures/Tiger.md +37 -0
- package/systems/5e/world/creatures/Treant.md +45 -0
- package/systems/5e/world/creatures/Tribal Warrior.md +33 -0
- package/systems/5e/world/creatures/Triceratops.md +33 -0
- package/systems/5e/world/creatures/Troll.md +42 -0
- package/systems/5e/world/creatures/Tyrannosaurus Rex.md +32 -0
- package/systems/5e/world/creatures/Unicorn.md +70 -0
- package/systems/5e/world/creatures/Vampire Spawn.md +55 -0
- package/systems/5e/world/creatures/Vampire.md +91 -0
- package/systems/5e/world/creatures/Veteran.md +38 -0
- package/systems/5e/world/creatures/Violet Fungus.md +34 -0
- package/systems/5e/world/creatures/Vrock.md +49 -0
- package/systems/5e/world/creatures/Vulture.md +34 -0
- package/systems/5e/world/creatures/Warhorse Skeleton.md +29 -0
- package/systems/5e/world/creatures/Warhorse.md +29 -0
- package/systems/5e/world/creatures/Water Elemental.md +47 -0
- package/systems/5e/world/creatures/Weasel.md +30 -0
- package/systems/5e/world/creatures/Werebear.md +45 -0
- package/systems/5e/world/creatures/Wereboar.md +45 -0
- package/systems/5e/world/creatures/Wererat.md +45 -0
- package/systems/5e/world/creatures/Weretiger.md +51 -0
- package/systems/5e/world/creatures/Werewolf.md +45 -0
- package/systems/5e/world/creatures/White Dragon Wyrmling.md +37 -0
- package/systems/5e/world/creatures/Wight.md +47 -0
- package/systems/5e/world/creatures/Will-o'-Wisp.md +47 -0
- package/systems/5e/world/creatures/Winter Wolf.md +44 -0
- package/systems/5e/world/creatures/Wolf.md +34 -0
- package/systems/5e/world/creatures/Worg.md +35 -0
- package/systems/5e/world/creatures/Wraith.md +41 -0
- package/systems/5e/world/creatures/Wyvern.md +37 -0
- package/systems/5e/world/creatures/Xorn.md +48 -0
- package/systems/5e/world/creatures/Young Black Dragon.md +47 -0
- package/systems/5e/world/creatures/Young Blue Dragon.md +42 -0
- package/systems/5e/world/creatures/Young Brass Dragon.md +46 -0
- package/systems/5e/world/creatures/Young Bronze Dragon.md +51 -0
- package/systems/5e/world/creatures/Young Copper Dragon.md +46 -0
- package/systems/5e/world/creatures/Young Gold Dragon.md +51 -0
- package/systems/5e/world/creatures/Young Green Dragon.md +48 -0
- package/systems/5e/world/creatures/Young Red Dragon.md +42 -0
- package/systems/5e/world/creatures/Young Silver Dragon.md +45 -0
- package/systems/5e/world/creatures/Young White Dragon.md +48 -0
- package/systems/5e/world/creatures/Zombie.md +34 -0
- package/systems/5e/world/items/Abacus.md +5 -0
- package/systems/5e/world/items/Acid.md +8 -0
- package/systems/5e/world/items/Adamantine Armor.md +6 -0
- package/systems/5e/world/items/Alchemist's Fire.md +8 -0
- package/systems/5e/world/items/Alchemist's Supplies.md +7 -0
- package/systems/5e/world/items/Ammunition, +1, +2, or +3.md +6 -0
- package/systems/5e/world/items/Amulet of Health.md +7 -0
- package/systems/5e/world/items/Amulet of Proof against Detection and Location.md +7 -0
- package/systems/5e/world/items/Amulet of the Planes.md +7 -0
- package/systems/5e/world/items/Amulet.md +7 -0
- package/systems/5e/world/items/Animated Shield.md +7 -0
- package/systems/5e/world/items/Antitoxin.md +7 -0
- package/systems/5e/world/items/Apparatus of the Crab.md +37 -0
- package/systems/5e/world/items/Armor of Invulnerability.md +7 -0
- package/systems/5e/world/items/Armor of Resistance.md +15 -0
- package/systems/5e/world/items/Armor of Vulnerability.md +9 -0
- package/systems/5e/world/items/Armor, +1, +2, or +3.md +6 -0
- package/systems/5e/world/items/Arrow of Slaying.md +10 -0
- package/systems/5e/world/items/Arrow-Catching Shield.md +7 -0
- package/systems/5e/world/items/Arrows.md +6 -0
- package/systems/5e/world/items/Backpack.md +5 -0
- package/systems/5e/world/items/Bag of Beans.md +25 -0
- package/systems/5e/world/items/Bag of Devouring.md +12 -0
- package/systems/5e/world/items/Bag of Holding.md +10 -0
- package/systems/5e/world/items/Bag of Tricks.md +51 -0
- package/systems/5e/world/items/Bagpipes.md +7 -0
- package/systems/5e/world/items/Ball Bearings.md +8 -0
- package/systems/5e/world/items/Barding.md +7 -0
- package/systems/5e/world/items/Barrel.md +5 -0
- package/systems/5e/world/items/Basic Poison.md +7 -0
- package/systems/5e/world/items/Basket.md +5 -0
- package/systems/5e/world/items/Battleaxe.md +10 -0
- package/systems/5e/world/items/Bead of Force.md +10 -0
- package/systems/5e/world/items/Bedroll.md +5 -0
- package/systems/5e/world/items/Bell.md +4 -0
- package/systems/5e/world/items/Belt of Dwarvenkind.md +18 -0
- package/systems/5e/world/items/Belt of Giant Strength.md +17 -0
- package/systems/5e/world/items/Berserker Axe.md +11 -0
- package/systems/5e/world/items/Bit and Bridle.md +5 -0
- package/systems/5e/world/items/Blanket.md +5 -0
- package/systems/5e/world/items/Block and Tackle.md +7 -0
- package/systems/5e/world/items/Blowgun Needles.md +6 -0
- package/systems/5e/world/items/Blowgun.md +10 -0
- package/systems/5e/world/items/Book.md +7 -0
- package/systems/5e/world/items/Boots of Elvenkind.md +6 -0
- package/systems/5e/world/items/Boots of Levitation.md +7 -0
- package/systems/5e/world/items/Boots of Speed.md +9 -0
- package/systems/5e/world/items/Boots of Striding and Springing.md +7 -0
- package/systems/5e/world/items/Boots of the Winterlands.md +11 -0
- package/systems/5e/world/items/Bowl of Commanding Water Elementals.md +8 -0
- package/systems/5e/world/items/Bracers of Archery.md +7 -0
- package/systems/5e/world/items/Bracers of Defense.md +7 -0
- package/systems/5e/world/items/Brazier of Commanding Fire Elementals.md +8 -0
- package/systems/5e/world/items/Breastplate.md +9 -0
- package/systems/5e/world/items/Brewer's Supplies.md +7 -0
- package/systems/5e/world/items/Brooch of Shielding.md +7 -0
- package/systems/5e/world/items/Broom of Flying.md +8 -0
- package/systems/5e/world/items/Bucket.md +5 -0
- package/systems/5e/world/items/Bullseye Lantern.md +8 -0
- package/systems/5e/world/items/Burglar's Pack.md +6 -0
- package/systems/5e/world/items/Calligrapher's Supplies.md +7 -0
- package/systems/5e/world/items/Caltrops.md +8 -0
- package/systems/5e/world/items/Candle of Invocation.md +25 -0
- package/systems/5e/world/items/Candle.md +6 -0
- package/systems/5e/world/items/Cape of the Mountebank.md +8 -0
- package/systems/5e/world/items/Carpenter's Tools.md +7 -0
- package/systems/5e/world/items/Carpet of Flying.md +17 -0
- package/systems/5e/world/items/Carriage.md +5 -0
- package/systems/5e/world/items/Cart.md +5 -0
- package/systems/5e/world/items/Cartographer's Tools.md +7 -0
- package/systems/5e/world/items/Censer of Controlling Air Elementals.md +8 -0
- package/systems/5e/world/items/Chain Mail.md +11 -0
- package/systems/5e/world/items/Chain Shirt.md +9 -0
- package/systems/5e/world/items/Chain.md +9 -0
- package/systems/5e/world/items/Chalk.md +5 -0
- package/systems/5e/world/items/Chariot.md +5 -0
- package/systems/5e/world/items/Chest.md +5 -0
- package/systems/5e/world/items/Chime of Opening.md +8 -0
- package/systems/5e/world/items/Circlet of Blasting.md +6 -0
- package/systems/5e/world/items/Climber's Kit.md +7 -0
- package/systems/5e/world/items/Cloak of Arachnida.md +13 -0
- package/systems/5e/world/items/Cloak of Displacement.md +7 -0
- package/systems/5e/world/items/Cloak of Elvenkind.md +7 -0
- package/systems/5e/world/items/Cloak of Protection.md +7 -0
- package/systems/5e/world/items/Cloak of the Bat.md +9 -0
- package/systems/5e/world/items/Cloak of the Manta Ray.md +6 -0
- package/systems/5e/world/items/Club.md +10 -0
- package/systems/5e/world/items/Cobbler's Tools.md +7 -0
- package/systems/5e/world/items/Common Clothes.md +6 -0
- package/systems/5e/world/items/Component Pouch.md +7 -0
- package/systems/5e/world/items/Cook's Utensils.md +7 -0
- package/systems/5e/world/items/Costume Clothes.md +6 -0
- package/systems/5e/world/items/Crossbow Bolt Case.md +8 -0
- package/systems/5e/world/items/Crossbow Bolts.md +6 -0
- package/systems/5e/world/items/Crowbar.md +7 -0
- package/systems/5e/world/items/Crystal Ball.md +15 -0
- package/systems/5e/world/items/Crystal.md +7 -0
- package/systems/5e/world/items/Cube of Force.md +32 -0
- package/systems/5e/world/items/Cubic Gate.md +10 -0
- package/systems/5e/world/items/Dagger of Venom.md +8 -0
- package/systems/5e/world/items/Dagger.md +10 -0
- package/systems/5e/world/items/Dancing Sword.md +11 -0
- package/systems/5e/world/items/Dart.md +10 -0
- package/systems/5e/world/items/Decanter of Endless Water.md +12 -0
- package/systems/5e/world/items/Deck of Illusions.md +48 -0
- package/systems/5e/world/items/Deck of Many Things.md +113 -0
- package/systems/5e/world/items/Defender.md +9 -0
- package/systems/5e/world/items/Demon Armor.md +9 -0
- package/systems/5e/world/items/Dice Set.md +6 -0
- package/systems/5e/world/items/Dimensional Shackles.md +8 -0
- package/systems/5e/world/items/Diplomat's Pack.md +6 -0
- package/systems/5e/world/items/Disguise Kit.md +7 -0
- package/systems/5e/world/items/Dragon Scale Mail.md +19 -0
- package/systems/5e/world/items/Dragon Slayer.md +8 -0
- package/systems/5e/world/items/Drum.md +7 -0
- package/systems/5e/world/items/Dulcimer.md +7 -0
- package/systems/5e/world/items/Dungeoneer's Pack.md +6 -0
- package/systems/5e/world/items/Dust of Disappearance.md +6 -0
- package/systems/5e/world/items/Dust of Dryness.md +10 -0
- package/systems/5e/world/items/Dust of Sneezing and Choking.md +8 -0
- package/systems/5e/world/items/Dwarven Plate.md +6 -0
- package/systems/5e/world/items/Dwarven Thrower.md +7 -0
- package/systems/5e/world/items/Efficient Quiver.md +8 -0
- package/systems/5e/world/items/Efreeti Bottle.md +14 -0
- package/systems/5e/world/items/Elemental Gem.md +13 -0
- package/systems/5e/world/items/Elven Chain.md +6 -0
- package/systems/5e/world/items/Emblem.md +6 -0
- package/systems/5e/world/items/Entertainer's Pack.md +6 -0
- package/systems/5e/world/items/Eversmoking Bottle.md +8 -0
- package/systems/5e/world/items/Exotic Saddle.md +7 -0
- package/systems/5e/world/items/Explorer's Pack.md +6 -0
- package/systems/5e/world/items/Eyes of Charming.md +7 -0
- package/systems/5e/world/items/Eyes of Minute Seeing.md +6 -0
- package/systems/5e/world/items/Eyes of the Eagle.md +7 -0
- package/systems/5e/world/items/Feather Token.md +26 -0
- package/systems/5e/world/items/Feed.md +6 -0
- package/systems/5e/world/items/Figurine of Wondrous Power.md +52 -0
- package/systems/5e/world/items/Fine Clothes.md +6 -0
- package/systems/5e/world/items/Fishing Tackle.md +7 -0
- package/systems/5e/world/items/Flail.md +9 -0
- package/systems/5e/world/items/Flame Tongue.md +7 -0
- package/systems/5e/world/items/Flask or Tankard.md +5 -0
- package/systems/5e/world/items/Flute.md +7 -0
- package/systems/5e/world/items/Folding Boat.md +14 -0
- package/systems/5e/world/items/Forgery Kit.md +7 -0
- package/systems/5e/world/items/Frost Brand.md +11 -0
- package/systems/5e/world/items/Galley.md +5 -0
- package/systems/5e/world/items/Gauntlets of Ogre Power.md +7 -0
- package/systems/5e/world/items/Gem of Brightness.md +12 -0
- package/systems/5e/world/items/Gem of Seeing.md +9 -0
- package/systems/5e/world/items/Giant Slayer.md +8 -0
- package/systems/5e/world/items/Glaive.md +10 -0
- package/systems/5e/world/items/Glamoured Studded Leather.md +6 -0
- package/systems/5e/world/items/Glass Bottle.md +6 -0
- package/systems/5e/world/items/Glassblower's Tools.md +7 -0
- package/systems/5e/world/items/Gloves of Missile Snaring.md +7 -0
- package/systems/5e/world/items/Gloves of Swimming and Climbing.md +7 -0
- package/systems/5e/world/items/Goggles of Night.md +6 -0
- package/systems/5e/world/items/Grappling Hook.md +5 -0
- package/systems/5e/world/items/Greataxe.md +10 -0
- package/systems/5e/world/items/Greatclub.md +10 -0
- package/systems/5e/world/items/Greatsword.md +10 -0
- package/systems/5e/world/items/Halberd.md +10 -0
- package/systems/5e/world/items/Half Plate Armor.md +11 -0
- package/systems/5e/world/items/Hammer of Thunderbolts.md +10 -0
- package/systems/5e/world/items/Hammer.md +5 -0
- package/systems/5e/world/items/Hand Crossbow.md +11 -0
- package/systems/5e/world/items/Handaxe.md +10 -0
- package/systems/5e/world/items/Handy Haversack.md +12 -0
- package/systems/5e/world/items/Hat of Disguise.md +7 -0
- package/systems/5e/world/items/Headband of Intellect.md +7 -0
- package/systems/5e/world/items/Healer's Kit.md +8 -0
- package/systems/5e/world/items/Heavy Crossbow.md +11 -0
- package/systems/5e/world/items/Helm of Brilliance.md +16 -0
- package/systems/5e/world/items/Helm of Comprehending Languages.md +6 -0
- package/systems/5e/world/items/Helm of Telepathy.md +9 -0
- package/systems/5e/world/items/Helm of Teleportation.md +7 -0
- package/systems/5e/world/items/Hempen Rope.md +9 -0
- package/systems/5e/world/items/Herbalism Kit.md +7 -0
- package/systems/5e/world/items/Hide Armor.md +10 -0
- package/systems/5e/world/items/Holy Avenger.md +9 -0
- package/systems/5e/world/items/Holy Water.md +10 -0
- package/systems/5e/world/items/Hooded Lantern.md +8 -0
- package/systems/5e/world/items/Horn of Blasting.md +8 -0
- package/systems/5e/world/items/Horn of Valhalla.md +17 -0
- package/systems/5e/world/items/Horn.md +7 -0
- package/systems/5e/world/items/Horseshoes of Speed.md +6 -0
- package/systems/5e/world/items/Horseshoes of a Zephyr.md +6 -0
- package/systems/5e/world/items/Hourglass.md +5 -0
- package/systems/5e/world/items/Hunting Trap.md +7 -0
- package/systems/5e/world/items/Immovable Rod.md +6 -0
- package/systems/5e/world/items/Ink Pen.md +4 -0
- package/systems/5e/world/items/Ink.md +5 -0
- package/systems/5e/world/items/Instant Fortress.md +12 -0
- package/systems/5e/world/items/Ioun Stone.md +47 -0
- package/systems/5e/world/items/Iron Bands of Binding.md +12 -0
- package/systems/5e/world/items/Iron Flask.md +33 -0
- package/systems/5e/world/items/Iron Pot.md +6 -0
- package/systems/5e/world/items/Iron Spikes.md +6 -0
- package/systems/5e/world/items/Javelin of Lightning.md +8 -0
- package/systems/5e/world/items/Javelin.md +10 -0
- package/systems/5e/world/items/Jeweler's Tools.md +7 -0
- package/systems/5e/world/items/Jug or Pitcher.md +5 -0
- package/systems/5e/world/items/Keelboat.md +7 -0
- package/systems/5e/world/items/Ladder.md +7 -0
- package/systems/5e/world/items/Lamp.md +7 -0
- package/systems/5e/world/items/Lance.md +12 -0
- package/systems/5e/world/items/Lantern of Revealing.md +6 -0
- package/systems/5e/world/items/Leather Armor.md +10 -0
- package/systems/5e/world/items/Leatherworker's Tools.md +7 -0
- package/systems/5e/world/items/Light Crossbow.md +11 -0
- package/systems/5e/world/items/Light Hammer.md +10 -0
- package/systems/5e/world/items/Lock.md +7 -0
- package/systems/5e/world/items/Longbow.md +10 -0
- package/systems/5e/world/items/Longship.md +5 -0
- package/systems/5e/world/items/Longsword.md +10 -0
- package/systems/5e/world/items/Luck Blade.md +11 -0
- package/systems/5e/world/items/Lute.md +7 -0
- package/systems/5e/world/items/Lyre.md +7 -0
- package/systems/5e/world/items/Mace of Disruption.md +9 -0
- package/systems/5e/world/items/Mace of Smiting.md +8 -0
- package/systems/5e/world/items/Mace of Terror.md +9 -0
- package/systems/5e/world/items/Mace.md +9 -0
- package/systems/5e/world/items/Magnifying Glass.md +6 -0
- package/systems/5e/world/items/Manacles.md +7 -0
- package/systems/5e/world/items/Mantle of Spell Resistance.md +7 -0
- package/systems/5e/world/items/Manual of Bodily Health.md +6 -0
- package/systems/5e/world/items/Manual of Gainful Exercise.md +6 -0
- package/systems/5e/world/items/Manual of Golems.md +17 -0
- package/systems/5e/world/items/Manual of Quickness of Action.md +6 -0
- package/systems/5e/world/items/Map or Scroll Case.md +8 -0
- package/systems/5e/world/items/Marvelous Pigments.md +14 -0
- package/systems/5e/world/items/Mason's Tools.md +7 -0
- package/systems/5e/world/items/Maul.md +10 -0
- package/systems/5e/world/items/Medallion of Thoughts.md +7 -0
- package/systems/5e/world/items/Merchant's Scale.md +8 -0
- package/systems/5e/world/items/Mess Kit.md +7 -0
- package/systems/5e/world/items/Military Saddle.md +7 -0
- package/systems/5e/world/items/Miner's Pick.md +6 -0
- package/systems/5e/world/items/Mirror of Life Trapping.md +18 -0
- package/systems/5e/world/items/Mithral Armor.md +6 -0
- package/systems/5e/world/items/Morningstar.md +9 -0
- package/systems/5e/world/items/Navigator's Tools.md +7 -0
- package/systems/5e/world/items/Necklace of Adaptation.md +7 -0
- package/systems/5e/world/items/Necklace of Fireballs.md +8 -0
- package/systems/5e/world/items/Necklace of Prayer Beads.md +18 -0
- package/systems/5e/world/items/Net.md +12 -0
- package/systems/5e/world/items/Nine Lives Stealer.md +9 -0
- package/systems/5e/world/items/Oathbow.md +11 -0
- package/systems/5e/world/items/Oil of Etherealness.md +6 -0
- package/systems/5e/world/items/Oil of Sharpness.md +6 -0
- package/systems/5e/world/items/Oil of Slipperiness.md +8 -0
- package/systems/5e/world/items/Oil.md +8 -0
- package/systems/5e/world/items/Orb of Dragonkind.md +31 -0
- package/systems/5e/world/items/Orb.md +7 -0
- package/systems/5e/world/items/Pack Saddle.md +7 -0
- package/systems/5e/world/items/Padded Armor.md +11 -0
- package/systems/5e/world/items/Painter's Supplies.md +7 -0
- package/systems/5e/world/items/Pan Flute.md +7 -0
- package/systems/5e/world/items/Paper.md +5 -0
- package/systems/5e/world/items/Parchment.md +5 -0
- package/systems/5e/world/items/Pearl of Power.md +7 -0
- package/systems/5e/world/items/Perfume.md +5 -0
- package/systems/5e/world/items/Periapt of Health.md +6 -0
- package/systems/5e/world/items/Periapt of Proof against Poison.md +6 -0
- package/systems/5e/world/items/Periapt of Wound Closure.md +7 -0
- package/systems/5e/world/items/Philter of Love.md +6 -0
- package/systems/5e/world/items/Pike.md +10 -0
- package/systems/5e/world/items/Pipes of Haunting.md +6 -0
- package/systems/5e/world/items/Pipes of the Sewers.md +11 -0
- package/systems/5e/world/items/Piton.md +5 -0
- package/systems/5e/world/items/Plate Armor of Etherealness.md +7 -0
- package/systems/5e/world/items/Plate Armor.md +12 -0
- package/systems/5e/world/items/Playing Card Set.md +6 -0
- package/systems/5e/world/items/Poisoner's Kit.md +7 -0
- package/systems/5e/world/items/Pole.md +7 -0
- package/systems/5e/world/items/Portable Hole.md +14 -0
- package/systems/5e/world/items/Portable Ram.md +8 -0
- package/systems/5e/world/items/Potion of Animal Friendship.md +6 -0
- package/systems/5e/world/items/Potion of Clairvoyance.md +6 -0
- package/systems/5e/world/items/Potion of Climbing.md +6 -0
- package/systems/5e/world/items/Potion of Diminution.md +6 -0
- package/systems/5e/world/items/Potion of Flying.md +6 -0
- package/systems/5e/world/items/Potion of Gaseous Form.md +6 -0
- package/systems/5e/world/items/Potion of Giant Strength.md +16 -0
- package/systems/5e/world/items/Potion of Growth.md +6 -0
- package/systems/5e/world/items/Potion of Healing.md +19 -0
- package/systems/5e/world/items/Potion of Heroism.md +6 -0
- package/systems/5e/world/items/Potion of Invisibility.md +6 -0
- package/systems/5e/world/items/Potion of Mind Reading.md +6 -0
- package/systems/5e/world/items/Potion of Poison.md +8 -0
- package/systems/5e/world/items/Potion of Resistance.md +14 -0
- package/systems/5e/world/items/Potion of Speed.md +6 -0
- package/systems/5e/world/items/Potion of Water Breathing.md +6 -0
- package/systems/5e/world/items/Potter's Tools.md +7 -0
- package/systems/5e/world/items/Pouch.md +7 -0
- package/systems/5e/world/items/Priest's Pack.md +6 -0
- package/systems/5e/world/items/Quarterstaff.md +10 -0
- package/systems/5e/world/items/Quiver.md +7 -0
- package/systems/5e/world/items/Rapier.md +10 -0
- package/systems/5e/world/items/Rations.md +8 -0
- package/systems/5e/world/items/Reliquary.md +7 -0
- package/systems/5e/world/items/Restorative Ointment.md +8 -0
- package/systems/5e/world/items/Riding Saddle.md +7 -0
- package/systems/5e/world/items/Ring Mail.md +10 -0
- package/systems/5e/world/items/Ring of Animal Influence.md +10 -0
- package/systems/5e/world/items/Ring of Djinni Summoning.md +11 -0
- package/systems/5e/world/items/Ring of Elemental Command.md +41 -0
- package/systems/5e/world/items/Ring of Evasion.md +7 -0
- package/systems/5e/world/items/Ring of Feather Falling.md +7 -0
- package/systems/5e/world/items/Ring of Free Action.md +7 -0
- package/systems/5e/world/items/Ring of Invisibility.md +7 -0
- package/systems/5e/world/items/Ring of Jumping.md +7 -0
- package/systems/5e/world/items/Ring of Mind Shielding.md +11 -0
- package/systems/5e/world/items/Ring of Protection.md +7 -0
- package/systems/5e/world/items/Ring of Regeneration.md +7 -0
- package/systems/5e/world/items/Ring of Resistance.md +20 -0
- package/systems/5e/world/items/Ring of Shooting Stars.md +26 -0
- package/systems/5e/world/items/Ring of Spell Storing.md +11 -0
- package/systems/5e/world/items/Ring of Spell Turning.md +7 -0
- package/systems/5e/world/items/Ring of Swimming.md +6 -0
- package/systems/5e/world/items/Ring of Telekinesis.md +7 -0
- package/systems/5e/world/items/Ring of Three Wishes.md +6 -0
- package/systems/5e/world/items/Ring of Warmth.md +7 -0
- package/systems/5e/world/items/Ring of Water Walking.md +6 -0
- package/systems/5e/world/items/Ring of X-ray Vision.md +9 -0
- package/systems/5e/world/items/Ring of the Ram.md +9 -0
- package/systems/5e/world/items/Robe of Eyes.md +15 -0
- package/systems/5e/world/items/Robe of Scintillating Colors.md +7 -0
- package/systems/5e/world/items/Robe of Stars.md +11 -0
- package/systems/5e/world/items/Robe of Useful Items.md +33 -0
- package/systems/5e/world/items/Robe of the Archmagi.md +13 -0
- package/systems/5e/world/items/Robes.md +5 -0
- package/systems/5e/world/items/Rod of Absorption.md +13 -0
- package/systems/5e/world/items/Rod of Alertness.md +15 -0
- package/systems/5e/world/items/Rod of Lordly Might.md +27 -0
- package/systems/5e/world/items/Rod of Rulership.md +7 -0
- package/systems/5e/world/items/Rod of Security.md +10 -0
- package/systems/5e/world/items/Rod.md +7 -0
- package/systems/5e/world/items/Rope of Climbing.md +10 -0
- package/systems/5e/world/items/Rope of Entanglement.md +10 -0
- package/systems/5e/world/items/Rowboat.md +7 -0
- package/systems/5e/world/items/Sack.md +5 -0
- package/systems/5e/world/items/Saddlebags.md +5 -0
- package/systems/5e/world/items/Sailing Ship.md +5 -0
- package/systems/5e/world/items/Scale Mail.md +10 -0
- package/systems/5e/world/items/Scarab of Protection.md +10 -0
- package/systems/5e/world/items/Scholar's Pack.md +6 -0
- package/systems/5e/world/items/Scimitar of Speed.md +7 -0
- package/systems/5e/world/items/Scimitar.md +10 -0
- package/systems/5e/world/items/Sealing Wax.md +4 -0
- package/systems/5e/world/items/Shawm.md +7 -0
- package/systems/5e/world/items/Shield of Missile Attraction.md +9 -0
- package/systems/5e/world/items/Shield, +1, +2, or +3.md +6 -0
- package/systems/5e/world/items/Shield.md +9 -0
- package/systems/5e/world/items/Shortbow.md +10 -0
- package/systems/5e/world/items/Shortsword.md +10 -0
- package/systems/5e/world/items/Shovel.md +5 -0
- package/systems/5e/world/items/Sickle.md +10 -0
- package/systems/5e/world/items/Signal Whistle.md +4 -0
- package/systems/5e/world/items/Signet Ring.md +4 -0
- package/systems/5e/world/items/Silk Rope.md +9 -0
- package/systems/5e/world/items/Sled.md +5 -0
- package/systems/5e/world/items/Sledgehammer.md +6 -0
- package/systems/5e/world/items/Sling Bullets.md +6 -0
- package/systems/5e/world/items/Sling.md +9 -0
- package/systems/5e/world/items/Slippers of Spider Climbing.md +7 -0
- package/systems/5e/world/items/Smith's Tools.md +7 -0
- package/systems/5e/world/items/Soap.md +4 -0
- package/systems/5e/world/items/Sovereign Glue.md +8 -0
- package/systems/5e/world/items/Spear.md +10 -0
- package/systems/5e/world/items/Spell Scroll.md +27 -0
- package/systems/5e/world/items/Spellbook.md +7 -0
- package/systems/5e/world/items/Spellguard Shield.md +7 -0
- package/systems/5e/world/items/Sphere of Annihilation.md +20 -0
- package/systems/5e/world/items/Splint Armor.md +12 -0
- package/systems/5e/world/items/Sprig of Mistletoe.md +6 -0
- package/systems/5e/world/items/Spyglass.md +7 -0
- package/systems/5e/world/items/Staff of Charming.md +11 -0
- package/systems/5e/world/items/Staff of Fire.md +11 -0
- package/systems/5e/world/items/Staff of Frost.md +11 -0
- package/systems/5e/world/items/Staff of Healing.md +9 -0
- package/systems/5e/world/items/Staff of Power.md +23 -0
- package/systems/5e/world/items/Staff of Striking.md +9 -0
- package/systems/5e/world/items/Staff of Swarming Insects.md +11 -0
- package/systems/5e/world/items/Staff of Thunder and Lightning.md +17 -0
- package/systems/5e/world/items/Staff of Withering.md +9 -0
- package/systems/5e/world/items/Staff of the Magi.md +25 -0
- package/systems/5e/world/items/Staff of the Python.md +11 -0
- package/systems/5e/world/items/Staff of the Woodlands.md +15 -0
- package/systems/5e/world/items/Staff.md +7 -0
- package/systems/5e/world/items/Steel Mirror.md +6 -0
- package/systems/5e/world/items/Stone of Controlling Earth Elementals.md +6 -0
- package/systems/5e/world/items/Stone of Good Luck.md +8 -0
- package/systems/5e/world/items/Studded Leather Armor.md +10 -0
- package/systems/5e/world/items/Sun Blade.md +11 -0
- package/systems/5e/world/items/Sword of Life Stealing.md +7 -0
- package/systems/5e/world/items/Sword of Sharpness.md +11 -0
- package/systems/5e/world/items/Sword of Wounding.md +9 -0
- package/systems/5e/world/items/Talisman of Pure Good.md +11 -0
- package/systems/5e/world/items/Talisman of Ultimate Evil.md +11 -0
- package/systems/5e/world/items/Talisman of the Sphere.md +7 -0
- package/systems/5e/world/items/Thieves' Tools.md +7 -0
- package/systems/5e/world/items/Tinderbox.md +7 -0
- package/systems/5e/world/items/Tinker's Tools.md +7 -0
- package/systems/5e/world/items/Tome of Clear Thought.md +6 -0
- package/systems/5e/world/items/Tome of Leadership and Influence.md +6 -0
- package/systems/5e/world/items/Tome of Understanding.md +6 -0
- package/systems/5e/world/items/Torch.md +7 -0
- package/systems/5e/world/items/Totem.md +6 -0
- package/systems/5e/world/items/Traveler's Clothes.md +6 -0
- package/systems/5e/world/items/Trident of Fish Command.md +7 -0
- package/systems/5e/world/items/Trident.md +10 -0
- package/systems/5e/world/items/Two-Person Tent.md +8 -0
- package/systems/5e/world/items/Unarmed Strike.md +7 -0
- package/systems/5e/world/items/Universal Solvent.md +6 -0
- package/systems/5e/world/items/Vial.md +4 -0
- package/systems/5e/world/items/Vicious Weapon.md +6 -0
- package/systems/5e/world/items/Viol.md +7 -0
- package/systems/5e/world/items/Vorpal Sword.md +9 -0
- package/systems/5e/world/items/Wagon.md +5 -0
- package/systems/5e/world/items/Wand of Binding.md +11 -0
- package/systems/5e/world/items/Wand of Enemy Detection.md +9 -0
- package/systems/5e/world/items/Wand of Fear.md +11 -0
- package/systems/5e/world/items/Wand of Fireballs.md +9 -0
- package/systems/5e/world/items/Wand of Lightning Bolts.md +9 -0
- package/systems/5e/world/items/Wand of Magic Detection.md +6 -0
- package/systems/5e/world/items/Wand of Magic Missiles.md +8 -0
- package/systems/5e/world/items/Wand of Paralysis.md +9 -0
- package/systems/5e/world/items/Wand of Polymorph.md +9 -0
- package/systems/5e/world/items/Wand of Secrets.md +6 -0
- package/systems/5e/world/items/Wand of Web.md +9 -0
- package/systems/5e/world/items/Wand of Wonder.md +38 -0
- package/systems/5e/world/items/Wand of the War Mage, +1, +2, or +3.md +7 -0
- package/systems/5e/world/items/Wand.md +7 -0
- package/systems/5e/world/items/War Pick.md +9 -0
- package/systems/5e/world/items/Warhammer.md +10 -0
- package/systems/5e/world/items/Warship.md +5 -0
- package/systems/5e/world/items/Waterskin.md +5 -0
- package/systems/5e/world/items/Weapon, +1, +2, or +3.md +6 -0
- package/systems/5e/world/items/Weaver's Tools.md +7 -0
- package/systems/5e/world/items/Well of Many Worlds.md +8 -0
- package/systems/5e/world/items/Whetstone.md +5 -0
- package/systems/5e/world/items/Whip.md +10 -0
- package/systems/5e/world/items/Wind Fan.md +6 -0
- package/systems/5e/world/items/Winged Boots.md +9 -0
- package/systems/5e/world/items/Wings of Flying.md +7 -0
- package/systems/5e/world/items/Woodcarver's Tools.md +7 -0
- package/systems/5e/world/items/Wooden Staff.md +7 -0
- package/systems/5e/world/items/Yew Wand.md +7 -0
- package/systems/5e/world/topics/Acid Arrow.md +14 -0
- package/systems/5e/world/topics/Acid Splash.md +14 -0
- package/systems/5e/world/topics/Acolyte (background).md +103 -0
- package/systems/5e/world/topics/Aid.md +14 -0
- package/systems/5e/world/topics/Alarm.md +17 -0
- package/systems/5e/world/topics/Alter Self.md +19 -0
- package/systems/5e/world/topics/Animal Friendship.md +14 -0
- package/systems/5e/world/topics/Animal Messenger.md +17 -0
- package/systems/5e/world/topics/Animal Shapes.md +17 -0
- package/systems/5e/world/topics/Animate Dead.md +18 -0
- package/systems/5e/world/topics/Animate Objects.md +31 -0
- package/systems/5e/world/topics/Antilife Shell.md +17 -0
- package/systems/5e/world/topics/Antimagic Field.md +31 -0
- package/systems/5e/world/topics/Antipathy-Sympathy.md +23 -0
- package/systems/5e/world/topics/Arcane Eye.md +17 -0
- package/systems/5e/world/topics/Arcane Hand.md +27 -0
- package/systems/5e/world/topics/Arcane Lock.md +14 -0
- package/systems/5e/world/topics/Arcane Sword.md +15 -0
- package/systems/5e/world/topics/Arcanist's Magic Aura.md +18 -0
- package/systems/5e/world/topics/Astral Projection.md +22 -0
- package/systems/5e/world/topics/Augury.md +22 -0
- package/systems/5e/world/topics/Awaken.md +14 -0
- package/systems/5e/world/topics/Bane.md +15 -0
- package/systems/5e/world/topics/Banishment.md +19 -0
- package/systems/5e/world/topics/Barbarian.md +123 -0
- package/systems/5e/world/topics/Bard Spells.md +147 -0
- package/systems/5e/world/topics/Bard.md +139 -0
- package/systems/5e/world/topics/Barkskin.md +13 -0
- package/systems/5e/world/topics/Beacon of Hope.md +13 -0
- package/systems/5e/world/topics/Bestow Curse.md +22 -0
- package/systems/5e/world/topics/Black Tentacles.md +17 -0
- package/systems/5e/world/topics/Blade Barrier.md +15 -0
- package/systems/5e/world/topics/Bless.md +15 -0
- package/systems/5e/world/topics/Blight.md +18 -0
- package/systems/5e/world/topics/Blindness-Deafness.md +15 -0
- package/systems/5e/world/topics/Blink.md +14 -0
- package/systems/5e/world/topics/Blur.md +13 -0
- package/systems/5e/world/topics/Branding Smite.md +15 -0
- package/systems/5e/world/topics/Burning Hands.md +16 -0
- package/systems/5e/world/topics/Call Lightning.md +19 -0
- package/systems/5e/world/topics/Calm Emotions.md +17 -0
- package/systems/5e/world/topics/Chain Lightning.md +16 -0
- package/systems/5e/world/topics/Champion.md +24 -0
- package/systems/5e/world/topics/Charm Person.md +14 -0
- package/systems/5e/world/topics/Chill Touch.md +16 -0
- package/systems/5e/world/topics/Circle of Death.md +14 -0
- package/systems/5e/world/topics/Circle of the Land.md +96 -0
- package/systems/5e/world/topics/Clairvoyance.md +17 -0
- package/systems/5e/world/topics/Cleric Spells.md +140 -0
- package/systems/5e/world/topics/Cleric.md +141 -0
- package/systems/5e/world/topics/Clone.md +14 -0
- package/systems/5e/world/topics/Cloudkill.md +19 -0
- package/systems/5e/world/topics/College of Lore.md +23 -0
- package/systems/5e/world/topics/Color Spray.md +16 -0
- package/systems/5e/world/topics/Command.md +26 -0
- package/systems/5e/world/topics/Commune with Nature.md +23 -0
- package/systems/5e/world/topics/Commune.md +17 -0
- package/systems/5e/world/topics/Comprehend Languages.md +15 -0
- package/systems/5e/world/topics/Compulsion.md +15 -0
- package/systems/5e/world/topics/Cone of Cold.md +16 -0
- package/systems/5e/world/topics/Confusion.md +26 -0
- package/systems/5e/world/topics/Conjure Animals.md +26 -0
- package/systems/5e/world/topics/Conjure Celestial.md +19 -0
- package/systems/5e/world/topics/Conjure Elemental.md +21 -0
- package/systems/5e/world/topics/Conjure Fey.md +21 -0
- package/systems/5e/world/topics/Conjure Minor Elementals.md +26 -0
- package/systems/5e/world/topics/Conjure Woodland Beings.md +26 -0
- package/systems/5e/world/topics/Contact Other Plane.md +15 -0
- package/systems/5e/world/topics/Contagion.md +28 -0
- package/systems/5e/world/topics/Contingency.md +16 -0
- package/systems/5e/world/topics/Continual Flame.md +12 -0
- package/systems/5e/world/topics/Control Water.md +29 -0
- package/systems/5e/world/topics/Control Weather.md +48 -0
- package/systems/5e/world/topics/Counterspell.md +14 -0
- package/systems/5e/world/topics/Create Food and Water.md +12 -0
- package/systems/5e/world/topics/Create Undead.md +18 -0
- package/systems/5e/world/topics/Create or Destroy Water.md +18 -0
- package/systems/5e/world/topics/Creation.md +26 -0
- package/systems/5e/world/topics/Cure Wounds.md +14 -0
- package/systems/5e/world/topics/Dancing Lights.md +15 -0
- package/systems/5e/world/topics/Darkness.md +17 -0
- package/systems/5e/world/topics/Darkvision.md +12 -0
- package/systems/5e/world/topics/Daylight.md +16 -0
- package/systems/5e/world/topics/Death Ward.md +16 -0
- package/systems/5e/world/topics/Delayed Blast Fireball.md +21 -0
- package/systems/5e/world/topics/Demiplane.md +14 -0
- package/systems/5e/world/topics/Detect Evil and Good.md +15 -0
- package/systems/5e/world/topics/Detect Magic.md +16 -0
- package/systems/5e/world/topics/Detect Poison and Disease.md +16 -0
- package/systems/5e/world/topics/Detect Thoughts.md +21 -0
- package/systems/5e/world/topics/Dimension Door.md +16 -0
- package/systems/5e/world/topics/Disguise Self.md +16 -0
- package/systems/5e/world/topics/Disintegrate.md +20 -0
- package/systems/5e/world/topics/Dispel Evil and Good.md +19 -0
- package/systems/5e/world/topics/Dispel Magic.md +14 -0
- package/systems/5e/world/topics/Divination.md +17 -0
- package/systems/5e/world/topics/Divine Favor.md +13 -0
- package/systems/5e/world/topics/Divine Word.md +19 -0
- package/systems/5e/world/topics/Dominate Beast.md +21 -0
- package/systems/5e/world/topics/Dominate Monster.md +21 -0
- package/systems/5e/world/topics/Dominate Person.md +21 -0
- package/systems/5e/world/topics/Draconic Bloodline.md +43 -0
- package/systems/5e/world/topics/Dream.md +18 -0
- package/systems/5e/world/topics/Druid Spells.md +140 -0
- package/systems/5e/world/topics/Druid.md +146 -0
- package/systems/5e/world/topics/Druidcraft.md +17 -0
- package/systems/5e/world/topics/Earthquake.md +25 -0
- package/systems/5e/world/topics/Eldritch Blast.md +14 -0
- package/systems/5e/world/topics/Enhance Ability.md +27 -0
- package/systems/5e/world/topics/Enlarge-Reduce.md +20 -0
- package/systems/5e/world/topics/Entangle.md +17 -0
- package/systems/5e/world/topics/Enthrall.md +12 -0
- package/systems/5e/world/topics/Etherealness.md +22 -0
- package/systems/5e/world/topics/Expeditious Retreat.md +13 -0
- package/systems/5e/world/topics/Eyebite.md +19 -0
- package/systems/5e/world/topics/Fabricate.md +16 -0
- package/systems/5e/world/topics/Faerie Fire.md +15 -0
- package/systems/5e/world/topics/Faithful Hound.md +16 -0
- package/systems/5e/world/topics/False Life.md +14 -0
- package/systems/5e/world/topics/Fear.md +15 -0
- package/systems/5e/world/topics/Feather Fall.md +12 -0
- package/systems/5e/world/topics/Feeblemind.md +18 -0
- package/systems/5e/world/topics/Fighter.md +109 -0
- package/systems/5e/world/topics/Find Familiar.md +25 -0
- package/systems/5e/world/topics/Find Steed.md +20 -0
- package/systems/5e/world/topics/Find Traps.md +14 -0
- package/systems/5e/world/topics/Find the Path.md +15 -0
- package/systems/5e/world/topics/Finger of Death.md +14 -0
- package/systems/5e/world/topics/Fire Bolt.md +14 -0
- package/systems/5e/world/topics/Fire Shield.md +16 -0
- package/systems/5e/world/topics/Fire Storm.md +14 -0
- package/systems/5e/world/topics/Fireball.md +16 -0
- package/systems/5e/world/topics/Flame Blade.md +19 -0
- package/systems/5e/world/topics/Flame Strike.md +14 -0
- package/systems/5e/world/topics/Flaming Sphere.md +19 -0
- package/systems/5e/world/topics/Flesh to Stone.md +19 -0
- package/systems/5e/world/topics/Floating Disk.md +17 -0
- package/systems/5e/world/topics/Fly.md +15 -0
- package/systems/5e/world/topics/Fog Cloud.md +15 -0
- package/systems/5e/world/topics/Forbiddance.md +19 -0
- package/systems/5e/world/topics/Forcecage.md +22 -0
- package/systems/5e/world/topics/Foresight.md +14 -0
- package/systems/5e/world/topics/Freedom of Movement.md +14 -0
- package/systems/5e/world/topics/Freezing Sphere.md +18 -0
- package/systems/5e/world/topics/Gaseous Form.md +17 -0
- package/systems/5e/world/topics/Gate.md +19 -0
- package/systems/5e/world/topics/Geas.md +18 -0
- package/systems/5e/world/topics/Gentle Repose.md +15 -0
- package/systems/5e/world/topics/Giant Insect.md +19 -0
- package/systems/5e/world/topics/Glibness.md +12 -0
- package/systems/5e/world/topics/Globe of Invulnerability.md +17 -0
- package/systems/5e/world/topics/Glyph of Warding.md +26 -0
- package/systems/5e/world/topics/Goodberry.md +14 -0
- package/systems/5e/world/topics/Grappler.md +17 -0
- package/systems/5e/world/topics/Grease.md +14 -0
- package/systems/5e/world/topics/Greater Invisibility.md +13 -0
- package/systems/5e/world/topics/Greater Restoration.md +17 -0
- package/systems/5e/world/topics/Guardian of Faith.md +14 -0
- package/systems/5e/world/topics/Guards and Wards.md +34 -0
- package/systems/5e/world/topics/Guidance.md +13 -0
- package/systems/5e/world/topics/Guiding Bolt.md +14 -0
- package/systems/5e/world/topics/Gust of Wind.md +19 -0
- package/systems/5e/world/topics/Hallow.md +36 -0
- package/systems/5e/world/topics/Hallucinatory Terrain.md +14 -0
- package/systems/5e/world/topics/Harm.md +12 -0
- package/systems/5e/world/topics/Haste.md +15 -0
- package/systems/5e/world/topics/Heal.md +14 -0
- package/systems/5e/world/topics/Healing Word.md +14 -0
- package/systems/5e/world/topics/Heat Metal.md +17 -0
- package/systems/5e/world/topics/Hellish Rebuke.md +14 -0
- package/systems/5e/world/topics/Heroes' Feast.md +14 -0
- package/systems/5e/world/topics/Heroism.md +15 -0
- package/systems/5e/world/topics/Hideous Laughter.md +15 -0
- package/systems/5e/world/topics/Hold Monster.md +15 -0
- package/systems/5e/world/topics/Hold Person.md +15 -0
- package/systems/5e/world/topics/Holy Aura.md +13 -0
- package/systems/5e/world/topics/Hunter's Mark.md +15 -0
- package/systems/5e/world/topics/Hunter.md +41 -0
- package/systems/5e/world/topics/Hypnotic Pattern.md +15 -0
- package/systems/5e/world/topics/Ice Storm.md +16 -0
- package/systems/5e/world/topics/Identify.md +15 -0
- package/systems/5e/world/topics/Illusory Script.md +19 -0
- package/systems/5e/world/topics/Imprisonment.md +38 -0
- package/systems/5e/world/topics/Incendiary Cloud.md +17 -0
- package/systems/5e/world/topics/Inflict Wounds.md +14 -0
- package/systems/5e/world/topics/Insect Plague.md +17 -0
- package/systems/5e/world/topics/Instant Summons.md +19 -0
- package/systems/5e/world/topics/Invisibility.md +15 -0
- package/systems/5e/world/topics/Irresistible Dance.md +15 -0
- package/systems/5e/world/topics/Jump.md +12 -0
- package/systems/5e/world/topics/Knock.md +18 -0
- package/systems/5e/world/topics/Legend Lore.md +14 -0
- package/systems/5e/world/topics/Lesser Restoration.md +12 -0
- package/systems/5e/world/topics/Levitate.md +17 -0
- package/systems/5e/world/topics/Life Domain.md +38 -0
- package/systems/5e/world/topics/Light.md +14 -0
- package/systems/5e/world/topics/Lightning Bolt.md +16 -0
- package/systems/5e/world/topics/Locate Animals or Plants.md +13 -0
- package/systems/5e/world/topics/Locate Creature.md +17 -0
- package/systems/5e/world/topics/Locate Object.md +17 -0
- package/systems/5e/world/topics/Longstrider.md +14 -0
- package/systems/5e/world/topics/Mage Armor.md +12 -0
- package/systems/5e/world/topics/Mage Hand.md +16 -0
- package/systems/5e/world/topics/Magic Circle.md +22 -0
- package/systems/5e/world/topics/Magic Jar.md +24 -0
- package/systems/5e/world/topics/Magic Missile.md +14 -0
- package/systems/5e/world/topics/Magic Mouth.md +17 -0
- package/systems/5e/world/topics/Magic Weapon.md +15 -0
- package/systems/5e/world/topics/Magnificent Mansion.md +16 -0
- package/systems/5e/world/topics/Major Image.md +19 -0
- package/systems/5e/world/topics/Mass Cure Wounds.md +14 -0
- package/systems/5e/world/topics/Mass Heal.md +12 -0
- package/systems/5e/world/topics/Mass Healing Word.md +14 -0
- package/systems/5e/world/topics/Mass Suggestion.md +20 -0
- package/systems/5e/world/topics/Maze.md +17 -0
- package/systems/5e/world/topics/Meld into Stone.md +17 -0
- package/systems/5e/world/topics/Mending.md +14 -0
- package/systems/5e/world/topics/Message.md +14 -0
- package/systems/5e/world/topics/Meteor Swarm.md +14 -0
- package/systems/5e/world/topics/Mind Blank.md +12 -0
- package/systems/5e/world/topics/Minor Illusion.md +18 -0
- package/systems/5e/world/topics/Mirage Arcane.md +18 -0
- package/systems/5e/world/topics/Mirror Image.md +20 -0
- package/systems/5e/world/topics/Mislead.md +17 -0
- package/systems/5e/world/topics/Misty Step.md +12 -0
- package/systems/5e/world/topics/Modify Memory.md +23 -0
- package/systems/5e/world/topics/Monk.md +153 -0
- package/systems/5e/world/topics/Moonbeam.md +21 -0
- package/systems/5e/world/topics/Move Earth.md +21 -0
- package/systems/5e/world/topics/Nondetection.md +12 -0
- package/systems/5e/world/topics/Oath of Devotion.md +62 -0
- package/systems/5e/world/topics/Paladin Spells.md +51 -0
- package/systems/5e/world/topics/Paladin.md +173 -0
- package/systems/5e/world/topics/Pass without Trace.md +13 -0
- package/systems/5e/world/topics/Passwall.md +14 -0
- package/systems/5e/world/topics/Path of the Berserker.md +21 -0
- package/systems/5e/world/topics/Phantasmal Killer.md +15 -0
- package/systems/5e/world/topics/Phantom Steed.md +15 -0
- package/systems/5e/world/topics/Planar Ally.md +22 -0
- package/systems/5e/world/topics/Planar Binding.md +16 -0
- package/systems/5e/world/topics/Plane Shift.md +16 -0
- package/systems/5e/world/topics/Plant Growth.md +18 -0
- package/systems/5e/world/topics/Poison Spray.md +14 -0
- package/systems/5e/world/topics/Polymorph.md +21 -0
- package/systems/5e/world/topics/Power Word Kill.md +12 -0
- package/systems/5e/world/topics/Power Word Stun.md +14 -0
- package/systems/5e/world/topics/Prayer of Healing.md +14 -0
- package/systems/5e/world/topics/Prestidigitation.md +21 -0
- package/systems/5e/world/topics/Prismatic Spray.md +28 -0
- package/systems/5e/world/topics/Prismatic Wall.md +34 -0
- package/systems/5e/world/topics/Private Sanctum.md +25 -0
- package/systems/5e/world/topics/Produce Flame.md +16 -0
- package/systems/5e/world/topics/Programmed Illusion.md +18 -0
- package/systems/5e/world/topics/Project Image.md +19 -0
- package/systems/5e/world/topics/Protection from Energy.md +13 -0
- package/systems/5e/world/topics/Protection from Evil and Good.md +15 -0
- package/systems/5e/world/topics/Protection from Poison.md +14 -0
- package/systems/5e/world/topics/Purify Food and Drink.md +13 -0
- package/systems/5e/world/topics/Raise Dead.md +18 -0
- package/systems/5e/world/topics/Ranger Spells.md +57 -0
- package/systems/5e/world/topics/Ranger.md +162 -0
- package/systems/5e/world/topics/Ray of Enfeeblement.md +15 -0
- package/systems/5e/world/topics/Ray of Frost.md +14 -0
- package/systems/5e/world/topics/Regenerate.md +14 -0
- package/systems/5e/world/topics/Reincarnate.md +33 -0
- package/systems/5e/world/topics/Remove Curse.md +12 -0
- package/systems/5e/world/topics/Resilient Sphere.md +19 -0
- package/systems/5e/world/topics/Resistance.md +13 -0
- package/systems/5e/world/topics/Resurrection.md +20 -0
- package/systems/5e/world/topics/Reverse Gravity.md +17 -0
- package/systems/5e/world/topics/Revivify.md +12 -0
- package/systems/5e/world/topics/Rogue.md +114 -0
- package/systems/5e/world/topics/Rope Trick.md +18 -0
- package/systems/5e/world/topics/Sacred Flame.md +14 -0
- package/systems/5e/world/topics/Sanctuary.md +14 -0
- package/systems/5e/world/topics/School of Evocation.md +24 -0
- package/systems/5e/world/topics/Scorching Ray.md +16 -0
- package/systems/5e/world/topics/Scrying.md +31 -0
- package/systems/5e/world/topics/Secret Chest.md +16 -0
- package/systems/5e/world/topics/See Invisibility.md +12 -0
- package/systems/5e/world/topics/Seeming.md +18 -0
- package/systems/5e/world/topics/Sending.md +14 -0
- package/systems/5e/world/topics/Sequester.md +16 -0
- package/systems/5e/world/topics/Shapechange.md +23 -0
- package/systems/5e/world/topics/Shatter.md +16 -0
- package/systems/5e/world/topics/Shield (spell).md +13 -0
- package/systems/5e/world/topics/Shield of Faith.md +13 -0
- package/systems/5e/world/topics/Shillelagh.md +12 -0
- package/systems/5e/world/topics/Shocking Grasp.md +14 -0
- package/systems/5e/world/topics/Silence.md +14 -0
- package/systems/5e/world/topics/Silent Image.md +17 -0
- package/systems/5e/world/topics/Simulacrum.md +18 -0
- package/systems/5e/world/topics/Sleep.md +18 -0
- package/systems/5e/world/topics/Sleet Storm.md +17 -0
- package/systems/5e/world/topics/Slow.md +19 -0
- package/systems/5e/world/topics/Sorcerer Spells.md +155 -0
- package/systems/5e/world/topics/Sorcerer.md +166 -0
- package/systems/5e/world/topics/Spare the Dying.md +12 -0
- package/systems/5e/world/topics/Speak with Animals.md +13 -0
- package/systems/5e/world/topics/Speak with Dead.md +14 -0
- package/systems/5e/world/topics/Speak with Plants.md +20 -0
- package/systems/5e/world/topics/Spider Climb.md +13 -0
- package/systems/5e/world/topics/Spike Growth.md +15 -0
- package/systems/5e/world/topics/Spirit Guardians.md +17 -0
- package/systems/5e/world/topics/Spiritual Weapon.md +18 -0
- package/systems/5e/world/topics/Stinking Cloud.md +17 -0
- package/systems/5e/world/topics/Stone Shape.md +12 -0
- package/systems/5e/world/topics/Stoneskin.md +13 -0
- package/systems/5e/world/topics/Storm of Vengeance.md +23 -0
- package/systems/5e/world/topics/Suggestion.md +19 -0
- package/systems/5e/world/topics/Sunbeam.md +17 -0
- package/systems/5e/world/topics/Sunburst.md +16 -0
- package/systems/5e/world/topics/Symbol.md +36 -0
- package/systems/5e/world/topics/Telekinesis.md +23 -0
- package/systems/5e/world/topics/Telepathic Bond.md +15 -0
- package/systems/5e/world/topics/Teleport.md +38 -0
- package/systems/5e/world/topics/Teleportation Circle.md +16 -0
- package/systems/5e/world/topics/Thaumaturgy.md +21 -0
- package/systems/5e/world/topics/The Fiend.md +47 -0
- package/systems/5e/world/topics/Thief.md +24 -0
- package/systems/5e/world/topics/Thunderwave.md +16 -0
- package/systems/5e/world/topics/Time Stop.md +14 -0
- package/systems/5e/world/topics/Tiny Hut.md +17 -0
- package/systems/5e/world/topics/Tongues.md +12 -0
- package/systems/5e/world/topics/Transport via Plants.md +12 -0
- package/systems/5e/world/topics/Tree Stride.md +15 -0
- package/systems/5e/world/topics/True Polymorph.md +29 -0
- package/systems/5e/world/topics/True Resurrection.md +16 -0
- package/systems/5e/world/topics/True Seeing.md +12 -0
- package/systems/5e/world/topics/True Strike.md +13 -0
- package/systems/5e/world/topics/Unseen Servant.md +17 -0
- package/systems/5e/world/topics/Vampiric Touch.md +15 -0
- package/systems/5e/world/topics/Vicious Mockery.md +14 -0
- package/systems/5e/world/topics/Wall of Fire.md +19 -0
- package/systems/5e/world/topics/Wall of Force.md +15 -0
- package/systems/5e/world/topics/Wall of Ice.md +19 -0
- package/systems/5e/world/topics/Wall of Stone.md +23 -0
- package/systems/5e/world/topics/Wall of Thorns.md +19 -0
- package/systems/5e/world/topics/Warding Bond.md +14 -0
- package/systems/5e/world/topics/Warlock Spells.md +99 -0
- package/systems/5e/world/topics/Warlock.md +283 -0
- package/systems/5e/world/topics/Water Breathing.md +13 -0
- package/systems/5e/world/topics/Water Walk.md +15 -0
- package/systems/5e/world/topics/Way of the Open Hand.md +25 -0
- package/systems/5e/world/topics/Web.md +21 -0
- package/systems/5e/world/topics/Weird.md +13 -0
- package/systems/5e/world/topics/Wind Walk.md +14 -0
- package/systems/5e/world/topics/Wind Wall.md +17 -0
- package/systems/5e/world/topics/Wish.md +26 -0
- package/systems/5e/world/topics/Wizard Spells.md +239 -0
- package/systems/5e/world/topics/Wizard.md +141 -0
- package/systems/5e/world/topics/Word of Recall.md +14 -0
- package/systems/5e/world/topics/Zone of Truth.md +14 -0
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { basename, join } from "node:path";
|
|
3
|
+
import { parse } from "yaml";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { fieldKinds } from "../core/field-kind.js";
|
|
6
|
+
import { formulaOf, readFormulas } from "../core/formula.js";
|
|
7
|
+
import { frozen } from "../core/frozen.js";
|
|
8
|
+
import { lengthHelp, readLength, readSpeed, speedHelp } from "../core/length.js";
|
|
9
|
+
import { files } from "../core/store.js";
|
|
10
|
+
import { comparableText, sameName } from "../core/text.js";
|
|
11
|
+
import { readYamlValues } from "../core/yaml-file.js";
|
|
12
|
+
/** The file that makes a folder a game system and says what it is. */
|
|
13
|
+
export const systemFileName = "system.yaml";
|
|
14
|
+
// An entry of the sheet: a field, ? when it is written only when it applies, and a field shown beside it in parentheses.
|
|
15
|
+
const sheetEntryPattern = /^([^\s()?]+)(\?)?(?: \(([^\s()?]+)\))?$/;
|
|
16
|
+
// The dice a number of the sheet is rolled with: dice alone, as 1d20 or 2d6+1d4 (D-280).
|
|
17
|
+
const sheetDicePattern = /^\d*d\d+(?:\+\d*d\d+)*$/;
|
|
18
|
+
// A roll the game has a name for: dice of one kind, with the highest or the lowest kept or dropped, as 2d20kh1 (D-399).
|
|
19
|
+
const rollNamePattern = /^\d*d(?:\d+|%)(?:[kd][hl]\d*)?$/i;
|
|
20
|
+
// A field named in the headline under a character's name: {level} (D-288).
|
|
21
|
+
const headlineFieldPattern = /\{([^{}]+)\}/g;
|
|
22
|
+
// A group's icon on the dashboard: the d of an SVG path, its letters and numbers alone (D-284).
|
|
23
|
+
const iconPattern = /^[Mm][MmLlHhVvCcSsQqTtAaZz\d.,\s+-]*$/;
|
|
24
|
+
const recipeSchema = z.object({
|
|
25
|
+
set: z.record(z.string(), z.union([z.literal("max"), z.number().int()])).optional(),
|
|
26
|
+
regain: z.record(z.string(), z.union([z.number(), z.string().min(1)])).optional(),
|
|
27
|
+
ends: z.array(z.string().min(1)).optional(),
|
|
28
|
+
rules: z.array(z.string().min(1)).optional(),
|
|
29
|
+
}).strict();
|
|
30
|
+
const lengthSchema = z.string().refine((text) => readLength(text) !== undefined, `write it ${lengthHelp}`);
|
|
31
|
+
const speedSchema = z.string().refine((text) => readSpeed(text) !== undefined, `write ${speedHelp}`);
|
|
32
|
+
// A factor of speed, such as 1/2 for difficult terrain, or 0.5.
|
|
33
|
+
const factorSchema = z.union([z.number().positive(), z.string().regex(/^\d+\/[1-9]\d*$/, "write it as 1/2, or as a number such as 0.5")]);
|
|
34
|
+
const hoursSchema = z.number().positive().max(24);
|
|
35
|
+
const travelSchema = z.object({
|
|
36
|
+
paces: z.record(z.string().min(1), speedSchema).optional(),
|
|
37
|
+
pace: z.string().min(1).optional(),
|
|
38
|
+
hours: hoursSchema.optional(),
|
|
39
|
+
rule: z.string().min(1).optional(),
|
|
40
|
+
beyond: z.string().min(1).optional(),
|
|
41
|
+
terrain: z.record(z.string().min(1), factorSchema).optional(),
|
|
42
|
+
kinds: z.record(z.string().min(1), z.object({
|
|
43
|
+
vehicle: z.record(z.string().min(1), z.string().min(1)).refine((match) => Object.keys(match).length === 1, "give one field and its value, such as {category: waterborne vehicle}").optional(),
|
|
44
|
+
speed: z.string().min(1).optional(),
|
|
45
|
+
hours: hoursSchema.optional(),
|
|
46
|
+
current: speedSchema.optional(),
|
|
47
|
+
}).strict().refine((kind) => (kind.vehicle === undefined) === (kind.speed === undefined), "give vehicle and speed together: what carries one on it, and its field that holds its speed")).optional(),
|
|
48
|
+
}).strict().refine((travel) => travel.pace === undefined || Object.keys(travel.paces ?? {}).some((pace) => comparableText(pace) === comparableText(travel.pace ?? "")), {
|
|
49
|
+
message: "pace must be one of paces",
|
|
50
|
+
path: ["pace"],
|
|
51
|
+
});
|
|
52
|
+
const gridSchema = z.object({
|
|
53
|
+
square: lengthSchema,
|
|
54
|
+
diagonal: z.number().positive(),
|
|
55
|
+
difficult: z.number().positive(),
|
|
56
|
+
speed: z.string().min(1),
|
|
57
|
+
size: z.string().min(1).optional(),
|
|
58
|
+
footprints: z.record(z.string().min(1), z.number().int().min(1)).optional(),
|
|
59
|
+
leaving: z.string().min(1).optional(),
|
|
60
|
+
}, { error: "write it as a square's length, a diagonal step's cost in squares, the factor of difficult ground and the field of the speed, such as {square: 1.5 m, diagonal: 1, difficult: 2, speed: speed}" }).strict();
|
|
61
|
+
const systemSchema = z.object({
|
|
62
|
+
title: z.string().min(1),
|
|
63
|
+
language: z.string().regex(/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/),
|
|
64
|
+
attribution: z.string().min(1).optional(),
|
|
65
|
+
fields: z.record(z.string(), z.enum(fieldKinds)).optional(),
|
|
66
|
+
coins: z.union([z.string().min(1), z.record(z.string(), z.unknown())]).optional(),
|
|
67
|
+
round: z.string().regex(/^[1-9]\d* seconds?$/, 'write it as "6 seconds"').optional(),
|
|
68
|
+
imperial: z.object({ mile: lengthSchema, foot: lengthSchema }).strict().optional(),
|
|
69
|
+
travel: travelSchema.optional(),
|
|
70
|
+
grid: gridSchema.optional(),
|
|
71
|
+
sheet: z.record(z.string().min(1), z.array(z.string().regex(sheetEntryPattern, 'write it as "str", "str (str-mod)" for a field shown beside it, or "flaw?" for one written only when it applies')).min(1), {
|
|
72
|
+
error: "write the sheet as groups, each with its fields, such as Abilities: [str (str-mod), dex (dex-mod)]",
|
|
73
|
+
}).optional(),
|
|
74
|
+
"sheet-notes": z.record(z.string().min(1), z.string().min(1)).optional(),
|
|
75
|
+
"sheet-cards": z.object({ rail: z.array(z.string().min(1)).optional(), order: z.array(z.string().min(1)).optional(), "at-hand": z.array(z.string().min(1)).optional() }, {
|
|
76
|
+
error: "write it as the groups the dashboard puts in its rail, the order of the others, and the fields and groups at hand in a fight, such as {rail: [Abilities], order: [Skills, Combat], at-hand: [ac, hp, Attacks]}",
|
|
77
|
+
}).strict().optional(),
|
|
78
|
+
"sheet-headline": z.string().min(1).regex(/\{[^{}\s]+\}/, "write it as words with fields in braces, such as Level {level} {classes}").optional(),
|
|
79
|
+
"sheet-icons": z.record(z.string().min(1), z.string().max(2000).regex(iconPattern, "write it as the d of an SVG path on a grid of 24, its letters and numbers alone, such as M4 12h16")).optional(),
|
|
80
|
+
"token-icons": z.object({
|
|
81
|
+
field: z.string().min(1),
|
|
82
|
+
icons: z.record(z.string().min(1), z.string().max(2000).regex(iconPattern, "write it as the d of an SVG path on a grid of 24, its letters and numbers alone, such as M4 12h16")),
|
|
83
|
+
}).strict().optional(),
|
|
84
|
+
"sheet-dice": z.record(z.string().regex(sheetDicePattern), z.array(z.string().min(1)).min(1), {
|
|
85
|
+
error: "write it as dice alone, as 1d20 or 2d6+1d4, and the fields of the sheet rolled with them, such as 1d20: [athletics, stealth]",
|
|
86
|
+
}).optional(),
|
|
87
|
+
"roll-names": z.record(z.string().regex(rollNamePattern), z.union([z.string().min(1), z.record(z.string().min(2), z.string().min(1))]), {
|
|
88
|
+
error: "write it as dice with the highest or the lowest kept or dropped, and the name the game gives such a roll, by language, such as 2d20kh1: {en: with advantage, it: con vantaggio}",
|
|
89
|
+
}).optional(),
|
|
90
|
+
values: z.record(z.string().min(1), z.array(z.string().min(1)).min(1)).optional(),
|
|
91
|
+
marks: z.array(z.string().min(1)).optional(),
|
|
92
|
+
"status-line": z.array(z.string().min(1)).optional(),
|
|
93
|
+
thresholds: z.record(z.string().regex(/^[^\s]+( -?\d+)?$/, 'write it as "hp 0", or the field alone'), z.string().min(1)).optional(),
|
|
94
|
+
recipes: z.record(z.string(), recipeSchema).optional(),
|
|
95
|
+
conditions: z.array(z.string().min(1)).optional(),
|
|
96
|
+
"condition-icons": z.record(z.string().min(1), z.string().max(2000).regex(iconPattern, "write it as the d of an SVG path on a grid of 24, its letters and numbers alone, such as M4 12h16")).optional(),
|
|
97
|
+
keeping: z.object({ counter: z.string().min(1), conditions: z.array(z.string().min(1)).optional(), rules: z.string().min(1) }, {
|
|
98
|
+
error: "write it as what can break what someone keeps alive, such as {counter: hp, conditions: [Unconscious], rules: Concentration}",
|
|
99
|
+
}).strict().optional(),
|
|
100
|
+
combat: z.object({ track: z.string().min(1), "in-words": z.boolean().optional(), inactive: z.array(z.string().min(1)).optional() }, {
|
|
101
|
+
error: "write it as the counter a fight follows, whether the player hears a foe's in words, and the conditions that keep from acting, such as {track: hp, in-words: true, inactive: [Stunned]}",
|
|
102
|
+
}).strict().optional(),
|
|
103
|
+
dying: z.object({ at: z.string().regex(/^[^\s]+ -?\d+$/, 'write it as "hp 0"'), show: z.array(z.string().min(1)).min(1) }, {
|
|
104
|
+
error: "write it as when the panel of the dying shows and its counters, such as {at: hp 0, show: [death-successes, death-failures]}",
|
|
105
|
+
}).strict().optional(),
|
|
106
|
+
tables: z.record(z.string(), z.record(z.string(), z.number())).optional(),
|
|
107
|
+
progression: z.object({
|
|
108
|
+
list: z.string().min(1),
|
|
109
|
+
features: z.string().min(1),
|
|
110
|
+
skip: z.array(z.string().min(1)).optional(),
|
|
111
|
+
parts: z.object({ list: z.string().min(1), field: z.string().min(1), lists: z.array(z.string().min(1)).optional() }).strict().optional(),
|
|
112
|
+
experience: z.object({ field: z.string().min(1), table: z.string().min(1), rules: z.string().min(1).optional() }).strict().optional(),
|
|
113
|
+
}).strict().optional(),
|
|
114
|
+
settings: z.record(z.string().min(1), z.record(z.string().min(1), z.union([z.string().min(1), z.object({ means: z.string().min(1), player: z.string().min(1).optional(), without: z.array(z.string().min(1)).optional() }).strict()])).refine((values) => Object.entries(values).every(([key, value]) => (key === "about") === (typeof value === "string")), "give about as what the setting is to the player, in a few words, and each value with what it means, such as {about: how your character levels up, xp: {means: ...}}").refine((values) => Object.keys(values).filter((key) => key !== "about").length >= 2, "give at least two values, each with what it means, such as {xp: {means: ...}, milestones: {means: ...}}")).optional(),
|
|
115
|
+
rewards: z.record(z.string().min(1), z.object({ from: z.string().min(1), overcome: z.string().regex(/^[^\s]+ -?\d+$/, 'write it as "hp 0"') }).strict()).optional(),
|
|
116
|
+
"item-formulas": z.record(z.string().min(1), z.array(z.string().min(1)).min(1)).optional(),
|
|
117
|
+
"always-in": z.record(z.string().min(1), z.array(z.string().min(1)).min(1), { error: "write it as lists, each with the names of the pages in it, such as equipped: [Unarmed Strike]" }).optional(),
|
|
118
|
+
computed: z.record(z.string(), z.union([z.number(), z.string().min(1), z.array(z.union([z.number(), z.string().min(1)]))])).optional(),
|
|
119
|
+
counters: z.record(z.string(), z.object({
|
|
120
|
+
min: z.union([z.number(), z.string().min(1)]).optional(),
|
|
121
|
+
max: z.union([z.number(), z.string().min(1)]).optional(),
|
|
122
|
+
refill: z.union([z.string().min(1), z.record(z.string().min(1), z.union([z.number(), z.string().min(1)]))]).optional(),
|
|
123
|
+
shields: z.string().min(1).optional(),
|
|
124
|
+
}).strict()).optional(),
|
|
125
|
+
}).strict();
|
|
126
|
+
/**
|
|
127
|
+
* The system as a campaign plays it, with the values its settings have (DAT-10): the fields a value leaves out are gone from the sheet, the line, the experience
|
|
128
|
+
* and the rewards. A setting without a value, or with one the system lacks, leaves out nothing.
|
|
129
|
+
*/
|
|
130
|
+
export function withSettings(system, valueOf) {
|
|
131
|
+
const leftOut = system.settings.flatMap((setting) => {
|
|
132
|
+
const chosen = valueOf(setting.name);
|
|
133
|
+
return setting.values.find((value) => chosen !== undefined && comparableText(value.value) === comparableText(chosen))?.without ?? [];
|
|
134
|
+
});
|
|
135
|
+
if (leftOut.length === 0) {
|
|
136
|
+
return system;
|
|
137
|
+
}
|
|
138
|
+
const kept = (field) => !leftOut.some((name) => comparableText(name) === comparableText(field));
|
|
139
|
+
const progression = system.progression === undefined ? undefined : withoutExperience(system.progression, kept);
|
|
140
|
+
return frozen({
|
|
141
|
+
...system,
|
|
142
|
+
sheet: system.sheet.map((group) => ({ ...group, entries: group.entries.filter((entry) => kept(entry.field)) })).filter((group) => group.entries.length > 0),
|
|
143
|
+
statusLine: system.statusLine.filter((entry) => kept(entry.field)),
|
|
144
|
+
...(progression === undefined ? {} : { progression }),
|
|
145
|
+
rewards: system.rewards.filter((reward) => kept(reward.field)),
|
|
146
|
+
leftOut,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The name the game gives a roll of these dice, in the language asked, else in the system's (D-399): 2d20kh1, or 2d20dl1, is "with advantage" in 5e; undefined
|
|
151
|
+
* when the game names it not, or the dice are more than one kind.
|
|
152
|
+
*/
|
|
153
|
+
export function rollName(system, dice, language) {
|
|
154
|
+
const names = system.rollNames[plainRoll(dice)];
|
|
155
|
+
return names === undefined ? undefined : (names[language] ?? names[language.split("-")[0] ?? language] ?? names[system.language]);
|
|
156
|
+
}
|
|
157
|
+
/** A roll's dice as a name reads them: in lower case, the highest or the lowest kept one when one of two is dropped, as 2d20dl1 is 2d20kh1. */
|
|
158
|
+
function plainRoll(dice) {
|
|
159
|
+
const compact = dice.toLowerCase().replace(/\s+/g, "").replace(/([kd][hl])$/, (rule) => `${rule}1`);
|
|
160
|
+
return /^2d/.test(compact) ? compact.replace(/dl1$/, "kh1").replace(/dh1$/, "kl1") : compact;
|
|
161
|
+
}
|
|
162
|
+
/** The systems installed in these folders, nearest folder first: each folder in them with a system.yaml. A name found twice is the nearest one. */
|
|
163
|
+
export function installedSystems(folders) {
|
|
164
|
+
const systems = [];
|
|
165
|
+
for (const folder of folders.filter((candidate) => existsSync(candidate))) {
|
|
166
|
+
for (const entry of readdirSync(folder, { withFileTypes: true }).filter((candidate) => candidate.isDirectory()).sort((first, second) => (first.name < second.name ? -1 : 1))) {
|
|
167
|
+
if (existsSync(join(folder, entry.name, systemFileName)) && !systems.some((system) => comparableText(system.name) === comparableText(entry.name))) {
|
|
168
|
+
systems.push(readSystem(join(folder, entry.name), entry.name));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return systems;
|
|
173
|
+
}
|
|
174
|
+
/** What a campaign may add to its game system in campaign.yaml (CAM-1): its own fields, tables, formulas, counters, recipes, line of the player character and travel. */
|
|
175
|
+
export const campaignDataNames = ["fields", "tables", "computed", "counters", "recipes", "status-line", "travel"];
|
|
176
|
+
/**
|
|
177
|
+
* The installed system with what the campaign adds to it, the nearest layer winning (CAM-2); when the additions do not read, the system alone and why (CAM-3).
|
|
178
|
+
* Undefined as a system when none is installed by that name.
|
|
179
|
+
*/
|
|
180
|
+
export function findCampaignSystem(folders, name, data) {
|
|
181
|
+
const system = findSystem(folders, name);
|
|
182
|
+
if (system === undefined || campaignDataNames.every((key) => data[key] === undefined || data[key] === null)) {
|
|
183
|
+
return { system };
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
return { system: findSystem(folders, name, data) };
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
190
|
+
return { system, problem: message.replace(/^The game system .*? cannot be read, because .*? is not valid:\s*/s, "") };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* The installed system with this name, ignoring case, from the nearest folder that has it, with what a campaign adds to it; undefined when none is. Only its own
|
|
195
|
+
* system.yaml is read.
|
|
196
|
+
*/
|
|
197
|
+
export function findSystem(folders, name, data) {
|
|
198
|
+
for (const folder of folders.filter((candidate) => existsSync(candidate))) {
|
|
199
|
+
const entry = readdirSync(folder, { withFileTypes: true })
|
|
200
|
+
.filter((candidate) => candidate.isDirectory() && comparableText(candidate.name) === comparableText(name.trim()))
|
|
201
|
+
.sort((first, second) => (first.name < second.name ? -1 : 1))
|
|
202
|
+
.find((candidate) => existsSync(join(folder, candidate.name, systemFileName)));
|
|
203
|
+
if (entry !== undefined) {
|
|
204
|
+
return readSystem(join(folder, entry.name), entry.name, data);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
function readSystem(folder, name, additions) {
|
|
210
|
+
const file = join(folder, systemFileName);
|
|
211
|
+
const path = additions === undefined ? file : `${file} with the additions of campaign.yaml`;
|
|
212
|
+
const raw = readYamlValues(file, 'what the system is, such as "title: ..."');
|
|
213
|
+
let merged = raw;
|
|
214
|
+
try {
|
|
215
|
+
merged = additions === undefined ? raw : withCampaignData(raw, additions);
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${error instanceof Error ? error.message : String(error)}`);
|
|
219
|
+
}
|
|
220
|
+
const parsed = systemSchema.safeParse(merged);
|
|
221
|
+
if (!parsed.success) {
|
|
222
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${issuesText(parsed.error)}`);
|
|
223
|
+
}
|
|
224
|
+
const data = parsed.data;
|
|
225
|
+
// What a counter shields is no limit of it: a counter with only that has none (DAT-14).
|
|
226
|
+
const limited = Object.entries(data.counters ?? {}).flatMap(([counter, { min, max, refill }]) => min === undefined && max === undefined && refill === undefined ? [] : [[counter, { min, max, refill }]]);
|
|
227
|
+
const formulas = systemFormulas({ ...data, counters: Object.fromEntries(limited) }, name, path);
|
|
228
|
+
const stray = strayOccasion(data, formulas);
|
|
229
|
+
if (stray !== undefined) {
|
|
230
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${stray}`);
|
|
231
|
+
}
|
|
232
|
+
const sheet = sheetOf(data, name, path);
|
|
233
|
+
const values = data.values ?? {};
|
|
234
|
+
const kindOf = (field) => Object.entries(data.fields ?? {}).find(([declared]) => comparableText(declared) === comparableText(field))?.[1];
|
|
235
|
+
const notList = Object.keys(values).find((field) => kindOf(field) !== "list");
|
|
236
|
+
if (notList !== undefined) {
|
|
237
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: values.${notList}: declare ${notList} as a list in fields, or give no values to it.`);
|
|
238
|
+
}
|
|
239
|
+
// What breaks what someone keeps, and what a counter shields, read counters (EFF-14, DAT-14).
|
|
240
|
+
const counted = [
|
|
241
|
+
...(data.keeping === undefined ? [] : [{ where: "keeping.counter", field: data.keeping.counter }]),
|
|
242
|
+
...(data.combat === undefined ? [] : [{ where: "combat.track", field: data.combat.track }]),
|
|
243
|
+
...(data.dying === undefined ? [] : [data.dying.at.split(" ")[0], ...data.dying.show].map((field) => ({ where: "dying", field }))),
|
|
244
|
+
...Object.entries(data.counters ?? {}).flatMap(([counter, limits]) => (limits.shields === undefined ? [] : [{ where: `counters.${counter}.shields`, field: limits.shields }])),
|
|
245
|
+
].find((entry) => kindOf(entry.field) !== "counter");
|
|
246
|
+
const unknownCondition = [
|
|
247
|
+
...(data.keeping?.conditions ?? []).map((condition) => ({ where: "keeping.conditions", condition })),
|
|
248
|
+
...(data.combat?.inactive ?? []).map((condition) => ({ where: "combat.inactive", condition })),
|
|
249
|
+
...Object.keys(data["condition-icons"] ?? {}).map((condition) => ({ where: "condition-icons", condition })),
|
|
250
|
+
].find((entry) => !(data.conditions ?? []).some((named) => comparableText(named) === comparableText(entry.condition)));
|
|
251
|
+
if (unknownCondition !== undefined) {
|
|
252
|
+
const named = (data.conditions ?? []).length === 0 ? "" : ` (${(data.conditions ?? []).join(", ")})`;
|
|
253
|
+
const what = `${unknownCondition.where}: ${unknownCondition.condition} is not one of its conditions${named}; write it as one of them, or add it to conditions.`;
|
|
254
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${what}`);
|
|
255
|
+
}
|
|
256
|
+
const gridField = [data.grid?.speed, data.grid?.size].find((field) => field !== undefined && kindOf(field) === undefined);
|
|
257
|
+
if (gridField !== undefined) {
|
|
258
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: grid: ${gridField} is not declared in fields.`);
|
|
259
|
+
}
|
|
260
|
+
if (counted !== undefined) {
|
|
261
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${counted.where}: ${counted.field} is not declared as a counter in fields.`);
|
|
262
|
+
}
|
|
263
|
+
const notMarking = [...(data.marks ?? []), ...[data.progression?.list, data.progression?.parts?.list].filter((field) => field !== undefined)].find((field) => kindOf(field) !== "list");
|
|
264
|
+
if (notMarking !== undefined) {
|
|
265
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${notMarking} is not declared as a list in fields, as marks and progression need.`);
|
|
266
|
+
}
|
|
267
|
+
// Each number rolled with dice is a declared field, and has one set of dice (D-280).
|
|
268
|
+
const rolled = Object.entries(data["sheet-dice"] ?? {}).flatMap(([dice, fields]) => fields.map((field) => [field, dice]));
|
|
269
|
+
const undeclared = rolled.find(([field]) => kindOf(field) === undefined);
|
|
270
|
+
const twice = rolled.find(([field], index) => rolled.findIndex(([other]) => comparableText(other) === comparableText(field)) !== index);
|
|
271
|
+
if (undeclared !== undefined) {
|
|
272
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: sheet-dice.${undeclared[1]}: ${undeclared[0]} is not declared in fields.`);
|
|
273
|
+
}
|
|
274
|
+
if (twice !== undefined) {
|
|
275
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: sheet-dice: ${twice[0]} is listed twice; give each field one set of dice.`);
|
|
276
|
+
}
|
|
277
|
+
// The cards the dashboard places are groups of the sheet (D-295); at hand in a fight, its fields too (D-315).
|
|
278
|
+
for (const [key, names] of Object.entries(data["sheet-cards"] ?? {})) {
|
|
279
|
+
const fields = key === "at-hand" ? sheet.flatMap((group) => group.entries.map((entry) => comparableText(entry.field))) : [];
|
|
280
|
+
const stray = (names ?? []).find((group) => !sheet.some((declared) => comparableText(declared.name) === comparableText(group)) && !fields.includes(comparableText(group)));
|
|
281
|
+
if (stray !== undefined) {
|
|
282
|
+
const kinds = key === "at-hand" ? "group or field" : "group";
|
|
283
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: sheet-cards.${key}: the sheet has no ${kinds} ${stray}; its groups are ${sheet.map((group) => group.name).join(", ")}.`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Each field the headline names is a declared one (D-288).
|
|
287
|
+
const unnamed = [...(data["sheet-headline"] ?? "").matchAll(headlineFieldPattern)].map((match) => match[1]).find((field) => kindOf(field) === undefined);
|
|
288
|
+
if (unnamed !== undefined) {
|
|
289
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: sheet-headline: ${unnamed} is not declared in fields.`);
|
|
290
|
+
}
|
|
291
|
+
// The tokens' icons read a declared field (D-414).
|
|
292
|
+
const iconField = data["token-icons"]?.field;
|
|
293
|
+
if (iconField !== undefined && kindOf(iconField) === undefined) {
|
|
294
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: token-icons.field: ${iconField} is not declared in fields.`);
|
|
295
|
+
}
|
|
296
|
+
const experience = data.progression?.experience?.table;
|
|
297
|
+
if (experience !== undefined && !Object.keys(formulas.tables).some((table) => comparableText(table) === comparableText(experience))) {
|
|
298
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: progression.experience.table: there is no table ${experience} in tables.`);
|
|
299
|
+
}
|
|
300
|
+
return frozen({
|
|
301
|
+
name,
|
|
302
|
+
folder,
|
|
303
|
+
title: data.title,
|
|
304
|
+
language: data.language,
|
|
305
|
+
attribution: data.attribution,
|
|
306
|
+
fields: data.fields ?? {},
|
|
307
|
+
coins: data.coins,
|
|
308
|
+
roundSeconds: data.round === undefined ? undefined : Number.parseInt(data.round, 10),
|
|
309
|
+
...(data.imperial === undefined ? {} : { imperial: { mile: readLength(data.imperial.mile) ?? 0, foot: readLength(data.imperial.foot) ?? 0 } }),
|
|
310
|
+
...(data.travel === undefined ? {} : { travel: travelOf(data.travel) }),
|
|
311
|
+
...(data.grid === undefined ? {} : { grid: gridOf(data.grid) }),
|
|
312
|
+
sheet,
|
|
313
|
+
sheetDice: Object.fromEntries(rolled),
|
|
314
|
+
rollNames: Object.fromEntries(Object.entries(data["roll-names"] ?? {}).map(([dice, names]) => [plainRoll(dice), typeof names === "string" ? { [data.language]: names } : names])),
|
|
315
|
+
...(data["sheet-headline"] === undefined ? {} : { sheetHeadline: data["sheet-headline"] }),
|
|
316
|
+
...(data["token-icons"] === undefined ? {} : { tokenIcons: data["token-icons"] }),
|
|
317
|
+
...(data["sheet-cards"] === undefined ? {} : { sheetCards: { rail: data["sheet-cards"].rail ?? [], order: data["sheet-cards"].order ?? [], atHand: data["sheet-cards"]["at-hand"] ?? [] } }),
|
|
318
|
+
values,
|
|
319
|
+
marks: data.marks ?? [],
|
|
320
|
+
statusLine: (data["status-line"] ?? []).map((entry) => ({ field: entry.replace(/\?$/, ""), whenSet: entry.endsWith("?") })),
|
|
321
|
+
thresholds: Object.entries(data.thresholds ?? {}).map(([key, rule]) => {
|
|
322
|
+
const [field, value] = key.split(" ");
|
|
323
|
+
return { field, value: value === undefined ? undefined : Number(value), rule };
|
|
324
|
+
}),
|
|
325
|
+
recipes: Object.entries(data.recipes ?? {}).map(([recipe, value]) => ({
|
|
326
|
+
name: recipe,
|
|
327
|
+
set: value.set ?? {},
|
|
328
|
+
regain: regainOf(value.regain ?? {}, name, path, recipe),
|
|
329
|
+
ends: value.ends ?? [],
|
|
330
|
+
rules: value.rules ?? [],
|
|
331
|
+
})),
|
|
332
|
+
conditions: data.conditions ?? [],
|
|
333
|
+
conditionIcons: data["condition-icons"] ?? {},
|
|
334
|
+
...(data.keeping === undefined ? {} : { keeping: { counter: data.keeping.counter, conditions: data.keeping.conditions ?? [], rules: data.keeping.rules } }),
|
|
335
|
+
...(data.combat === undefined ? {} : { combat: { track: data.combat.track, inWords: data.combat["in-words"] ?? false, inactive: data.combat.inactive ?? [] } }),
|
|
336
|
+
...(data.dying === undefined ? {} : { dying: { field: data.dying.at.split(" ")[0], value: Number(data.dying.at.split(" ")[1]), show: data.dying.show } }),
|
|
337
|
+
shields: Object.fromEntries(Object.entries(data.counters ?? {}).flatMap(([counter, limits]) => (limits.shields === undefined ? [] : [[counter, limits.shields]]))),
|
|
338
|
+
formulas,
|
|
339
|
+
...(data.progression === undefined ? {} : { progression: progressionRule(data.progression) }),
|
|
340
|
+
itemFormulas: data["item-formulas"] ?? {},
|
|
341
|
+
alwaysIn: data["always-in"] ?? {},
|
|
342
|
+
uses: usesOf(data),
|
|
343
|
+
settings: Object.entries(data.settings ?? {}).map(([setting, values]) => ({
|
|
344
|
+
name: setting,
|
|
345
|
+
...(typeof values.about === "string" ? { about: values.about } : {}),
|
|
346
|
+
values: Object.entries(values).flatMap(([value, meaning]) => typeof meaning === "string" ? [] : [{
|
|
347
|
+
value,
|
|
348
|
+
means: meaning.means,
|
|
349
|
+
...(meaning.player === undefined ? {} : { player: meaning.player }),
|
|
350
|
+
without: meaning.without ?? [],
|
|
351
|
+
}]),
|
|
352
|
+
})),
|
|
353
|
+
leftOut: [],
|
|
354
|
+
rewards: Object.entries(data.rewards ?? {}).map(([field, reward]) => {
|
|
355
|
+
const [counter, value] = reward.overcome.split(" ");
|
|
356
|
+
return { field, from: reward.from, counter, value: Number(value) };
|
|
357
|
+
}),
|
|
358
|
+
parts: readParts(folder, name),
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* "counters.superiority-dice: unknown key "Combat Superiority)", a formula with commas goes in quotes": the problems of a system's data, one after the other on
|
|
363
|
+
* a line, each at its place.
|
|
364
|
+
*/
|
|
365
|
+
function issuesText(error) {
|
|
366
|
+
return error.issues.map((issue) => {
|
|
367
|
+
const place = issue.path.map(String).join(".");
|
|
368
|
+
const keys = issue.code === "unrecognized_keys" ? issue.keys : [];
|
|
369
|
+
const quotes = keys.some((key) => /[()]/.test(key)) ? ": a formula with commas goes in quotes" : "";
|
|
370
|
+
const vague = issue.message === "Invalid input" ? "not a value it takes, as system.yaml writes it" : issue.message;
|
|
371
|
+
const message = keys.length > 0 ? `unknown ${keys.length === 1 ? "key" : "keys"} ${keys.map((key) => `"${key}"`).join(", ")}${quotes}` : vague;
|
|
372
|
+
return place === "" ? `${message}.` : `${place}: ${message}.`;
|
|
373
|
+
}).join(" ");
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* A recipe that sets kept rolls (KEP-4), or a refill on an occasion that no recipe ends, which would never bring the use back (DAT-9): where it is and why;
|
|
377
|
+
* undefined when there is none.
|
|
378
|
+
*/
|
|
379
|
+
function strayOccasion(data, formulas) {
|
|
380
|
+
const occasions = Object.values(data.recipes ?? {}).flatMap((recipe) => recipe.ends ?? []).filter((occasion, index, all) => all.findIndex((other) => comparableText(other) === comparableText(occasion)) === index);
|
|
381
|
+
// Kept rolls come back as the player rolls them again (KEP-4), never at a value a recipe gives.
|
|
382
|
+
for (const [recipe, value] of Object.entries(data.recipes ?? {})) {
|
|
383
|
+
const rolls = Object.keys(value.set ?? {}).find((field) => Object.entries(data.fields ?? {}).some(([declared, kind]) => kind === "rolls" && comparableText(declared) === comparableText(field)));
|
|
384
|
+
if (rolls !== undefined) {
|
|
385
|
+
return `recipes.${recipe}.set.${rolls}: ${rolls} keeps rolls, which come back as they are rolled again with roll and keep, not at a value.`;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
for (const [counter, limits] of Object.entries(formulas.counters)) {
|
|
389
|
+
const occasion = Object.keys(limits.refill ?? {}).find((candidate) => !occasions.some((other) => comparableText(other) === comparableText(candidate)));
|
|
390
|
+
if (occasion !== undefined) {
|
|
391
|
+
const known = occasions.length === 0 ? "no recipe ends one yet: give a recipe its ends" : `the occasions are ${occasions.join(", ")}`;
|
|
392
|
+
return `counters.${counter}.refill: ${occasion} is no occasion a recipe ends, so it would never come back; ${known}.`;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
/** The progression as the system declares it (PRO-1–PRO-4, PRO-6). */
|
|
398
|
+
function progressionRule(data) {
|
|
399
|
+
const { skip, ...rule } = data;
|
|
400
|
+
return { ...rule, skip: skip ?? [] };
|
|
401
|
+
}
|
|
402
|
+
/** The system's parts of the master's instructions, from the files of its instructions folder: a part is named after its file (D-121). */
|
|
403
|
+
function readParts(folder, name) {
|
|
404
|
+
const parts = {};
|
|
405
|
+
for (const path of files().files(join(folder, "instructions"), (file) => file.endsWith(".md"))) {
|
|
406
|
+
parts[basename(path, ".md")] = partOf(files().text(path) ?? "", name, path);
|
|
407
|
+
}
|
|
408
|
+
return parts;
|
|
409
|
+
}
|
|
410
|
+
/** A part from its file: the text after its frontmatter, which says only whether it takes the place of the core's part, replace: true (D-121). */
|
|
411
|
+
function partOf(file, system, path) {
|
|
412
|
+
const text = file.replace(/^\uFEFF/, "").replace(/\r\n/g, "\n");
|
|
413
|
+
const frontmatter = text.match(/^---\n([\s\S]*?)\n---(?:\n|$)/);
|
|
414
|
+
let settings;
|
|
415
|
+
try {
|
|
416
|
+
settings = frontmatter === null ? {} : (parse(frontmatter[1]) ?? {});
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
settings = undefined;
|
|
420
|
+
}
|
|
421
|
+
const parsed = z.object({ replace: z.boolean().optional() }).strict().safeParse(settings);
|
|
422
|
+
if (!parsed.success) {
|
|
423
|
+
throw new Error(`The game system ${system} cannot be read, because ${path} is not valid: a part's frontmatter says only replace: true, for a part that takes the place of the core's.`);
|
|
424
|
+
}
|
|
425
|
+
return { text: (frontmatter === null ? text : text.slice(frontmatter[0].length)).trim(), replace: parsed.data.replace === true };
|
|
426
|
+
}
|
|
427
|
+
/** The progression without its experience, when a setting leaves its field out (DAT-10). */
|
|
428
|
+
function withoutExperience(progression, kept) {
|
|
429
|
+
if (progression.experience === undefined || kept(progression.experience.field)) {
|
|
430
|
+
return progression;
|
|
431
|
+
}
|
|
432
|
+
const rest = { ...progression };
|
|
433
|
+
delete rest.experience;
|
|
434
|
+
return rest;
|
|
435
|
+
}
|
|
436
|
+
/** The groups of a system's sheet, each with its note and its icon; a note or an icon for a group the sheet does not have is refused. */
|
|
437
|
+
function sheetOf(data, name, path) {
|
|
438
|
+
const groups = Object.entries(data.sheet ?? {});
|
|
439
|
+
const notes = Object.entries(data["sheet-notes"] ?? {});
|
|
440
|
+
const icons = Object.entries(data["sheet-icons"] ?? {});
|
|
441
|
+
const byGroup = (pairs, group) => pairs.find(([other]) => comparableText(other) === comparableText(group))?.[1];
|
|
442
|
+
for (const [key, pairs] of [["sheet-notes", notes], ["sheet-icons", icons]]) {
|
|
443
|
+
const stray = pairs.find(([group]) => !groups.some(([other]) => comparableText(other) === comparableText(group)));
|
|
444
|
+
if (stray !== undefined) {
|
|
445
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${key}.${stray[0]}: the sheet has no group ${stray[0]}; its groups are ${groups.map(([group]) => group).join(", ")}.`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return groups.map(([group, entries]) => {
|
|
449
|
+
const note = byGroup(notes, group);
|
|
450
|
+
const icon = byGroup(icons, group);
|
|
451
|
+
return {
|
|
452
|
+
name: group,
|
|
453
|
+
entries: entries.map((entry) => {
|
|
454
|
+
const [, field, optional, beside] = sheetEntryPattern.exec(entry) ?? [];
|
|
455
|
+
return { field, optional: optional === "?", ...(beside === undefined ? {} : { beside }) };
|
|
456
|
+
}),
|
|
457
|
+
...(note === undefined ? {} : { note }),
|
|
458
|
+
...(icon === undefined ? {} : { icon }),
|
|
459
|
+
};
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* A system's data with a campaign's additions over it (CAM-2): fields, tables, formulas and counters by name, the campaign's taking the place of the system's
|
|
464
|
+
* with that name; a recipe added to the system's of that name, field by field, with its occasions and rules; the line's fields after the system's; travel key
|
|
465
|
+
* by key, its paces, terrain and kinds by name.
|
|
466
|
+
*/
|
|
467
|
+
function withCampaignData(raw, data) {
|
|
468
|
+
const base = isMap(raw) ? raw : {};
|
|
469
|
+
const merged = { ...base };
|
|
470
|
+
for (const key of ["fields", "tables", "computed", "counters"]) {
|
|
471
|
+
const added = mapOf(data[key], key);
|
|
472
|
+
merged[key] = added === undefined ? base[key] : { ...withoutNames(isMap(base[key]) ? base[key] : {}, Object.keys(added)), ...added };
|
|
473
|
+
}
|
|
474
|
+
const recipes = mapOf(data.recipes, "recipes");
|
|
475
|
+
if (recipes !== undefined) {
|
|
476
|
+
const own = isMap(base.recipes) ? base.recipes : {};
|
|
477
|
+
merged.recipes = { ...own, ...Object.fromEntries(Object.entries(recipes).map(([recipe, added]) => [nameIn(own, recipe) ?? recipe, recipeWith(own[nameIn(own, recipe) ?? ""], added, recipe)])) };
|
|
478
|
+
}
|
|
479
|
+
const travel = mapOf(data.travel, "travel");
|
|
480
|
+
if (travel !== undefined) {
|
|
481
|
+
const own = isMap(base.travel) ? base.travel : {};
|
|
482
|
+
const byName = (key) => (isMap(travel[key]) ? { ...withoutNames(isMap(own[key]) ? own[key] : {}, Object.keys(travel[key])), ...travel[key] } : own[key]);
|
|
483
|
+
merged.travel = Object.fromEntries(Object.entries({ ...own, ...travel, paces: byName("paces"), terrain: byName("terrain"), kinds: byName("kinds") }).filter(([, value]) => value !== undefined));
|
|
484
|
+
}
|
|
485
|
+
const line = data["status-line"];
|
|
486
|
+
if (line !== undefined && line !== null) {
|
|
487
|
+
if (!Array.isArray(line)) {
|
|
488
|
+
throw new Error("status-line: give it as a list of fields, such as [portent?].");
|
|
489
|
+
}
|
|
490
|
+
const own = Array.isArray(base["status-line"]) ? base["status-line"].map(String) : [];
|
|
491
|
+
const plain = (entry) => comparableText(entry.replace(/\?$/, ""));
|
|
492
|
+
const added = line.map(String).filter((entry, index, all) => all.findIndex((other) => plain(other) === plain(entry)) === index);
|
|
493
|
+
merged["status-line"] = [...own, ...added.filter((entry) => !own.some((other) => plain(other) === plain(entry)))];
|
|
494
|
+
}
|
|
495
|
+
return merged;
|
|
496
|
+
}
|
|
497
|
+
/** A system's recipe with a campaign's over it (CAM-2): what both set and regain, the campaign's first, and the occasions and rules of both. */
|
|
498
|
+
function recipeWith(own, added, name) {
|
|
499
|
+
if (!isMap(added)) {
|
|
500
|
+
throw new Error(`recipes.${name}: give it as what it sets, regains, ends and the rules to read, such as {set: {superiority-dice: max}}.`);
|
|
501
|
+
}
|
|
502
|
+
const base = isMap(own) ? own : {};
|
|
503
|
+
const map = (key) => isMap(base[key]) || isMap(added[key]) ? { ...withoutNames(isMap(base[key]) ? base[key] : {}, Object.keys(isMap(added[key]) ? added[key] : {})), ...(isMap(added[key]) ? added[key] : {}) } : undefined;
|
|
504
|
+
const list = (key) => {
|
|
505
|
+
const items = [...(Array.isArray(base[key]) ? base[key] : []), ...(Array.isArray(added[key]) ? added[key] : [])];
|
|
506
|
+
return items.length === 0 ? undefined : items.filter((item, index) => items.findIndex((other) => comparableText(String(other)) === comparableText(String(item))) === index);
|
|
507
|
+
};
|
|
508
|
+
const merged = { ...base, ...added, set: map("set"), regain: map("regain"), ends: list("ends"), rules: list("rules") };
|
|
509
|
+
return Object.fromEntries(Object.entries(merged).filter(([, value]) => value !== undefined));
|
|
510
|
+
}
|
|
511
|
+
/** An addition that must be a map by name, such as counters; undefined when the campaign gives none. */
|
|
512
|
+
function mapOf(value, key) {
|
|
513
|
+
if (value === undefined || value === null) {
|
|
514
|
+
return undefined;
|
|
515
|
+
}
|
|
516
|
+
if (!isMap(value)) {
|
|
517
|
+
throw new Error(`${key}: give it as a map by name, such as {superiority-dice: ...}.`);
|
|
518
|
+
}
|
|
519
|
+
return value;
|
|
520
|
+
}
|
|
521
|
+
/** The entries of a map whose names are none of these, as names are compared. */
|
|
522
|
+
function withoutNames(map, names) {
|
|
523
|
+
return Object.fromEntries(Object.entries(map).filter(([name]) => !names.some((other) => comparableText(other) === comparableText(name))));
|
|
524
|
+
}
|
|
525
|
+
/** The name under which a map holds this one, as names are compared. */
|
|
526
|
+
function nameIn(map, name) {
|
|
527
|
+
return sameName(Object.keys(map), name);
|
|
528
|
+
}
|
|
529
|
+
/** How the system's map of a place counts, as the engine reads it (GRD-4): the square in metres. */
|
|
530
|
+
function gridOf(data) {
|
|
531
|
+
const { square, size, footprints, leaving, ...rest } = data;
|
|
532
|
+
return { ...rest, square: readLength(square) ?? 0, ...(size === undefined ? {} : { size }), footprints: footprints ?? {}, ...(leaving === undefined ? {} : { leaving }) };
|
|
533
|
+
}
|
|
534
|
+
/** The system's travel as the engine reads it (TRV-1–TRV-3): speeds in metres an hour, factors as numbers. */
|
|
535
|
+
function travelOf(data) {
|
|
536
|
+
const paces = Object.fromEntries(Object.entries(data.paces ?? {}).map(([name, speed]) => [name, readSpeed(speed) ?? 0]));
|
|
537
|
+
return {
|
|
538
|
+
paces,
|
|
539
|
+
pace: data.pace === undefined ? Object.keys(paces)[0] : sameName(Object.keys(paces), data.pace),
|
|
540
|
+
hours: data.hours,
|
|
541
|
+
rule: data.rule,
|
|
542
|
+
beyond: data.beyond,
|
|
543
|
+
terrain: Object.fromEntries(Object.entries(data.terrain ?? {}).map(([value, factor]) => [value, factorOf(factor)])),
|
|
544
|
+
kinds: Object.entries(data.kinds ?? {}).map(([name, kind]) => {
|
|
545
|
+
const [field, value] = Object.entries(kind.vehicle ?? {})[0] ?? [];
|
|
546
|
+
return {
|
|
547
|
+
name,
|
|
548
|
+
...(field === undefined || value === undefined || kind.speed === undefined ? {} : { vehicle: { field, value, speed: kind.speed } }),
|
|
549
|
+
hours: kind.hours,
|
|
550
|
+
current: kind.current === undefined ? undefined : readSpeed(kind.current),
|
|
551
|
+
};
|
|
552
|
+
}),
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
/** A factor of speed as a number: 1/2 is 0.5. */
|
|
556
|
+
function factorOf(factor) {
|
|
557
|
+
if (typeof factor === "number") {
|
|
558
|
+
return factor;
|
|
559
|
+
}
|
|
560
|
+
const [numerator, denominator] = factor.split("/").map(Number);
|
|
561
|
+
return numerator / denominator;
|
|
562
|
+
}
|
|
563
|
+
function isMap(value) {
|
|
564
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
565
|
+
}
|
|
566
|
+
/** The counters that come back with a rest (DAT-9): those with a refill, and those a recipe sets or regains. */
|
|
567
|
+
function usesOf(data) {
|
|
568
|
+
const names = [
|
|
569
|
+
...Object.entries(data.counters ?? {}).filter(([, limits]) => limits.refill !== undefined).map(([name]) => name),
|
|
570
|
+
...Object.values(data.recipes ?? {}).flatMap((recipe) => [...Object.keys(recipe.set ?? {}), ...Object.keys(recipe.regain ?? {})]),
|
|
571
|
+
];
|
|
572
|
+
return names.filter((name, index) => names.findIndex((other) => comparableText(other) === comparableText(name)) === index);
|
|
573
|
+
}
|
|
574
|
+
/** The formulas of a recipe's regain, each read at its place (FOR-9). */
|
|
575
|
+
function regainOf(regain, name, path, recipe) {
|
|
576
|
+
return Object.fromEntries(Object.entries(regain).map(([field, amount]) => {
|
|
577
|
+
try {
|
|
578
|
+
return [field, formulaOf(amount)];
|
|
579
|
+
}
|
|
580
|
+
catch (error) {
|
|
581
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: recipes.${recipe}.regain.${field}: ${error instanceof Error ? error.message : String(error)}`);
|
|
582
|
+
}
|
|
583
|
+
}));
|
|
584
|
+
}
|
|
585
|
+
/** The formulas of a system, read once; a system whose formulas do not read cannot be read either (FOR-9). */
|
|
586
|
+
function systemFormulas(data, name, path) {
|
|
587
|
+
try {
|
|
588
|
+
return readFormulas(data);
|
|
589
|
+
}
|
|
590
|
+
catch (error) {
|
|
591
|
+
throw new Error(`The game system ${name} cannot be read, because ${path} is not valid: ${error instanceof Error ? error.message : String(error)}`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { type CampaignData, campaignDataNames, findCampaignSystem, findSystem, type GameSystem, type GridRules, installedSystems, type InstructionPart, type Recipe, type Reward, rollName, type SheetEntry, type SheetGroup, systemFileName, type SystemSetting, type Threshold, type Travel, type TravelKind, withSettings, } from "./game-system.ts";
|
|
2
|
+
export { type SystemWords, systemWords } from "./words.ts";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// The game systems installed beside the engine (D-27, SYS-1): which they are and what each declares. Their pages are read by the pages module.
|
|
2
|
+
export { campaignDataNames, findCampaignSystem, findSystem, installedSystems, rollName, systemFileName, withSettings, } from "./game-system.js";
|
|
3
|
+
export { systemWords } from "./words.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A system's words in one language: its groups by their names, its fields' labels by their ids, other words and texts by their English, and its headline. */
|
|
2
|
+
export interface SystemWords {
|
|
3
|
+
groups: Record<string, string>;
|
|
4
|
+
fields: Record<string, string>;
|
|
5
|
+
words: Record<string, string>;
|
|
6
|
+
headline?: string;
|
|
7
|
+
}
|
|
8
|
+
/** The words of the system in this folder for a language, or for its base language (pt for pt-BR); undefined when the system has none in it. */
|
|
9
|
+
export declare function systemWords(folder: string, language: string): SystemWords | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// A game system's words in the languages it ships (D-403): beside its system.yaml, words/<code>.yaml gives what the dashboard shows of the system in that
|
|
2
|
+
// language: its groups, its fields' labels, any other word or text it writes, and its headline. The core knows no game's words: it only hands them on.
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { readYamlValues } from "../core/yaml-file.js";
|
|
7
|
+
const named = z.record(z.string().min(1), z.string().min(1));
|
|
8
|
+
const wordsSchema = z.object({ groups: named.optional(), fields: named.optional(), words: named.optional(), headline: z.string().min(1).optional() }, {
|
|
9
|
+
error: "write it as groups, fields and words, each from the English to the language's own, and the headline, such as {groups: {Skills: Abilità}, fields: {str: FOR}}",
|
|
10
|
+
}).strict();
|
|
11
|
+
/** The words of the system in this folder for a language, or for its base language (pt for pt-BR); undefined when the system has none in it. */
|
|
12
|
+
export function systemWords(folder, language) {
|
|
13
|
+
const file = [language, language.split("-")[0]].map((code) => join(folder, "words", `${code.toLowerCase()}.yaml`)).find((path) => existsSync(path));
|
|
14
|
+
if (file === undefined) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const parsed = wordsSchema.safeParse(readYamlValues(file, 'the system\'s words in a language, such as "groups: {Skills: Abilità}"'));
|
|
18
|
+
if (!parsed.success) {
|
|
19
|
+
throw new Error(`The words of the game system in ${file} cannot be read: ${parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ")}. Fix the file.`);
|
|
20
|
+
}
|
|
21
|
+
const { groups = {}, fields = {}, words = {}, headline } = parsed.data;
|
|
22
|
+
return { groups, fields, words, ...(headline === undefined ? {} : { headline }) };
|
|
23
|
+
}
|