@opencharacter/5e-srd-5.1 0.1.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 (101) hide show
  1. package/README.md +58 -7
  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 -7
  14. package/content/classes/wizard.yaml +56 -0
  15. package/content/features/druid/natural-recovery.yaml +23 -45
  16. package/content/features/sorcerer/dragon-ancestor.yaml +1 -43
  17. package/content/features/sorcerer/elemental-affinity.yaml +29 -8
  18. package/content/features/sorcerer/metamagic.yaml +1 -93
  19. package/content/features/wizard/arcane-recovery.yaml +22 -67
  20. package/content/hunter-tactics/colossus-slayer.yaml +4 -0
  21. package/content/hunter-tactics/escape-the-horde.yaml +4 -0
  22. package/content/hunter-tactics/evasion.yaml +6 -0
  23. package/content/hunter-tactics/giant-killer.yaml +4 -0
  24. package/content/hunter-tactics/horde-breaker.yaml +4 -0
  25. package/content/hunter-tactics/multiattack-defense.yaml +4 -0
  26. package/content/hunter-tactics/stand-against-the-tide.yaml +4 -0
  27. package/content/hunter-tactics/steel-will.yaml +4 -0
  28. package/content/hunter-tactics/uncanny-dodge.yaml +6 -0
  29. package/content/hunter-tactics/volley.yaml +6 -0
  30. package/content/hunter-tactics/whirlwind-attack.yaml +6 -0
  31. package/content/invocations/bewitching-whispers.yaml +4 -2
  32. package/content/invocations/dreadful-word.yaml +4 -2
  33. package/content/invocations/eldritch-spear.yaml +3 -2
  34. package/content/invocations/minions-of-chaos.yaml +4 -2
  35. package/content/invocations/mire-the-mind.yaml +4 -2
  36. package/content/invocations/sculptor-of-flesh.yaml +4 -2
  37. package/content/invocations/sign-of-ill-omen.yaml +4 -2
  38. package/content/invocations/thief-of-five-fates.yaml +4 -2
  39. package/content/magic-items/arrow-of-slaying.yaml +1 -0
  40. package/content/magic-items/bag-of-holding.yaml +2 -0
  41. package/content/magic-items/efficient-quiver.yaml +2 -0
  42. package/content/magic-items/handy-haversack.yaml +2 -0
  43. package/content/magic-items/holy-avenger.yaml +9 -2
  44. package/content/magic-items/necklace-of-prayer-beads.yaml +1 -1
  45. package/content/magic-items/portable-hole.yaml +2 -0
  46. package/content/magic-items/ring-of-x-ray-vision.yaml +6 -0
  47. package/content/magic-items/robe-of-the-archmagi.yaml +1 -1
  48. package/content/magic-items/staff-of-charming.yaml +17 -12
  49. package/content/magic-items/staff-of-fire.yaml +9 -2
  50. package/content/magic-items/staff-of-frost.yaml +9 -2
  51. package/content/magic-items/staff-of-healing.yaml +9 -2
  52. package/content/magic-items/staff-of-power.yaml +2 -1
  53. package/content/magic-items/staff-of-swarming-insects.yaml +17 -12
  54. package/content/magic-items/staff-of-the-magi.yaml +2 -1
  55. package/content/magic-items/staff-of-the-python.yaml +7 -2
  56. package/content/magic-items/staff-of-the-woodlands.yaml +2 -1
  57. package/content/magic-items/staff-of-withering.yaml +9 -2
  58. package/content/metamagic/careful-spell.yaml +11 -0
  59. package/content/metamagic/distant-spell.yaml +11 -0
  60. package/content/metamagic/empowered-spell.yaml +22 -0
  61. package/content/metamagic/extended-spell.yaml +11 -0
  62. package/content/metamagic/heightened-spell.yaml +11 -0
  63. package/content/metamagic/quickened-spell.yaml +11 -0
  64. package/content/metamagic/subtle-spell.yaml +11 -0
  65. package/content/metamagic/twinned-spell.yaml +16 -0
  66. package/content/races/half-orc.yaml +0 -2
  67. package/content/races/tiefling.yaml +0 -3
  68. package/content/spells/death-ward.yaml +11 -0
  69. package/content/spells/eldritch-blast.yaml +1 -1
  70. package/content/subclasses/hunter.yaml +4 -29
  71. package/content/templates/eldritch-spear.yaml +4 -0
  72. package/content/traits/infernal-legacy.yaml +24 -2
  73. package/content/traits/relentless-endurance.yaml +11 -10
  74. package/content/weapons/javelin.yaml +1 -1
  75. package/dist/i18n/en.js +1 -1
  76. package/dist/i18n/en.json +301 -224
  77. package/dist/index.js +1 -1
  78. package/dist/release.json +6564 -7424
  79. package/i18n/en/monster-rules.yaml +1 -1
  80. package/i18n/en/type-fields.yaml +7 -0
  81. package/i18n/en.yaml +292 -246
  82. package/pack.yaml +2 -2
  83. package/package.json +2 -2
  84. package/rules/advancement.yaml +67 -38
  85. package/rules/checks.yaml +1 -1
  86. package/rules/classes.yaml +25 -4
  87. package/rules/combat.yaml +8 -2
  88. package/rules/conditions.yaml +1 -0
  89. package/rules/content-types.yaml +64 -4
  90. package/rules/core.yaml +6 -16
  91. package/rules/creation.yaml +26 -36
  92. package/rules/display.yaml +20 -11
  93. package/rules/equipment.yaml +13 -16
  94. package/rules/magic-items.yaml +19 -1
  95. package/rules/monsters.yaml +8 -2
  96. package/rules/rest.yaml +2 -73
  97. package/rules/spellcasting.yaml +1 -0
  98. package/rules/starting-equipment.yaml +17 -646
  99. package/rules/tags.yaml +12 -12
  100. package/upgrades/0.1.0-to-0.2.0.yaml +62 -0
  101. package/upgrades/0.2.0-to-0.3.0.yaml +152 -0
@@ -14,29 +14,36 @@ actions:
14
14
  available: character.creating
15
15
  steps:
16
16
  - id: race
17
+ tags: [creation.race]
17
18
  kind: choice
18
19
  options: { content: { type: race } }
19
20
  changes:
20
21
  - type: addItem
21
22
  entry: { id: race, item: picked.id }
22
23
  - id: subrace
24
+ tags: [creation.subrace]
23
25
  kind: choice
24
26
  options: { content: { type: subrace, where: item.race == steps.race.picked } }
25
27
  changes:
26
- - { type: choose, path: { entry: race, choice: [subrace] }, option: picked.id }
28
+ - type: choose
29
+ path: { entry: { formula: 'steps.race.added[0]' }, choice: [subrace] }
30
+ option: picked.id
27
31
  - id: class
32
+ tags: [creation.class]
28
33
  kind: choice
29
34
  options: { content: { type: class } }
30
35
  changes:
31
36
  - type: addItem
32
37
  entry: { id: class, item: picked.id, state: { level: 1, startingClass: true } }
33
38
  - id: background
39
+ tags: [creation.background]
34
40
  kind: choice
35
41
  options: { content: { type: background } }
36
42
  changes:
37
43
  - type: addItem
38
44
  entry: { id: background, item: picked.id }
39
45
  - id: method
46
+ tags: [creation.method]
40
47
  kind: choice
41
48
  options: [{ id: roll }, { id: point-buy }, { id: standard-array }]
42
49
  recommend: "'standard-array'"
@@ -93,12 +100,12 @@ actions:
93
100
  - id: equipment
94
101
  kind: action
95
102
  use: starting-equipment
96
- params: { class: steps.class.picked, background: steps.background.picked }
97
103
  - id: hitDie
98
104
  kind: changes
99
105
  changes:
100
106
  - { type: set, field: hp.base, value: maxOf(steps.class.item.hitDie) }
101
107
  - id: finish
108
+ tags: [creation.finish]
102
109
  kind: changes
103
110
  sheet: proposed
104
111
  changes:
@@ -118,6 +125,7 @@ actions:
118
125
  - { id: roll5, kind: roll, tags: [creation], parts: [{ dice: 4d6dl1 }] }
119
126
  - { id: roll6, kind: roll, tags: [creation], parts: [{ dice: 4d6dl1 }] }
120
127
  - id: race
128
+ tags: [creation.race]
121
129
  kind: choice
122
130
  options: { content: { type: race } }
123
131
  random: true
@@ -125,12 +133,16 @@ actions:
125
133
  - type: addItem
126
134
  entry: { id: race, item: picked.id }
127
135
  - id: subrace
136
+ tags: [creation.subrace]
128
137
  kind: choice
129
138
  options: { content: { type: subrace, where: item.race == steps.race.picked } }
130
139
  random: true
131
140
  changes:
132
- - { type: choose, path: { entry: race, choice: [subrace] }, option: picked.id }
141
+ - type: choose
142
+ path: { entry: { formula: 'steps.race.added[0]' }, choice: [subrace] }
143
+ option: picked.id
133
144
  - id: class
145
+ tags: [creation.class]
134
146
  kind: choice
135
147
  options: { content: { type: class } }
136
148
  random: true
@@ -138,14 +150,15 @@ actions:
138
150
  - type: addItem
139
151
  entry: { id: class, item: picked.id, state: { level: 1, startingClass: true } }
140
152
  - id: background
153
+ tags: [creation.background]
141
154
  kind: choice
142
155
  options: { content: { type: background } }
143
156
  random: true
144
157
  changes:
145
158
  - type: addItem
146
159
  entry: { id: background, item: picked.id }
147
- # The class's ability priority: the highest roll goes to its first ability, the next to its
148
- # second, and so on. A class this pack doesn't know takes the barbarian's (the first).
160
+ # The class's ability priority (its abilityPriority): the highest roll goes to its
161
+ # first ability, the next to its second, and so on.
149
162
  - id: priority
150
163
  kind: branch
151
164
  cases:
@@ -154,34 +167,7 @@ actions:
154
167
  sorted: >-
155
168
  sortList([steps.roll1.total, steps.roll2.total, steps.roll3.total,
156
169
  steps.roll4.total, steps.roll5.total, steps.roll6.total], -x)
157
- priority: >-
158
- [
159
- ['str', 'con', 'dex', 'wis', 'cha', 'int'],
160
- ['cha', 'dex', 'con', 'wis', 'int', 'str'],
161
- ['wis', 'con', 'str', 'dex', 'cha', 'int'],
162
- ['wis', 'con', 'dex', 'int', 'cha', 'str'],
163
- ['str', 'con', 'dex', 'wis', 'cha', 'int'],
164
- ['dex', 'wis', 'con', 'str', 'int', 'cha'],
165
- ['str', 'cha', 'con', 'wis', 'dex', 'int'],
166
- ['dex', 'wis', 'con', 'str', 'int', 'cha'],
167
- ['dex', 'con', 'wis', 'int', 'cha', 'str'],
168
- ['cha', 'con', 'dex', 'wis', 'int', 'str'],
169
- ['cha', 'con', 'dex', 'wis', 'int', 'str'],
170
- ['int', 'con', 'dex', 'wis', 'cha', 'str']
171
- ][max(0, indexOf([
172
- @classes.barbarian,
173
- @classes.bard,
174
- @classes.cleric,
175
- @classes.druid,
176
- @classes.fighter,
177
- @classes.monk,
178
- @classes.paladin,
179
- @classes.ranger,
180
- @classes.rogue,
181
- @classes.sorcerer,
182
- @classes.warlock,
183
- @classes.wizard
184
- ], steps.class.picked))]
170
+ priority: steps.class.item.abilityPriority
185
171
  - id: scores
186
172
  kind: allocate
187
173
  fields: { type: field, where: "'ability-base' in item.tags" }
@@ -193,21 +179,25 @@ actions:
193
179
  - steps.roll5.total
194
180
  - steps.roll6.total
195
181
  recommend:
196
- 'abilities.{ability}.base': flags.sorted[indexOf(flags.priority, '{ability}')]
182
+ 'abilities.{ability}.base': flags.sorted[indexOf(flags.priority, @abilities.{ability}.score)]
197
183
  - id: picks
198
184
  kind: choice
199
185
  options: { pending: {} }
200
186
  random: "!(choice.owner == @races.half-elf && choice.id == 'ability-scores')"
201
- recommend: flags.priority[minList(options, indexOf(flags.priority, x))]
187
+ recommend: >-
188
+ sortList(options, indexOf(flags.priority, [@abilities.str.score, @abilities.dex.score,
189
+ @abilities.con.score, @abilities.int.score, @abilities.wis.score,
190
+ @abilities.cha.score][indexOf(['str', 'dex', 'con', 'int', 'wis', 'cha'], x)]))[0]
202
191
  - id: equipment
203
192
  kind: action
204
193
  use: starting-equipment
205
- params: { class: steps.class.picked, background: steps.background.picked, random: true }
194
+ params: { random: true }
206
195
  - id: hitDie
207
196
  kind: changes
208
197
  changes:
209
198
  - { type: set, field: hp.base, value: maxOf(steps.class.item.hitDie) }
210
199
  - id: finish
200
+ tags: [creation.finish]
211
201
  kind: changes
212
202
  sheet: proposed
213
203
  changes:
@@ -267,7 +267,7 @@ display:
267
267
  combat.highJump: { unit: ft, groups: [combat], priority: 2 }
268
268
  combat.critRange: { groups: [combat], priority: 3 }
269
269
  proficiency.bonus: { groups: [combat, summary], priority: 1, format: signed }
270
- level.total: { groups: [summary], priority: 0 }
270
+ level.total: { groups: [summary], priority: 0, showWhen: '!sheet.monster || level.total > 0' }
271
271
  challenge.rating:
272
272
  { groups: [summary], priority: 2, format: fraction, showWhen: level.total == 0 }
273
273
  proficiencies.weapons: { groups: [proficiencies] }
@@ -319,6 +319,7 @@ display:
319
319
  groups: [combat],
320
320
  priority: 2,
321
321
  input: { min: 0, max: 3, widget: dots },
322
+ showWhen: '!sheet.monster',
322
323
  rolls: [{ action: death-save }],
323
324
  }
324
325
  deathSaves.failures:
@@ -326,6 +327,7 @@ display:
326
327
  groups: [combat],
327
328
  priority: 2,
328
329
  input: { min: 0, max: 3, widget: dots },
330
+ showWhen: '!sheet.monster',
329
331
  rolls: [{ action: death-save }],
330
332
  }
331
333
  proficiencies.languages: { groups: [proficiencies], visibility: background }
@@ -336,15 +338,24 @@ display:
336
338
  creature.type: { groups: [summary], priority: 2 }
337
339
  senses.darkvision: { unit: ft, groups: [summary], priority: 2, showWhen: senses.darkvision > 0 }
338
340
  senses.blindsense: { unit: ft, groups: [summary], priority: 2, showWhen: senses.blindsense > 0 }
341
+ # A monster carries only what it was given, so its carrying shows once it has some.
339
342
  carrying.weight:
340
343
  {
341
344
  unit: lb,
342
345
  groups: [summary],
343
346
  priority: 2,
344
347
  visibility: secondary,
348
+ showWhen: '!sheet.monster || carrying.weight > 0',
345
349
  with: [{ field: carrying.capacity, as: max }],
346
350
  }
347
- carrying.capacity: { unit: lb, groups: [summary], priority: 2, visibility: secondary }
351
+ carrying.capacity:
352
+ {
353
+ unit: lb,
354
+ groups: [summary],
355
+ priority: 2,
356
+ visibility: secondary,
357
+ showWhen: '!sheet.monster || carrying.weight > 0',
358
+ }
348
359
  carrying.stowed:
349
360
  {
350
361
  unit: lb,
@@ -354,6 +365,7 @@ display:
354
365
  showWhen: carrying.stowed > 0,
355
366
  }
356
367
  carrying.stowCapacity: { hidden: true }
368
+ carrying.stowUnlimited: { hidden: true }
357
369
  combat.featherFall: { hidden: true }
358
370
  carrying.quivers: { hidden: true }
359
371
  carrying.quiveredAmmunition: { hidden: true }
@@ -361,6 +373,7 @@ display:
361
373
  carrying.quiveredLong: { hidden: true }
362
374
  combat.ignoreArmorStrength: { hidden: true }
363
375
  classes.held: { hidden: true }
376
+ attunement.classUnmet: { hidden: true }
364
377
  creature.race: { hidden: true }
365
378
  magicItems.ignoreRequirements: { hidden: true }
366
379
  combat.missToHit: { hidden: true }
@@ -437,7 +450,6 @@ display:
437
450
  hideInPlainSight.active:
438
451
  { groups: [class-features], priority: 0, showWhen: hideInPlainSight.active }
439
452
  foeSlayer.bonus: { hidden: true }
440
- hunter.colossusSlayer: { hidden: true }
441
453
  sneakAttack.dice: { groups: [class-features], priority: 1, showWhen: sneakAttack.dice > 0 }
442
454
  sorcery.points: { groups: [class-features], priority: 1, showWhen: sorcery.points > 0 }
443
455
  eldritchBlast.beams:
@@ -446,21 +458,18 @@ display:
446
458
  priority: 1,
447
459
  showWhen: '@spells.eldritch-blast in spells.warlock',
448
460
  }
449
- eldritchBlast.range:
450
- {
451
- groups: [class-features],
452
- priority: 2,
453
- showWhen: '@spells.eldritch-blast in spells.warlock',
454
- }
455
461
  eldritchBlast.push: { groups: [class-features], priority: 2, showWhen: eldritchBlast.push > 0 }
456
462
  sorcery.left: { groups: [class-features], priority: 1, showWhen: sorcery.points > 0 }
457
463
  sorcery.shortRestRegain: { hidden: true }
458
464
  sorcery.metamagic: { hidden: true }
459
- draconic.damageType: { hidden: true }
460
465
  elementalAffinity.resistant:
461
466
  { groups: [class-features], priority: 0, showWhen: elementalAffinity.resistant }
462
467
  dragonWings.active:
463
- { groups: [class-features], priority: 0, showWhen: draconic.damageType != 'none' }
468
+ {
469
+ groups: [class-features],
470
+ priority: 0,
471
+ showWhen: "size(picksOf('features.sorcerer.dragon-ancestor', 'dragon')) > 0",
472
+ }
464
473
  warlock.boons: { groups: [class-features], priority: 1, showWhen: size(warlock.boons) > 0 }
465
474
  spellcasting.bard.dc:
466
475
  { groups: [spellcasting], priority: 0, showWhen: spellcasting.bard.dc > 0 }
@@ -19,11 +19,13 @@ contentTypes:
19
19
  trade-good,
20
20
  ],
21
21
  required: true,
22
+ open: true,
22
23
  }
23
24
  cost: { type: decimal } # gold pieces, per unit
24
25
  weight: { type: decimal } # pounds, per unit
25
26
  bundle: { type: integer, min: 1 }
26
- ammunition: { type: enum, values: [arrow, blowgun-needle, crossbow-bolt, sling-bullet] }
27
+ ammunition:
28
+ { type: enum, values: [arrow, blowgun-needle, crossbow-bolt, sling-bullet], open: true }
27
29
  state:
28
30
  stowed: { type: boolean, default: false }
29
31
  quivered: { type: boolean, default: false } # in an Efficient Quiver (below)
@@ -38,6 +40,7 @@ contentTypes:
38
40
  type: enum,
39
41
  values: [artisans-tools, gaming-set, musical-instrument, kit, other],
40
42
  required: true,
43
+ open: true,
41
44
  }
42
45
  cost: { type: decimal }
43
46
  weight: { type: decimal }
@@ -54,7 +57,7 @@ contentTypes:
54
57
  vehicle:
55
58
  carried: true
56
59
  fields:
57
- category: { type: enum, values: [drawn, waterborne], required: true }
60
+ category: { type: enum, values: [drawn, waterborne], required: true, open: true }
58
61
  cost: { type: decimal }
59
62
  pulledWeight: { type: decimal }
60
63
  speedMph: { type: decimal }
@@ -65,14 +68,10 @@ fields:
65
68
  formula: >-
66
69
  sumCopies(copy.fields.weight * copy.quantity, has(copy.fields.weight)
67
70
  && has(copy.state.stowed) && copy.state.stowed)
68
- carrying.stowCapacity:
69
- type: decimal
70
- formula: >-
71
- 500 * sumCopies(copy.quantity, copy.item == @magic-items.bag-of-holding)
72
- + 120 * sumCopies(copy.quantity, copy.item == @magic-items.handy-haversack)
73
- carrying.quivers:
74
- type: integer
75
- formula: 'sumCopies(copy.quantity, copy.item == @magic-items.efficient-quiver)'
71
+ # What extradimensional containers and quivers hold: each adds its own (content effects).
72
+ carrying.stowCapacity: { type: decimal, formula: 0, min: 0 }
73
+ carrying.stowUnlimited: { type: boolean, formula: false }
74
+ carrying.quivers: { type: integer, formula: 0, min: 0 }
76
75
  carrying.quiveredAmmunition:
77
76
  type: integer
78
77
  formula: >-
@@ -81,25 +80,23 @@ fields:
81
80
  carrying.quiveredJavelins:
82
81
  type: integer
83
82
  formula: >-
84
- sumCopies(copy.quantity, copy.item == @weapons.javelin
83
+ sumCopies(copy.quantity, 'quiver.javelin' in copy.tags
85
84
  && has(copy.state.quivered) && copy.state.quivered)
86
85
  carrying.quiveredLong:
87
86
  type: integer
88
87
  formula: >-
89
88
  sumCopies(copy.quantity, copy.type == 'weapon'
90
- && copy.item != @weapons.javelin
89
+ && !('quiver.javelin' in copy.tags)
91
90
  && has(copy.state.quivered) && copy.state.quivered)
92
91
 
93
92
  constraints:
94
93
  - id: stowed-without-container
95
94
  check: >-
96
95
  countCopies(has(copy.state.stowed) && copy.state.stowed) == 0
97
- || countCopies(copy.item in [@magic-items.bag-of-holding,
98
- @magic-items.handy-haversack, @magic-items.portable-hole]) > 0
96
+ || carrying.stowUnlimited || carrying.stowCapacity > 0
99
97
  - id: stowed-over-capacity
100
98
  check: >-
101
- carrying.stowed <= carrying.stowCapacity
102
- || countCopies(copy.item == @magic-items.portable-hole) > 0
99
+ carrying.stowUnlimited || carrying.stowed <= carrying.stowCapacity
103
100
  data:
104
101
  stowed: carrying.stowed
105
102
  capacity: carrying.stowCapacity
@@ -3,6 +3,8 @@
3
3
  templateFields:
4
4
  rarity: { type: enum, values: [common, uncommon, rare, very-rare, legendary, artifact] }
5
5
  requiresAttunement: { type: boolean, default: false }
6
+ # Only a character with one of these classes can attune to it.
7
+ attunementClasses: { type: set, of: class }
6
8
  maxCharges: { type: integer, min: 1 }
7
9
  recharge: { type: dice }
8
10
  attackBonus: { type: integer, default: 0 }
@@ -15,7 +17,12 @@ contentTypes:
15
17
  equippable: true
16
18
  fields:
17
19
  category:
18
- { type: enum, values: [potion, ring, rod, scroll, wand, wondrous-item], required: true }
20
+ {
21
+ type: enum,
22
+ values: [potion, ring, rod, scroll, wand, wondrous-item],
23
+ required: true,
24
+ open: true,
25
+ }
19
26
  rarity:
20
27
  {
21
28
  type: enum,
@@ -23,6 +30,7 @@ contentTypes:
23
30
  required: true,
24
31
  }
25
32
  requiresAttunement: { type: boolean }
33
+ attunementClasses: { type: set, of: class }
26
34
  cost: { type: decimal } # gold pieces, where the SRD gives one
27
35
  weight: { type: decimal } # pounds, where the SRD gives one
28
36
  maxCharges: { type: integer, min: 1 }
@@ -40,6 +48,15 @@ contentTypes:
40
48
  state:
41
49
  attuned: { type: boolean, default: false }
42
50
  stowed: { type: boolean, default: false } # in an extradimensional container (equipment.yaml)
51
+ usedToday: { type: set, of: string, default: [] }
52
+ effects:
53
+ # An attuned item for other classes than the character's (attunementClasses).
54
+ - target: attunement.classUnmet
55
+ op: add
56
+ value: 1
57
+ when: >-
58
+ self.attuned && has(item.attunementClasses) && size(item.attunementClasses) > 0
59
+ && countList(item.attunementClasses, x in classes.held) == 0
43
60
 
44
61
  storedSpell:
45
62
  carried: false
@@ -341,6 +358,7 @@ actions:
341
358
  dice: { type: dice, optional: true }
342
359
  damageType:
343
360
  type: enum
361
+ open: true
344
362
  optional: true
345
363
  values:
346
364
  [
@@ -12,6 +12,7 @@ contentTypes:
12
12
  creatureType:
13
13
  {
14
14
  type: enum,
15
+ open: true,
15
16
  values:
16
17
  [
17
18
  aberration,
@@ -53,6 +54,7 @@ contentTypes:
53
54
  sahuagin,
54
55
  titan,
55
56
  ],
57
+ open: true,
56
58
  }
57
59
  shapechanger: { type: boolean }
58
60
  swarm: { type: boolean }
@@ -145,7 +147,7 @@ contentTypes:
145
147
  cr: { type: decimal, required: true, min: 0, max: 30 }
146
148
  xp: { type: integer, min: 0 }
147
149
  legendaryActions: { type: integer, min: 1 }
148
- ownCopies: { type: set, of: monsterAction, default: [] }
150
+ ownCopies: { type: list, of: monsterAction, unique: true, default: [] }
149
151
  innateOncePerDay: { type: set, of: spell, default: [] }
150
152
  innateTwicePerDay: { type: set, of: spell, default: [] }
151
153
  innateThricePerDay: { type: set, of: spell, default: [] }
@@ -222,6 +224,7 @@ contentTypes:
222
224
  - use: change-form
223
225
 
224
226
  monsterSpellcasting:
227
+ grantOnly: true
225
228
  carried: false
226
229
  fields:
227
230
  ability: { type: enum, values: [str, dex, con, int, wis, cha], required: true }
@@ -297,6 +300,7 @@ contentTypes:
297
300
  slashing,
298
301
  thunder,
299
302
  ],
303
+ open: true,
300
304
  }
301
305
  versatileDamage: { type: dice }
302
306
  damage2: { type: dice }
@@ -319,6 +323,7 @@ contentTypes:
319
323
  slashing,
320
324
  thunder,
321
325
  ],
326
+ open: true,
322
327
  }
323
328
  magical: { type: boolean }
324
329
  save: { type: enum, values: [str, dex, con, int, wis, cha] }
@@ -343,6 +348,7 @@ contentTypes:
343
348
  slashing,
344
349
  thunder,
345
350
  ],
351
+ open: true,
346
352
  }
347
353
  saveEffect: { type: enum, values: [half, none], default: none }
348
354
  condition: { type: id, of: condition }
@@ -540,7 +546,7 @@ actions:
540
546
  changes:
541
547
  - type: choose
542
548
  when: has(steps.monster.item.startingForm)
543
- path: { entry: monster, choice: [form] }
549
+ path: { entry: { formula: 'steps.monster.added[0]' }, choice: [form] }
544
550
  option: steps.monster.item.startingForm
545
551
  - type: addItem
546
552
  forEach: steps.monster.item.ownCopies
package/rules/rest.yaml CHANGED
@@ -86,6 +86,8 @@ actions:
86
86
  steps:
87
87
  - id: rest
88
88
  kind: changes
89
+ # Content resets its own uses here (`rest.long` changes effects).
90
+ tags: [rest.long]
89
91
  changes:
90
92
  - { type: set, field: hp.current, value: hp.max, when: rest.longRestHeals }
91
93
  - { type: set, field: hp.temp, value: 0 }
@@ -278,38 +280,6 @@ actions:
278
280
  copies: { type: class, where: has(self.wholenessUsed) && self.wholenessUsed }
279
281
  key: wholenessUsed
280
282
  value: false
281
- - type: setState
282
- when: countCopies(has(copy.state.hellishRebukeUsed) && copy.state.hellishRebukeUsed) > 0
283
- copies: { type: race, where: has(self.hellishRebukeUsed) && self.hellishRebukeUsed }
284
- key: hellishRebukeUsed
285
- value: false
286
- - type: setState
287
- when: countCopies(has(copy.state.darknessUsed) && copy.state.darknessUsed) > 0
288
- copies: { type: race, where: has(self.darknessUsed) && self.darknessUsed }
289
- key: darknessUsed
290
- value: false
291
- - type: setState
292
- when: >-
293
- countCopies(copy.item == @magic-items.ring-of-x-ray-vision
294
- && copy.state.used) > 0
295
- copies:
296
- {
297
- type: magicItem,
298
- where: 'item.id == @magic-items.ring-of-x-ray-vision && self.used',
299
- }
300
- key: used
301
- value: false
302
- - type: setState
303
- when: >-
304
- countCopies(has(copy.state.relentlessEnduranceUsed)
305
- && copy.state.relentlessEnduranceUsed) > 0
306
- copies:
307
- {
308
- type: race,
309
- where: has(self.relentlessEnduranceUsed) && self.relentlessEnduranceUsed,
310
- }
311
- key: relentlessEnduranceUsed
312
- value: false
313
283
  - type: setState
314
284
  when: countCopies(has(copy.state.signatureSpell1Used) && copy.state.signatureSpell1Used) > 0
315
285
  copies:
@@ -322,47 +292,6 @@ actions:
322
292
  { type: class, where: has(self.signatureSpell2Used) && self.signatureSpell2Used }
323
293
  key: signatureSpell2Used
324
294
  value: false
325
- - type: setState
326
- when: countCopies(has(copy.state.bewitchingWhispersUsed) && copy.state.bewitchingWhispersUsed) > 0
327
- copies:
328
- {
329
- type: class,
330
- where: has(self.bewitchingWhispersUsed) && self.bewitchingWhispersUsed,
331
- }
332
- key: bewitchingWhispersUsed
333
- value: false
334
- - type: setState
335
- when: countCopies(has(copy.state.dreadfulWordUsed) && copy.state.dreadfulWordUsed) > 0
336
- copies: { type: class, where: has(self.dreadfulWordUsed) && self.dreadfulWordUsed }
337
- key: dreadfulWordUsed
338
- value: false
339
- - type: setState
340
- when: countCopies(has(copy.state.minionsOfChaosUsed) && copy.state.minionsOfChaosUsed) > 0
341
- copies: { type: class, where: has(self.minionsOfChaosUsed) && self.minionsOfChaosUsed }
342
- key: minionsOfChaosUsed
343
- value: false
344
- - type: setState
345
- when: countCopies(has(copy.state.mireTheMindUsed) && copy.state.mireTheMindUsed) > 0
346
- copies: { type: class, where: has(self.mireTheMindUsed) && self.mireTheMindUsed }
347
- key: mireTheMindUsed
348
- value: false
349
- - type: setState
350
- when: countCopies(has(copy.state.sculptorOfFleshUsed) && copy.state.sculptorOfFleshUsed) > 0
351
- copies:
352
- { type: class, where: has(self.sculptorOfFleshUsed) && self.sculptorOfFleshUsed }
353
- key: sculptorOfFleshUsed
354
- value: false
355
- - type: setState
356
- when: countCopies(has(copy.state.signOfIllOmenUsed) && copy.state.signOfIllOmenUsed) > 0
357
- copies: { type: class, where: has(self.signOfIllOmenUsed) && self.signOfIllOmenUsed }
358
- key: signOfIllOmenUsed
359
- value: false
360
- - type: setState
361
- when: countCopies(has(copy.state.thiefOfFiveFatesUsed) && copy.state.thiefOfFiveFatesUsed) > 0
362
- copies:
363
- { type: class, where: has(self.thiefOfFiveFatesUsed) && self.thiefOfFiveFatesUsed }
364
- key: thiefOfFiveFatesUsed
365
- value: false
366
295
  - type: setState
367
296
  when: countCopies(copy.type == 'monsterAction') > 0
368
297
  copies:
@@ -601,6 +601,7 @@ actions:
601
601
  steps:
602
602
  - id: rest
603
603
  kind: changes
604
+ tags: [rest.short]
604
605
  changes:
605
606
  - { type: set, field: pactSlots.used, value: 0 }
606
607
  - type: removeEffect