@opencharacter/orc-sf-2e 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 (91) hide show
  1. package/README.md +54 -5
  2. package/content/classes/envoy.yaml +2 -52
  3. package/content/classes/mystic/connections/akashic.yaml +1 -1
  4. package/content/classes/mystic/connections/elemental.yaml +62 -1
  5. package/content/classes/mystic/connections/healing.yaml +1 -1
  6. package/content/classes/mystic/connections/rhythm.yaml +1 -1
  7. package/content/classes/mystic/connections/shadow.yaml +1 -1
  8. package/content/classes/mystic.yaml +2 -51
  9. package/content/classes/operative.yaml +1 -44
  10. package/content/classes/solarian.yaml +1 -44
  11. package/content/classes/soldier.yaml +2 -51
  12. package/content/classes/witchwarper/anchors/core-memories.yaml +1 -1
  13. package/content/classes/witchwarper/anchors/focal-point.yaml +1 -1
  14. package/content/classes/witchwarper/anchors/tangible-object.yaml +1 -1
  15. package/content/classes/witchwarper/paradoxes/analyst.yaml +1 -1
  16. package/content/classes/witchwarper/paradoxes/anomaly.yaml +1 -1
  17. package/content/classes/witchwarper/paradoxes/lost-history.yaml +1 -1
  18. package/content/classes/witchwarper/paradoxes/precog.yaml +1 -1
  19. package/content/classes/witchwarper.yaml +3 -55
  20. package/content/effects/treated-disease.yaml +4 -0
  21. package/content/effects/treated-poison.yaml +4 -0
  22. package/content/feats/ancestry/fixation.yaml +11 -49
  23. package/content/feats/ancestry/harmonic-sensitivity.yaml +16 -6
  24. package/content/feats/ancestry/lashunta-lore.yaml +6 -0
  25. package/content/feats/archetype/envoy/envoy-dedication.yaml +2 -88
  26. package/content/feats/mystic/new-epiphany.yaml +1 -1
  27. package/content/feats/mystic/realized-epiphany.yaml +1 -1
  28. package/content/feats/mystic/syncretic-epiphany.yaml +1 -1
  29. package/content/feats/skill/additional-lore.yaml +54 -391
  30. package/content/feats/skill/assurance.yaml +3 -57
  31. package/content/feats/skill/skill-training.yaml +1 -57
  32. package/content/features/envoy/style/from-the-front.yaml +1 -1
  33. package/content/features/envoy/style/from-the-shadows.yaml +1 -1
  34. package/content/features/envoy/style/guns-blazing.yaml +1 -1
  35. package/content/features/envoy/style/in-the-spotlight.yaml +1 -1
  36. package/content/features/envoy/style/infosphere-director.yaml +1 -1
  37. package/content/features/envoy/style/through-desperate-times.yaml +1 -1
  38. package/content/features/soldier/style/action-hero.yaml +1 -1
  39. package/content/features/soldier/style/armor-storm.yaml +1 -1
  40. package/content/features/soldier/style/bombard.yaml +1 -1
  41. package/content/features/soldier/style/close-quarters.yaml +1 -1
  42. package/content/features/soldier/style/erudite-warrior.yaml +1 -1
  43. package/content/gear/comm-unit.yaml +1 -0
  44. package/content/spells/elemental-barrier.yaml +2 -1
  45. package/content/spells/elemental-weapon.yaml +10 -1
  46. package/content/spells/guidance.yaml +2 -0
  47. package/content/spells/sure-strike.yaml +8 -1
  48. package/content/spells/true-target.yaml +2 -0
  49. package/content/templates/elemental/air.yaml +6 -0
  50. package/content/templates/elemental/earth.yaml +6 -0
  51. package/content/templates/elemental/fire.yaml +6 -0
  52. package/content/templates/elemental/metal.yaml +6 -0
  53. package/content/templates/elemental/water.yaml +6 -0
  54. package/content/templates/elemental/wood.yaml +6 -0
  55. package/dist/i18n/en.js +1 -1
  56. package/dist/i18n/en.json +50 -59
  57. package/dist/index.js +1 -1
  58. package/dist/release.json +5419 -3339
  59. package/i18n/en/ancestry-feats.yaml +4 -40
  60. package/i18n/en/archetypes.yaml +2 -2
  61. package/i18n/en/core.yaml +8 -2
  62. package/i18n/en/headline.yaml +4 -0
  63. package/i18n/en/mystic.yaml +12 -0
  64. package/i18n/en/sf-core.yaml +0 -11
  65. package/i18n/en/skills.yaml +6 -3
  66. package/i18n/en/tags.yaml +2 -0
  67. package/i18n/en/types.yaml +1 -0
  68. package/i18n/en.yaml +14 -1
  69. package/pack.yaml +2 -2
  70. package/package.json +2 -2
  71. package/rules/advancement.yaml +1 -0
  72. package/rules/afflictions.yaml +4 -5
  73. package/rules/archetypes.yaml +1 -0
  74. package/rules/building.yaml +7 -1
  75. package/rules/checks.yaml +1 -1
  76. package/rules/conditions.yaml +1 -0
  77. package/rules/core.yaml +1 -0
  78. package/rules/creation.yaml +18 -0
  79. package/rules/equipment.yaml +7 -2
  80. package/rules/heritages.yaml +1 -1
  81. package/rules/layout.yaml +62 -4
  82. package/rules/mystic.yaml +24 -1
  83. package/rules/skill-actions-stealth.yaml +1 -1
  84. package/rules/skills.yaml +254 -81
  85. package/rules/solarian.yaml +1 -2
  86. package/rules/spellcasting.yaml +89 -21
  87. package/rules/spells-high.yaml +3 -3
  88. package/rules/strikes.yaml +3 -1
  89. package/rules/tags.yaml +6 -0
  90. package/rules/witchwarper.yaml +7 -7
  91. package/upgrades/0.2.0-to-0.3.0.yaml +12 -0
package/README.md CHANGED
@@ -14,6 +14,9 @@ cast spells, use skill actions, and buy, sell, implant and upgrade equipment. Th
14
14
  pnpm add @opencharacter/engine @opencharacter/orc-sf-2e
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: 'orc-sf-2e', version: '0.2.0' }],
36
+ packs: [{ id: 'orc-sf-2e', version: '0.3.0' }],
34
37
  creating: true,
35
38
  };
36
39
  const created = startAction(ruleset, blank, {
@@ -84,6 +87,45 @@ offer fantasy content. The format can hide a dependency's content only item by i
84
87
  would still be in the ruleset. Where the two books print the same rule or item, this pack's
85
88
  copy has the same shape as `orc-2e`'s, and the same text where the wording matches.
86
89
 
90
+ ## Add-on packs
91
+
92
+ A pack that depends on `orc-sf-2e` can add to what it offers:
93
+
94
+ - **Subclasses:** a feature whose `classOption` names a class's choice (`envoy.leadership-style`,
95
+ `mystic.connection`, `soldier.fighting-style`, `witchwarper.paradox`, `witchwarper.anchor`)
96
+ joins it, and gear tagged `tool.compass` counts for Sense Direction.
97
+ - **Open enums** (`extendEnums`): `mystic.connection` and `witchwarper.paradox`, which a new
98
+ connection or paradox sets with its own effect, as the core's do; weapon `group`,
99
+ `damageType` and `ammoKind`, ammunition `kind`, armor `group`, consumable `category`,
100
+ `damageType` and `persistentType`, spell damage types, affliction and persistent damage
101
+ condition damage types, feat `category`, and `cast-spell`'s `damageType` parameter
102
+ (`orc-sf-2e:actions.cast-spell.params.damageType`). A new damage type or group also needs its tag,
103
+ declared and named in the add-on.
104
+ - **Choices** (`extendChoices`): written value and inline option choices take additions: the
105
+ operative's `specialization`, the epiphany feats' `spell` (Basic, New, Advanced, Greater and
106
+ Syncretic Epiphany), Additional Lore's `lore`, and the short skill lists. A new connection's
107
+ epiphany counts for New Epiphany, Syncretic Epiphany and Realized Epiphany through rules
108
+ effects on `mystic.otherExpertConnections`, `mystic.otherMasterEpiphanies` and
109
+ `mystic.connectionRank`.
110
+ - **Naming what an add-on adds:** it names each added value, option or key in its own text,
111
+ under the key this pack would use, and `createText` finds it there when the app passes the
112
+ ruleset's `enumOrigins`, `optionOrigins` and `familyOrigins`. For example,
113
+ `void` added to `orc-sf-2e:mystic.connection` is
114
+ `fields.mystic.connection.values.void.name: Void` (through `enumOrigins`), and a Specialized
115
+ Operative option `saboteur` is
116
+ `feats.archetype.operative.specialized-operative.choices.specialization.options.saboteur.name: Saboteur`
117
+ (through `optionOrigins`).
118
+ - **Skills and Lores:** a choice of any skill reads `skills.offered` and one of any Lore
119
+ `skills.lores`; an add-on's Lore declares its fields (`skills.lore.<name>.rank`, `.mod`, …,
120
+ as `rules/skills.yaml` does) and grants its tag into both with a rules effect.
121
+ - **Step tags** for rules-level `option` and `changes` effects: `creation.ancestry`,
122
+ `creation.heritage`, `creation.background`, `creation.class` and `creation.finish` (guided and
123
+ random creation), `level-up.gain`, and the actions' own (`strike.hit`, …).
124
+
125
+ Still closed: attributes, proficiency ranks, saves, spell traditions, weapon and armor
126
+ categories, the solarian's attunement and physical damage types for `versatile`, the game's
127
+ fixed sets.
128
+
87
129
  ## License
88
130
 
89
131
  - **License:** the ORC License. Its four notices (Article III) are in the manifest, which apps
@@ -198,7 +240,8 @@ Where the book leaves a rule open, or the format needs a choice the book doesn't
198
240
  reads it as below. These are the pack's provisional calls; a table may rule otherwise.
199
241
 
200
242
  - **Random start:** the book has players choose, so the odds are the pack's, as in `orc-2e`:
201
- each pick is drawn uniformly among the options eligible then, in the guided start's order, and
243
+ each pick is drawn uniformly among the options eligible then, in the guided start's order
244
+ (except that the free boosts follow the class's picks, once the key attribute is known), and
202
245
  boosts follow the planned key attribute, then Constitution, Dexterity, Wisdom, Strength,
203
246
  Intelligence and Charisma.
204
247
  - **Specialized Skill Set:** a slot can find no eligible feat (the specialization's skill has few
@@ -212,7 +255,11 @@ reads it as below. These are the pack's provisional calls; a table may rule othe
212
255
  - **Mystic:** Transfer Vitality moves as many Hit Points as the target is missing, up to the
213
256
  limit and what the network holds, unless the player gives an amount; the mystic archetype's
214
257
  network regains Hit Points each turn and on Refocus as the class's does; the rhythm
215
- connection's 9th-rank spell (_unfathomable song_) is the fantasy core's.
258
+ connection's 9th-rank spell (_unfathomable song_) is the fantasy core's. Elemental weapon and
259
+ elemental barrier are applied to the caster with their element (Cast a Spell's `element`), the
260
+ record of the active spell; what they give the target is text. While one is active, the
261
+ elemental connection's wall of fire and absolute zero take its element's trait and first damage
262
+ type (electricity, bludgeoning, fire, acid, cold, poison), a kept template per element.
216
263
  - **Witchwarper:** the spellcasting attribute is the key attribute chosen; Core Memories'
217
264
  Assurance skill and In Another Life's ancestry feat are set by an action and kept until the
218
265
  player sets them again (the book's "during daily preparations").
@@ -231,7 +278,9 @@ reads it as below. These are the pack's provisional calls; a table may rule othe
231
278
  - **Left to the app:** turns (it runs `start-turn` and `end-turn`), movement, reach, distances,
232
279
  areas and auras (who is in a burst, a quantum field, a harmony's emanation or a bond's range is
233
280
  the participants the app passes), cover and flanking (situational choices), when a condition
234
- is gained, daily preparations and rests, a spell's duration and sustaining.
281
+ is gained, daily preparations and rests, a spell's duration and sustaining (a spell or
282
+ treatment for the next roll, such as guidance, sure strike or Treat Poison, ends on the roll it
283
+ changes).
235
284
  - **Text only:** critical specialization; the feats and features about movement, positions,
236
285
  other creatures' sheets, starships and drones; most harmony and quantum field effects; skill
237
286
  feats that change time or what the GM tells you; more than half the spells (utility,
@@ -53,62 +53,12 @@ choices:
53
53
  when: '!(pick.value in skills.chosen)'
54
54
  - { target: skills.trainings, op: add, value: 1 }
55
55
  - id: leadership-style
56
- from:
57
- items:
58
- - features.envoy.style.from-the-front
59
- - features.envoy.style.from-the-shadows
60
- - features.envoy.style.guns-blazing
61
- - features.envoy.style.in-the-spotlight
62
- - features.envoy.style.infosphere-director
63
- - features.envoy.style.through-desperate-times
56
+ from: { type: feature, where: "item.classOption == 'envoy.leadership-style'" }
64
57
  - id: skills
65
58
  unique: skill-training
66
59
  pick: '6 + max(0, attributes.int.mod)'
67
60
  from:
68
- values:
69
- - skill.acrobatics
70
- - skill.arcana
71
- - skill.athletics
72
- - skill.computers
73
- - skill.crafting
74
- - skill.deception
75
- - skill.diplomacy
76
- - skill.intimidation
77
- - skill.medicine
78
- - skill.nature
79
- - skill.occultism
80
- - skill.performance
81
- - skill.piloting
82
- - skill.religion
83
- - skill.society
84
- - skill.stealth
85
- - skill.survival
86
- - skill.thievery
87
- - skill.lore.academia
88
- - skill.lore.alcohol
89
- - skill.lore.animal
90
- - skill.lore.art
91
- - skill.lore.augmentation
92
- - skill.lore.business
93
- - skill.lore.cooking
94
- - skill.lore.corporate
95
- - skill.lore.games
96
- - skill.lore.genealogy
97
- - skill.lore.history
98
- - skill.lore.hyperspace
99
- - skill.lore.infosphere
100
- - skill.lore.labor
101
- - skill.lore.legal
102
- - skill.lore.life-science
103
- - skill.lore.media
104
- - skill.lore.mining
105
- - skill.lore.physical-science
106
- - skill.lore.piracy
107
- - skill.lore.plant
108
- - skill.lore.sports
109
- - skill.lore.underworld
110
- - skill.lore.vidgame
111
- - skill.lore.warfare
61
+ values: { formula: skills.offered }
112
62
  where: '!(value in skills.trained) && !(value in skills.chosen) || value in choice.picks'
113
63
  effects: [{ target: skills.chosen, op: grant, value: { formula: pick.value } }]
114
64
  - id: class-feat
@@ -1,6 +1,6 @@
1
1
  id: classes.mystic.connections.akashic
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: mystic.connection }
4
4
  effects:
5
5
  - { target: mystic.connection, op: set, value: "'akashic'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'occult'" }
@@ -1,6 +1,6 @@
1
1
  id: classes.mystic.connections.elemental
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: mystic.connection }
4
4
  effects:
5
5
  - { target: mystic.connection, op: set, value: "'elemental'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'primal'" }
@@ -100,3 +100,64 @@ grants:
100
100
  - { item: spells.falling-stars, when: 'level >= 17' }
101
101
  - { item: spells.elemental-weapon }
102
102
  - { item: feats.general.shield-block, waivePrerequisites: true }
103
+ keepsTemplates:
104
+ - template: templates.elemental.air
105
+ content:
106
+ type: spell
107
+ where: item.id == @spells.wall-of-fire || item.id == @spells.absolute-zero
108
+ when: >-
109
+ countList(character.applied, x.active
110
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier)) > 0
111
+ && filterList(character.applied, x.active
112
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier))[0]
113
+ .state.element == 'air'
114
+ - template: templates.elemental.earth
115
+ content:
116
+ type: spell
117
+ where: item.id == @spells.wall-of-fire || item.id == @spells.absolute-zero
118
+ when: >-
119
+ countList(character.applied, x.active
120
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier)) > 0
121
+ && filterList(character.applied, x.active
122
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier))[0]
123
+ .state.element == 'earth'
124
+ - template: templates.elemental.fire
125
+ content:
126
+ type: spell
127
+ where: item.id == @spells.wall-of-fire || item.id == @spells.absolute-zero
128
+ when: >-
129
+ countList(character.applied, x.active
130
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier)) > 0
131
+ && filterList(character.applied, x.active
132
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier))[0]
133
+ .state.element == 'fire'
134
+ - template: templates.elemental.metal
135
+ content:
136
+ type: spell
137
+ where: item.id == @spells.wall-of-fire || item.id == @spells.absolute-zero
138
+ when: >-
139
+ countList(character.applied, x.active
140
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier)) > 0
141
+ && filterList(character.applied, x.active
142
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier))[0]
143
+ .state.element == 'metal'
144
+ - template: templates.elemental.water
145
+ content:
146
+ type: spell
147
+ where: item.id == @spells.wall-of-fire || item.id == @spells.absolute-zero
148
+ when: >-
149
+ countList(character.applied, x.active
150
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier)) > 0
151
+ && filterList(character.applied, x.active
152
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier))[0]
153
+ .state.element == 'water'
154
+ - template: templates.elemental.wood
155
+ content:
156
+ type: spell
157
+ where: item.id == @spells.wall-of-fire || item.id == @spells.absolute-zero
158
+ when: >-
159
+ countList(character.applied, x.active
160
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier)) > 0
161
+ && filterList(character.applied, x.active
162
+ && (x.source == @spells.elemental-weapon || x.source == @spells.elemental-barrier))[0]
163
+ .state.element == 'wood'
@@ -1,6 +1,6 @@
1
1
  id: classes.mystic.connections.healing
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: mystic.connection }
4
4
  effects:
5
5
  - { target: mystic.connection, op: set, value: "'healing'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'divine'" }
@@ -1,6 +1,6 @@
1
1
  id: classes.mystic.connections.rhythm
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: mystic.connection }
4
4
  effects:
5
5
  - { target: mystic.connection, op: set, value: "'rhythm'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'primal'" }
@@ -1,6 +1,6 @@
1
1
  id: classes.mystic.connections.shadow
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: mystic.connection }
4
4
  effects:
5
5
  - { target: mystic.connection, op: set, value: "'shadow'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'divine'" }
@@ -42,61 +42,12 @@ grants:
42
42
  - { item: features.mystic.transcendence, when: 'level >= 19' }
43
43
  choices:
44
44
  - id: connection
45
- from:
46
- items:
47
- - classes.mystic.connections.akashic
48
- - classes.mystic.connections.elemental
49
- - classes.mystic.connections.healing
50
- - classes.mystic.connections.rhythm
51
- - classes.mystic.connections.shadow
45
+ from: { type: feature, where: "item.classOption == 'mystic.connection'" }
52
46
  - id: skills
53
47
  unique: skill-training
54
48
  pick: '3 + max(0, attributes.int.mod)'
55
49
  from:
56
- values:
57
- - skill.acrobatics
58
- - skill.arcana
59
- - skill.athletics
60
- - skill.computers
61
- - skill.crafting
62
- - skill.deception
63
- - skill.diplomacy
64
- - skill.intimidation
65
- - skill.medicine
66
- - skill.nature
67
- - skill.occultism
68
- - skill.performance
69
- - skill.piloting
70
- - skill.religion
71
- - skill.society
72
- - skill.stealth
73
- - skill.survival
74
- - skill.thievery
75
- - skill.lore.academia
76
- - skill.lore.alcohol
77
- - skill.lore.animal
78
- - skill.lore.art
79
- - skill.lore.augmentation
80
- - skill.lore.business
81
- - skill.lore.cooking
82
- - skill.lore.corporate
83
- - skill.lore.games
84
- - skill.lore.genealogy
85
- - skill.lore.history
86
- - skill.lore.hyperspace
87
- - skill.lore.infosphere
88
- - skill.lore.labor
89
- - skill.lore.legal
90
- - skill.lore.life-science
91
- - skill.lore.media
92
- - skill.lore.mining
93
- - skill.lore.physical-science
94
- - skill.lore.piracy
95
- - skill.lore.plant
96
- - skill.lore.sports
97
- - skill.lore.underworld
98
- - skill.lore.vidgame
99
- - skill.lore.warfare
50
+ values: { formula: skills.offered }
100
51
  where: '!(value in skills.trained) && !(value in skills.chosen) || value in choice.picks'
101
52
  effects: [{ target: skills.chosen, op: grant, value: { formula: pick.value } }]
102
53
  - id: class-feat
@@ -144,50 +144,7 @@ choices:
144
144
  unique: skill-training
145
145
  pick: '3 + max(0, attributes.int.mod)'
146
146
  from:
147
- values:
148
- - skill.acrobatics
149
- - skill.arcana
150
- - skill.athletics
151
- - skill.computers
152
- - skill.crafting
153
- - skill.deception
154
- - skill.diplomacy
155
- - skill.intimidation
156
- - skill.medicine
157
- - skill.nature
158
- - skill.occultism
159
- - skill.performance
160
- - skill.piloting
161
- - skill.religion
162
- - skill.society
163
- - skill.stealth
164
- - skill.survival
165
- - skill.thievery
166
- - skill.lore.academia
167
- - skill.lore.alcohol
168
- - skill.lore.animal
169
- - skill.lore.art
170
- - skill.lore.augmentation
171
- - skill.lore.business
172
- - skill.lore.cooking
173
- - skill.lore.corporate
174
- - skill.lore.games
175
- - skill.lore.genealogy
176
- - skill.lore.history
177
- - skill.lore.hyperspace
178
- - skill.lore.infosphere
179
- - skill.lore.labor
180
- - skill.lore.legal
181
- - skill.lore.life-science
182
- - skill.lore.media
183
- - skill.lore.mining
184
- - skill.lore.physical-science
185
- - skill.lore.piracy
186
- - skill.lore.plant
187
- - skill.lore.sports
188
- - skill.lore.underworld
189
- - skill.lore.vidgame
190
- - skill.lore.warfare
147
+ values: { formula: skills.offered }
191
148
  where: '!(value in skills.trained) && !(value in skills.chosen) || value in choice.picks'
192
149
  effects: [{ target: skills.chosen, op: grant, value: { formula: pick.value } }]
193
150
  - id: class-feat
@@ -53,50 +53,7 @@ choices:
53
53
  unique: skill-training
54
54
  pick: '4 + max(0, attributes.int.mod)'
55
55
  from:
56
- values:
57
- - skill.acrobatics
58
- - skill.arcana
59
- - skill.athletics
60
- - skill.computers
61
- - skill.crafting
62
- - skill.deception
63
- - skill.diplomacy
64
- - skill.intimidation
65
- - skill.medicine
66
- - skill.nature
67
- - skill.occultism
68
- - skill.performance
69
- - skill.piloting
70
- - skill.religion
71
- - skill.society
72
- - skill.stealth
73
- - skill.survival
74
- - skill.thievery
75
- - skill.lore.academia
76
- - skill.lore.alcohol
77
- - skill.lore.animal
78
- - skill.lore.art
79
- - skill.lore.augmentation
80
- - skill.lore.business
81
- - skill.lore.cooking
82
- - skill.lore.corporate
83
- - skill.lore.games
84
- - skill.lore.genealogy
85
- - skill.lore.history
86
- - skill.lore.hyperspace
87
- - skill.lore.infosphere
88
- - skill.lore.labor
89
- - skill.lore.legal
90
- - skill.lore.life-science
91
- - skill.lore.media
92
- - skill.lore.mining
93
- - skill.lore.physical-science
94
- - skill.lore.piracy
95
- - skill.lore.plant
96
- - skill.lore.sports
97
- - skill.lore.underworld
98
- - skill.lore.vidgame
99
- - skill.lore.warfare
56
+ values: { formula: skills.offered }
100
57
  where: '!(value in skills.trained) && !(value in skills.chosen) || value in choice.picks'
101
58
  effects: [{ target: skills.chosen, op: grant, value: { formula: pick.value } }]
102
59
  - id: class-feat
@@ -43,61 +43,12 @@ grants:
43
43
  - { item: features.soldier.legendary-soldier, when: 'level >= 19' }
44
44
  choices:
45
45
  - id: fighting-style
46
- from:
47
- items:
48
- - features.soldier.style.action-hero
49
- - features.soldier.style.armor-storm
50
- - features.soldier.style.bombard
51
- - features.soldier.style.close-quarters
52
- - features.soldier.style.erudite-warrior
46
+ from: { type: feature, where: "item.classOption == 'soldier.fighting-style'" }
53
47
  - id: skills
54
48
  unique: skill-training
55
49
  pick: '3 + max(0, attributes.int.mod)'
56
50
  from:
57
- values:
58
- - skill.acrobatics
59
- - skill.arcana
60
- - skill.athletics
61
- - skill.computers
62
- - skill.crafting
63
- - skill.deception
64
- - skill.diplomacy
65
- - skill.intimidation
66
- - skill.medicine
67
- - skill.nature
68
- - skill.occultism
69
- - skill.performance
70
- - skill.piloting
71
- - skill.religion
72
- - skill.society
73
- - skill.stealth
74
- - skill.survival
75
- - skill.thievery
76
- - skill.lore.academia
77
- - skill.lore.alcohol
78
- - skill.lore.animal
79
- - skill.lore.art
80
- - skill.lore.augmentation
81
- - skill.lore.business
82
- - skill.lore.cooking
83
- - skill.lore.corporate
84
- - skill.lore.games
85
- - skill.lore.genealogy
86
- - skill.lore.history
87
- - skill.lore.hyperspace
88
- - skill.lore.infosphere
89
- - skill.lore.labor
90
- - skill.lore.legal
91
- - skill.lore.life-science
92
- - skill.lore.media
93
- - skill.lore.mining
94
- - skill.lore.physical-science
95
- - skill.lore.piracy
96
- - skill.lore.plant
97
- - skill.lore.sports
98
- - skill.lore.underworld
99
- - skill.lore.vidgame
100
- - skill.lore.warfare
51
+ values: { formula: skills.offered }
101
52
  where: '!(value in skills.trained) && !(value in skills.chosen) || value in choice.picks'
102
53
  effects: [{ target: skills.chosen, op: grant, value: { formula: pick.value } }]
103
54
  - id: class-feat
@@ -1,6 +1,6 @@
1
1
  id: classes.witchwarper.anchors.core-memories
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: witchwarper.anchor }
4
4
  state: { used: { type: boolean, default: false } }
5
5
  effects:
6
6
  - target: { steps: [turn.start] }
@@ -1,6 +1,6 @@
1
1
  id: classes.witchwarper.anchors.focal-point
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: witchwarper.anchor }
4
4
  state: { used: { type: boolean, default: false } }
5
5
  effects:
6
6
  - target: { steps: [turn.start] }
@@ -1,6 +1,6 @@
1
1
  id: classes.witchwarper.anchors.tangible-object
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: witchwarper.anchor }
4
4
  state: { used: { type: boolean, default: false } }
5
5
  effects:
6
6
  - target: { steps: [turn.start] }
@@ -1,6 +1,6 @@
1
1
  id: classes.witchwarper.paradoxes.analyst
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: witchwarper.paradox }
4
4
  effects:
5
5
  - { target: witchwarper.paradox, op: set, value: "'analyst'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'arcane'" }
@@ -1,6 +1,6 @@
1
1
  id: classes.witchwarper.paradoxes.anomaly
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: witchwarper.paradox }
4
4
  effects:
5
5
  - { target: witchwarper.paradox, op: set, value: "'anomaly'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'arcane'" }
@@ -1,6 +1,6 @@
1
1
  id: classes.witchwarper.paradoxes.lost-history
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: witchwarper.paradox }
4
4
  effects:
5
5
  - { target: witchwarper.paradox, op: set, value: "'lost-history'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'occult'" }
@@ -1,6 +1,6 @@
1
1
  id: classes.witchwarper.paradoxes.precog
2
2
  type: feature
3
- fields: { level: 1 }
3
+ fields: { level: 1, classOption: witchwarper.paradox }
4
4
  effects:
5
5
  - { target: witchwarper.paradox, op: set, value: "'precog'" }
6
6
  - { target: spellcasting.tradition, op: set, value: "'occult'" }
@@ -50,66 +50,14 @@ choices:
50
50
  - { target: attributes.int.boosts, op: add, value: 1 }
51
51
  - { target: class.keyAttribute, op: set, value: "'int'" }
52
52
  - id: paradox
53
- from:
54
- items:
55
- - classes.witchwarper.paradoxes.analyst
56
- - classes.witchwarper.paradoxes.anomaly
57
- - classes.witchwarper.paradoxes.lost-history
58
- - classes.witchwarper.paradoxes.precog
53
+ from: { type: feature, where: "item.classOption == 'witchwarper.paradox'" }
59
54
  - id: anchor
60
- from:
61
- items:
62
- - classes.witchwarper.anchors.core-memories
63
- - classes.witchwarper.anchors.focal-point
64
- - classes.witchwarper.anchors.tangible-object
55
+ from: { type: feature, where: "item.classOption == 'witchwarper.anchor'" }
65
56
  - id: skills
66
57
  unique: skill-training
67
58
  pick: '3 + max(0, attributes.int.mod)'
68
59
  from:
69
- values:
70
- - skill.acrobatics
71
- - skill.arcana
72
- - skill.athletics
73
- - skill.computers
74
- - skill.crafting
75
- - skill.deception
76
- - skill.diplomacy
77
- - skill.intimidation
78
- - skill.medicine
79
- - skill.nature
80
- - skill.occultism
81
- - skill.performance
82
- - skill.piloting
83
- - skill.religion
84
- - skill.society
85
- - skill.stealth
86
- - skill.survival
87
- - skill.thievery
88
- - skill.lore.academia
89
- - skill.lore.alcohol
90
- - skill.lore.animal
91
- - skill.lore.art
92
- - skill.lore.augmentation
93
- - skill.lore.business
94
- - skill.lore.cooking
95
- - skill.lore.corporate
96
- - skill.lore.games
97
- - skill.lore.genealogy
98
- - skill.lore.history
99
- - skill.lore.hyperspace
100
- - skill.lore.infosphere
101
- - skill.lore.labor
102
- - skill.lore.legal
103
- - skill.lore.life-science
104
- - skill.lore.media
105
- - skill.lore.mining
106
- - skill.lore.physical-science
107
- - skill.lore.piracy
108
- - skill.lore.plant
109
- - skill.lore.sports
110
- - skill.lore.underworld
111
- - skill.lore.vidgame
112
- - skill.lore.warfare
60
+ values: { formula: skills.offered }
113
61
  where: '!(value in skills.trained) && !(value in skills.chosen) || value in choice.picks'
114
62
  effects: [{ target: skills.chosen, op: grant, value: { formula: pick.value } }]
115
63
  - id: class-feat
@@ -10,12 +10,16 @@ effects:
10
10
  stackKey: circumstance-bonus
11
11
  when: situational.againstDisease && self.bonus > 0
12
12
  scope: applied
13
+ then:
14
+ - { type: removeEffect, entry: self }
13
15
  - target: { rolls: [save] }
14
16
  op: add
15
17
  value: self.bonus
16
18
  stackKey: circumstance-penalty
17
19
  when: situational.againstDisease && self.bonus < 0
18
20
  scope: applied
21
+ then:
22
+ - { type: removeEffect, entry: self }
19
23
  - target: { rolls: [save], tally: successToCrit }
20
24
  op: add
21
25
  value: 1