@opencharacter/5e-srd-5.1 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +53 -3
  2. package/content/backgrounds/acolyte.yaml +22 -0
  3. package/content/classes/barbarian.yaml +57 -0
  4. package/content/classes/bard.yaml +68 -0
  5. package/content/classes/cleric.yaml +83 -0
  6. package/content/classes/druid.yaml +61 -0
  7. package/content/classes/fighter.yaml +75 -0
  8. package/content/classes/monk.yaml +47 -0
  9. package/content/classes/paladin.yaml +76 -0
  10. package/content/classes/ranger.yaml +69 -0
  11. package/content/classes/rogue.yaml +59 -0
  12. package/content/classes/sorcerer.yaml +64 -0
  13. package/content/classes/warlock.yaml +71 -0
  14. package/content/classes/wizard.yaml +56 -0
  15. package/content/features/sorcerer/dragon-ancestor.yaml +1 -43
  16. package/content/features/sorcerer/elemental-affinity.yaml +29 -8
  17. package/content/features/sorcerer/metamagic.yaml +1 -93
  18. package/content/features/wizard/arcane-recovery.yaml +4 -4
  19. package/content/hunter-tactics/colossus-slayer.yaml +4 -0
  20. package/content/hunter-tactics/escape-the-horde.yaml +4 -0
  21. package/content/hunter-tactics/evasion.yaml +6 -0
  22. package/content/hunter-tactics/giant-killer.yaml +4 -0
  23. package/content/hunter-tactics/horde-breaker.yaml +4 -0
  24. package/content/hunter-tactics/multiattack-defense.yaml +4 -0
  25. package/content/hunter-tactics/stand-against-the-tide.yaml +4 -0
  26. package/content/hunter-tactics/steel-will.yaml +4 -0
  27. package/content/hunter-tactics/uncanny-dodge.yaml +6 -0
  28. package/content/hunter-tactics/volley.yaml +6 -0
  29. package/content/hunter-tactics/whirlwind-attack.yaml +6 -0
  30. package/content/invocations/bewitching-whispers.yaml +1 -6
  31. package/content/invocations/dreadful-word.yaml +1 -6
  32. package/content/invocations/minions-of-chaos.yaml +1 -6
  33. package/content/invocations/mire-the-mind.yaml +1 -6
  34. package/content/invocations/sculptor-of-flesh.yaml +1 -6
  35. package/content/invocations/sign-of-ill-omen.yaml +1 -6
  36. package/content/invocations/thief-of-five-fates.yaml +1 -6
  37. package/content/magic-items/arrow-of-slaying.yaml +1 -0
  38. package/content/magic-items/bag-of-holding.yaml +2 -0
  39. package/content/magic-items/efficient-quiver.yaml +2 -0
  40. package/content/magic-items/handy-haversack.yaml +2 -0
  41. package/content/magic-items/holy-avenger.yaml +9 -2
  42. package/content/magic-items/necklace-of-prayer-beads.yaml +1 -1
  43. package/content/magic-items/portable-hole.yaml +2 -0
  44. package/content/magic-items/ring-of-x-ray-vision.yaml +6 -0
  45. package/content/magic-items/robe-of-the-archmagi.yaml +1 -1
  46. package/content/magic-items/staff-of-charming.yaml +17 -12
  47. package/content/magic-items/staff-of-fire.yaml +9 -2
  48. package/content/magic-items/staff-of-frost.yaml +9 -2
  49. package/content/magic-items/staff-of-healing.yaml +9 -2
  50. package/content/magic-items/staff-of-power.yaml +2 -1
  51. package/content/magic-items/staff-of-swarming-insects.yaml +17 -12
  52. package/content/magic-items/staff-of-the-magi.yaml +2 -1
  53. package/content/magic-items/staff-of-the-python.yaml +7 -2
  54. package/content/magic-items/staff-of-the-woodlands.yaml +2 -1
  55. package/content/magic-items/staff-of-withering.yaml +9 -2
  56. package/content/metamagic/careful-spell.yaml +11 -0
  57. package/content/metamagic/distant-spell.yaml +11 -0
  58. package/content/metamagic/empowered-spell.yaml +22 -0
  59. package/content/metamagic/extended-spell.yaml +11 -0
  60. package/content/metamagic/heightened-spell.yaml +11 -0
  61. package/content/metamagic/quickened-spell.yaml +11 -0
  62. package/content/metamagic/subtle-spell.yaml +11 -0
  63. package/content/metamagic/twinned-spell.yaml +16 -0
  64. package/content/subclasses/hunter.yaml +4 -29
  65. package/content/traits/infernal-legacy.yaml +15 -2
  66. package/content/traits/relentless-endurance.yaml +6 -0
  67. package/content/weapons/javelin.yaml +1 -1
  68. package/dist/i18n/en.js +1 -1
  69. package/dist/i18n/en.json +277 -201
  70. package/dist/index.js +1 -1
  71. package/dist/release.json +5795 -5769
  72. package/i18n/en/monster-rules.yaml +1 -1
  73. package/i18n/en/type-fields.yaml +7 -0
  74. package/i18n/en.yaml +268 -223
  75. package/pack.yaml +2 -2
  76. package/package.json +2 -2
  77. package/rules/advancement.yaml +67 -38
  78. package/rules/checks.yaml +1 -1
  79. package/rules/classes.yaml +25 -3
  80. package/rules/combat.yaml +3 -2
  81. package/rules/conditions.yaml +1 -0
  82. package/rules/content-types.yaml +61 -4
  83. package/rules/core.yaml +6 -16
  84. package/rules/creation.yaml +20 -34
  85. package/rules/display.yaml +20 -5
  86. package/rules/equipment.yaml +13 -16
  87. package/rules/magic-items.yaml +19 -1
  88. package/rules/monsters.yaml +7 -1
  89. package/rules/rest.yaml +2 -36
  90. package/rules/spellcasting.yaml +1 -5
  91. package/rules/starting-equipment.yaml +17 -646
  92. package/rules/tags.yaml +12 -12
  93. package/upgrades/0.2.0-to-0.3.0.yaml +152 -0
package/README.md CHANGED
@@ -14,6 +14,9 @@ out.
14
14
  pnpm add @opencharacter/engine @opencharacter/5e-srd-5.1
15
15
  ```
16
16
 
17
+ This release needs spec 0.3: `@opencharacter/engine` 0.3.0 or later. An engine for an older
18
+ spec refuses it (`spec-version-unsupported`).
19
+
17
20
  The package's default export is the built pack (a `PackRelease`), and `i18n/en` its English
18
21
  text:
19
22
 
@@ -28,9 +31,9 @@ const { ruleset } = loaded;
28
31
 
29
32
  // A new character, made by the random creation start: every pick is drawn, so it finishes.
30
33
  const blank = {
31
- specVersion: '0.2.0',
34
+ specVersion: '0.3.0',
32
35
  id: 'new-character',
33
- packs: [{ id: '5e-srd-5.1', version: '0.2.0' }],
36
+ packs: [{ id: '5e-srd-5.1', version: '0.3.0' }],
34
37
  creating: true,
35
38
  };
36
39
  const created = startAction(ruleset, blank, {
@@ -241,7 +244,8 @@ Where the SRD is unclear or silent, the pack reads it this way:
241
244
  run the attacks they name; legendary actions spend their cost; recharge and per-day actions
242
245
  are copies with their own state; Spellcasting and Innate Spellcasting cast with the printed
243
246
  numbers; the vampire and the lycanthropes change form. Languages only monsters speak aren't
244
- offered to players.
247
+ offered to players. A monster's sheet leaves out experience points, character level (at 0) and
248
+ death saves, and shows carrying weight only once it carries something.
245
249
  - **Resting:** `death-save`, `spend-hit-die`, `short-rest` and `long-rest` (spent hit dice back
246
250
  up to half the total level, the player choosing the classes).
247
251
  - **Follow-ups:** concentration checks, a failed death save from damage at 0 hit points,
@@ -269,6 +273,52 @@ Where the SRD is unclear or silent, the pack reads it this way:
269
273
  - **Sheet layout:** display groups for actions and content, with units (feet, pounds, gold
270
274
  pieces, miles per hour) and a compact `summary` view.
271
275
 
276
+ ## Add-on packs
277
+
278
+ A pack that depends on this one can add content of its types, and it flows into the same
279
+ processes:
280
+
281
+ - **Classes** take part in creation, random starts and multiclassing through item fields: a
282
+ `kit` action (`listed: false`, a `random` parameter) with `startingKit: true` gives the
283
+ starting equipment; `abilityPriority` lists a random start's abilities, best first (`abilities.str.score`, …);
284
+ `multiclassAll` and `multiclassAny` name the abilities multiclassing into it needs 13 in. Like a
285
+ core class, it carries the `multiclass` prerequisite
286
+ (`(self.startingClass && self.level == level.total) || item.id in multiclass.qualified`).
287
+ - **Backgrounds** bring their starting equipment the same way (`startingKit` and a `kit` action).
288
+ - **Magic items** and magic weapon or armor templates restricted to classes list them in
289
+ `attunementClasses`.
290
+ - **Metamagic options** are `metamagic` content and the Hunter's options `hunterTactic` content
291
+ (`feature` names the choice that offers them). Containers add to `carrying.stowCapacity`,
292
+ `carrying.stowUnlimited` or `carrying.quivers`, and content resets its uses on a rest with a
293
+ `changes` effect on the `rest.long` or `rest.short` step. A weapon tagged `quiver.javelin` goes
294
+ in an Efficient Quiver's javelin compartment.
295
+ - **Open enums** (`extendEnums`): weapon `damageType` and `ammunition`, gear `category` and
296
+ `ammunition`, tool, vehicle and magic item `category`, spell `school`, `damageType` and
297
+ `damage2Type`, monster `subtype`, and monster action `damageType`, `damage2Type` and
298
+ `saveDamageType`, and the `item-power` action's `damageType`
299
+ (`5e-srd-5.1:actions.item-power.params.damageType`). A new damage type also needs its tag
300
+ (`damage.sonic`), declared and named in the add-on.
301
+ - **Creature types:** a new one goes in `5e-srd-5.1:fields.creature.type`, the monster's
302
+ `creatureType`, a condition's `by` (`types.condition.state.by`) and the Arrow of Slaying's
303
+ `slays` (`magic-items.arrow-of-slaying.state.slays`); an attack reads the target's type through
304
+ an open view field, so a target of the added type is attacked as any other.
305
+ - **Choices** (`extendChoices`): a class's listed choices (skills, fighting styles, expertise)
306
+ take values and items; choices over a type (subclasses, spells, feats) offer the add-on's
307
+ content already.
308
+ - **Naming what an add-on adds:** it names each added value, option or key in its own text,
309
+ under the key this pack would use, and `createText` finds it there when the app passes the
310
+ ruleset's `enumOrigins`, `optionOrigins` and `familyOrigins`. For example,
311
+ `sonic` added to `5e-srd-5.1:types.weapon.fields.damageType` is
312
+ `types.weapon.fields.damageType.values.sonic.name: Sonic` (through `enumOrigins`).
313
+ - **Step tags** for rules-level `option` and `changes` effects: `creation.race`,
314
+ `creation.subrace`, `creation.class`, `creation.background`, `creation.method` and
315
+ `creation.finish` (guided and random creation), `level-up.class`, `level-up.hit-points` and
316
+ `level-up.gain`, `rest.long` and `rest.short`, and the attack's `weapon-hit` and
317
+ `ammunition`.
318
+
319
+ Still closed: the abilities, skills, weapon and armor categories and conditions are the game's
320
+ fixed sets.
321
+
272
322
  ## Limitations
273
323
 
274
324
  Of the 152 class and subclass features, 8 have no mechanics, and 63 of the 318 magic items are
@@ -1,5 +1,7 @@
1
1
  id: backgrounds.acolyte
2
2
  type: background
3
+ fields:
4
+ startingKit: true
3
5
  effects:
4
6
  - { target: proficiencies.skills, op: grant, value: { tag: skill.insight } }
5
7
  - { target: proficiencies.skills, op: grant, value: { tag: skill.religion } }
@@ -11,3 +13,23 @@ choices:
11
13
  unique: languages
12
14
  from: { type: language, where: "!('secret' in item.tags) && !('monster' in item.tags)" }
13
15
  eligible: '!(item.id in proficiencies.languages) || item.id in choice.picks'
16
+ actions:
17
+ - id: kit
18
+ listed: false
19
+ params:
20
+ random: { type: boolean, default: false }
21
+ steps:
22
+ - id: acolyteSymbol
23
+ kind: choice
24
+ options: { content: { type: gear, where: "item.category == 'holy-symbol'" } }
25
+ random: params.random
26
+ changes:
27
+ - { type: addItem, entry: { item: picked.id } }
28
+ - id: acolyteKit
29
+ kind: changes
30
+ changes:
31
+ - { type: addItem, entry: { item: "'gear.book'" } }
32
+ - { type: addItem, entry: { item: "'gear.incense'", quantity: 5 } }
33
+ - { type: addItem, entry: { item: "'gear.vestments'" } }
34
+ - { type: addItem, entry: { item: "'gear.common-clothes'" } }
35
+ - { type: addItem, entry: { item: "'gear.pouch'" } }
@@ -2,6 +2,17 @@ id: classes.barbarian
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d12
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.str.score,
9
+ abilities.con.score,
10
+ abilities.dex.score,
11
+ abilities.wis.score,
12
+ abilities.cha.score,
13
+ abilities.int.score,
14
+ ]
15
+ multiclassAll: [str]
5
16
  state:
6
17
  rageSpent: { type: integer, default: 0, min: 0 }
7
18
  relentlessRageSpent: { type: integer, default: 0, min: 0 }
@@ -57,3 +68,49 @@ choices:
57
68
  - id: primal-path
58
69
  from: { type: subclass, where: 'item.class == @classes.barbarian' }
59
70
  when: self.level >= 3
71
+ actions:
72
+ - id: kit
73
+ listed: false
74
+ params:
75
+ random: { type: boolean, default: false }
76
+ steps:
77
+ - id: barbarianWeapon
78
+ kind: choice
79
+ options:
80
+ - id: greataxe
81
+ changes:
82
+ - { type: addItem, entry: { item: "'weapons.greataxe'", equipped: true } }
83
+ - id: martial-melee
84
+ recommend: options[0]
85
+ random: params.random
86
+ - id: barbarianMartial
87
+ kind: choice
88
+ when: "steps.barbarianWeapon.picked == 'martial-melee'"
89
+ options:
90
+ content: { type: weapon, where: "item.category == 'martial' && item.range == 'melee'" }
91
+ random: params.random
92
+ changes:
93
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
94
+ - id: barbarianSecond
95
+ kind: choice
96
+ options:
97
+ - id: two-handaxes
98
+ changes:
99
+ - type: addItem
100
+ entry: { item: "'weapons.handaxe'", quantity: 2, equipped: true }
101
+ - id: simple
102
+ recommend: options[0]
103
+ random: params.random
104
+ - id: barbarianSimple
105
+ kind: choice
106
+ when: "steps.barbarianSecond.picked == 'simple'"
107
+ options: { content: { type: weapon, where: "item.category == 'simple'" } }
108
+ random: params.random
109
+ changes:
110
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
111
+ - id: barbarianKit
112
+ kind: changes
113
+ changes:
114
+ - { type: addItem, entry: { item: "'gear.explorers-pack'" } }
115
+ - type: addItem
116
+ entry: { item: "'weapons.javelin'", quantity: 4, equipped: true }
@@ -2,6 +2,17 @@ id: classes.bard
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d8
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.cha.score,
9
+ abilities.dex.score,
10
+ abilities.con.score,
11
+ abilities.wis.score,
12
+ abilities.int.score,
13
+ abilities.str.score,
14
+ ]
15
+ multiclassAll: [cha]
5
16
  state:
6
17
  bardicInspirationSpent: { type: integer, default: 0, min: 0 }
7
18
  prerequisites:
@@ -132,3 +143,60 @@ choices:
132
143
  - id: bard-college
133
144
  from: { type: subclass, where: 'item.class == @classes.bard' }
134
145
  when: self.level >= 3
146
+ actions:
147
+ - id: kit
148
+ listed: false
149
+ params:
150
+ random: { type: boolean, default: false }
151
+ steps:
152
+ - id: bardWeapon
153
+ kind: choice
154
+ options:
155
+ - id: rapier
156
+ changes:
157
+ - { type: addItem, entry: { item: "'weapons.rapier'", equipped: true } }
158
+ - id: longsword
159
+ changes:
160
+ - { type: addItem, entry: { item: "'weapons.longsword'", equipped: true } }
161
+ - id: simple
162
+ recommend: options[0]
163
+ random: params.random
164
+ - id: bardSimple
165
+ kind: choice
166
+ when: "steps.bardWeapon.picked == 'simple'"
167
+ options: { content: { type: weapon, where: "item.category == 'simple'" } }
168
+ random: params.random
169
+ changes:
170
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
171
+ - id: bardPack
172
+ kind: choice
173
+ options:
174
+ - id: diplomats-pack
175
+ changes: [{ type: addItem, entry: { item: "'gear.diplomats-pack'" } }]
176
+ - id: entertainers-pack
177
+ changes: [{ type: addItem, entry: { item: "'gear.entertainers-pack'" } }]
178
+ recommend: options[0]
179
+ random: params.random
180
+ - id: bardInstrument
181
+ kind: choice
182
+ options:
183
+ - id: lute
184
+ changes: [{ type: addItem, entry: { item: "'tools.lute'" } }]
185
+ - id: other-instrument
186
+ recommend: options[0]
187
+ random: params.random
188
+ - id: bardOtherInstrument
189
+ kind: choice
190
+ when: "steps.bardInstrument.picked == 'other-instrument'"
191
+ options:
192
+ content:
193
+ type: tool
194
+ where: "item.category == 'musical-instrument' && item.id != @tools.lute"
195
+ random: params.random
196
+ changes:
197
+ - { type: addItem, entry: { item: picked.id } }
198
+ - id: bardKit
199
+ kind: changes
200
+ changes:
201
+ - { type: addItem, entry: { item: "'armor.leather'", equipped: true } }
202
+ - { type: addItem, entry: { item: "'weapons.dagger'", equipped: true } }
@@ -2,6 +2,17 @@ id: classes.cleric
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d8
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.wis.score,
9
+ abilities.con.score,
10
+ abilities.str.score,
11
+ abilities.dex.score,
12
+ abilities.cha.score,
13
+ abilities.int.score,
14
+ ]
15
+ multiclassAll: [wis]
5
16
  state:
6
17
  channelDivinitySpent: { type: integer, default: 0, min: 0 }
7
18
  divineIntervention: { type: enum, values: [ready, failed, answered], default: ready }
@@ -40,3 +51,75 @@ choices:
40
51
  - id: divine-domain
41
52
  from: { type: subclass, where: 'item.class == @classes.cleric' }
42
53
  when: self.level >= 1
54
+ actions:
55
+ - id: kit
56
+ listed: false
57
+ params:
58
+ random: { type: boolean, default: false }
59
+ steps:
60
+ - id: clericWeapon
61
+ kind: choice
62
+ sheet: proposed
63
+ options:
64
+ - id: mace
65
+ changes:
66
+ - { type: addItem, entry: { item: "'weapons.mace'", equipped: true } }
67
+ - id: warhammer
68
+ when: '@weapons.warhammer in proficiencies.weapons'
69
+ changes:
70
+ - { type: addItem, entry: { item: "'weapons.warhammer'", equipped: true } }
71
+ recommend: options[0]
72
+ random: params.random
73
+ - id: clericArmor
74
+ kind: choice
75
+ sheet: proposed
76
+ options:
77
+ - id: scale-mail
78
+ changes:
79
+ - { type: addItem, entry: { item: "'armor.scale-mail'", equipped: true } }
80
+ - id: leather-armor
81
+ changes:
82
+ - { type: addItem, entry: { item: "'armor.leather'", equipped: true } }
83
+ - id: chain-mail
84
+ when: "'heavy' in proficiencies.armor"
85
+ changes:
86
+ - { type: addItem, entry: { item: "'armor.chain-mail'", equipped: true } }
87
+ recommend: options[0]
88
+ random: params.random
89
+ - id: clericRanged
90
+ kind: choice
91
+ options:
92
+ - id: light-crossbow
93
+ changes:
94
+ - type: addItem
95
+ entry: { item: "'weapons.light-crossbow'", equipped: true }
96
+ - { type: addItem, entry: { item: "'gear.crossbow-bolts'", quantity: 20 } }
97
+ - id: simple
98
+ recommend: options[0]
99
+ random: params.random
100
+ - id: clericSimple
101
+ kind: choice
102
+ when: "steps.clericRanged.picked == 'simple'"
103
+ options: { content: { type: weapon, where: "item.category == 'simple'" } }
104
+ random: params.random
105
+ changes:
106
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
107
+ - id: clericPack
108
+ kind: choice
109
+ options:
110
+ - id: priests-pack
111
+ changes: [{ type: addItem, entry: { item: "'gear.priests-pack'" } }]
112
+ - id: explorers-pack
113
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
114
+ recommend: options[0]
115
+ random: params.random
116
+ - id: clericSymbol
117
+ kind: choice
118
+ options: { content: { type: gear, where: "item.category == 'holy-symbol'" } }
119
+ random: params.random
120
+ changes:
121
+ - { type: addItem, entry: { item: picked.id } }
122
+ - id: clericKit
123
+ kind: changes
124
+ changes:
125
+ - { type: addItem, entry: { item: "'armor.shield'", equipped: true } }
@@ -2,6 +2,17 @@ id: classes.druid
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d8
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.wis.score,
9
+ abilities.con.score,
10
+ abilities.dex.score,
11
+ abilities.int.score,
12
+ abilities.cha.score,
13
+ abilities.str.score,
14
+ ]
15
+ multiclassAll: [wis]
5
16
  state:
6
17
  wildShapeSpent: { type: integer, default: 0, min: 0 }
7
18
  naturalRecoveryUsed: { type: boolean, default: false }
@@ -113,3 +124,53 @@ choices:
113
124
  - id: druid-circle
114
125
  from: { type: subclass, where: 'item.class == @classes.druid' }
115
126
  when: self.level >= 2
127
+ actions:
128
+ - id: kit
129
+ listed: false
130
+ params:
131
+ random: { type: boolean, default: false }
132
+ steps:
133
+ - id: druidFirst
134
+ kind: choice
135
+ options:
136
+ - id: wooden-shield
137
+ changes:
138
+ - { type: addItem, entry: { item: "'armor.shield'", equipped: true } }
139
+ - id: simple
140
+ recommend: options[0]
141
+ random: params.random
142
+ - id: druidSimple
143
+ kind: choice
144
+ when: "steps.druidFirst.picked == 'simple'"
145
+ options: { content: { type: weapon, where: "item.category == 'simple'" } }
146
+ random: params.random
147
+ changes:
148
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
149
+ - id: druidWeapon
150
+ kind: choice
151
+ options:
152
+ - id: scimitar
153
+ changes:
154
+ - { type: addItem, entry: { item: "'weapons.scimitar'", equipped: true } }
155
+ - id: simple-melee
156
+ recommend: options[0]
157
+ random: params.random
158
+ - id: druidSimpleMelee
159
+ kind: choice
160
+ when: "steps.druidWeapon.picked == 'simple-melee'"
161
+ options:
162
+ content: { type: weapon, where: "item.category == 'simple' && item.range == 'melee'" }
163
+ random: params.random
164
+ changes:
165
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
166
+ - id: druidFocus
167
+ kind: choice
168
+ options: { content: { type: gear, where: "item.category == 'druidic-focus'" } }
169
+ random: params.random
170
+ changes:
171
+ - { type: addItem, entry: { item: picked.id } }
172
+ - id: druidKit
173
+ kind: changes
174
+ changes:
175
+ - { type: addItem, entry: { item: "'armor.leather'", equipped: true } }
176
+ - { type: addItem, entry: { item: "'gear.explorers-pack'" } }
@@ -2,6 +2,17 @@ id: classes.fighter
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d10
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.str.score,
9
+ abilities.con.score,
10
+ abilities.dex.score,
11
+ abilities.wis.score,
12
+ abilities.cha.score,
13
+ abilities.int.score,
14
+ ]
15
+ multiclassAny: [str, dex]
5
16
  state:
6
17
  secondWindUsed: { type: boolean, default: false }
7
18
  actionSurgeSpent: { type: integer, default: 0, min: 0 }
@@ -57,3 +68,67 @@ choices:
57
68
  when: self.startingClass
58
69
  effects:
59
70
  - { target: proficiencies.skills, op: grant, value: { formula: pick.value } }
71
+ actions:
72
+ - id: kit
73
+ listed: false
74
+ params:
75
+ random: { type: boolean, default: false }
76
+ steps:
77
+ - id: fighterArmor
78
+ kind: choice
79
+ options:
80
+ - id: chain-mail
81
+ changes:
82
+ - { type: addItem, entry: { item: "'armor.chain-mail'", equipped: true } }
83
+ - id: leather-longbow
84
+ changes:
85
+ - { type: addItem, entry: { item: "'armor.leather'", equipped: true } }
86
+ - { type: addItem, entry: { item: "'weapons.longbow'", equipped: true } }
87
+ - { type: addItem, entry: { item: "'gear.arrows'", quantity: 20 } }
88
+ recommend: options[0]
89
+ random: params.random
90
+ - id: fighterWeapons
91
+ kind: choice
92
+ options:
93
+ - id: martial-and-shield
94
+ changes:
95
+ - { type: addItem, entry: { item: "'armor.shield'", equipped: true } }
96
+ - id: two-martial
97
+ recommend: options[0]
98
+ random: params.random
99
+ - id: fighterMartial
100
+ kind: choice
101
+ options: { content: { type: weapon, where: "item.category == 'martial'" } }
102
+ random: params.random
103
+ changes:
104
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
105
+ - id: fighterMartial2
106
+ kind: choice
107
+ when: "steps.fighterWeapons.picked == 'two-martial'"
108
+ options: { content: { type: weapon, where: "item.category == 'martial'" } }
109
+ random: params.random
110
+ changes:
111
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
112
+ - id: fighterRanged
113
+ kind: choice
114
+ options:
115
+ - id: light-crossbow
116
+ changes:
117
+ - type: addItem
118
+ entry: { item: "'weapons.light-crossbow'", equipped: true }
119
+ - { type: addItem, entry: { item: "'gear.crossbow-bolts'", quantity: 20 } }
120
+ - id: two-handaxes
121
+ changes:
122
+ - type: addItem
123
+ entry: { item: "'weapons.handaxe'", quantity: 2, equipped: true }
124
+ recommend: options[0]
125
+ random: params.random
126
+ - id: fighterPack
127
+ kind: choice
128
+ options:
129
+ - id: dungeoneers-pack
130
+ changes: [{ type: addItem, entry: { item: "'gear.dungeoneers-pack'" } }]
131
+ - id: explorers-pack
132
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
133
+ recommend: options[0]
134
+ random: params.random
@@ -2,6 +2,17 @@ id: classes.monk
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d8
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.dex.score,
9
+ abilities.wis.score,
10
+ abilities.con.score,
11
+ abilities.str.score,
12
+ abilities.int.score,
13
+ abilities.cha.score,
14
+ ]
15
+ multiclassAll: [dex, wis]
5
16
  state:
6
17
  kiSpent: { type: integer, default: 0, min: 0 }
7
18
  wholenessUsed: { type: boolean, default: false }
@@ -66,3 +77,39 @@ choices:
66
77
  - id: monastic-tradition
67
78
  from: { type: subclass, where: 'item.class == @classes.monk' }
68
79
  when: self.level >= 3
80
+ actions:
81
+ - id: kit
82
+ listed: false
83
+ params:
84
+ random: { type: boolean, default: false }
85
+ steps:
86
+ - id: monkWeapon
87
+ kind: choice
88
+ options:
89
+ - id: shortsword
90
+ changes:
91
+ - { type: addItem, entry: { item: "'weapons.shortsword'", equipped: true } }
92
+ - id: simple
93
+ recommend: options[0]
94
+ random: params.random
95
+ - id: monkSimple
96
+ kind: choice
97
+ when: "steps.monkWeapon.picked == 'simple'"
98
+ options: { content: { type: weapon, where: "item.category == 'simple'" } }
99
+ random: params.random
100
+ changes:
101
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
102
+ - id: monkPack
103
+ kind: choice
104
+ options:
105
+ - id: dungeoneers-pack
106
+ changes: [{ type: addItem, entry: { item: "'gear.dungeoneers-pack'" } }]
107
+ - id: explorers-pack
108
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
109
+ recommend: options[0]
110
+ random: params.random
111
+ - id: monkKit
112
+ kind: changes
113
+ changes:
114
+ - type: addItem
115
+ entry: { item: "'weapons.dart'", quantity: 10, equipped: true }
@@ -2,6 +2,17 @@ id: classes.paladin
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d10
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.str.score,
9
+ abilities.cha.score,
10
+ abilities.con.score,
11
+ abilities.wis.score,
12
+ abilities.dex.score,
13
+ abilities.int.score,
14
+ ]
15
+ multiclassAll: [str, cha]
5
16
  state:
6
17
  divineSenseSpent: { type: integer, default: 0, min: 0 }
7
18
  layOnHandsSpent: { type: integer, default: 0, min: 0 }
@@ -74,3 +85,68 @@ choices:
74
85
  - id: sacred-oath
75
86
  from: { type: subclass, where: 'item.class == @classes.paladin' }
76
87
  when: self.level >= 3
88
+ actions:
89
+ - id: kit
90
+ listed: false
91
+ params:
92
+ random: { type: boolean, default: false }
93
+ steps:
94
+ - id: paladinWeapons
95
+ kind: choice
96
+ options:
97
+ - id: martial-and-shield
98
+ changes:
99
+ - { type: addItem, entry: { item: "'armor.shield'", equipped: true } }
100
+ - id: two-martial
101
+ recommend: options[0]
102
+ random: params.random
103
+ - id: paladinMartial
104
+ kind: choice
105
+ options: { content: { type: weapon, where: "item.category == 'martial'" } }
106
+ random: params.random
107
+ changes:
108
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
109
+ - id: paladinMartial2
110
+ kind: choice
111
+ when: "steps.paladinWeapons.picked == 'two-martial'"
112
+ options: { content: { type: weapon, where: "item.category == 'martial'" } }
113
+ random: params.random
114
+ changes:
115
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
116
+ - id: paladinSecond
117
+ kind: choice
118
+ options:
119
+ - id: five-javelins
120
+ changes:
121
+ - type: addItem
122
+ entry: { item: "'weapons.javelin'", quantity: 5, equipped: true }
123
+ - id: simple-melee
124
+ recommend: options[0]
125
+ random: params.random
126
+ - id: paladinSimpleMelee
127
+ kind: choice
128
+ when: "steps.paladinSecond.picked == 'simple-melee'"
129
+ options:
130
+ content: { type: weapon, where: "item.category == 'simple' && item.range == 'melee'" }
131
+ random: params.random
132
+ changes:
133
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
134
+ - id: paladinPack
135
+ kind: choice
136
+ options:
137
+ - id: priests-pack
138
+ changes: [{ type: addItem, entry: { item: "'gear.priests-pack'" } }]
139
+ - id: explorers-pack
140
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
141
+ recommend: options[0]
142
+ random: params.random
143
+ - id: paladinSymbol
144
+ kind: choice
145
+ options: { content: { type: gear, where: "item.category == 'holy-symbol'" } }
146
+ random: params.random
147
+ changes:
148
+ - { type: addItem, entry: { item: picked.id } }
149
+ - id: paladinKit
150
+ kind: changes
151
+ changes:
152
+ - { type: addItem, entry: { item: "'armor.chain-mail'", equipped: true } }