@opencharacter/awn-core 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.
- package/README.md +48 -3
- package/content/edges/educated.yaml +11 -0
- package/content/edges/focused.yaml +1 -0
- package/content/edges/forged-by-fire.yaml +1 -0
- package/content/edges/hardened-genetics.yaml +1 -0
- package/content/edges/mutant.yaml +17 -0
- package/content/edges/mutation-acceleration.yaml +24 -0
- package/content/edges/prodigy.yaml +1 -0
- package/content/foci/unstable-mutant.yaml +14 -0
- package/content/mutation-categories/cognition.yaml +2 -0
- package/content/mutation-categories/exotic.yaml +2 -0
- package/content/mutation-categories/hybrid.yaml +2 -0
- package/content/mutation-categories/pseudo-psychic.yaml +2 -0
- package/content/mutation-categories/sense.yaml +2 -0
- package/content/mutation-categories/structure.yaml +2 -0
- package/content/mutations/cognition/augmented-cognition.yaml +1 -1
- package/content/mutations/cognition/ballistic-calculator.yaml +1 -1
- package/content/mutations/cognition/eidetic-memory.yaml +1 -1
- package/content/mutations/cognition/internal-map.yaml +1 -1
- package/content/mutations/cognition/intuitive-leap.yaml +1 -1
- package/content/mutations/cognition/memory-eater.yaml +1 -1
- package/content/mutations/cognition/mental-bifurcation.yaml +1 -1
- package/content/mutations/cognition/mind-over-body.yaml +1 -1
- package/content/mutations/cognition/omniglot.yaml +1 -1
- package/content/mutations/cognition/predictive-analysis.yaml +1 -1
- package/content/mutations/exotic/chameleon-field.yaml +1 -1
- package/content/mutations/exotic/electrical-generation.yaml +1 -1
- package/content/mutations/exotic/hemovore.yaml +1 -1
- package/content/mutations/exotic/image-projection.yaml +1 -1
- package/content/mutations/exotic/metamorph.yaml +1 -1
- package/content/mutations/exotic/molecular-phasing.yaml +1 -1
- package/content/mutations/exotic/natural-projectiles.yaml +1 -1
- package/content/mutations/exotic/pheromone-cloud.yaml +1 -1
- package/content/mutations/exotic/photon-manipulation.yaml +1 -1
- package/content/mutations/exotic/sound-generation.yaml +1 -1
- package/content/mutations/hybrid/aquatic-adaptation.yaml +1 -1
- package/content/mutations/hybrid/arboreal-aptitude.yaml +1 -1
- package/content/mutations/hybrid/centauroid.yaml +1 -1
- package/content/mutations/hybrid/crushing-jaws.yaml +1 -1
- package/content/mutations/hybrid/digitigrade-legs.yaml +1 -1
- package/content/mutations/hybrid/functional-wings.yaml +1 -1
- package/content/mutations/hybrid/prehensile-limb.yaml +1 -1
- package/content/mutations/hybrid/savage-claws.yaml +1 -1
- package/content/mutations/hybrid/thick-hide.yaml +1 -1
- package/content/mutations/hybrid/venom-glands.yaml +1 -1
- package/content/mutations/pseudo-psychic/force-field.yaml +1 -1
- package/content/mutations/pseudo-psychic/induce-confusion.yaml +1 -1
- package/content/mutations/pseudo-psychic/limited-precognition.yaml +1 -1
- package/content/mutations/pseudo-psychic/mental-domination.yaml +1 -1
- package/content/mutations/pseudo-psychic/mind-reader.yaml +1 -1
- package/content/mutations/pseudo-psychic/neural-lockdown.yaml +1 -1
- package/content/mutations/pseudo-psychic/panic-wave.yaml +1 -1
- package/content/mutations/pseudo-psychic/spatial-displacement.yaml +1 -1
- package/content/mutations/pseudo-psychic/telekinetic-reach.yaml +1 -1
- package/content/mutations/pseudo-psychic/thermokinesis.yaml +1 -1
- package/content/mutations/sense/accelerated-perception.yaml +1 -1
- package/content/mutations/sense/acute-hearing.yaml +1 -1
- package/content/mutations/sense/acute-olfaction.yaml +1 -1
- package/content/mutations/sense/echolocation.yaml +1 -1
- package/content/mutations/sense/empathic-sensitivity.yaml +1 -1
- package/content/mutations/sense/night-vision.yaml +1 -1
- package/content/mutations/sense/panoptic-vision.yaml +1 -1
- package/content/mutations/sense/tactile-analysis.yaml +1 -1
- package/content/mutations/sense/telescopic-sight.yaml +1 -1
- package/content/mutations/sense/thermal-vision.yaml +1 -1
- package/content/mutations/structure/augmented-muscle.yaml +1 -1
- package/content/mutations/structure/explosive-exertion.yaml +1 -1
- package/content/mutations/structure/hypercontortion.yaml +1 -1
- package/content/mutations/structure/improved-joints.yaml +1 -1
- package/content/mutations/structure/leaper.yaml +1 -1
- package/content/mutations/structure/redundant-organs.yaml +1 -1
- package/content/mutations/structure/regenerator.yaml +1 -1
- package/content/mutations/structure/reinforced-tissues.yaml +1 -1
- package/content/mutations/structure/sealed-systems.yaml +1 -1
- package/content/mutations/structure/stamina-reserves.yaml +1 -1
- package/content/prepared/backpack.yaml +5 -0
- package/content/prepared/binoculars.yaml +4 -0
- package/content/prepared/camping-kit.yaml +4 -0
- package/content/prepared/cash.yaml +4 -0
- package/content/prepared/cold-weather-clothes.yaml +5 -0
- package/content/prepared/criminal-firearm.yaml +7 -0
- package/content/prepared/first-aid-kit.yaml +4 -0
- package/content/prepared/flashlight.yaml +4 -0
- package/content/prepared/heavy-pistol.yaml +7 -0
- package/content/prepared/knife.yaml +5 -0
- package/content/prepared/laptop.yaml +4 -0
- package/content/prepared/light-pistol.yaml +7 -0
- package/content/prepared/lighters.yaml +4 -0
- package/content/prepared/lockpick-kit.yaml +4 -0
- package/content/prepared/preserved-food.yaml +4 -0
- package/content/prepared/profession-item.yaml +4 -0
- package/content/prepared/purification-tablets.yaml +4 -0
- package/content/prepared/radio.yaml +4 -0
- package/content/prepared/rifle.yaml +7 -0
- package/content/prepared/shotgun.yaml +7 -0
- package/content/prepared/sleeping-bag.yaml +4 -0
- package/content/prepared/smartphone.yaml +4 -0
- package/content/prepared/solar-charger.yaml +4 -0
- package/content/prepared/tent.yaml +4 -0
- package/content/prepared/toolkit.yaml +4 -0
- package/content/prepared/walkie-talkies.yaml +5 -0
- package/content/prepared/water-purifier.yaml +4 -0
- package/content/weapons/primitive-bow.yaml +1 -0
- package/dist/i18n/en.js +1 -1
- package/dist/i18n/en.json +101 -34
- package/dist/index.js +1 -1
- package/dist/release.json +2008 -1434
- package/i18n/en/content.yaml +49 -0
- package/i18n/en/core.yaml +52 -34
- package/pack.yaml +2 -2
- package/package.json +2 -2
- package/rules/advancement.yaml +41 -42
- package/rules/backgrounds.yaml +17 -16
- package/rules/checks.yaml +5 -1
- package/rules/combat.yaml +1 -1
- package/rules/creation.yaml +71 -25
- package/rules/features.yaml +9 -4
- package/rules/gear.yaml +20 -1
- package/rules/layout.yaml +2 -0
- package/rules/mutations.yaml +50 -26
- package/rules/skills.yaml +8 -4
- package/rules/starting-equipment.yaml +24 -101
- package/rules/tags.yaml +13 -0
package/rules/creation.yaml
CHANGED
|
@@ -290,96 +290,112 @@ actions:
|
|
|
290
290
|
kind: action
|
|
291
291
|
use: starting-equipment
|
|
292
292
|
params: { random: params.random }
|
|
293
|
-
# A start may bring more than the survivor can haul. Readied items past the
|
|
294
|
-
# stowed
|
|
295
|
-
# first), so play starts
|
|
293
|
+
# A start may bring more than the survivor can haul. Readied items past the limit are
|
|
294
|
+
# stowed; Stowed gear past it is readied where it fits, then left behind (gear, then weapons,
|
|
295
|
+
# then armor, the heaviest first), so play starts unencumbered.
|
|
296
296
|
- id: stowGear
|
|
297
297
|
kind: choice
|
|
298
298
|
sheet: proposed
|
|
299
|
-
when: encumbrance.overload >
|
|
300
|
-
repeat: { max: 20 }
|
|
299
|
+
when: encumbrance.overload > 0
|
|
300
|
+
repeat: { max: 20, min: 20 }
|
|
301
301
|
options:
|
|
302
302
|
copies:
|
|
303
303
|
type: gear
|
|
304
304
|
where: >-
|
|
305
305
|
self.equipped && has(item.enc) && item.enc > 0
|
|
306
306
|
&& !(has(item.wornFree) && item.wornFree)
|
|
307
|
-
&& encumbrance.readied > encumbrance.readied.max
|
|
307
|
+
&& encumbrance.readied > encumbrance.readied.max
|
|
308
308
|
prefer: item.enc
|
|
309
309
|
changes:
|
|
310
310
|
- { type: equip, entry: picked, equipped: false }
|
|
311
311
|
- id: stowWeapon
|
|
312
312
|
kind: choice
|
|
313
313
|
sheet: proposed
|
|
314
|
-
when: encumbrance.overload >
|
|
315
|
-
repeat: { max: 20 }
|
|
314
|
+
when: encumbrance.overload > 0
|
|
315
|
+
repeat: { max: 20, min: 20 }
|
|
316
316
|
options:
|
|
317
317
|
copies:
|
|
318
318
|
type: weapon
|
|
319
319
|
where: >-
|
|
320
320
|
self.equipped && item.enc > 0
|
|
321
|
-
&& encumbrance.readied > encumbrance.readied.max
|
|
321
|
+
&& encumbrance.readied > encumbrance.readied.max
|
|
322
322
|
prefer: item.enc
|
|
323
323
|
changes:
|
|
324
324
|
- { type: equip, entry: picked, equipped: false }
|
|
325
325
|
- id: stowArmor
|
|
326
326
|
kind: choice
|
|
327
327
|
sheet: proposed
|
|
328
|
-
when: encumbrance.overload >
|
|
329
|
-
repeat: { max: 20 }
|
|
328
|
+
when: encumbrance.overload > 0
|
|
329
|
+
repeat: { max: 20, min: 20 }
|
|
330
330
|
options:
|
|
331
331
|
copies:
|
|
332
332
|
type: armor
|
|
333
333
|
where: >-
|
|
334
334
|
self.equipped && item.enc > 0
|
|
335
|
-
&& encumbrance.readied > encumbrance.readied.max
|
|
335
|
+
&& encumbrance.readied > encumbrance.readied.max
|
|
336
336
|
prefer: item.enc
|
|
337
337
|
changes:
|
|
338
338
|
- { type: equip, entry: picked, equipped: false }
|
|
339
|
-
- id:
|
|
339
|
+
- id: readyGear
|
|
340
340
|
kind: choice
|
|
341
341
|
sheet: proposed
|
|
342
|
-
when: encumbrance.overload >
|
|
343
|
-
repeat: { max: 20 }
|
|
342
|
+
when: encumbrance.overload > 0
|
|
343
|
+
repeat: { max: 20, min: 20 }
|
|
344
344
|
options:
|
|
345
345
|
copies:
|
|
346
346
|
type: gear
|
|
347
347
|
where: >-
|
|
348
348
|
!self.equipped && has(item.enc) && item.enc > 0
|
|
349
|
-
&& encumbrance.stowed > encumbrance.stowed.max
|
|
349
|
+
&& encumbrance.stowed > encumbrance.stowed.max
|
|
350
|
+
&& encumbrance.readied + item.enc * self.quantity <= encumbrance.readied.max
|
|
350
351
|
prefer: item.enc
|
|
352
|
+
changes:
|
|
353
|
+
- { type: equip, entry: picked, equipped: true }
|
|
354
|
+
- id: dropGear
|
|
355
|
+
kind: choice
|
|
356
|
+
sheet: proposed
|
|
357
|
+
when: encumbrance.overload > 0
|
|
358
|
+
repeat: { max: 20, min: 20 }
|
|
359
|
+
options:
|
|
360
|
+
copies:
|
|
361
|
+
type: gear
|
|
362
|
+
where: >-
|
|
363
|
+
!self.equipped && has(item.enc) && item.enc > 0
|
|
364
|
+
&& encumbrance.stowed > encumbrance.stowed.max
|
|
365
|
+
prefer: "item.enc * ('bundleable' in item.tags ? floor((self.quantity + 2) / 3) : self.quantity)"
|
|
351
366
|
changes:
|
|
352
367
|
- { type: removeItem, entry: picked }
|
|
353
368
|
- id: dropWeapon
|
|
354
369
|
kind: choice
|
|
355
370
|
sheet: proposed
|
|
356
|
-
when: encumbrance.overload >
|
|
357
|
-
repeat: { max: 20 }
|
|
371
|
+
when: encumbrance.overload > 0
|
|
372
|
+
repeat: { max: 20, min: 20 }
|
|
358
373
|
options:
|
|
359
374
|
copies:
|
|
360
375
|
type: weapon
|
|
361
376
|
where: >-
|
|
362
377
|
!self.equipped && item.enc > 0
|
|
363
|
-
&& encumbrance.stowed > encumbrance.stowed.max
|
|
378
|
+
&& encumbrance.stowed > encumbrance.stowed.max
|
|
364
379
|
prefer: item.enc
|
|
365
380
|
changes:
|
|
366
381
|
- { type: removeItem, entry: picked }
|
|
367
382
|
- id: dropArmor
|
|
368
383
|
kind: choice
|
|
369
384
|
sheet: proposed
|
|
370
|
-
when: encumbrance.overload >
|
|
371
|
-
repeat: { max: 20 }
|
|
385
|
+
when: encumbrance.overload > 0
|
|
386
|
+
repeat: { max: 20, min: 20 }
|
|
372
387
|
options:
|
|
373
388
|
copies:
|
|
374
389
|
type: armor
|
|
375
390
|
where: >-
|
|
376
391
|
!self.equipped && item.enc > 0
|
|
377
|
-
&& encumbrance.stowed > encumbrance.stowed.max
|
|
392
|
+
&& encumbrance.stowed > encumbrance.stowed.max
|
|
378
393
|
prefer: item.enc
|
|
379
394
|
changes:
|
|
380
395
|
- { type: removeItem, entry: picked }
|
|
381
396
|
|
|
382
397
|
- id: finish
|
|
398
|
+
tags: [creation.finish]
|
|
383
399
|
kind: changes
|
|
384
400
|
sheet: proposed
|
|
385
401
|
changes:
|
|
@@ -391,11 +407,41 @@ actions:
|
|
|
391
407
|
# One entry of a background's tables: a skill (`any-combat`, `any-skill` or a skill key), or
|
|
392
408
|
# an attribute bonus, which the highest attribute that can take it all is recommended.
|
|
393
409
|
- id: gain-benefit
|
|
410
|
+
available: character.creating
|
|
394
411
|
params:
|
|
395
|
-
entry:
|
|
412
|
+
entry:
|
|
413
|
+
type: enum
|
|
414
|
+
open: true
|
|
415
|
+
values:
|
|
416
|
+
[
|
|
417
|
+
administer,
|
|
418
|
+
connect,
|
|
419
|
+
drive,
|
|
420
|
+
exert,
|
|
421
|
+
fix,
|
|
422
|
+
heal,
|
|
423
|
+
know,
|
|
424
|
+
lead,
|
|
425
|
+
notice,
|
|
426
|
+
perform,
|
|
427
|
+
program,
|
|
428
|
+
punch,
|
|
429
|
+
shoot,
|
|
430
|
+
sneak,
|
|
431
|
+
stab,
|
|
432
|
+
survive,
|
|
433
|
+
talk,
|
|
434
|
+
trade,
|
|
435
|
+
work,
|
|
436
|
+
any-combat,
|
|
437
|
+
any-skill,
|
|
438
|
+
any-stat-1,
|
|
439
|
+
physical2,
|
|
440
|
+
mental2,
|
|
441
|
+
]
|
|
396
442
|
prefer: { type: set, of: string, default: [] }
|
|
397
443
|
random: { type: boolean, default: false }
|
|
398
|
-
results: [gained]
|
|
444
|
+
results: [gained, none]
|
|
399
445
|
steps:
|
|
400
446
|
- id: skill
|
|
401
447
|
kind: action
|
|
@@ -446,4 +492,4 @@ actions:
|
|
|
446
492
|
by: 1
|
|
447
493
|
- id: result
|
|
448
494
|
kind: outcome
|
|
449
|
-
result: "'gained'"
|
|
495
|
+
result: "has(steps.skill) && steps.skill.result == 'none' ? 'none' : 'gained'"
|
package/rules/features.yaml
CHANGED
|
@@ -4,6 +4,8 @@ contentTypes:
|
|
|
4
4
|
edge:
|
|
5
5
|
fields:
|
|
6
6
|
bonusSkill: { type: set, of: string, default: [] }
|
|
7
|
+
# It has a `gain-part` action, run when the edge is taken.
|
|
8
|
+
gainPart: { type: boolean, default: false }
|
|
7
9
|
effects:
|
|
8
10
|
- { target: edges.held, op: grant, value: { formula: item.id } }
|
|
9
11
|
|
|
@@ -18,6 +20,8 @@ contentTypes:
|
|
|
18
20
|
specialty: { type: boolean, default: false }
|
|
19
21
|
bonusSkill: { type: set, of: string, default: [] }
|
|
20
22
|
bonusSkill2: { type: set, of: string, default: [] }
|
|
23
|
+
# It has a `gain-part` action, run when the focus is taken.
|
|
24
|
+
gainPart: { type: boolean, default: false }
|
|
21
25
|
state:
|
|
22
26
|
level: { type: integer, default: 1, min: 1, max: item.maxLevel }
|
|
23
27
|
effects:
|
|
@@ -35,7 +39,9 @@ fields:
|
|
|
35
39
|
|
|
36
40
|
# Two edges at 1st level and one at 5th; Forged By Fire takes the place of the first two and
|
|
37
41
|
# gives one at each of 2nd, 3rd and 4th instead.
|
|
38
|
-
edges.forgedByFire:
|
|
42
|
+
edges.forgedByFire:
|
|
43
|
+
type: boolean
|
|
44
|
+
formula: "countCopies(copy.type == 'edge' && 'first-edge' in copy.tags) > 0"
|
|
39
45
|
edges.allowed:
|
|
40
46
|
type: integer
|
|
41
47
|
formula: >-
|
|
@@ -61,9 +67,8 @@ constraints:
|
|
|
61
67
|
check: '!character.creating || !edges.underdog || attributes.baseTotal <= -1'
|
|
62
68
|
# Each edge once, but Focused; each focus once, but Specialist.
|
|
63
69
|
- id: edge-once
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
- (@edges.focused in edges.held ? 1 : 0)
|
|
70
|
+
copies: { type: edge, where: "!('repeatable' in item.tags)" }
|
|
71
|
+
check: countCopies(copy.item == item.id) == 1
|
|
67
72
|
- id: focus-once
|
|
68
73
|
copies: { type: focus, where: '!item.multiple' }
|
|
69
74
|
check: countCopies(copy.item == item.id) == 1
|
package/rules/gear.yaml
CHANGED
|
@@ -20,6 +20,8 @@ contentTypes:
|
|
|
20
20
|
techLevel: { type: integer, min: 0, max: 5 }
|
|
21
21
|
traumaDie: { type: dice }
|
|
22
22
|
traumaRating: { type: integer, min: 1 }
|
|
23
|
+
# The ammunition a primitive missile weapon starts with in a wasteland warrior's kit.
|
|
24
|
+
kitAmmo: { type: id, of: gear }
|
|
23
25
|
state:
|
|
24
26
|
shots: { type: integer, min: 0, default: 'has(item.magazine) ? item.magazine : 0' }
|
|
25
27
|
computed:
|
|
@@ -101,6 +103,19 @@ contentTypes:
|
|
|
101
103
|
# Drugs and stims: the Heal level applying it needs.
|
|
102
104
|
healSkill: { type: integer, min: 0 }
|
|
103
105
|
|
|
106
|
+
# A pick on the prepared survivors' list: the item (`gear`, a weapon, armor or gear ID; another
|
|
107
|
+
# pack's qualified), how many, readied or not, and what comes with it (a firearm's magazines).
|
|
108
|
+
prepared:
|
|
109
|
+
grantOnly: true
|
|
110
|
+
carried: false
|
|
111
|
+
copies: { max: 0 }
|
|
112
|
+
fields:
|
|
113
|
+
gear: { type: string, required: true }
|
|
114
|
+
quantity: { type: integer, default: 1, min: 1 }
|
|
115
|
+
equipped: { type: boolean, default: false }
|
|
116
|
+
extra: { type: string }
|
|
117
|
+
extraQuantity: { type: integer, default: 1, min: 1 }
|
|
118
|
+
|
|
104
119
|
# Everyone has fists.
|
|
105
120
|
standardCopies:
|
|
106
121
|
- { type: weapon, where: 'item.id == @weapons.unarmed' }
|
|
@@ -154,7 +169,11 @@ situational:
|
|
|
154
169
|
|
|
155
170
|
resultBands:
|
|
156
171
|
attack:
|
|
157
|
-
- {
|
|
172
|
+
- {
|
|
173
|
+
id: hit,
|
|
174
|
+
when: 'roll.kept[0] == 20 || (roll.kept[0] != 1 && roll.total >= flags.ac)',
|
|
175
|
+
success: true,
|
|
176
|
+
}
|
|
158
177
|
- { id: miss, when: true }
|
|
159
178
|
|
|
160
179
|
actions:
|
package/rules/layout.yaml
CHANGED
|
@@ -118,6 +118,8 @@ display:
|
|
|
118
118
|
foci.bonus: { hidden: true }
|
|
119
119
|
encumbrance.armorFactor: { hidden: true }
|
|
120
120
|
mutations.mutant: { hidden: true }
|
|
121
|
+
mutations.barred: { hidden: true }
|
|
122
|
+
mutations.points.edges: { hidden: true }
|
|
121
123
|
mutations.noVision: { hidden: true }
|
|
122
124
|
mutations.noHearing: { hidden: true }
|
|
123
125
|
mutations.sensitiveSkin: { hidden: true }
|
package/rules/mutations.yaml
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
contentTypes:
|
|
2
|
+
# The positive mutations' categories: the book's six, in its order on the d6 table.
|
|
3
|
+
mutationCategory:
|
|
4
|
+
grantOnly: true
|
|
5
|
+
carried: false
|
|
6
|
+
copies: { max: 0 }
|
|
7
|
+
|
|
2
8
|
# Positive mutations: their category and their d10 roll within it (the d6 picks the category).
|
|
3
9
|
# `origin` is how it was bought: one point rolled, three for a pair rolled in one category,
|
|
4
10
|
# three chosen, or free (a negative mutation's compensation, the Unstable Mutant focus).
|
|
5
11
|
mutation:
|
|
6
12
|
fields:
|
|
7
|
-
category:
|
|
8
|
-
{
|
|
9
|
-
type: enum,
|
|
10
|
-
values: [structure, sense, hybrid, cognition, pseudo-psychic, exotic],
|
|
11
|
-
required: true,
|
|
12
|
-
}
|
|
13
|
+
category: { type: id, of: mutationCategory, required: true }
|
|
13
14
|
roll: { type: integer, required: true, min: 1, max: 10 }
|
|
14
15
|
bonusSkill: { type: set, of: string, default: [] }
|
|
15
16
|
state:
|
|
@@ -23,14 +24,20 @@ contentTypes:
|
|
|
23
24
|
light: { type: boolean, default: false }
|
|
24
25
|
|
|
25
26
|
fields:
|
|
26
|
-
mutations.mutant:
|
|
27
|
+
mutations.mutant:
|
|
28
|
+
type: boolean
|
|
29
|
+
formula: "countCopies(copy.type == 'edge' && 'makes-mutant' in copy.tags) > 0"
|
|
30
|
+
# An edge that bars mutation is held (Hardened Genetics).
|
|
31
|
+
mutations.barred:
|
|
32
|
+
type: boolean
|
|
33
|
+
formula: "countCopies(copy.type == 'edge' && 'not-mutant' in copy.tags) > 0"
|
|
34
|
+
# Mutation points edges give: 2 for Mutant, 2 for Mutation Acceleration.
|
|
35
|
+
mutations.points.edges: { type: integer, formula: 0 }
|
|
27
36
|
mutations.negatives: { type: integer, formula: "countCopies(copy.type == 'negative')" }
|
|
28
|
-
# Mutation points:
|
|
37
|
+
# Mutation points: the edges', and 2 per negative mutation.
|
|
29
38
|
mutations.points.total:
|
|
30
39
|
type: integer
|
|
31
|
-
formula:
|
|
32
|
-
(mutations.mutant ? 2 : 0) + (@edges.mutation-acceleration in edges.held ? 2 : 0)
|
|
33
|
-
+ 2 * mutations.negatives
|
|
40
|
+
formula: mutations.points.edges + 2 * mutations.negatives
|
|
34
41
|
# A stigma that normal clothing hides costs a point.
|
|
35
42
|
mutations.stigmaConcealed: { type: boolean, input: true, default: false }
|
|
36
43
|
mutations.points.spent:
|
|
@@ -50,17 +57,31 @@ fields:
|
|
|
50
57
|
# The stigma, from the suggestion tables: a body part (a second one when the first roll says
|
|
51
58
|
# so), the nature of the change, and a detail.
|
|
52
59
|
stigma.part:
|
|
53
|
-
{
|
|
60
|
+
{
|
|
61
|
+
type: enum,
|
|
62
|
+
input: true,
|
|
63
|
+
open: true,
|
|
64
|
+
default: none,
|
|
65
|
+
values: [none, head, arms, legs, torso, senses],
|
|
66
|
+
}
|
|
54
67
|
stigma.part2:
|
|
55
|
-
{
|
|
68
|
+
{
|
|
69
|
+
type: enum,
|
|
70
|
+
input: true,
|
|
71
|
+
open: true,
|
|
72
|
+
default: none,
|
|
73
|
+
values: [none, head, arms, legs, torso, senses],
|
|
74
|
+
}
|
|
56
75
|
stigma.nature:
|
|
57
76
|
type: enum
|
|
58
77
|
input: true
|
|
78
|
+
open: true
|
|
59
79
|
default: none
|
|
60
80
|
values: [none, appearance, animal, size, plant, amorphous, mineral]
|
|
61
81
|
stigma.detail:
|
|
62
82
|
type: enum
|
|
63
83
|
input: true
|
|
84
|
+
open: true
|
|
64
85
|
default: none
|
|
65
86
|
values:
|
|
66
87
|
[
|
|
@@ -137,6 +158,7 @@ actions:
|
|
|
137
158
|
# The random start rolls a d4 for 0-3 negative mutations and spends every point on single
|
|
138
159
|
# random rolls; the guided one recommends no negative mutation and the same rolls.
|
|
139
160
|
- id: mutate
|
|
161
|
+
available: character.creating
|
|
140
162
|
tags: [creation]
|
|
141
163
|
params:
|
|
142
164
|
random: { type: boolean, default: false }
|
|
@@ -275,6 +297,7 @@ actions:
|
|
|
275
297
|
# The stigma suggestions: a d6 body part (on a 6, two parts), a d6 nature, and a d12 detail
|
|
276
298
|
# from the column that matches the nature (texture for size, amorphous and mineral changes).
|
|
277
299
|
- id: roll-stigma
|
|
300
|
+
available: character.creating
|
|
278
301
|
tags: [creation]
|
|
279
302
|
results: [rolled]
|
|
280
303
|
steps:
|
|
@@ -333,6 +356,7 @@ actions:
|
|
|
333
356
|
# (or a second lightly touched result) is rolled again, twice; after that a uniform draw among
|
|
334
357
|
# the ones left stands in for rolling until something new comes up.
|
|
335
358
|
- id: roll-negative-mutation
|
|
359
|
+
available: character.creating
|
|
336
360
|
tags: [creation]
|
|
337
361
|
params:
|
|
338
362
|
random: { type: boolean, default: false }
|
|
@@ -490,7 +514,7 @@ actions:
|
|
|
490
514
|
content:
|
|
491
515
|
type: mutation
|
|
492
516
|
where: >-
|
|
493
|
-
item.category ==
|
|
517
|
+
item.category == @mutation-categories.sense && !('vision' in item.tags)
|
|
494
518
|
&& countCopies(copy.item == item.id) == 0
|
|
495
519
|
random: params.random
|
|
496
520
|
recommend: options[0]
|
|
@@ -504,12 +528,14 @@ actions:
|
|
|
504
528
|
# Spending mutation points: one to roll a positive mutation, three to roll two in a category,
|
|
505
529
|
# three to choose one.
|
|
506
530
|
- id: buy-mutation
|
|
531
|
+
available: character.creating
|
|
507
532
|
tags: [creation]
|
|
508
533
|
params:
|
|
509
534
|
random: { type: boolean, default: false }
|
|
510
535
|
results: [bought]
|
|
511
536
|
steps:
|
|
512
537
|
- id: how
|
|
538
|
+
tags: [creation.mutation]
|
|
513
539
|
kind: choice
|
|
514
540
|
sheet: proposed
|
|
515
541
|
options:
|
|
@@ -525,15 +551,9 @@ actions:
|
|
|
525
551
|
- id: category
|
|
526
552
|
kind: choice
|
|
527
553
|
when: "steps.how.picked == 'category'"
|
|
528
|
-
options:
|
|
529
|
-
- { id: structure }
|
|
530
|
-
- { id: sense }
|
|
531
|
-
- { id: hybrid }
|
|
532
|
-
- { id: cognition }
|
|
533
|
-
- { id: pseudo-psychic }
|
|
534
|
-
- { id: exotic }
|
|
554
|
+
options: { content: { type: mutationCategory } }
|
|
535
555
|
random: params.random
|
|
536
|
-
recommend: options[0]
|
|
556
|
+
recommend: 'filterList([@mutation-categories.structure, options[0]], x in options)[0]'
|
|
537
557
|
- id: pair1
|
|
538
558
|
kind: action
|
|
539
559
|
when: "steps.how.picked == 'category'"
|
|
@@ -574,10 +594,11 @@ actions:
|
|
|
574
594
|
# it. A result the character can't take (held already, or barred by a negative mutation) is
|
|
575
595
|
# rolled again; a uniform draw among those it can take stands in for rolling until one fits.
|
|
576
596
|
- id: roll-mutation
|
|
597
|
+
available: character.creating
|
|
577
598
|
tags: [creation]
|
|
578
599
|
params:
|
|
579
600
|
origin: { type: enum, values: [random, category, chosen, free, unstable], default: random }
|
|
580
|
-
category: { type:
|
|
601
|
+
category: { type: id, of: mutationCategory, optional: true }
|
|
581
602
|
random: { type: boolean, default: false }
|
|
582
603
|
results: [rolled]
|
|
583
604
|
steps:
|
|
@@ -595,8 +616,10 @@ actions:
|
|
|
595
616
|
flags:
|
|
596
617
|
category: >-
|
|
597
618
|
has(params.category) ? params.category
|
|
598
|
-
: [
|
|
599
|
-
|
|
619
|
+
: [@mutation-categories.structure, @mutation-categories.sense,
|
|
620
|
+
@mutation-categories.hybrid, @mutation-categories.cognition,
|
|
621
|
+
@mutation-categories.pseudo-psychic,
|
|
622
|
+
@mutation-categories.exotic][steps.categoryRoll.total - 1]
|
|
600
623
|
- { id: roll, kind: roll, tags: [creation], parts: [{ dice: 1d10 }] }
|
|
601
624
|
- id: exact
|
|
602
625
|
kind: choice
|
|
@@ -645,6 +668,7 @@ actions:
|
|
|
645
668
|
# Levels past a skill's cap (a skill a negative mutation forbids, or Slow Development's lower
|
|
646
669
|
# maximum) go to other skills, a pick per level: the skill drops to its cap.
|
|
647
670
|
- id: reassign-barred-skills
|
|
671
|
+
available: character.creating
|
|
648
672
|
tags: [creation]
|
|
649
673
|
params:
|
|
650
674
|
random: { type: boolean, default: false }
|
|
@@ -669,7 +693,7 @@ actions:
|
|
|
669
693
|
changes:
|
|
670
694
|
- type: set
|
|
671
695
|
forEach: flags.barred
|
|
672
|
-
field: { formula: "'skills.'
|
|
696
|
+
field: { formula: "fieldId('skills.{skill}.level', x)" }
|
|
673
697
|
value: "max(-1, fieldOf('skills.{skill}.cap', x))"
|
|
674
698
|
- {
|
|
675
699
|
id: relearn1,
|
package/rules/skills.yaml
CHANGED
|
@@ -59,11 +59,12 @@ actions:
|
|
|
59
59
|
# skill when none of the offered ones can take it). `skills` lists the skill keys offered (all
|
|
60
60
|
# when empty); `prefer` the ones to recommend, in order.
|
|
61
61
|
- id: gain-skill
|
|
62
|
+
listed: false
|
|
62
63
|
params:
|
|
63
64
|
skills: { type: set, of: string, default: [] }
|
|
64
65
|
prefer: { type: set, of: string, default: [] }
|
|
65
66
|
random: { type: boolean, default: false }
|
|
66
|
-
results: [gained]
|
|
67
|
+
results: [gained, none]
|
|
67
68
|
steps:
|
|
68
69
|
- id: open
|
|
69
70
|
kind: branch
|
|
@@ -91,16 +92,19 @@ actions:
|
|
|
91
92
|
flags:
|
|
92
93
|
suggest: >-
|
|
93
94
|
size(filterList(params.prefer, x in flags.offered)) > 0
|
|
94
|
-
? filterList(params.prefer, x in flags.offered)[0]
|
|
95
|
+
? filterList(params.prefer, x in flags.offered)[0]
|
|
96
|
+
: size(flags.offered) > 0 ? flags.offered[0] : ''
|
|
97
|
+
# Every skill at its cap: nothing to gain.
|
|
95
98
|
- id: skill
|
|
96
99
|
kind: choice
|
|
100
|
+
when: size(flags.offered) > 0
|
|
97
101
|
options: { values: { formula: flags.offered } }
|
|
98
102
|
random: params.random
|
|
99
103
|
recommend: flags.suggest
|
|
100
104
|
changes:
|
|
101
105
|
- type: adjust
|
|
102
|
-
field: { formula: "'skills.'
|
|
106
|
+
field: { formula: "fieldId('skills.{skill}.level', picked.value)" }
|
|
103
107
|
by: 1
|
|
104
108
|
- id: result
|
|
105
109
|
kind: outcome
|
|
106
|
-
result: "'gained'"
|
|
110
|
+
result: "has(steps.skill) ? 'gained' : 'none'"
|
|
@@ -4,121 +4,43 @@ actions:
|
|
|
4
4
|
# wasteland warriors get a kit, then one pick or three rolls on a d20 table: the near-future
|
|
5
5
|
# one or the wasteland one. The book's default setting is a wasteland, so that is recommended.
|
|
6
6
|
- id: starting-equipment
|
|
7
|
+
available: character.creating
|
|
7
8
|
tags: [creation]
|
|
8
9
|
params:
|
|
9
10
|
random: { type: boolean, default: false }
|
|
10
11
|
results: [equipped]
|
|
11
12
|
steps:
|
|
12
13
|
- id: kit
|
|
14
|
+
tags: [creation.kit]
|
|
13
15
|
kind: choice
|
|
14
16
|
options: [{ id: innocents }, { id: prepared }, { id: near-future }, { id: wasteland }]
|
|
15
17
|
recommend: "'wasteland'"
|
|
18
|
+
# Four different picks from the list (`prepared` content, an add-on pack's too).
|
|
16
19
|
- id: prepared
|
|
17
20
|
kind: choice
|
|
18
21
|
when: "steps.kit.picked == 'prepared'"
|
|
19
22
|
repeat: { max: 4, min: 4 }
|
|
20
23
|
random: params.random
|
|
21
24
|
recommend: >-
|
|
22
|
-
size(filterList([
|
|
23
|
-
|
|
25
|
+
size(filterList([@prepared.knife, @prepared.first-aid-kit, @prepared.preserved-food,
|
|
26
|
+
@prepared.backpack], x in options)) > 0
|
|
27
|
+
? filterList([@prepared.knife, @prepared.first-aid-kit, @prepared.preserved-food,
|
|
28
|
+
@prepared.backpack], x in options)[0]
|
|
24
29
|
: options[0]
|
|
25
|
-
options:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- { type: addItem, entry: { item: "'gear.magazine'", quantity: 2 } }
|
|
36
|
-
- id: rifle
|
|
37
|
-
when: picks == 0
|
|
38
|
-
changes:
|
|
39
|
-
- { type: addItem, entry: { item: "'weapons.rifle'", equipped: true } }
|
|
40
|
-
- { type: addItem, entry: { item: "'gear.magazine'", quantity: 2 } }
|
|
41
|
-
- id: shotgun
|
|
42
|
-
when: picks == 0
|
|
43
|
-
changes:
|
|
44
|
-
- { type: addItem, entry: { item: "'weapons.shotgun'", equipped: true } }
|
|
45
|
-
- { type: addItem, entry: { item: "'gear.ammo'", quantity: 2 } }
|
|
46
|
-
# A criminal's non-military firearm: the semi-auto shotgun stands for any of them.
|
|
47
|
-
- id: criminal-firearm
|
|
48
|
-
when: picks == 0
|
|
49
|
-
changes:
|
|
50
|
-
- { type: addItem, entry: { item: "'weapons.semi-auto-shotgun'", equipped: true } }
|
|
51
|
-
- { type: addItem, entry: { item: "'gear.magazine'", quantity: 2 } }
|
|
52
|
-
- id: knife
|
|
53
|
-
when: picks == 0
|
|
54
|
-
changes: [{ type: addItem, entry: { item: "'weapons.knife'", equipped: true } }]
|
|
55
|
-
- id: smartphone
|
|
56
|
-
when: picks == 0
|
|
57
|
-
changes: [{ type: addItem, entry: { item: "'gear.smartphone'" } }]
|
|
58
|
-
- id: preserved-food
|
|
59
|
-
when: picks == 0
|
|
60
|
-
changes: [{ type: addItem, entry: { item: "'gear.preserved-food'" } }]
|
|
61
|
-
- id: camping-kit
|
|
62
|
-
when: picks == 0
|
|
63
|
-
changes: [{ type: addItem, entry: { item: "'gear.camping-kit'" } }]
|
|
64
|
-
- id: first-aid-kit
|
|
65
|
-
when: picks == 0
|
|
66
|
-
changes: [{ type: addItem, entry: { item: "'gear.first-aid-kit'" } }]
|
|
67
|
-
- id: tent
|
|
68
|
-
when: picks == 0
|
|
69
|
-
changes: [{ type: addItem, entry: { item: "'gear.tent'" } }]
|
|
70
|
-
- id: toolkit
|
|
71
|
-
when: picks == 0
|
|
72
|
-
changes: [{ type: addItem, entry: { item: "'gear.toolkit'" } }]
|
|
73
|
-
- id: flashlight
|
|
74
|
-
when: picks == 0
|
|
75
|
-
changes: [{ type: addItem, entry: { item: "'gear.flashlight'" } }]
|
|
76
|
-
- id: cold-weather-clothes
|
|
77
|
-
when: picks == 0
|
|
78
|
-
changes:
|
|
79
|
-
[{ type: addItem, entry: { item: "'gear.clothes-cold-weather'", equipped: true } }]
|
|
80
|
-
- id: sleeping-bag
|
|
81
|
-
when: picks == 0
|
|
82
|
-
changes: [{ type: addItem, entry: { item: "'gear.sleeping-bag'" } }]
|
|
83
|
-
- id: cash
|
|
84
|
-
when: picks == 0
|
|
85
|
-
changes: [{ type: addItem, entry: { item: "'gear.cash'" } }]
|
|
86
|
-
- id: laptop
|
|
87
|
-
when: picks == 0
|
|
88
|
-
changes: [{ type: addItem, entry: { item: "'gear.laptop'" } }]
|
|
89
|
-
- id: walkie-talkies
|
|
90
|
-
when: picks == 0
|
|
91
|
-
changes: [{ type: addItem, entry: { item: "'gear.walkie-talkie'", quantity: 2 } }]
|
|
92
|
-
- id: solar-charger
|
|
93
|
-
when: picks == 0
|
|
94
|
-
changes: [{ type: addItem, entry: { item: "'gear.solar-charger'" } }]
|
|
95
|
-
- id: radio
|
|
96
|
-
when: picks == 0
|
|
97
|
-
changes: [{ type: addItem, entry: { item: "'gear.radio'" } }]
|
|
98
|
-
- id: lockpick-kit
|
|
99
|
-
when: picks == 0
|
|
100
|
-
changes: [{ type: addItem, entry: { item: "'gear.lockpick-kit'" } }]
|
|
101
|
-
- id: lighters
|
|
102
|
-
when: picks == 0
|
|
103
|
-
changes: [{ type: addItem, entry: { item: "'gear.lighters'" } }]
|
|
104
|
-
- id: purification-tablets
|
|
105
|
-
when: picks == 0
|
|
106
|
-
changes: [{ type: addItem, entry: { item: "'gear.purification-tablets'" } }]
|
|
107
|
-
- id: profession-item
|
|
108
|
-
when: picks == 0
|
|
109
|
-
changes: [{ type: addItem, entry: { item: "'gear.profession-item'" } }]
|
|
110
|
-
- id: backpack
|
|
111
|
-
when: picks == 0
|
|
112
|
-
changes: [{ type: addItem, entry: { item: "'gear.backpack'", equipped: true } }]
|
|
113
|
-
- id: binoculars
|
|
114
|
-
when: picks == 0
|
|
115
|
-
changes: [{ type: addItem, entry: { item: "'gear.binoculars'" } }]
|
|
116
|
-
- id: water-purifier
|
|
117
|
-
when: picks == 0
|
|
118
|
-
changes: [{ type: addItem, entry: { item: "'gear.water-purifier'" } }]
|
|
30
|
+
options: { content: { type: prepared, where: picks == 0 } }
|
|
31
|
+
changes:
|
|
32
|
+
- type: addItem
|
|
33
|
+
entry:
|
|
34
|
+
item: picked.item.gear
|
|
35
|
+
quantity: picked.item.quantity
|
|
36
|
+
equipped: picked.item.equipped
|
|
37
|
+
- type: addItem
|
|
38
|
+
when: has(picked.item.extra)
|
|
39
|
+
entry: { item: picked.item.extra, quantity: picked.item.extraQuantity }
|
|
119
40
|
|
|
120
|
-
# The warrior's kit: a primitive melee weapon or a primitive bow with 20 arrows
|
|
121
|
-
# backpack, sleeping bag, tinderbox, three
|
|
41
|
+
# The warrior's kit: a primitive melee weapon or a primitive bow with 20 arrows (a primitive
|
|
42
|
+
# missile weapon with its `kitAmmo`), a knife, backpack, sleeping bag, tinderbox, three
|
|
43
|
+
# torches, clothes and 1d4 days of food.
|
|
122
44
|
- id: weapon
|
|
123
45
|
kind: choice
|
|
124
46
|
when: "steps.kit.picked == 'near-future' || steps.kit.picked == 'wasteland'"
|
|
@@ -127,14 +49,14 @@ actions:
|
|
|
127
49
|
type: weapon
|
|
128
50
|
where: >-
|
|
129
51
|
has(item.techLevel) && item.techLevel <= 1 && !('grenade' in item.tags)
|
|
130
|
-
&& ('stab' in item.skills || item.
|
|
52
|
+
&& ('stab' in item.skills || has(item.kitAmmo))
|
|
131
53
|
random: params.random
|
|
132
54
|
recommend: options[0]
|
|
133
55
|
changes:
|
|
134
56
|
- { type: addItem, entry: { item: picked.id, equipped: true } }
|
|
135
57
|
- type: addItem
|
|
136
|
-
when: picked.
|
|
137
|
-
entry: { item:
|
|
58
|
+
when: has(picked.item.kitAmmo)
|
|
59
|
+
entry: { item: picked.item.kitAmmo }
|
|
138
60
|
- id: food
|
|
139
61
|
kind: roll
|
|
140
62
|
tags: [creation]
|
|
@@ -207,6 +129,7 @@ actions:
|
|
|
207
129
|
# One entry of a warrior's d20 table. The wasteland table's three high-tech items stand for
|
|
208
130
|
# rolls on the GM's loot tables, which this pack doesn't model.
|
|
209
131
|
- id: kit-entry
|
|
132
|
+
available: character.creating
|
|
210
133
|
tags: [creation]
|
|
211
134
|
params:
|
|
212
135
|
table: { type: string }
|