@opencharacter/cwn-srd 0.1.0 → 0.2.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.
@@ -49,6 +49,7 @@ cyberware.funes-complex.description: 'A synthetic eidetic memory is granted by t
49
49
  cyberware.medusa-implant.name: 'Medusa Implant'
50
50
  cyberware.medusa-implant.description: 'These prehensile cranial tendrils take multiple forms, from thick armored cables to bundles of brightly-colored articulated polymer fibers not unlike normal hair. The tendrils are shoulder-length under most circumstances, but can extend to manipulate objects up to three meters distant with the agility of a human hand. The bundles are not very strong, however, and cannot lift more than ten kilograms. Like other extra limbs, they do not grant extra actions, but can hold and use items as any other limb could.'
51
51
  cyberware.neural-buffer.name: 'Neural Buffer'
52
+ cyberware.neural-buffer.state.bufferUsed.name: 'Buffer absorbed'
52
53
  cyberware.neural-buffer.description: 'A system favored by hackers, a Neural Buffer rearranges the user’s brain topography, making it more difficult to harm the user with neural feedback. The user gains an additional 3 hit points per level that can only absorb cyberspace damage from Stun or Kill Verbs. These phantom hit points refresh completely each hour.'
53
54
  cyberware.skull-citadel.name: 'Skull Citadel'
54
55
  cyberware.skull-citadel.description: 'The user’s head is augmented with independent blood oxygenation pumps, armor plating, and trauma buffers designed to keep the brain intact even after the rest of the body is critically damaged. Barring dismemberment or the use of high-powered ammunition directly on the target’s head, the subject ignores head-affecting Major Injuries and can be stabilized even as long as ten minutes after their technical “death”. Each such delayed revivification permanently reduces a randomly-chosen attribute by 2 points, however. This ability damage cannot be undone.'
package/i18n/en.yaml CHANGED
@@ -45,7 +45,7 @@ fields.attributes.cha.mod.short: 'Cha'
45
45
  fields.attributes.cha.base.name: 'Charisma (rolled)'
46
46
  tags.attr.cha.name: 'Charisma'
47
47
  fields.attributes.modTotal.name: 'Modifier total'
48
- fields.attributes.modTotal.description: 'The six modifiers summed, for the Underdog Rule.'
48
+ fields.attributes.modTotal.description: 'The modifiers of the six rolled scores summed, before Edges, Foci and cyber, for the Underdog Rule.'
49
49
  fields.skills.administer.level.name: 'Administer'
50
50
  fields.skills.administer.base.name: 'Administer (trained)'
51
51
  fields.skills.administer.credit.name: 'Administer skill point credit'
@@ -254,13 +254,17 @@ fields.hacking.programming.used.name: 'Programs written'
254
254
  fields.magic.cyberPenalty.name: 'Cyberware penalty to magic'
255
255
  fields.effort.mage.max.name: 'Mage Effort'
256
256
  fields.effort.mage.scene.name: 'Mage Effort committed for the scene'
257
+ fields.effort.mage.scene.short: 'Mage scene'
257
258
  fields.effort.mage.day.name: 'Mage Effort committed for the day'
259
+ fields.effort.mage.day.short: 'Mage day'
258
260
  fields.effort.mage.current.name: 'Mage Effort left'
259
261
  fields.spells.preparedMax.name: 'Spells prepared allowed'
260
262
  fields.spells.prepared.name: 'Spells prepared'
261
263
  fields.effort.summoner.max.name: 'Summoner Effort'
262
264
  fields.effort.summoner.scene.name: 'Summoner Effort committed for the scene'
265
+ fields.effort.summoner.scene.short: 'Summoner scene'
263
266
  fields.effort.summoner.day.name: 'Summoner Effort committed for the day'
267
+ fields.effort.summoner.day.short: 'Summoner day'
264
268
  fields.effort.summoner.current.name: 'Summoner Effort left'
265
269
  fields.arts.points.name: 'Art points'
266
270
  fields.arts.spent.name: 'Art points spent'
@@ -303,10 +307,10 @@ groups.campaign.label: 'Campaign options'
303
307
  groups.checks.label: 'Checks and saves'
304
308
  groups.attacks.label: 'Attacks'
305
309
  groups.combat-actions.label: 'In a fight'
306
- groups.hacking-actions.label: 'Hacking'
307
- groups.magic-actions.label: 'Magic'
310
+ groups.hacking-actions.label: 'Programs'
311
+ groups.magic-actions.label: 'Spells and spirits'
308
312
  groups.rests.label: 'Rest and recovery'
309
- groups.advancement-actions.label: 'Advancement'
313
+ groups.advancement-actions.label: 'Level up'
310
314
  groups.creation.label: 'Character creation'
311
315
  groups.background.label: 'Background'
312
316
  groups.edges.label: 'Edges'
@@ -481,6 +485,8 @@ types.art.name: 'Graced art'
481
485
  types.art.fields.cost.name: 'Art points'
482
486
  types.spirit.name: 'Spirit'
483
487
  types.spirit.computed.cost.name: 'Summoning Effort'
488
+ types.spirit.fields.powerCount.name: 'Spirit powers'
489
+ types.spirit.fields.powerCount.description: 'How many powers a spirit without a powers pick has'
484
490
  types.spiritPower.name: 'Spirit power'
485
491
  types.spiritPower.fields.minLevel.name: 'Minimum level'
486
492
  types.spiritPower.fields.physicalOnly.name: 'Physical form only'
@@ -1039,10 +1045,13 @@ actions.initiative.name: 'Initiative'
1039
1045
  actions.initiative.results.rolled.name: 'Rolled'
1040
1046
  actions.initiative.steps.roll.name: 'Initiative'
1041
1047
  actions.end-scene.name: 'End of the scene'
1048
+ actions.end-scene.results.ended.name: 'Scene ended'
1042
1049
  actions.end-scene.description: 'Damage Soak and deck Shielding refresh, and Effort Committed for the scene returns.'
1043
1050
  actions.rest.name: 'Night’s rest'
1051
+ actions.rest.results.rested.name: 'Rested'
1044
1052
  actions.rest.description: 'Hit points equal to the level (not while Frail), one System Strain, Effort Committed for the day and the day’s Access.'
1045
1053
  actions.first-aid.name: 'First aid'
1054
+ actions.first-aid.results.healed.name: 'Healed'
1046
1055
  actions.first-aid.description: 'A medic heals 1d6 plus their Heal skill (1d6-1 without one), adding one System Strain.'
1047
1056
  actions.first-aid.params.healerSkill.name: 'Medic’s Heal skill'
1048
1057
  actions.first-aid.steps.heal.name: 'Healing'
@@ -1070,10 +1079,13 @@ actions.attack.steps.hit.name: 'Hit roll'
1070
1079
  actions.attack.steps.damage.name: 'Damage'
1071
1080
  actions.attack.steps.trauma.name: 'Trauma Die'
1072
1081
  actions.reload.name: 'Reload'
1082
+ actions.reload.results.reloaded.name: 'Reloaded'
1073
1083
  actions.use-drug.name: 'Take a dose'
1084
+ actions.use-drug.results.applied.name: 'Applied'
1074
1085
  actions.use-drug.params.healerSkill.name: 'Medic’s Heal skill'
1075
1086
  actions.use-drug.steps.heal.name: 'Healing'
1076
1087
  actions.trigger-cyber.name: 'Trigger'
1088
+ actions.trigger-cyber.results.triggered.name: 'Triggered'
1077
1089
  actions.run-program.name: 'Run program'
1078
1090
  actions.run-program.description: 'Pair this Verb with a Subject in Memory, pay its Access and roll Int/Program against the security difficulty.'
1079
1091
  actions.run-program.params.difficulty.name: 'Security difficulty'
@@ -1095,6 +1107,7 @@ actions.cast-spell.results.cast.name: 'Cast'
1095
1107
  actions.cast-spell.results.overcast.name: 'Overcast'
1096
1108
  actions.cast-spell.steps.overcasting.name: 'Overcasting'
1097
1109
  actions.summon-spirit.name: 'Summon a spirit'
1110
+ actions.summon-spirit.results.summoned.name: 'Summoned'
1098
1111
  actions.summon-spirit.description: 'Commit Summoner Effort for the day: one per power, less one for a ritual summoning, less the Summon skill, plus one per immediate summoning already this scene.'
1099
1112
  actions.summon-spirit.params.earlier.name: 'Immediate summonings already this scene'
1100
1113
  actions.level-up.name: 'Level up'
@@ -1192,6 +1205,7 @@ actions.gain-skill.options.work.name: 'Work'
1192
1205
  actions.gain-skill.options.cast.name: 'Cast'
1193
1206
  actions.gain-skill.options.summon.name: 'Summon'
1194
1207
  actions.gain-attribute.name: 'Gain an attribute bonus'
1208
+ actions.gain-attribute.results.raised.name: 'Raised'
1195
1209
  actions.gain-attribute.params.code.name: 'Bonus'
1196
1210
  actions.gain-attribute.params.code.values.any-stat-1.name: '+1 Any Stat'
1197
1211
  actions.gain-attribute.params.code.values.physical-2.name: '+2 Physical'
@@ -1237,6 +1251,7 @@ actions.gain-edge.params.choice.values.edge-2.name: 'Second Edge'
1237
1251
  actions.gain-edge.params.choice.values.edge-5.name: '5th-level Edge'
1238
1252
  actions.gain-edge.params.choice.values.underdog-edge.name: 'Underdog Edge'
1239
1253
  actions.gain-edge.params.random.name: 'Random picks'
1254
+ actions.gain-edge.results.closed.name: 'Not open'
1240
1255
  actions.gain-edge.results.gained.name: 'Gained'
1241
1256
  actions.gain-edge.steps.edge.prompt: 'Edge'
1242
1257
  actions.gain-edge.steps.attribute.prompt: 'Prodigy attribute'
@@ -1249,6 +1264,7 @@ actions.gain-edge.options.int.name: 'Intelligence'
1249
1264
  actions.gain-edge.options.wis.name: 'Wisdom'
1250
1265
  actions.gain-edge.options.cha.name: 'Charisma'
1251
1266
  actions.acquire-focus-gear.name: 'Acquire focus gear'
1267
+ actions.acquire-focus-gear.results.acquired.name: 'Acquired'
1252
1268
  actions.acquire-focus-gear.params.kind.name: 'Gear'
1253
1269
  actions.acquire-focus-gear.params.kind.values.vehicle.name: 'Vehicles'
1254
1270
  actions.acquire-focus-gear.params.kind.values.drone.name: 'Drones'
@@ -1258,6 +1274,7 @@ actions.acquire-focus-gear.steps.vehicles.prompt: 'More vehicles'
1258
1274
  actions.acquire-focus-gear.steps.drone.prompt: 'Drone'
1259
1275
  actions.acquire-focus-gear.steps.drones.prompt: 'More drones'
1260
1276
  actions.acquire-wired-cyber.name: 'Acquire Wired cyber'
1277
+ actions.acquire-wired-cyber.results.acquired.name: 'Acquired'
1261
1278
  actions.acquire-wired-cyber.params.random.name: 'Random picks'
1262
1279
  actions.acquire-wired-cyber.steps.cyber.prompt: 'Cyberware'
1263
1280
  actions.create-character.name: 'Create a character'
@@ -1396,8 +1413,12 @@ tags.first-aid.name: 'First aid'
1396
1413
  tags.major-injury.name: 'Major Injury'
1397
1414
  tags.overcast.name: 'Overcasting'
1398
1415
  tags.creation.name: 'Creation'
1416
+ tags.creation.item.name: 'Free starting item'
1417
+ tags.creation.gear.name: 'Starting money'
1418
+ tags.creation.finish.name: 'Creation finish'
1399
1419
  tags.building.name: 'Character building'
1400
1420
  tags.advancement.name: 'Advancement'
1421
+ tags.advancement.level.name: 'New level'
1401
1422
  tags.skill-pick.name: 'Skill pick'
1402
1423
  tags.focus-pick.name: 'Focus pick'
1403
1424
  tags.edge-pick.name: 'Edge pick'
@@ -1409,6 +1430,8 @@ tags.magic.name: 'Magic'
1409
1430
  tags.spell.name: 'Spell'
1410
1431
  tags.summoning.name: 'Summoning'
1411
1432
  tags.rest.name: 'Rest'
1433
+ tags.rest.night.name: "Night's rest"
1434
+ tags.rest.scene.name: 'Scene end'
1412
1435
  tags.injury.name: 'Injury'
1413
1436
  tags.armor.name: 'Armor'
1414
1437
  tags.armor.heavy.name: 'Heavy armor'
@@ -1421,6 +1444,7 @@ tags.standard.name: 'Standard'
1421
1444
  tags.repeatable.name: 'Repeatable'
1422
1445
  tags.asks-attribute.name: 'Asks for an attribute'
1423
1446
  tags.brings-cyber.name: 'Brings cyberware'
1447
+ tags.bars-cyber.name: 'Bars cyberware'
1424
1448
  tags.not-underdog.name: 'Not under the Underdog Rule'
1425
1449
  tags.retroactive-points.name: 'Retroactive skill points'
1426
1450
  tags.restricted.name: 'Restricted'
package/pack.yaml CHANGED
@@ -1,6 +1,6 @@
1
1
  id: cwn-srd
2
- version: 0.1.0
3
- specVersion: 0.2.0
2
+ version: 0.2.0
3
+ specVersion: 0.3.0
4
4
  license: CC0-1.0
5
5
  # CC0 asks for nothing, but the SRD's waiver asks that a work built on it not be presented as
6
6
  # official or endorsed, so apps pass this on as they would any notice.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencharacter/cwn-srd",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Open Character Format pack for the character rules of the Cities Without Number SRD (CC0). Unofficial.",
5
5
  "keywords": [
6
6
  "character-sheet",
@@ -52,7 +52,7 @@
52
52
  "access": "public"
53
53
  },
54
54
  "devDependencies": {
55
- "@opencharacter/engine": "0.2.0"
55
+ "@opencharacter/engine": "0.3.0"
56
56
  },
57
57
  "engines": {
58
58
  "node": ">=22"
@@ -3,12 +3,13 @@ actions:
3
3
  # points, and skill points to spend.
4
4
  - id: level-up
5
5
  tags: [advancement]
6
- available: '!character.creating && level < 10'
6
+ available: '!character.creating && level < 10 && xp.current >= xp.next'
7
7
  params:
8
8
  random: { type: boolean, default: false }
9
9
  results: [raised]
10
10
  steps:
11
11
  - id: raise
12
+ tags: [advancement.level]
12
13
  kind: changes
13
14
  changes:
14
15
  - { type: adjust, field: level, by: 1 }
@@ -58,10 +59,12 @@ actions:
58
59
  # 3rd level), level-3 4 (from 6th) and level-4 5 (from 9th). Banked credit is spent first.
59
60
  - id: improve-skill
60
61
  tags: [advancement]
61
- available: '!character.creating'
62
+ available: >-
63
+ !character.creating && (skillPoints.unspent > 0 || maxList(keysOf('skill'), fieldOf('skills.{skill}.credit', x)) > 0)
62
64
  params:
63
65
  skill:
64
66
  type: enum
67
+ open: true
65
68
  values:
66
69
  [
67
70
  administer,
@@ -111,10 +114,10 @@ actions:
111
114
  when: flags.allowed
112
115
  changes:
113
116
  - type: set
114
- field: { formula: "'skills.' + params.skill + '.base'" }
117
+ field: { formula: "fieldId('skills.{skill}.base', params.skill)" }
115
118
  value: flags.level + 1
116
119
  - type: set
117
- field: { formula: "'skills.' + params.skill + '.credit'" }
120
+ field: { formula: "fieldId('skills.{skill}.credit', params.skill)" }
118
121
  value: max(0, flags.credit - flags.cost)
119
122
  - type: adjust
120
123
  field: skillPoints.unspent
@@ -128,7 +131,10 @@ actions:
128
131
  # all. Not for characters who took the Underdog Rule.
129
132
  - id: improve-attribute
130
133
  tags: [advancement]
131
- available: '!character.creating && !underdog && advancement.attributeBoosts < 5'
134
+ available: >-
135
+ !character.creating && !underdog && advancement.attributeBoosts < 5
136
+ && skillPoints.unspent > advancement.attributeBoosts
137
+ && level >= [1, 1, 3, 6, 9][advancement.attributeBoosts]
132
138
  params:
133
139
  attribute: { type: enum, values: [str, dex, con, int, wis, cha] }
134
140
  results: [improved, refused]
@@ -34,9 +34,13 @@ fields:
34
34
  max(-3, min(max(attributes.{attribute}.modCap, attributes.{attribute}.scoreMod),
35
35
  attributes.{attribute}.scoreMod + attributes.{attribute}.modBonus))
36
36
 
37
- # The Underdog Rule reads the sum of the six modifiers.
37
+ # The Underdog Rule reads the sum of the modifiers the six rolled scores give, before Edges,
38
+ # Foci and cyber (so its own bonus Edge can't undo it).
38
39
  attributes.modTotal:
39
40
  type: integer
40
41
  formula: >-
41
- attributes.str.mod + attributes.dex.mod + attributes.con.mod + attributes.int.mod
42
- + attributes.wis.mod + attributes.cha.mod
42
+ sumList(['str', 'dex', 'con', 'int', 'wis', 'cha'],
43
+ fieldOf('attributes.{attribute}.base', x) >= 18 ? 2
44
+ : fieldOf('attributes.{attribute}.base', x) >= 14 ? 1
45
+ : fieldOf('attributes.{attribute}.base', x) >= 8 ? 0
46
+ : fieldOf('attributes.{attribute}.base', x) >= 4 ? -1 : -2)
@@ -7,10 +7,12 @@ contentTypes:
7
7
  # creation action: the free skill, then three rolls split between Growth (d6) and Learning (d8),
8
8
  # or two picks from Learning.
9
9
  background:
10
+ grantOnly: true
10
11
  copies: { max: 0 }
11
12
  fields:
12
13
  freeSkill:
13
14
  type: enum
15
+ open: true
14
16
  required: true
15
17
  values:
16
18
  [
@@ -37,6 +39,7 @@ contentTypes:
37
39
  ]
38
40
  'growth{growthRoll}':
39
41
  type: enum
42
+ open: true
40
43
  required: true
41
44
  values:
42
45
  [
@@ -67,6 +70,7 @@ contentTypes:
67
70
  ]
68
71
  'learning{learningRoll}':
69
72
  type: enum
73
+ open: true
70
74
  required: true
71
75
  values:
72
76
  [
@@ -7,10 +7,12 @@ actions:
7
7
  # skill, which may raise it past the level the character could normally buy; what doesn't buy a
8
8
  # level stays as credit toward it. On a skill already at level-4 the points go to the pool.
9
9
  - id: gain-skill
10
+ listed: false
10
11
  tags: [building]
11
12
  params:
12
13
  code:
13
14
  type: enum
15
+ open: true
14
16
  values:
15
17
  [
16
18
  administer,
@@ -87,7 +89,7 @@ actions:
87
89
  when: '!flags.points'
88
90
  changes:
89
91
  - type: adjust
90
- field: { formula: "'skills.' + flags.skill + '.base'" }
92
+ field: { formula: "fieldId('skills.{skill}.base', flags.skill)" }
91
93
  by: 1
92
94
  # Three points (and any credit) buy levels in order: level-0 costs 1, level-1 2, and so on.
93
95
  - id: pool
@@ -122,10 +124,10 @@ actions:
122
124
  when: flags.points
123
125
  changes:
124
126
  - type: set
125
- field: { formula: "'skills.' + flags.skill + '.base'" }
127
+ field: { formula: "fieldId('skills.{skill}.base', flags.skill)" }
126
128
  value: flags.level
127
129
  - type: set
128
- field: { formula: "'skills.' + flags.skill + '.credit'" }
130
+ field: { formula: "fieldId('skills.{skill}.credit', flags.skill)" }
129
131
  value: 'flags.level >= 4 ? 0 : flags.pool'
130
132
  - type: adjust
131
133
  when: flags.level >= 4 && flags.pool > 0
@@ -139,10 +141,12 @@ actions:
139
141
  # An attribute bonus from a background's Growth table: +1 to any attribute, or +2 to physical
140
142
  # or mental attributes, split between two of them as the player likes. No score passes 18.
141
143
  - id: gain-attribute
144
+ listed: false
142
145
  tags: [building]
143
146
  params:
144
147
  code: { type: enum, values: [any-stat-1, physical-2, mental-2] }
145
148
  random: { type: boolean, default: false }
149
+ results: [raised]
146
150
  steps:
147
151
  - id: start
148
152
  kind: branch
@@ -181,10 +185,12 @@ actions:
181
185
  recommend:
182
186
  'attributes.{attribute}.base': >-
183
187
  size(flags.best) > 0 && flags.best[0] == '{attribute}' ? flags.amount : 0
188
+ - { id: result, kind: outcome, result: "'raised'" }
184
189
 
185
190
  # A new Focus at level 1, or a Focus the character has raised to level 2, with its bonus skill
186
191
  # and the gear it brings.
187
192
  - id: gain-focus
193
+ available: foci.taken < foci.allowed
188
194
  tags: [building, advancement]
189
195
  params:
190
196
  random: { type: boolean, default: false }
@@ -215,8 +221,8 @@ actions:
215
221
  where: >-
216
222
  ('repeatable' in item.tags || countCopies(copy.item == item.id) == 0)
217
223
  && !('brings-cyber' in item.tags
218
- && (magic.graced || countCopies(copy.item == @foci.all-natural) > 0))
219
- && !(item.id == @foci.all-natural && (underdog || magic.mage || magic.summoner
224
+ && (magic.graced || countCopies('bars-cyber' in copy.tags) > 0))
225
+ && !('bars-cyber' in item.tags && (underdog || magic.mage || magic.summoner
220
226
  || magic.graced || countCopies(copy.type == 'cyberware' && copy.fields.strain > 0) > 0))
221
227
  recommend: options[0]
222
228
  random: params.random
@@ -326,11 +332,27 @@ actions:
326
332
  # An Edge in one of the rules' Edge choices, with its bonus skill and what it brings.
327
333
  - id: gain-edge
328
334
  tags: [building]
335
+ available: >-
336
+ size(picksOf('edge-1')) == 0 || size(picksOf('edge-2')) == 0
337
+ || (level >= 5 && size(picksOf('edge-5')) == 0)
338
+ || (underdog && size(picksOf('underdog-edge')) == 0)
329
339
  params:
330
340
  choice: { type: enum, values: [edge-1, edge-2, edge-5, underdog-edge] }
331
341
  random: { type: boolean, default: false }
332
- results: [gained]
342
+ results: [gained, closed]
333
343
  steps:
344
+ # The 5th-level Edge waits for 5th level, the Underdog Rule's for the rule; a taken one is
345
+ # taken.
346
+ - id: closed
347
+ kind: outcome
348
+ sheet: proposed
349
+ when: >-
350
+ (params.choice == 'edge-5' && level < 5) || (params.choice == 'underdog-edge' && !underdog)
351
+ || (params.choice == 'edge-1' && size(picksOf('edge-1')) > 0)
352
+ || (params.choice == 'edge-2' && size(picksOf('edge-2')) > 0)
353
+ || (params.choice == 'edge-5' && size(picksOf('edge-5')) > 0)
354
+ || (params.choice == 'underdog-edge' && size(picksOf('underdog-edge')) > 0)
355
+ result: "'closed'"
334
356
  - id: edge
335
357
  kind: choice
336
358
  tags: [edge-pick]
@@ -344,7 +366,7 @@ actions:
344
366
  && params.choice != 'edge-5'))
345
367
  && !('not-underdog' in item.tags && (underdog || params.choice == 'underdog-edge'))
346
368
  && !('brings-cyber' in item.tags
347
- && (magic.graced || countCopies(copy.item == @foci.all-natural) > 0))
369
+ && (magic.graced || countCopies('bars-cyber' in copy.tags) > 0))
348
370
  recommend: options[0]
349
371
  random: params.random
350
372
  changes:
package/rules/checks.yaml CHANGED
@@ -6,12 +6,12 @@ settings:
6
6
 
7
7
  resultBands:
8
8
  check:
9
- - { id: success, when: roll.total >= flags.dc }
9
+ - { id: success, when: roll.total >= flags.dc, success: true }
10
10
  - { id: failure, when: true }
11
11
  # A natural 1 always fails a save and a natural 20 always succeeds.
12
12
  save:
13
13
  - { id: failure, when: 'roll.kept[0] == 1' }
14
- - { id: success, when: 'roll.kept[0] == 20 || roll.total >= flags.target' }
14
+ - { id: success, when: 'roll.kept[0] == 20 || roll.total >= flags.target', success: true }
15
15
  - { id: failure, when: true }
16
16
  major-injury:
17
17
  - { id: death, when: roll.total <= 1 }
@@ -101,8 +101,10 @@ actions:
101
101
  # The end of a fight or scene: Damage Soak and deck Shielding refresh, scene Effort returns.
102
102
  - id: end-scene
103
103
  tags: [rest]
104
+ results: [ended]
104
105
  steps:
105
106
  - id: refresh
107
+ tags: [rest.scene]
106
108
  kind: changes
107
109
  changes:
108
110
  - type: setState
@@ -115,13 +117,16 @@ actions:
115
117
  value: 0
116
118
  - { type: set, field: effort.mage.scene, value: 0 }
117
119
  - { type: set, field: effort.summoner.scene, value: 0 }
120
+ - { id: result, kind: outcome, result: "'ended'" }
118
121
 
119
122
  # A night's rest, warm and fed: hit points equal to the level (none while Frail), one point of
120
123
  # System Strain, all Effort Committed for the day, the day's Access and Martial Instinct's rolls.
121
124
  - id: rest
122
125
  tags: [rest]
126
+ results: [rested]
123
127
  steps:
124
128
  - id: recover
129
+ tags: [rest.night]
125
130
  kind: changes
126
131
  changes:
127
132
  - { type: adjust, when: '!hp.frail', field: hp.current, by: level }
@@ -132,6 +137,7 @@ actions:
132
137
  - { type: set, field: effort.summoner.scene, value: 0 }
133
138
  - { type: set, field: hacking.access.spent, value: 0 }
134
139
  - { type: set, field: arts.bonusRolls.used, value: 0 }
140
+ - { id: result, kind: outcome, result: "'rested'" }
135
141
 
136
142
  # First aid from a medic: 1d6 plus their Heal skill (1d6-1 without one), and one System
137
143
  # Strain. It can't be applied past the System Strain maximum.
@@ -140,6 +146,7 @@ actions:
140
146
  available: strain.total + 1 <= strain.max
141
147
  params:
142
148
  healerSkill: { type: integer, min: -1, max: 4 }
149
+ results: [healed]
143
150
  steps:
144
151
  - id: heal
145
152
  kind: roll
@@ -152,6 +159,12 @@ actions:
152
159
  changes:
153
160
  - { type: adjust, field: hp.current, by: 'max(0, steps.heal.total)' }
154
161
  - { type: adjust, field: strain.temporary, by: 1 }
162
+ - {
163
+ id: result,
164
+ kind: outcome,
165
+ result: "'healed'",
166
+ data: { healed: 'max(0, steps.heal.total)' },
167
+ }
155
168
 
156
169
  # A Major Injury: after a failed Physical save at zero hit points in a scene with a Traumatic
157
170
  # Hit, roll 1d12 on the table.
@@ -326,6 +326,7 @@ actions:
326
326
 
327
327
  # Gear: $500 to spend, one item of up to $1,000 and a month of middle-class life.
328
328
  - id: freeItemKind
329
+ tags: [creation.item]
329
330
  kind: choice
330
331
  options: [{ id: weapon }, { id: armor }, { id: gear }, { id: cyberdeck }, { id: drone }]
331
332
  recommend: "'weapon'"
@@ -381,12 +382,14 @@ actions:
381
382
  - type: addItem
382
383
  entry: { item: picked.id }
383
384
  - id: gear
385
+ tags: [creation.gear]
384
386
  kind: changes
385
387
  changes:
386
388
  - { type: set, field: money, value: 500 }
387
389
  - { type: set, field: lifestyle, value: "'middle'" }
388
390
 
389
391
  - id: finish
392
+ tags: [creation.finish]
390
393
  kind: changes
391
394
  sheet: proposed
392
395
  changes:
@@ -5,6 +5,7 @@ contentTypes:
5
5
  cost: { type: integer, default: 0, min: 0 }
6
6
  category:
7
7
  type: enum
8
+ open: true
8
9
  values: [body, head, skin, limb, sensory, medical, nerve]
9
10
  required: true
10
11
  concealment: { type: enum, values: [medical, touch, sight], required: true }
@@ -126,17 +127,21 @@ actions:
126
127
  tags: [cyber]
127
128
  available: >-
128
129
  has(item.triggerStrain) && !self.damaged && strain.total + item.triggerStrain <= strain.max
130
+ results: [triggered]
129
131
  steps:
130
132
  - id: strain
131
133
  kind: changes
132
134
  changes:
133
135
  - { type: adjust, field: strain.temporary, by: item.triggerStrain }
136
+ - { id: result, kind: outcome, result: "'triggered'" }
134
137
 
135
138
  # Pick cyber with the Wired Edge's budget: new systems the character's strain can carry.
136
139
  - id: acquire-wired-cyber
140
+ listed: false
137
141
  tags: [building]
138
142
  params:
139
143
  random: { type: boolean, default: false }
144
+ results: [acquired]
140
145
  steps:
141
146
  - id: cyber
142
147
  kind: choice
@@ -154,3 +159,4 @@ actions:
154
159
  changes:
155
160
  - type: addItem
156
161
  entry: { item: picked.id, state: { wired: true } }
162
+ - { id: result, kind: outcome, result: "'acquired'" }
package/rules/drones.yaml CHANGED
@@ -13,7 +13,7 @@ contentTypes:
13
13
  fittings: { type: integer, default: 0, min: 0 }
14
14
  fittingsUsed: { type: integer, default: 0, min: 0 }
15
15
  move: { type: integer, required: true, min: 0 }
16
- moveKind: { type: enum, values: [ground, fly, swim], required: true }
16
+ moveKind: { type: enum, values: [ground, fly, swim], required: true, open: true }
17
17
  hardpoints: { type: integer, default: 0, min: 0 }
18
18
  state:
19
19
  hp: { type: integer, default: item.hp, min: 0, max: item.hp }
package/rules/edges.yaml CHANGED
@@ -2,11 +2,13 @@ contentTypes:
2
2
  # Edges are picked in the rules-level choices below: two at creation, a bonus one under the
3
3
  # Underdog Rule, and a third at 5th level.
4
4
  edge:
5
+ grantOnly: true
5
6
  copies: { max: 0 }
6
7
  fields:
7
8
  # The skill the Edge grants as a bonus skill: a skill, `combat` (a combat skill) or `any`.
8
9
  bonusSkill:
9
10
  type: enum
11
+ open: true
10
12
  values:
11
13
  [
12
14
  administer,
package/rules/foci.yaml CHANGED
@@ -8,6 +8,7 @@ contentTypes:
8
8
  # `noncombat` (the Specialist's skill). `bonusSkill2` is a second one.
9
9
  bonusSkill:
10
10
  type: enum
11
+ open: true
11
12
  values:
12
13
  [
13
14
  administer,
@@ -36,6 +37,7 @@ contentTypes:
36
37
  ]
37
38
  bonusSkill2:
38
39
  type: enum
40
+ open: true
39
41
  values:
40
42
  [
41
43
  administer,
@@ -61,6 +63,7 @@ contentTypes:
61
63
  # A bonus skill on taking the second level (Ace Driver's Fix).
62
64
  levelTwoSkill:
63
65
  type: enum
66
+ open: true
64
67
  values:
65
68
  [
66
69
  administer,
package/rules/gear.yaml CHANGED
@@ -89,6 +89,7 @@ actions:
89
89
  available: self.quantity > 0
90
90
  params:
91
91
  healerSkill: { type: integer, optional: true }
92
+ results: [applied]
92
93
  steps:
93
94
  - id: heal
94
95
  kind: roll
@@ -103,6 +104,12 @@ actions:
103
104
  - { type: adjustQuantity, entry: self, by: -1 }
104
105
  - { type: adjust, when: item.strain > 0, field: strain.temporary, by: item.strain }
105
106
  - { type: adjust, when: has(steps.heal), field: hp.current, by: steps.heal.total }
107
+ - {
108
+ id: result,
109
+ kind: outcome,
110
+ result: "'applied'",
111
+ data: { healed: 'has(steps.heal) ? steps.heal.total : 0' },
112
+ }
106
113
 
107
114
  # Buy vehicles or drones with a Focus's gear budget: the dearest one the budget buys is
108
115
  # recommended. More are offered while the budget lasts, the dearest that still fits recommended,
@@ -113,6 +120,7 @@ actions:
113
120
  params:
114
121
  kind: { type: enum, values: [vehicle, drone] }
115
122
  random: { type: boolean, default: false }
123
+ results: [acquired]
116
124
  steps:
117
125
  - id: vehicle
118
126
  kind: choice
@@ -174,3 +182,4 @@ actions:
174
182
  changes:
175
183
  - type: addItem
176
184
  entry: { item: picked.id, state: { focusGear: true } }
185
+ - { id: result, kind: outcome, result: "'acquired'" }
@@ -41,7 +41,7 @@ contentTypes:
41
41
  accessCost: { type: integer, default: 1, min: 0 }
42
42
  checkMod: { type: integer, default: 0 }
43
43
  # A Subject's type.
44
- subjectType: { type: enum, values: [avatar, data, device, cyber, program] }
44
+ subjectType: { type: enum, values: [avatar, data, device, cyber, program], open: true }
45
45
  state:
46
46
  # Bought on the street, written and maintained by the hacker, or one of the Hacker Edge's
47
47
  # eight free elements.
package/rules/layout.yaml CHANGED
@@ -309,6 +309,13 @@ display:
309
309
  showWhen: magic.graced
310
310
  with: [{ field: arts.points, as: max }]
311
311
  magic.cyberPenalty: { groups: [magic], priority: 8, showWhen: magic.cyberPenalty > 0 }
312
+ arts.bonusRolls.used:
313
+ groups: [magic]
314
+ priority: 9
315
+ showWhen: arts.bonusRolls.max > 0
316
+ with: [{ field: arts.bonusRolls.max, as: max }]
317
+ arts.bonusRolls.max:
318
+ { groups: [magic], priority: 9, visibility: background, showWhen: arts.bonusRolls.max > 0 }
312
319
  magic.mage: { hidden: true }
313
320
  magic.summoner: { hidden: true }
314
321
  magic.graced: { hidden: true }
@@ -411,6 +418,8 @@ display:
411
418
  art: { quantity: { hidden: true } }
412
419
  spirit:
413
420
  quantity: { hidden: true }
421
+ fields:
422
+ powerCount: { hidden: true }
414
423
  state:
415
424
  form: { priority: 0 }
416
425
  ritual: { priority: 1 }