@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
@@ -2,6 +2,17 @@ id: classes.ranger
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d10
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
  prerequisites:
6
17
  - id: multiclass
7
18
  when: (self.startingClass && self.level == level.total) || item.id in multiclass.qualified
@@ -88,3 +99,61 @@ choices:
88
99
  - id: ranger-archetype
89
100
  from: { type: subclass, where: 'item.class == @classes.ranger' }
90
101
  when: self.level >= 3
102
+ actions:
103
+ - id: kit
104
+ listed: false
105
+ params:
106
+ random: { type: boolean, default: false }
107
+ steps:
108
+ - id: rangerArmor
109
+ kind: choice
110
+ options:
111
+ - id: scale-mail
112
+ changes:
113
+ - { type: addItem, entry: { item: "'armor.scale-mail'", equipped: true } }
114
+ - id: leather-armor
115
+ changes:
116
+ - { type: addItem, entry: { item: "'armor.leather'", equipped: true } }
117
+ recommend: options[0]
118
+ random: params.random
119
+ - id: rangerWeapons
120
+ kind: choice
121
+ options:
122
+ - id: two-shortswords
123
+ changes:
124
+ - type: addItem
125
+ entry: { item: "'weapons.shortsword'", quantity: 2, equipped: true }
126
+ - id: two-simple-melee
127
+ recommend: options[0]
128
+ random: params.random
129
+ - id: rangerSimpleMelee
130
+ kind: choice
131
+ when: "steps.rangerWeapons.picked == 'two-simple-melee'"
132
+ options:
133
+ content: { type: weapon, where: "item.category == 'simple' && item.range == 'melee'" }
134
+ random: params.random
135
+ changes:
136
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
137
+ - id: rangerSimpleMelee2
138
+ kind: choice
139
+ when: "steps.rangerWeapons.picked == 'two-simple-melee'"
140
+ options:
141
+ content: { type: weapon, where: "item.category == 'simple' && item.range == 'melee'" }
142
+ random: params.random
143
+ changes:
144
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
145
+ - id: rangerPack
146
+ kind: choice
147
+ options:
148
+ - id: dungeoneers-pack
149
+ changes: [{ type: addItem, entry: { item: "'gear.dungeoneers-pack'" } }]
150
+ - id: explorers-pack
151
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
152
+ recommend: options[0]
153
+ random: params.random
154
+ - id: rangerKit
155
+ kind: changes
156
+ changes:
157
+ - { type: addItem, entry: { item: "'weapons.longbow'", equipped: true } }
158
+ - { type: addItem, entry: { item: "'gear.quiver'" } }
159
+ - { type: addItem, entry: { item: "'gear.arrows'", quantity: 20 } }
@@ -2,6 +2,17 @@ id: classes.rogue
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d8
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.dex.score,
9
+ abilities.con.score,
10
+ abilities.wis.score,
11
+ abilities.int.score,
12
+ abilities.cha.score,
13
+ abilities.str.score,
14
+ ]
15
+ multiclassAll: [dex]
5
16
  state:
6
17
  strokeOfLuckUsed: { type: boolean, default: false }
7
18
  prerequisites:
@@ -105,3 +116,51 @@ choices:
105
116
  - id: roguish-archetype
106
117
  from: { type: subclass, where: 'item.class == @classes.rogue' }
107
118
  when: self.level >= 3
119
+ actions:
120
+ - id: kit
121
+ listed: false
122
+ params:
123
+ random: { type: boolean, default: false }
124
+ steps:
125
+ - id: rogueWeapon
126
+ kind: choice
127
+ options:
128
+ - id: rapier
129
+ changes:
130
+ - { type: addItem, entry: { item: "'weapons.rapier'", equipped: true } }
131
+ - id: shortsword
132
+ changes:
133
+ - { type: addItem, entry: { item: "'weapons.shortsword'", equipped: true } }
134
+ recommend: options[0]
135
+ random: params.random
136
+ - id: rogueSecond
137
+ kind: choice
138
+ options:
139
+ - id: shortbow
140
+ changes:
141
+ - { type: addItem, entry: { item: "'weapons.shortbow'", equipped: true } }
142
+ - { type: addItem, entry: { item: "'gear.quiver'" } }
143
+ - { type: addItem, entry: { item: "'gear.arrows'", quantity: 20 } }
144
+ - id: shortsword
145
+ changes:
146
+ - { type: addItem, entry: { item: "'weapons.shortsword'", equipped: true } }
147
+ recommend: options[0]
148
+ random: params.random
149
+ - id: roguePack
150
+ kind: choice
151
+ options:
152
+ - id: burglars-pack
153
+ changes: [{ type: addItem, entry: { item: "'gear.burglars-pack'" } }]
154
+ - id: dungeoneers-pack
155
+ changes: [{ type: addItem, entry: { item: "'gear.dungeoneers-pack'" } }]
156
+ - id: explorers-pack
157
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
158
+ recommend: options[0]
159
+ random: params.random
160
+ - id: rogueKit
161
+ kind: changes
162
+ changes:
163
+ - { type: addItem, entry: { item: "'armor.leather'", equipped: true } }
164
+ - type: addItem
165
+ entry: { item: "'weapons.dagger'", quantity: 2, equipped: true }
166
+ - { type: addItem, entry: { item: "'tools.thieves-tools'" } }
@@ -2,6 +2,17 @@ id: classes.sorcerer
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d6
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.cha.score,
9
+ abilities.con.score,
10
+ abilities.dex.score,
11
+ abilities.wis.score,
12
+ abilities.int.score,
13
+ abilities.str.score,
14
+ ]
15
+ multiclassAll: [cha]
5
16
  state:
6
17
  sorceryPointsSpent: { type: integer, default: 0, min: 0 }
7
18
  prerequisites:
@@ -69,3 +80,56 @@ choices:
69
80
  - id: sorcerous-origin
70
81
  from: { type: subclass, where: 'item.class == @classes.sorcerer' }
71
82
  when: self.level >= 1
83
+ actions:
84
+ - id: kit
85
+ listed: false
86
+ params:
87
+ random: { type: boolean, default: false }
88
+ steps:
89
+ - id: sorcererWeapon
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: sorcererSimple
101
+ kind: choice
102
+ when: "steps.sorcererWeapon.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: sorcererFocus
108
+ kind: choice
109
+ options:
110
+ - id: component-pouch
111
+ changes: [{ type: addItem, entry: { item: "'gear.component-pouch'" } }]
112
+ - id: arcane-focus
113
+ recommend: options[0]
114
+ random: params.random
115
+ - id: sorcererArcaneFocus
116
+ kind: choice
117
+ when: "steps.sorcererFocus.picked == 'arcane-focus'"
118
+ options: { content: { type: gear, where: "item.category == 'arcane-focus'" } }
119
+ random: params.random
120
+ changes:
121
+ - { type: addItem, entry: { item: picked.id } }
122
+ - id: sorcererPack
123
+ kind: choice
124
+ options:
125
+ - id: dungeoneers-pack
126
+ changes: [{ type: addItem, entry: { item: "'gear.dungeoneers-pack'" } }]
127
+ - id: explorers-pack
128
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
129
+ recommend: options[0]
130
+ random: params.random
131
+ - id: sorcererKit
132
+ kind: changes
133
+ changes:
134
+ - type: addItem
135
+ entry: { item: "'weapons.dagger'", quantity: 2, equipped: true }
@@ -2,6 +2,17 @@ id: classes.warlock
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d8
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.cha.score,
9
+ abilities.con.score,
10
+ abilities.dex.score,
11
+ abilities.wis.score,
12
+ abilities.int.score,
13
+ abilities.str.score,
14
+ ]
15
+ multiclassAll: [cha]
5
16
  state:
6
17
  arcanum6Used: { type: boolean, default: false }
7
18
  arcanum7Used: { type: boolean, default: false }
@@ -51,3 +62,63 @@ choices:
51
62
  - id: otherworldly-patron
52
63
  from: { type: subclass, where: 'item.class == @classes.warlock' }
53
64
  when: self.level >= 1
65
+ actions:
66
+ - id: kit
67
+ listed: false
68
+ params:
69
+ random: { type: boolean, default: false }
70
+ steps:
71
+ - id: warlockWeapon
72
+ kind: choice
73
+ options:
74
+ - id: light-crossbow
75
+ changes:
76
+ - type: addItem
77
+ entry: { item: "'weapons.light-crossbow'", equipped: true }
78
+ - { type: addItem, entry: { item: "'gear.crossbow-bolts'", quantity: 20 } }
79
+ - id: simple
80
+ recommend: options[0]
81
+ random: params.random
82
+ - id: warlockSimple
83
+ kind: choice
84
+ when: "steps.warlockWeapon.picked == 'simple'"
85
+ options: { content: { type: weapon, where: "item.category == 'simple'" } }
86
+ random: params.random
87
+ changes:
88
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
89
+ - id: warlockFocus
90
+ kind: choice
91
+ options:
92
+ - id: component-pouch
93
+ changes: [{ type: addItem, entry: { item: "'gear.component-pouch'" } }]
94
+ - id: arcane-focus
95
+ recommend: options[0]
96
+ random: params.random
97
+ - id: warlockArcaneFocus
98
+ kind: choice
99
+ when: "steps.warlockFocus.picked == 'arcane-focus'"
100
+ options: { content: { type: gear, where: "item.category == 'arcane-focus'" } }
101
+ random: params.random
102
+ changes:
103
+ - { type: addItem, entry: { item: picked.id } }
104
+ - id: warlockPack
105
+ kind: choice
106
+ options:
107
+ - id: scholars-pack
108
+ changes: [{ type: addItem, entry: { item: "'gear.scholars-pack'" } }]
109
+ - id: dungeoneers-pack
110
+ changes: [{ type: addItem, entry: { item: "'gear.dungeoneers-pack'" } }]
111
+ recommend: options[0]
112
+ random: params.random
113
+ - id: warlockExtra
114
+ kind: choice
115
+ options: { content: { type: weapon, where: "item.category == 'simple'" } }
116
+ random: params.random
117
+ changes:
118
+ - { type: addItem, entry: { item: picked.id, equipped: true } }
119
+ - id: warlockKit
120
+ kind: changes
121
+ changes:
122
+ - { type: addItem, entry: { item: "'armor.leather'", equipped: true } }
123
+ - type: addItem
124
+ entry: { item: "'weapons.dagger'", quantity: 2, equipped: true }
@@ -2,6 +2,17 @@ id: classes.wizard
2
2
  type: class
3
3
  fields:
4
4
  hitDie: 1d6
5
+ startingKit: true
6
+ abilityPriority:
7
+ [
8
+ abilities.int.score,
9
+ abilities.con.score,
10
+ abilities.dex.score,
11
+ abilities.wis.score,
12
+ abilities.cha.score,
13
+ abilities.str.score,
14
+ ]
15
+ multiclassAll: [int]
5
16
  state:
6
17
  arcaneRecoveryUsed: { type: boolean, default: false }
7
18
  overchannelUses: { type: integer, default: 0, min: 0 }
@@ -72,3 +83,48 @@ choices:
72
83
  - id: arcane-tradition
73
84
  from: { type: subclass, where: 'item.class == @classes.wizard' }
74
85
  when: self.level >= 2
86
+ actions:
87
+ - id: kit
88
+ listed: false
89
+ params:
90
+ random: { type: boolean, default: false }
91
+ steps:
92
+ - id: wizardWeapon
93
+ kind: choice
94
+ options:
95
+ - id: quarterstaff
96
+ changes:
97
+ - { type: addItem, entry: { item: "'weapons.quarterstaff'", equipped: true } }
98
+ - id: dagger
99
+ changes:
100
+ - { type: addItem, entry: { item: "'weapons.dagger'", equipped: true } }
101
+ recommend: options[0]
102
+ random: params.random
103
+ - id: wizardFocus
104
+ kind: choice
105
+ options:
106
+ - id: component-pouch
107
+ changes: [{ type: addItem, entry: { item: "'gear.component-pouch'" } }]
108
+ - id: arcane-focus
109
+ recommend: options[0]
110
+ random: params.random
111
+ - id: wizardArcaneFocus
112
+ kind: choice
113
+ when: "steps.wizardFocus.picked == 'arcane-focus'"
114
+ options: { content: { type: gear, where: "item.category == 'arcane-focus'" } }
115
+ random: params.random
116
+ changes:
117
+ - { type: addItem, entry: { item: picked.id } }
118
+ - id: wizardPack
119
+ kind: choice
120
+ options:
121
+ - id: scholars-pack
122
+ changes: [{ type: addItem, entry: { item: "'gear.scholars-pack'" } }]
123
+ - id: explorers-pack
124
+ changes: [{ type: addItem, entry: { item: "'gear.explorers-pack'" } }]
125
+ recommend: options[0]
126
+ random: params.random
127
+ - id: wizardKit
128
+ kind: changes
129
+ changes:
130
+ - { type: addItem, entry: { item: "'gear.spellbook'" } }
@@ -3,46 +3,4 @@ type: feature
3
3
  effects:
4
4
  - { target: proficiencies.languages, op: grant, value: { item: languages.draconic } }
5
5
  choices:
6
- - id: dragon
7
- from:
8
- options:
9
- - id: black
10
- tags: [damage.acid]
11
- effects:
12
- - { target: draconic.damageType, op: set, value: "'acid'" }
13
- - id: blue
14
- tags: [damage.lightning]
15
- effects:
16
- - { target: draconic.damageType, op: set, value: "'lightning'" }
17
- - id: brass
18
- tags: [damage.fire]
19
- effects:
20
- - { target: draconic.damageType, op: set, value: "'fire'" }
21
- - id: bronze
22
- tags: [damage.lightning]
23
- effects:
24
- - { target: draconic.damageType, op: set, value: "'lightning'" }
25
- - id: copper
26
- tags: [damage.acid]
27
- effects:
28
- - { target: draconic.damageType, op: set, value: "'acid'" }
29
- - id: gold
30
- tags: [damage.fire]
31
- effects:
32
- - { target: draconic.damageType, op: set, value: "'fire'" }
33
- - id: green
34
- tags: [damage.poison]
35
- effects:
36
- - { target: draconic.damageType, op: set, value: "'poison'" }
37
- - id: red
38
- tags: [damage.fire]
39
- effects:
40
- - { target: draconic.damageType, op: set, value: "'fire'" }
41
- - id: silver
42
- tags: [damage.cold]
43
- effects:
44
- - { target: draconic.damageType, op: set, value: "'cold'" }
45
- - id: white
46
- tags: [damage.cold]
47
- effects:
48
- - { target: draconic.damageType, op: set, value: "'cold'" }
6
+ - { id: dragon, from: { type: draconicAncestry }, activate: false }
@@ -4,34 +4,55 @@ effects:
4
4
  - target: { rolls: [damage.spell] }
5
5
  op: add
6
6
  value: abilities.cha.mod
7
- tags: [{ formula: "'damage.' + draconic.damageType" }]
8
- when: has(roll.item.damageType) && roll.item.damageType == draconic.damageType
7
+ tags:
8
+ - formula: >-
9
+ mapList(picksOf('features.sorcerer.dragon-ancestor', 'dragon'),
10
+ 'damage.' + itemField(x, 'damageType'))
11
+ when: >-
12
+ has(roll.item.damageType)
13
+ && roll.item.damageType in mapList(picksOf('features.sorcerer.dragon-ancestor', 'dragon'),
14
+ itemField(x, 'damageType'))
9
15
  - target: { incoming: { fields: [hp.current], tags: [damage.acid] } }
10
16
  op: multiply
11
17
  value: 0.5
12
- when: elementalAffinity.resistant && draconic.damageType == 'acid'
18
+ when: >-
19
+ elementalAffinity.resistant
20
+ && 'acid' in mapList(picksOf('features.sorcerer.dragon-ancestor', 'dragon'),
21
+ itemField(x, 'damageType'))
13
22
  - target: { incoming: { fields: [hp.current], tags: [damage.cold] } }
14
23
  op: multiply
15
24
  value: 0.5
16
- when: elementalAffinity.resistant && draconic.damageType == 'cold'
25
+ when: >-
26
+ elementalAffinity.resistant
27
+ && 'cold' in mapList(picksOf('features.sorcerer.dragon-ancestor', 'dragon'),
28
+ itemField(x, 'damageType'))
17
29
  - target: { incoming: { fields: [hp.current], tags: [damage.fire] } }
18
30
  op: multiply
19
31
  value: 0.5
20
- when: elementalAffinity.resistant && draconic.damageType == 'fire'
32
+ when: >-
33
+ elementalAffinity.resistant
34
+ && 'fire' in mapList(picksOf('features.sorcerer.dragon-ancestor', 'dragon'),
35
+ itemField(x, 'damageType'))
21
36
  - target: { incoming: { fields: [hp.current], tags: [damage.lightning] } }
22
37
  op: multiply
23
38
  value: 0.5
24
- when: elementalAffinity.resistant && draconic.damageType == 'lightning'
39
+ when: >-
40
+ elementalAffinity.resistant
41
+ && 'lightning' in mapList(picksOf('features.sorcerer.dragon-ancestor', 'dragon'),
42
+ itemField(x, 'damageType'))
25
43
  - target: { incoming: { fields: [hp.current], tags: [damage.poison] } }
26
44
  op: multiply
27
45
  value: 0.5
28
- when: elementalAffinity.resistant && draconic.damageType == 'poison'
46
+ when: >-
47
+ elementalAffinity.resistant
48
+ && 'poison' in mapList(picksOf('features.sorcerer.dragon-ancestor', 'dragon'),
49
+ itemField(x, 'damageType'))
29
50
  actions:
30
51
  - id: elemental-resistance
31
52
  tags: [feature]
32
53
  results: [resistant]
33
54
  available: >-
34
- draconic.damageType != 'none' && !elementalAffinity.resistant
55
+ size(picksOf('features.sorcerer.dragon-ancestor', 'dragon')) > 0 && !elementalAffinity.resistant
35
56
  && self.sorceryPointsSpent < sorcery.points
36
57
  steps:
37
58
  - id: spend
@@ -1,98 +1,6 @@
1
1
  id: features.sorcerer.metamagic
2
2
  type: feature
3
- # Empowered Spell rerolls, once, the lowest damage dice at or below half their faces, up to the
4
- # Charisma modifier (at least one).
5
- effects:
6
- - target: { rolls: [damage.spell] }
7
- op: rollModifier
8
- value:
9
- kind: reroll
10
- below: 'floor(maxOf(dieOf(roll.item.damage)) / 2)'
11
- once: true
12
- count: max(1, abilities.cha.mod)
13
- when: >-
14
- has(flags.metamagic) && flags.metamagic == 'empowered' && has(roll.item.damage)
15
3
  choices:
16
4
  - id: options
17
5
  pick: 'self.level >= 17 ? 4 : self.level >= 10 ? 3 : 2'
18
- from:
19
- options:
20
- - { id: careful-spell }
21
- - { id: distant-spell }
22
- - { id: empowered-spell }
23
- - { id: extended-spell }
24
- - { id: heightened-spell }
25
- - { id: quickened-spell }
26
- - { id: subtle-spell }
27
- - { id: twinned-spell }
28
- effects:
29
- - { target: sorcery.metamagic, op: set, value: sorcery.left > 0 }
30
- - target: { choices: [metamagic] }
31
- op: option
32
- when: "pick.id == 'careful-spell' && has(action.item.save) && sorcery.left >= 1"
33
- value:
34
- id: careful
35
- flags: { metamagic: "'careful'" }
36
- changes:
37
- - { type: adjustState, entry: self, key: sorceryPointsSpent, by: 1 }
38
- - target: { choices: [metamagic] }
39
- op: option
40
- when: "pick.id == 'distant-spell' && sorcery.left >= 1"
41
- value:
42
- id: distant
43
- flags: { metamagic: "'distant'" }
44
- changes:
45
- - { type: adjustState, entry: self, key: sorceryPointsSpent, by: 1 }
46
- - target: { choices: [metamagic] }
47
- op: option
48
- when: "pick.id == 'empowered-spell' && has(action.item.damage) && sorcery.left >= 1"
49
- value:
50
- id: empowered
51
- flags: { metamagic: "'empowered'" }
52
- changes:
53
- - { type: adjustState, entry: self, key: sorceryPointsSpent, by: 1 }
54
- - target: { choices: [metamagic] }
55
- op: option
56
- when: "pick.id == 'extended-spell' && sorcery.left >= 1"
57
- value:
58
- id: extended
59
- flags: { metamagic: "'extended'" }
60
- changes:
61
- - { type: adjustState, entry: self, key: sorceryPointsSpent, by: 1 }
62
- - target: { choices: [metamagic] }
63
- op: option
64
- when: "pick.id == 'heightened-spell' && has(action.item.save) && sorcery.left >= 3"
65
- value:
66
- id: heightened
67
- flags: { metamagic: "'heightened'" }
68
- changes:
69
- - { type: adjustState, entry: self, key: sorceryPointsSpent, by: 3 }
70
- - target: { choices: [metamagic] }
71
- op: option
72
- when: "pick.id == 'quickened-spell' && sorcery.left >= 2"
73
- value:
74
- id: quickened
75
- flags: { metamagic: "'quickened'" }
76
- changes:
77
- - { type: adjustState, entry: self, key: sorceryPointsSpent, by: 2 }
78
- - target: { choices: [metamagic] }
79
- op: option
80
- when: "pick.id == 'subtle-spell' && sorcery.left >= 1"
81
- value:
82
- id: subtle
83
- flags: { metamagic: "'subtle'" }
84
- changes:
85
- - { type: adjustState, entry: self, key: sorceryPointsSpent, by: 1 }
86
- - target: { choices: [metamagic] }
87
- op: option
88
- when: "pick.id == 'twinned-spell' && sorcery.left >= max(1, action.item.level)"
89
- value:
90
- id: twinned
91
- flags: { metamagic: "'twinned'" }
92
- changes:
93
- - {
94
- type: adjustState,
95
- entry: self,
96
- key: sorceryPointsSpent,
97
- by: 'max(1, action.item.level)',
98
- }
6
+ from: { type: metamagic }
@@ -16,9 +16,9 @@ actions:
16
16
  options:
17
17
  values: [1, 2, 3, 4, 5]
18
18
  where: >-
19
- picks < fieldOf('spellSlots.level{slot}.used', value)
20
- && value + sumList(steps.slots.picked, indexOf(['1', '2', '3', '4', '5'], x) + 1)
21
- <= ceil(self.level / 2)
19
+ countList(steps.slots.values, x == value)
20
+ < fieldOf('spellSlots.level{slot}.used', value)
21
+ && sumList(steps.slots.values, x) + value <= ceil(self.level / 2)
22
22
  repeat: { max: ceil(self.level / 2), min: 1 }
23
23
  prefer: value
24
24
  changes:
@@ -33,4 +33,4 @@ actions:
33
33
  kind: outcome
34
34
  result: "'recovered'"
35
35
  data:
36
- levels: sumList(steps.slots.picked, indexOf(['1', '2', '3', '4', '5'], x) + 1)
36
+ levels: sumList(steps.slots.values, x)
@@ -0,0 +1,4 @@
1
+ id: hunter-tactics.colossus-slayer
2
+ type: hunterTactic
3
+ fields:
4
+ feature: hunters-prey
@@ -0,0 +1,4 @@
1
+ id: hunter-tactics.escape-the-horde
2
+ type: hunterTactic
3
+ fields:
4
+ feature: defensive-tactics
@@ -0,0 +1,6 @@
1
+ id: hunter-tactics.evasion
2
+ type: hunterTactic
3
+ fields:
4
+ feature: superior-hunters-defense
5
+ grants:
6
+ - { item: features.evasion }
@@ -0,0 +1,4 @@
1
+ id: hunter-tactics.giant-killer
2
+ type: hunterTactic
3
+ fields:
4
+ feature: hunters-prey
@@ -0,0 +1,4 @@
1
+ id: hunter-tactics.horde-breaker
2
+ type: hunterTactic
3
+ fields:
4
+ feature: hunters-prey
@@ -0,0 +1,4 @@
1
+ id: hunter-tactics.multiattack-defense
2
+ type: hunterTactic
3
+ fields:
4
+ feature: defensive-tactics
@@ -0,0 +1,4 @@
1
+ id: hunter-tactics.stand-against-the-tide
2
+ type: hunterTactic
3
+ fields:
4
+ feature: superior-hunters-defense
@@ -0,0 +1,4 @@
1
+ id: hunter-tactics.steel-will
2
+ type: hunterTactic
3
+ fields:
4
+ feature: defensive-tactics
@@ -0,0 +1,6 @@
1
+ id: hunter-tactics.uncanny-dodge
2
+ type: hunterTactic
3
+ fields:
4
+ feature: superior-hunters-defense
5
+ grants:
6
+ - { item: features.rogue.uncanny-dodge }
@@ -0,0 +1,6 @@
1
+ id: hunter-tactics.volley
2
+ type: hunterTactic
3
+ fields:
4
+ feature: multiattack
5
+ grants:
6
+ - { item: features.ranger.volley }
@@ -0,0 +1,6 @@
1
+ id: hunter-tactics.whirlwind-attack
2
+ type: hunterTactic
3
+ fields:
4
+ feature: multiattack
5
+ grants:
6
+ - { item: features.ranger.whirlwind-attack }