@opencharacter/wwn-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.
Files changed (42) hide show
  1. package/README.md +41 -3
  2. package/content/classes/mage.yaml +2 -14
  3. package/content/foci/lucky.yaml +3 -2
  4. package/content/foci/traditional-education.yaml +1 -1
  5. package/content/partials/accursed.yaml +1 -0
  6. package/content/partials/bard.yaml +1 -0
  7. package/content/partials/beastmaster.yaml +1 -0
  8. package/content/partials/blood-priest.yaml +1 -0
  9. package/content/partials/duelist.yaml +1 -0
  10. package/content/partials/healer.yaml +1 -0
  11. package/content/partials/mage.yaml +2 -23
  12. package/content/partials/mageslayer.yaml +1 -0
  13. package/content/partials/skinshifter.yaml +1 -0
  14. package/content/partials/thought-noble.yaml +1 -0
  15. package/content/partials/vowed.yaml +1 -0
  16. package/content/partials/wise.yaml +1 -0
  17. package/content/traditions/elementalist.yaml +8 -0
  18. package/content/traditions/high-mage.yaml +8 -0
  19. package/content/traditions/invoker.yaml +9 -0
  20. package/content/traditions/necromancer.yaml +8 -0
  21. package/dist/i18n/en.js +1 -1
  22. package/dist/i18n/en.json +21 -17
  23. package/dist/index.js +1 -1
  24. package/dist/release.json +3461 -2759
  25. package/i18n/en/content.yaml +13 -15
  26. package/i18n/en.yaml +8 -2
  27. package/pack.yaml +2 -2
  28. package/package.json +2 -2
  29. package/rules/advancement.yaml +7 -9
  30. package/rules/backgrounds.yaml +1 -0
  31. package/rules/classes.yaml +1 -0
  32. package/rules/combat.yaml +2 -2
  33. package/rules/creation-steps.yaml +6 -6
  34. package/rules/creation.yaml +30 -95
  35. package/rules/display.yaml +108 -21
  36. package/rules/foci.yaml +1 -0
  37. package/rules/health.yaml +5 -3
  38. package/rules/magic.yaml +46 -59
  39. package/rules/saves.yaml +1 -1
  40. package/rules/skills.yaml +1 -1
  41. package/rules/tags.yaml +7 -0
  42. package/upgrades/0.1.0-to-0.2.0.yaml +61 -0
package/rules/magic.yaml CHANGED
@@ -51,10 +51,24 @@ families:
51
51
  wise,
52
52
  ]
53
53
  effortSpan: [scene, day, ongoing]
54
+ # The traditions whose arts worn armor or a shield stops as it stops spells, and the ones
55
+ # medium or heavy armor or a large shield stops (the Duelist's).
56
+ armorTrad: [highmage, elementalist, necromancer, vowed]
57
+ heavyArmorTrad: [duelist]
58
+ # The traditions that cast spells from the spell lists (the Invoker aside).
59
+ spellTrad: [highmage, elementalist, necromancer]
54
60
 
55
61
  fields:
56
- # 2 for a full Mage of the tradition, 1 for a partial one, 0 otherwise.
57
- 'tradition.{trad}.tier': { type: integer, formula: 0, tags: [tradition-tier] }
62
+ # 2 for a full Mage of the tradition, 1 for a partial one, 0 otherwise: a Mage's or partial
63
+ # Mage's picked tradition (`tradition` content) counts here, the other partial classes add
64
+ # theirs. The skill the tradition brings at creation, '' for none.
65
+ 'tradition.{trad}.tier':
66
+ type: integer
67
+ tags: [tradition-tier]
68
+ formula: >-
69
+ countPicks(pick.type == 'tradition' && pick.fields.key == '{trad}')
70
+ * (countCopies(copy.type == 'class' && 'full-mage' in copy.tags) > 0 ? 2 : 1)
71
+ 'tradition.{trad}.skill': { type: string, formula: "''" }
58
72
 
59
73
  # How the character casts: a full caster, one partial caster, two partial casters, an
60
74
  # Invoker (full or partial), or none.
@@ -64,12 +78,9 @@ fields:
64
78
  formula: >-
65
79
  tradition.invoker.tier == 2 ? 'invoker'
66
80
  : tradition.invoker.tier == 1 ? 'partial-invoker'
67
- : tradition.highmage.tier == 2 || tradition.elementalist.tier == 2
68
- || tradition.necromancer.tier == 2 ? 'full'
69
- : (tradition.highmage.tier == 1 ? 1 : 0) + (tradition.elementalist.tier == 1 ? 1 : 0)
70
- + (tradition.necromancer.tier == 1 ? 1 : 0) >= 2 ? 'dual'
71
- : tradition.highmage.tier == 1 || tradition.elementalist.tier == 1
72
- || tradition.necromancer.tier == 1 ? 'partial'
81
+ : countList(keysOf('spellTrad'), fieldOf('tradition.{trad}.tier', x) == 2) > 0 ? 'full'
82
+ : countList(keysOf('spellTrad'), fieldOf('tradition.{trad}.tier', x) == 1) >= 2 ? 'dual'
83
+ : countList(keysOf('spellTrad'), fieldOf('tradition.{trad}.tier', x) == 1) > 0 ? 'partial'
73
84
  : 'none'
74
85
  spells.maxLevel:
75
86
  type: integer
@@ -277,21 +288,7 @@ fields:
277
288
  { type: integer, formula: 'max(0, arts.{artTrad}.allowed - arts.{artTrad}.taken)' }
278
289
  arts.owed:
279
290
  type: integer
280
- formula: >-
281
- arts.highmage.owed
282
- + arts.elementalist.owed
283
- + arts.necromancer.owed
284
- + arts.healer.owed
285
- + arts.vowed.owed
286
- + arts.accursed.owed
287
- + arts.bard.owed
288
- + arts.beastmaster.owed
289
- + arts.bloodpriest.owed
290
- + arts.duelist.owed
291
- + arts.mageslayer.owed
292
- + arts.skinshifter.owed
293
- + arts.thoughtnoble.owed
294
- + arts.wise.owed
291
+ formula: "sumList(keysOf('artTrad'), fieldOf('arts.{artTrad}.owed', x))"
295
292
 
296
293
  # Armored Magic's level, and whether worn armor or a shield stops spells and arts.
297
294
  magic.armoredLevel: { type: integer, formula: 0 }
@@ -307,10 +304,18 @@ fields:
307
304
  formula: armor.wornHeavy || (armor.shield && armor.shieldAc >= 14)
308
305
 
309
306
  contentTypes:
307
+ # A Mage's magical tradition, picked by the Mage and the partial Mage: its `trad` key.
308
+ tradition:
309
+ grantOnly: true
310
+ carried: false
311
+ copies: { max: 0 }
312
+ fields:
313
+ key: { type: string, required: true }
314
+
310
315
  spell:
311
316
  fields:
312
317
  level: { type: integer, required: true, min: 1, max: 5 }
313
- list: { type: enum, values: [high, elementalist, necromancer], required: true }
318
+ list: { type: enum, values: [high, elementalist, necromancer], required: true, open: true }
314
319
  state:
315
320
  prepared: { type: boolean, default: false }
316
321
  actions:
@@ -320,6 +325,7 @@ contentTypes:
320
325
  fields:
321
326
  tradition:
322
327
  type: enum
328
+ open: true
323
329
  values:
324
330
  [
325
331
  highmage,
@@ -360,44 +366,21 @@ constraints:
360
366
  check: >-
361
367
  item.level <= spells.maxLevel
362
368
  && (item.list == 'high' ? spells.mode != 'none'
363
- : item.list == 'elementalist'
364
- ? tradition.elementalist.tier > 0 || invoker.education == 'elementalist'
365
- : tradition.necromancer.tier > 0 || invoker.education == 'necromancer')
369
+ : item.list in keysOf('trad')
370
+ && (fieldOf('tradition.{trad}.tier', item.list) > 0 || invoker.education == item.list))
366
371
  - id: art-tradition
367
372
  copies: { type: art }
368
373
  check: >-
369
374
  fieldOf('tradition.{trad}.tier', item.tradition) > 0 || invoker.education == item.tradition
370
375
  - id: arts-allowed
371
376
  check: >-
372
- arts.highmage.taken <= arts.highmage.allowed
373
- && arts.elementalist.taken <= arts.elementalist.allowed
374
- && arts.necromancer.taken <= arts.necromancer.allowed
375
- && arts.healer.taken <= arts.healer.allowed
376
- && arts.vowed.taken <= arts.vowed.allowed
377
- && arts.accursed.taken <= arts.accursed.allowed
378
- && arts.bard.taken <= arts.bard.allowed
379
- && arts.beastmaster.taken <= arts.beastmaster.allowed
380
- && arts.bloodpriest.taken <= arts.bloodpriest.allowed
381
- && arts.duelist.taken <= arts.duelist.allowed
382
- && arts.mageslayer.taken <= arts.mageslayer.allowed
383
- && arts.skinshifter.taken <= arts.skinshifter.allowed
384
- && arts.thoughtnoble.taken <= arts.thoughtnoble.allowed
385
- && arts.wise.taken <= arts.wise.allowed
377
+ countList(keysOf('artTrad'),
378
+ fieldOf('arts.{artTrad}.taken', x) > fieldOf('arts.{artTrad}.allowed', x)) == 0
386
379
  - id: effort-committed
387
380
  check: >-
388
- effort.highmage.scene + effort.highmage.day + effort.highmage.ongoing <= effort.highmage.max
389
- && effort.elementalist.scene + effort.elementalist.day + effort.elementalist.ongoing <= effort.elementalist.max
390
- && effort.necromancer.scene + effort.necromancer.day + effort.necromancer.ongoing <= effort.necromancer.max
391
- && effort.healer.scene + effort.healer.day + effort.healer.ongoing <= effort.healer.max
392
- && effort.vowed.scene + effort.vowed.day + effort.vowed.ongoing <= effort.vowed.max
393
- && effort.accursed.scene + effort.accursed.day + effort.accursed.ongoing <= effort.accursed.max
394
- && effort.bard.scene + effort.bard.day + effort.bard.ongoing <= effort.bard.max
395
- && effort.beastmaster.scene + effort.beastmaster.day + effort.beastmaster.ongoing <= effort.beastmaster.max
396
- && effort.bloodpriest.scene + effort.bloodpriest.day + effort.bloodpriest.ongoing <= effort.bloodpriest.max
397
- && effort.duelist.scene + effort.duelist.day + effort.duelist.ongoing <= effort.duelist.max
398
- && effort.mageslayer.scene + effort.mageslayer.day + effort.mageslayer.ongoing <= effort.mageslayer.max
399
- && effort.skinshifter.scene + effort.skinshifter.day + effort.skinshifter.ongoing <= effort.skinshifter.max
400
- && effort.thoughtnoble.scene + effort.thoughtnoble.day + effort.thoughtnoble.ongoing <= effort.thoughtnoble.max
381
+ countList(keysOf('effortTrad'), fieldOf('effort.{effortTrad}.scene', x)
382
+ + fieldOf('effort.{effortTrad}.day', x) + fieldOf('effort.{effortTrad}.ongoing', x)
383
+ > fieldOf('effort.{effortTrad}.max', x)) == 0
401
384
 
402
385
  actions:
403
386
  # Casting a prepared spell spends a casting, or an Invoker's spell points.
@@ -430,16 +413,20 @@ actions:
430
413
  tags: [art]
431
414
  available: >-
432
415
  item.effort != 'none' && level >= item.minLevel && !(item.effort == 'ongoing' && self.active)
433
- && item.tradition != 'wise' && fieldOf('effort.{effortTrad}.free', item.tradition) > 0
434
- && (item.tradition in ['highmage', 'elementalist', 'necromancer', 'vowed'] ? !magic.hindered
435
- : item.tradition == 'duelist' ? !duelist.hindered : true)
416
+ && item.tradition in keysOf('effortTrad')
417
+ && fieldOf('effort.{effortTrad}.free', item.tradition) > 0
418
+ && !(item.tradition in keysOf('armorTrad') && magic.hindered)
419
+ && !(item.tradition in keysOf('heavyArmorTrad') && duelist.hindered)
436
420
  results: [committed]
437
421
  steps:
438
422
  - id: commit
439
423
  kind: changes
440
424
  changes:
441
425
  - type: adjust
442
- field: { formula: "'effort.' + item.tradition + '.' + item.effort" }
426
+ field:
427
+ {
428
+ formula: "fieldId('effort.{effortTrad}.{effortSpan}', item.tradition, item.effort)",
429
+ }
443
430
  by: 1
444
431
  # A copy keeps its state; an art a class grants, its grant's saved state.
445
432
  - type: setState
@@ -467,7 +454,7 @@ actions:
467
454
  changes:
468
455
  - type: adjust
469
456
  when: "fieldOf('effort.{effortTrad}.ongoing', item.tradition) > 0"
470
- field: { formula: "'effort.' + item.tradition + '.ongoing'" }
457
+ field: { formula: "fieldId('effort.{effortTrad}.ongoing', item.tradition)" }
471
458
  by: -1
472
459
  - type: setState
473
460
  when: "!('granted' in item.tags)"
package/rules/saves.yaml CHANGED
@@ -30,7 +30,7 @@ situational:
30
30
 
31
31
  resultBands:
32
32
  save:
33
- - { id: success, when: roll.total >= flags.target }
33
+ - { id: success, when: roll.total >= flags.target, success: true }
34
34
  - { id: failure, when: true }
35
35
 
36
36
  actions:
package/rules/skills.yaml CHANGED
@@ -52,7 +52,7 @@ constraints:
52
52
  resultBands:
53
53
  check:
54
54
  - { id: rolled, when: flags.difficulty < 0 }
55
- - { id: success, when: roll.total >= flags.difficulty }
55
+ - { id: success, when: roll.total >= flags.difficulty, success: true }
56
56
  - { id: failure, when: true }
57
57
 
58
58
  actions:
package/rules/tags.yaml CHANGED
@@ -54,10 +54,16 @@ tags:
54
54
  - healing
55
55
  - health
56
56
  - rest
57
+ # Steps an add-on pack's rules effects reach.
58
+ - rest.night
59
+ - rest.scene
57
60
  - spell
58
61
  - art
59
62
  - creation
63
+ - creation.purse
64
+ - creation.finish
60
65
  - advancement
66
+ - advancement.level
61
67
  # Weapons
62
68
  - unarmed
63
69
  - two-handed
@@ -77,6 +83,7 @@ tags:
77
83
  - beast
78
84
  # Classes, foci and arts
79
85
  - mage-class
86
+ - full-mage
80
87
  - noncombat
81
88
  - gm-defined
82
89
  - granted
@@ -0,0 +1,61 @@
1
+ pack: wwn-srd
2
+ from: 0.1.0
3
+ to: 0.2.0
4
+ steps:
5
+ # The Mage's and the partial Mage's traditions were inline options; they are tradition content.
6
+ - {
7
+ op: renameOption,
8
+ owner: classes.mage,
9
+ choice: tradition,
10
+ from: high-mage,
11
+ to: traditions.high-mage,
12
+ }
13
+ - {
14
+ op: renameOption,
15
+ owner: classes.mage,
16
+ choice: tradition,
17
+ from: elementalist,
18
+ to: traditions.elementalist,
19
+ }
20
+ - {
21
+ op: renameOption,
22
+ owner: classes.mage,
23
+ choice: tradition,
24
+ from: necromancer,
25
+ to: traditions.necromancer,
26
+ }
27
+ - {
28
+ op: renameOption,
29
+ owner: classes.mage,
30
+ choice: tradition,
31
+ from: invoker,
32
+ to: traditions.invoker,
33
+ }
34
+ - {
35
+ op: renameOption,
36
+ owner: partials.mage,
37
+ choice: tradition,
38
+ from: high-mage,
39
+ to: traditions.high-mage,
40
+ }
41
+ - {
42
+ op: renameOption,
43
+ owner: partials.mage,
44
+ choice: tradition,
45
+ from: elementalist,
46
+ to: traditions.elementalist,
47
+ }
48
+ - {
49
+ op: renameOption,
50
+ owner: partials.mage,
51
+ choice: tradition,
52
+ from: necromancer,
53
+ to: traditions.necromancer,
54
+ }
55
+ - {
56
+ op: renameOption,
57
+ owner: partials.mage,
58
+ choice: tradition,
59
+ from: invoker,
60
+ to: traditions.invoker,
61
+ }