@opencharacter/swn-revised 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.
Files changed (78) hide show
  1. package/README.md +64 -10
  2. package/content/classes/adventurer.yaml +2 -0
  3. package/content/classes/expert.yaml +2 -0
  4. package/content/classes/psychic.yaml +6 -6
  5. package/content/classes/warrior.yaml +2 -0
  6. package/content/foci/psychic-training.yaml +1 -0
  7. package/content/foci/specialist.yaml +1 -1
  8. package/content/foci/wild-psychic-talent.yaml +1 -0
  9. package/content/kits/barbarian.yaml +17 -0
  10. package/content/kits/blade.yaml +17 -0
  11. package/content/kits/civilian.yaml +12 -0
  12. package/content/kits/credits.yaml +11 -0
  13. package/content/kits/gunslinger.yaml +16 -0
  14. package/content/kits/hacker.yaml +18 -0
  15. package/content/kits/medic.yaml +18 -0
  16. package/content/kits/scout.yaml +19 -0
  17. package/content/kits/soldier.yaml +16 -0
  18. package/content/kits/technician.yaml +19 -0
  19. package/content/kits/thief.yaml +19 -0
  20. package/content/partial-classes/psychic.yaml +4 -6
  21. package/content/styles/expert-nimble.yaml +11 -0
  22. package/content/styles/expert-smart.yaml +11 -0
  23. package/content/styles/expert-smooth.yaml +11 -0
  24. package/content/styles/psychic-adept.yaml +11 -0
  25. package/content/styles/psychic-seer.yaml +11 -0
  26. package/content/styles/warrior-leader.yaml +11 -0
  27. package/content/styles/warrior-melee.yaml +11 -0
  28. package/content/styles/warrior-ranged.yaml +11 -0
  29. package/content/techniques/psychic-succor.yaml +16 -3
  30. package/content/weapons/advanced-bow.yaml +0 -2
  31. package/content/weapons/anti-vehicle-laser.yaml +0 -2
  32. package/content/weapons/combat-rifle.yaml +0 -2
  33. package/content/weapons/combat-shotgun.yaml +0 -2
  34. package/content/weapons/conversion-bow.yaml +0 -2
  35. package/content/weapons/crude-pistol.yaml +0 -2
  36. package/content/weapons/distortion-cannon.yaml +0 -2
  37. package/content/weapons/heavy-machine-gun.yaml +0 -2
  38. package/content/weapons/hydra-array.yaml +0 -2
  39. package/content/weapons/laser-pistol.yaml +0 -2
  40. package/content/weapons/laser-rifle.yaml +0 -2
  41. package/content/weapons/mag-pistol.yaml +0 -2
  42. package/content/weapons/mag-rifle.yaml +0 -2
  43. package/content/weapons/musket.yaml +0 -2
  44. package/content/weapons/plasma-projector.yaml +0 -2
  45. package/content/weapons/primitive-bow.yaml +0 -2
  46. package/content/weapons/railgun.yaml +0 -2
  47. package/content/weapons/revolver.yaml +0 -2
  48. package/content/weapons/rifle.yaml +0 -2
  49. package/content/weapons/rocket-launcher.yaml +0 -2
  50. package/content/weapons/semi-auto-pistol.yaml +0 -2
  51. package/content/weapons/shear-rifle.yaml +0 -2
  52. package/content/weapons/shotgun.yaml +0 -2
  53. package/content/weapons/sniper-rifle.yaml +0 -2
  54. package/content/weapons/spike-thrower.yaml +0 -2
  55. package/content/weapons/submachine-gun.yaml +0 -2
  56. package/content/weapons/thermal-pistol.yaml +0 -2
  57. package/content/weapons/thunder-gun.yaml +0 -2
  58. package/content/weapons/void-carbine.yaml +0 -2
  59. package/content/weapons/vortex-cannon.yaml +0 -2
  60. package/content/weapons/wheatcutter-belt.yaml +0 -2
  61. package/dist/i18n/en.js +1 -1
  62. package/dist/i18n/en.json +140 -85
  63. package/dist/index.js +1 -1
  64. package/dist/release.json +5068 -3511
  65. package/i18n/en/content.yaml +105 -63
  66. package/i18n/en/rules.yaml +35 -22
  67. package/pack.yaml +2 -2
  68. package/package.json +2 -2
  69. package/rules/advancement.yaml +30 -9
  70. package/rules/character.yaml +30 -5
  71. package/rules/checks.yaml +8 -2
  72. package/rules/combat.yaml +11 -2
  73. package/rules/creation.yaml +164 -366
  74. package/rules/gear.yaml +16 -4
  75. package/rules/layout.yaml +4 -2
  76. package/rules/psionics.yaml +64 -4
  77. package/rules/start.yaml +46 -32
  78. package/rules/tags.yaml +11 -0
@@ -21,7 +21,7 @@ actions:
21
21
  # throws and the attack bonus follow the level.
22
22
  - id: level-up
23
23
  tags: [level-up]
24
- available: '!character.creating && level < 20'
24
+ available: '!character.creating && level < 20 && xp.current >= xp.next'
25
25
  results: [advanced]
26
26
  steps:
27
27
  - id: start
@@ -69,6 +69,7 @@ actions:
69
69
  # Psychic Training's second level: a point each level, and the levels before it when it is
70
70
  # taken late.
71
71
  - id: points
72
+ tags: [level-up.level]
72
73
  kind: changes
73
74
  sheet: proposed
74
75
  changes:
@@ -92,10 +93,12 @@ actions:
92
93
  # doesn't buy a level is saved as credit toward the skill; on a skill at level-4 it goes to the
93
94
  # general pool.
94
95
  - id: focus-skill-points
96
+ listed: false
95
97
  tags: [level-up]
96
98
  params:
97
99
  entry:
98
100
  type: enum
101
+ open: true
99
102
  required: true
100
103
  values:
101
104
  [
@@ -130,7 +133,7 @@ actions:
130
133
  any-skill,
131
134
  ]
132
135
  random: { type: boolean, default: false }
133
- results: [spent]
136
+ results: [spent, none]
134
137
  steps:
135
138
  - id: start
136
139
  kind: branch
@@ -145,7 +148,11 @@ actions:
145
148
  ? filterList(keysOf('psychic'), psionics.access == 'unrestricted'
146
149
  || x == psionics.discipline)
147
150
  : params.entry == 'any-skill' ? keysOf('general') + keysOf('combat')
151
+ : params.entry in keysOf('psychic') && psionics.access != 'unrestricted'
152
+ && params.entry != psionics.discipline ? []
148
153
  : [params.entry]
154
+ # A psychic skill the character can't learn: nothing to raise.
155
+ - { id: none, kind: outcome, when: size(flags.open) == 0, result: "'none'" }
149
156
  - id: choose
150
157
  kind: choice
151
158
  when: size(flags.open) > 1
@@ -191,11 +198,11 @@ actions:
191
198
  changes:
192
199
  - type: set
193
200
  when: flags.level != flags.from
194
- field: { formula: "'skills.' + flags.skill + '.level'" }
201
+ field: { formula: "fieldId('skills.{skill}.level', flags.skill)" }
195
202
  value: flags.level
196
203
  - type: set
197
204
  when: '(flags.level >= 4 ? 0 : flags.pool) != flags.had'
198
- field: { formula: "'skills.' + flags.skill + '.credit'" }
205
+ field: { formula: "fieldId('skills.{skill}.credit', flags.skill)" }
199
206
  value: 'flags.level >= 4 ? 0 : flags.pool'
200
207
  - type: adjust
201
208
  when: flags.level >= 4 && flags.pool > 0
@@ -216,10 +223,12 @@ actions:
216
223
 
217
224
  # A technique of the discipline at or below its skill level, free with a new skill level.
218
225
  - id: pick-technique
226
+ listed: false
219
227
  tags: [level-up]
220
228
  params:
221
229
  discipline:
222
230
  type: enum
231
+ open: true
223
232
  required: true
224
233
  values: [biopsionics, metapsionics, precognition, telekinesis, telepathy, teleportation]
225
234
  random: { type: boolean, default: false }
@@ -245,10 +254,14 @@ actions:
245
254
  # higher levels need a character level: level-2 at 3rd, level-3 at 6th, level-4 at 9th.
246
255
  - id: raise-skill
247
256
  tags: [level-up]
248
- available: '!character.creating'
257
+ available: >-
258
+ !character.creating
259
+ && (skillPoints.general + skillPoints.expert + skillPoints.psychic + skillPoints.training > 0
260
+ || maxList(keysOf('skill'), fieldOf('skills.{skill}.credit', x)) > 0)
249
261
  params:
250
262
  skill:
251
263
  type: enum
264
+ open: true
252
265
  required: true
253
266
  values:
254
267
  [
@@ -327,7 +340,7 @@ actions:
327
340
  changes:
328
341
  - type: adjust
329
342
  when: flags.fromCredit > 0
330
- field: { formula: "'skills.' + params.skill + '.credit'" }
343
+ field: { formula: "fieldId('skills.{skill}.credit', params.skill)" }
331
344
  by: -flags.fromCredit
332
345
  - {
333
346
  type: adjust,
@@ -353,7 +366,11 @@ actions:
353
366
  by: -flags.fromGeneral,
354
367
  when: flags.fromGeneral > 0,
355
368
  }
356
- - { type: adjust, field: { formula: "'skills.' + params.skill + '.level'" }, by: 1 }
369
+ - {
370
+ type: adjust,
371
+ field: { formula: "fieldId('skills.{skill}.level', params.skill)" },
372
+ by: 1,
373
+ }
357
374
  - id: technique
358
375
  kind: action
359
376
  when: >-
@@ -368,7 +385,9 @@ actions:
368
385
  # Spend skill points on a technique: as many as its level.
369
386
  - id: learn-technique
370
387
  tags: [level-up]
371
- available: "!character.creating && psionics.access != 'none'"
388
+ available: >-
389
+ !character.creating && psionics.access != 'none'
390
+ && skillPoints.general + skillPoints.psychic + skillPoints.training > 0
372
391
  params:
373
392
  technique: { type: id, of: technique, required: true, where: '!item.core' }
374
393
  results: [learned, refused]
@@ -433,7 +452,9 @@ actions:
433
452
  # the third needs 3rd level, the fourth 6th and the fifth 9th.
434
453
  - id: boost-attribute
435
454
  tags: [level-up]
436
- available: '!character.creating && attributes.boosts < 5'
455
+ available: >-
456
+ !character.creating && attributes.boosts < 5 && skillPoints.general > attributes.boosts
457
+ && level >= [1, 1, 3, 6, 9][attributes.boosts]
437
458
  params:
438
459
  attribute: { type: enum, required: true, values: [str, dex, con, int, wis, cha] }
439
460
  results: [boosted, refused]
@@ -6,7 +6,11 @@ fields:
6
6
  # Set by the class and its partial classes.
7
7
  psionics.access: { type: enum, values: [none, restricted, unrestricted], formula: "'none'" }
8
8
  # A restricted psychic's one discipline, picked with the Partial Psychic option.
9
- psionics.discipline: { type: string, formula: "''" }
9
+ psionics.discipline:
10
+ type: enum
11
+ open: true
12
+ values: [none, biopsionics, metapsionics, precognition, telekinesis, telepathy, teleportation]
13
+ formula: "'none'"
10
14
  # Extra focus levels a new character picks: non-combat (Expert) and combat (Warrior).
11
15
  class.focus.noncombat: { type: integer, formula: 0 }
12
16
  class.focus.combat: { type: integer, formula: 0 }
@@ -19,14 +23,34 @@ fields:
19
23
  contentTypes:
20
24
  class:
21
25
  copies: { max: 1 }
26
+ fields:
27
+ # The starting package recommended for the class.
28
+ kit: { type: id, of: kit }
22
29
  # Picked, two of them, by the Adventurer.
23
30
  partialClass:
31
+ grantOnly: true
32
+ copies: { max: 0 }
33
+ # A quick character's class and style: the class, the attribute scores and, for the book's
34
+ # styles, the style's column of the quick foci table (0-7).
35
+ style:
36
+ grantOnly: true
37
+ carried: false
24
38
  copies: { max: 0 }
39
+ fields:
40
+ class: { type: id, of: class, required: true }
41
+ str: { type: integer, required: true }
42
+ dex: { type: integer, required: true }
43
+ con: { type: integer, required: true }
44
+ int: { type: integer, required: true }
45
+ wis: { type: integer, required: true }
46
+ cha: { type: integer, required: true }
47
+ table: { type: integer, min: 0, max: 7 }
25
48
  background:
26
49
  copies: { max: 1 }
27
50
  fields:
28
51
  freeSkill:
29
52
  type: enum
53
+ open: true
30
54
  required: true
31
55
  values:
32
56
  &entries [
@@ -58,16 +82,17 @@ contentTypes:
58
82
  mental,
59
83
  ]
60
84
  # The quick skills besides the free one.
61
- quick1: { type: enum, required: true, values: *entries }
62
- quick2: { type: enum, required: true, values: *entries }
63
- 'growth{growthRow}': { type: enum, required: true, values: *entries }
64
- 'learning{learningRow}': { type: enum, required: true, values: *entries }
85
+ quick1: { type: enum, required: true, values: *entries, open: true }
86
+ quick2: { type: enum, required: true, values: *entries, open: true }
87
+ 'growth{growthRow}': { type: enum, required: true, values: *entries, open: true }
88
+ 'learning{learningRow}': { type: enum, required: true, values: *entries, open: true }
65
89
  focus:
66
90
  fields:
67
91
  kind: { type: enum, values: [combat, noncombat, psychic, special], required: true }
68
92
  # The bonus skill its first level gives; `chosen` is the skill the focus's own choice names.
69
93
  skill:
70
94
  type: enum
95
+ open: true
71
96
  default: none
72
97
  values:
73
98
  [
package/rules/checks.yaml CHANGED
@@ -27,7 +27,11 @@ situational:
27
27
 
28
28
  resultBands:
29
29
  check:
30
- - { id: success, when: 'flags.difficulty >= 0 && roll.total >= flags.difficulty' }
30
+ - {
31
+ id: success,
32
+ when: 'flags.difficulty >= 0 && roll.total >= flags.difficulty',
33
+ success: true,
34
+ }
31
35
  - { id: failure, when: 'flags.difficulty >= 0' }
32
36
  - { id: rolled, when: true }
33
37
  # A natural 1 always fails and a natural 20 always succeeds.
@@ -35,10 +39,11 @@ resultBands:
35
39
  - {
36
40
  id: success,
37
41
  when: 'roll.faces[0] == 20 || (roll.faces[0] != 1 && roll.total >= flags.target)',
42
+ success: true,
38
43
  }
39
44
  - { id: failure, when: true }
40
45
  attack:
41
- - { id: hit, when: 'flags.ac >= 0 && roll.total >= flags.ac' }
46
+ - { id: hit, when: 'flags.ac >= 0 && roll.total >= flags.ac', success: true }
42
47
  - { id: miss, when: 'flags.ac >= 0' }
43
48
  - { id: rolled, when: true }
44
49
 
@@ -49,6 +54,7 @@ actions:
49
54
  params:
50
55
  skill:
51
56
  type: enum
57
+ open: true
52
58
  required: true
53
59
  values:
54
60
  &skills [
package/rules/combat.yaml CHANGED
@@ -179,6 +179,7 @@ actions:
179
179
  results: [rested]
180
180
  steps:
181
181
  - id: rest
182
+ tags: [rest.night]
182
183
  kind: changes
183
184
  changes:
184
185
  - { type: adjust, field: hp.current, by: level, when: hp.current > 0, tags: [healing] }
@@ -195,6 +196,7 @@ actions:
195
196
  results: [ended]
196
197
  steps:
197
198
  - id: reset
199
+ tags: [rest.scene]
198
200
  kind: changes
199
201
  changes:
200
202
  - { type: set, field: effort.scene, value: 0 }
@@ -265,11 +267,18 @@ actions:
265
267
  until: { type: enum, values: [scene, day], default: scene }
266
268
  results: [committed]
267
269
  steps:
270
+ # Torched Effort lasts only for the scene, whatever it is committed for.
271
+ - id: source
272
+ kind: branch
273
+ cases:
274
+ - when: true
275
+ flags:
276
+ day: "params.until == 'day' && effort.max - effort.scene - effort.day - effort.active > 0"
268
277
  - id: commit
269
278
  kind: changes
270
279
  changes:
271
- - { type: adjust, field: effort.scene, by: 1, when: "params.until == 'scene'" }
272
- - { type: adjust, field: effort.day, by: 1, when: "params.until == 'day'" }
280
+ - { type: adjust, field: effort.scene, by: 1, when: '!flags.day' }
281
+ - { type: adjust, field: effort.day, by: 1, when: flags.day }
273
282
  - { id: result, kind: outcome, result: "'committed'" }
274
283
 
275
284
  # Torching: a free point of Effort for the scene, at a risk to Wisdom or Constitution.