@maka/maka-cli 5.123.0 → 5.124.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/bundle/typescript/package.json +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/adept-powers.d.ts +0 -8
- package/bundle/typescript/src/commands/game/sideQuest/adept-powers.js +6 -50
- package/bundle/typescript/src/commands/game/sideQuest/adept-powers.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/archetypes.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/archetypes.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/augmentations.d.ts +0 -4
- package/bundle/typescript/src/commands/game/sideQuest/augmentations.js +0 -1342
- package/bundle/typescript/src/commands/game/sideQuest/augmentations.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.d.ts +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js +5 -6
- package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/initiate.d.ts +0 -38
- package/bundle/typescript/src/commands/game/sideQuest/commands/initiate.js +11 -45
- package/bundle/typescript/src/commands/game/sideQuest/commands/initiate.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/install.js +5 -4
- package/bundle/typescript/src/commands/game/sideQuest/commands/install.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/quality-trade.js +10 -7
- package/bundle/typescript/src/commands/game/sideQuest/commands/quality-trade.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +5 -6
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/source.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/source.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.d.ts +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.js +14 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js +11 -12
- package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/game.js +5 -9
- package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/metamagics.d.ts +32 -0
- package/bundle/typescript/src/commands/game/sideQuest/metamagics.js +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/metamagics.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/metatypes.d.ts +6 -4
- package/bundle/typescript/src/commands/game/sideQuest/metatypes.js +3 -83
- package/bundle/typescript/src/commands/game/sideQuest/metatypes.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +5 -5
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js +10 -14
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/qualities.d.ts +3 -7
- package/bundle/typescript/src/commands/game/sideQuest/qualities.js +15 -715
- package/bundle/typescript/src/commands/game/sideQuest/qualities.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/spells.d.ts +5 -7
- package/bundle/typescript/src/commands/game/sideQuest/spells.js +5 -63
- package/bundle/typescript/src/commands/game/sideQuest/spells.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/ui.js +22 -0
- package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.d.ts +36 -20
- package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.js +24 -658
- package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog.d.ts +100 -20
- package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog.js +314 -57
- package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js +3 -2
- package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +26 -0
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
- package/bundle/typescript/src/error.js +1 -1
- package/bundle/typescript/src/error.js.map +1 -1
- package/bundle/typescript/src/tool.d.ts +2 -0
- package/bundle/typescript/src/tool.js +5 -2
- package/bundle/typescript/src/tool.js.map +1 -1
- package/bundle/typescript/src/tools/mpi/sdk-runtime.d.ts +1 -0
- package/bundle/typescript/src/tools/mpi/sdk-runtime.js +29 -0
- package/bundle/typescript/src/tools/mpi/sdk-runtime.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,667 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* THE
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
2
|
+
* THE SHAPE OF THE CATALOG -- every kind of thing the game can obtain,
|
|
3
|
+
* as TypeScript. Gear (what the swag network can source; see
|
|
4
|
+
* commands/catalog.ts and commands/source.ts), augmentations, qualities,
|
|
5
|
+
* spells, adept powers, metamagics and metatypes: one collection,
|
|
6
|
+
* several kinds, discriminated by `kind` (absent = gear).
|
|
7
|
+
*
|
|
8
|
+
* THIS FILE HOLDS NO ROWS. The rows live in ONE place, maka-cli.com's
|
|
9
|
+
* GameCatalog collection, seeded from
|
|
10
|
+
* maka-cli.com/app/private/catalog/full-catalog.json and served at
|
|
11
|
+
* /api/v1/game-catalog/list. The CLI reads them through
|
|
12
|
+
* utilities/catalog.ts (live list > local cache; nothing baked in), and
|
|
13
|
+
* every rule the engine applies -- a quality's dice, a spell's drain, a
|
|
14
|
+
* power's cost -- is reconstructed from a row by the accessors there
|
|
15
|
+
* (augFor, qualityFor, spellFor, adeptPowerFor, metamagicFor,
|
|
16
|
+
* metatypeFor). Until 2026-09-05 this file also carried the seed and
|
|
17
|
+
* derived the non-gear rows from the engine's own arrays; the user's
|
|
18
|
+
* ruling is that the database is the single source of truth, so the
|
|
19
|
+
* arrays are gone and there is nothing left here to drift.
|
|
15
20
|
*
|
|
16
21
|
* STATS ARE REFERENCE, NOT ENGINE INPUT: `stats` is the book's own line
|
|
17
|
-
* for
|
|
18
|
-
* engine
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
+
* for a gear row (Acc/DV/AP/mode/ammo, armor rating, deck array...). The
|
|
23
|
+
* engine reads the typed block (models/item.ts); the string is what the
|
|
24
|
+
* player reads, and what an NPC's swag briefing quotes.
|
|
25
|
+
*
|
|
26
|
+
* Co-owned with maka-cli.com's game-catalog-shape.ts: a field added to
|
|
27
|
+
* a row has to be declared on both sides in the same breath.
|
|
22
28
|
*/
|
|
23
|
-
import { AUGMENTATIONS } from '../augmentations.js';
|
|
24
|
-
import { QUALITIES } from '../qualities.js';
|
|
25
|
-
import { ADEPT_POWER_CATALOG } from '../adept-powers.js';
|
|
26
|
-
import { SPELL_CATALOG } from '../spells.js';
|
|
27
|
-
import { METATYPES } from '../metatypes.js';
|
|
28
|
-
import { METAMAGICS } from '../commands/initiate.js';
|
|
29
|
-
export const CATALOG_VERSION = 14;
|
|
30
29
|
/** Gear or not -- the discriminator every consumer of the gear list uses. */
|
|
31
30
|
export function isGearRow(r) {
|
|
32
31
|
return r.kind === undefined || r.kind === 'gear';
|
|
33
32
|
}
|
|
34
|
-
const row = (slug, name, category, price, availability, description, extra = {}) => ({
|
|
35
|
-
slug, name, category, price, availability, description,
|
|
36
|
-
rating: extra.rating ?? (price >= 5000 ? 'Rare' : price >= 500 ? 'Standard' : 'Common'),
|
|
37
|
-
size: extra.size ?? 'Small',
|
|
38
|
-
shape: extra.shape ?? 'gear',
|
|
39
|
-
color: extra.color ?? 'matte black',
|
|
40
|
-
texture: extra.texture ?? 'street-worn',
|
|
41
|
-
weight: extra.weight ?? 1,
|
|
42
|
-
...extra,
|
|
43
|
-
});
|
|
44
|
-
export const CATALOG_ITEMS = [
|
|
45
|
-
// ---- Melee (p.423) ----
|
|
46
|
-
row('combat-knife', 'Combat Knife', 'MeleeWeapon', 300, 4, 'Mil-spec steel that holds an edge through anything.', { page: 'p.423', shape: 'blade', stats: 'Acc 6, DV (STR+2)P, AP -3', weapon: { skill: 'blades', accuracy: 6, dv: 2, dvAttribute: 'strength', damageType: 'P', ap: -3, range: 'melee' } }),
|
|
47
|
-
row('sword', 'Sword', 'MeleeWeapon', 500, 5, 'A proper length of sharpened argument.', { page: 'p.423', shape: 'blade', size: 'Medium', weight: 1.5, legality: 'R', stats: 'Acc 6, Reach 1, DV (STR+3)P, AP -2', weapon: { skill: 'blades', accuracy: 6, dv: 3, dvAttribute: 'strength', damageType: 'P', ap: -2, range: 'melee', reach: 1 } }),
|
|
48
|
-
row('katana', 'Katana', 'MeleeWeapon', 1000, 9, 'Folded steel and folded history. Restricted, naturally.', { page: 'p.423', shape: 'blade', size: 'Medium', weight: 1.2, rating: 'Rare', legality: 'R', stats: 'Acc 7, Reach 1, DV (STR+3)P, AP -3', weapon: { skill: 'blades', accuracy: 7, dv: 3, dvAttribute: 'strength', damageType: 'P', ap: -3, range: 'melee', reach: 1 } }),
|
|
49
|
-
row('pole-arm', 'Pole Arm', 'MeleeWeapon', 1000, 6, 'Three meters of reach and a very old idea about crowd control.', { page: 'p.423', shape: 'polearm', size: 'Large', weight: 3, rating: 'Standard', legality: 'R', stats: 'Acc 5, Reach 3, DV (STR+3)P, AP -2', weapon: { skill: 'blades', accuracy: 5, dv: 3, dvAttribute: 'strength', damageType: 'P', ap: -2, range: 'melee', reach: 3 } }),
|
|
50
|
-
row('club', 'Club', 'MeleeWeapon', 30, 0, 'The oldest tool in the world, still in production.', { page: 'p.423', shape: 'club', size: 'Medium', weight: 2, stats: 'Acc 4, Reach 1, DV (STR+3)P, AP --', weapon: { skill: 'clubs', accuracy: 4, dv: 3, dvAttribute: 'strength', damageType: 'P', ap: 0, range: 'melee', reach: 1 } }),
|
|
51
|
-
row('sap', 'Sap', 'MeleeWeapon', 30, 2, 'Lead shot in a leather sock. Quiet, deniable, effective.', { page: 'p.423', shape: 'sap', size: 'Tiny', weight: 0.5, texture: 'leather', stats: 'Acc 5, DV (STR+2)P, AP --', weapon: { skill: 'clubs', accuracy: 5, dv: 2, dvAttribute: 'strength', damageType: 'P', ap: 0, range: 'melee' } }),
|
|
52
|
-
row('stun-baton', 'Stun Baton', 'MeleeWeapon', 750, 6, 'Collapsible shock stick -- the polite end of crowd control.', { page: 'p.423', shape: 'baton', legality: 'R', stats: 'Acc 4, Reach 1, DV 9S(e), AP -5', weapon: { skill: 'clubs', accuracy: 4, dv: 9, damageType: 'S', electric: true, ap: -5, reach: 1, range: 'melee' } }),
|
|
53
|
-
row('shock-gloves', 'Shock Gloves', 'MeleeWeapon', 550, 6, 'Capacitor plates across the knuckles. A crackling non-lethal argument.', { page: 'p.423', shape: 'gloves', weight: 0.5, texture: 'insulated weave', legality: 'R', stats: 'DV 8S(e), AP -5 (Unarmed Combat)', weapon: { skill: 'unarmed', accuracy: 'physical', dv: 8, damageType: 'S', electric: true, ap: -5, range: 'melee' } }),
|
|
54
|
-
row('monofilament-whip', 'Monofilament Whip', 'MeleeWeapon', 10000, 12, 'A thread that cuts bone like warm butter -- yours included, on a bad roll.', { page: 'p.423', shape: 'whip', size: 'Tiny', weight: 0.5, rating: 'Legendary', legality: 'F', stats: 'Acc 5 (7), Reach 2, DV 12P, AP -8 (Exotic Melee)', weapon: { skill: 'exotic-melee', accuracy: 5, dv: 12, damageType: 'P', ap: -8, reach: 2, range: 'melee' } }),
|
|
55
|
-
row('staff', 'Staff', 'MeleeWeapon', 100, 3, 'Two meters of reach and no questions at checkpoints.', { page: 'p.423', shape: 'staff', size: 'Large', weight: 2, stats: 'Acc 6, Reach 2, DV (STR+3)P, AP --', weapon: { skill: 'clubs', accuracy: 6, dv: 3, dvAttribute: 'strength', damageType: 'P', ap: 0, range: 'melee', reach: 2 } }),
|
|
56
|
-
// ---- Projectile (p.424) ----
|
|
57
|
-
row('medium-crossbow', 'Medium Crossbow', 'RangedWeapon', 500, 4, 'Silent, reusable, and legal in more places than it should be.', { page: 'p.424', shape: 'crossbow', size: 'Medium', weight: 3, legality: 'R', stats: 'Acc 6, DV 7P, AP -2, 4 (m)', weapon: { skill: 'archery', accuracy: 6, dv: 7, damageType: 'P', ap: -2, ammo: { rounds: 4, feed: 'm' }, range: 'medium-crossbow' } }),
|
|
58
|
-
row('throwing-knives', 'Throwing Knives (set)', 'MeleeWeapon', 25, 4, 'Balanced steel that solves problems across a room.', { page: 'p.424', shape: 'blades', size: 'Tiny', weight: 0.4, legality: 'R', stats: 'DV (STR+1)P, AP -1 (Throwing Weapons)', weapon: { skill: 'throwing-weapons', accuracy: 'physical', dv: 1, dvAttribute: 'strength', damageType: 'P', ap: -1, range: 'thrown-knife' } }),
|
|
59
|
-
// ---- Tasers & hold-outs (p.426) ----
|
|
60
|
-
row('yamaha-pulsar', 'Yamaha Pulsar', 'RangedWeapon', 180, 0, 'A taser that ends arguments without ending anyone.', { page: 'p.426', shape: 'taser', weight: 0.7, stats: 'Acc 5, DV 7S(e), AP -5, SA, 4 (m)', weapon: { skill: 'pistols', accuracy: 5, dv: 7, damageType: 'S', electric: true, ap: -5, modes: ['SA'], ammo: { rounds: 4, feed: 'm' }, range: 'taser', mounts: ['top'] } }),
|
|
61
|
-
row('walther-palm-pistol', 'Walther Palm Pistol', 'RangedWeapon', 180, 4, 'Two shots that fit in a closed fist. Ask no more of it.', { page: 'p.426', shape: 'holdout', size: 'Tiny', weight: 0.4, legality: 'R', stats: 'Acc 4, DV 7P, AP --, SS/BF, 2 (b)', weapon: { skill: 'pistols', accuracy: 4, dv: 7, damageType: 'P', ap: 0, modes: ['SS', 'BF'], ammo: { rounds: 2, feed: 'b' }, range: 'holdout' } }),
|
|
62
|
-
// ---- Sidearms & long guns (p.426-p.430) ----
|
|
63
|
-
row('ares-light-fire-70', 'Ares Light Fire 70', 'RangedWeapon', 200, 3, 'The quiet one: a light pistol built around the silencer everyone bolts onto it.', { page: 'p.426', shape: 'pistol', legality: 'R', stats: 'Acc 7, DV 6P, AP --, SA, 16 (c)', weapon: { skill: 'pistols', accuracy: 7, dv: 6, damageType: 'P', ap: 0, modes: ['SA'], ammo: { rounds: 16, feed: 'c' }, range: 'light-pistol', mounts: ['top', 'barrel'] } }),
|
|
64
|
-
row('beretta-201t', 'Beretta 201T', 'RangedWeapon', 210, 7, 'A burst-capable light pistol with a folding trigger and a temper.', { page: 'p.426', shape: 'pistol', legality: 'R', stats: 'Acc 6, DV 6P, AP --, SA/BF, RC (1), 21 (c)', weapon: { skill: 'pistols', accuracy: 6, dv: 6, damageType: 'P', ap: 0, modes: ['SA', 'BF'], ammo: { rounds: 21, feed: 'c' }, range: 'light-pistol', mounts: ['top', 'barrel'], rc: 1, builtIn: ['folding-stock', 'laser-sight'] } }),
|
|
65
|
-
row('colt-america-l36', 'Colt America L36', 'RangedWeapon', 320, 4, 'A light pistol as common as rain and twice as honest.', { page: 'p.426', shape: 'pistol', legality: 'R', stats: 'Acc 7, DV 7P, AP --, SA, 11 (c)', weapon: { skill: 'pistols', accuracy: 7, dv: 7, damageType: 'P', ap: 0, modes: ['SA'], ammo: { rounds: 11, feed: 'c' }, range: 'light-pistol', mounts: ['top', 'barrel'] } }),
|
|
66
|
-
row('taurus-omni-6', 'Taurus Omni-6', 'RangedWeapon', 300, 3, 'A revolver that swaps cylinders: light rounds or heavy, your night, your call.', { page: 'p.426', shape: 'revolver', weight: 1.2, legality: 'R', stats: 'Acc 5 (6), DV 6P/7P, AP 0/-1, SA/SS, 6 (cy)', weapon: { skill: 'pistols', accuracy: 5, dv: 7, damageType: 'P', ap: -1, modes: ['SA', 'SS'], ammo: { rounds: 6, feed: 'cy' }, range: 'heavy-pistol', mounts: ['top', 'barrel'], builtIn: ['laser-sight'] } }),
|
|
67
|
-
row('ares-predator-v', 'Ares Predator V', 'RangedWeapon', 725, 5, 'THE heavy pistol. Smartgun system built in, reputation included.', { page: 'p.426', shape: 'pistol', weight: 1.2, legality: 'R', stats: 'Acc 5 (7), DV 8P, AP -1, SA, 15 (c)', weapon: { skill: 'pistols', accuracy: 5, dv: 8, damageType: 'P', ap: -1, modes: ['SA'], ammo: { rounds: 15, feed: 'c' }, range: 'heavy-pistol', mounts: ['top', 'barrel'], builtIn: ['smartgun-internal'] } }),
|
|
68
|
-
row('browning-ultra-power', 'Browning Ultra-Power', 'RangedWeapon', 640, 4, 'A working professional\'s heavy pistol, with an integral laser sight.', { page: 'p.426', shape: 'pistol', weight: 1.2, legality: 'R', stats: 'Acc 5 (6), DV 8P, AP -1, SA, 10 (c)', weapon: { skill: 'pistols', accuracy: 5, dv: 8, damageType: 'P', ap: -1, modes: ['SA'], ammo: { rounds: 10, feed: 'c' }, range: 'heavy-pistol', mounts: ['top', 'barrel'], builtIn: ['laser-sight'] } }),
|
|
69
|
-
row('ruger-super-warhawk', 'Ruger Super Warhawk', 'RangedWeapon', 400, 4, 'A revolver with opinions. Loud ones.', { page: 'p.426', shape: 'revolver', weight: 1.4, legality: 'R', stats: 'Acc 5, DV 9P, AP -2, SS, 6 (cy)', weapon: { skill: 'pistols', accuracy: 5, dv: 9, damageType: 'P', ap: -2, modes: ['SS'], ammo: { rounds: 6, feed: 'cy' }, range: 'heavy-pistol', mounts: ['top', 'barrel'] } }),
|
|
70
|
-
row('remington-roomsweeper', 'Remington Roomsweeper', 'RangedWeapon', 250, 6, 'A heavy pistol that thinks it is a shotgun. It is not wrong.', { page: 'p.426', shape: 'pistol', weight: 1.5, legality: 'R', stats: 'Acc 4, DV 7P, AP -1, SA, 8 (m)', weapon: { skill: 'pistols', accuracy: 4, dv: 7, damageType: 'P', ap: -1, modes: ['SA'], ammo: { rounds: 8, feed: 'm' }, range: 'heavy-pistol', mounts: ['top', 'barrel'] } }),
|
|
71
|
-
row('ceska-black-scorpion', 'Ceska Black Scorpion', 'RangedWeapon', 270, 6, 'A machine pistol with a folding stock and no manners at all.', { page: 'p.427', shape: 'machine pistol', weight: 1.4, legality: 'R', stats: 'Acc 5, DV 6P, AP --, SA/BF, RC (1), 35 (c)', weapon: { skill: 'automatics', accuracy: 5, dv: 6, damageType: 'P', ap: 0, modes: ['SA', 'BF'], ammo: { rounds: 35, feed: 'c' }, range: 'machine-pistol', mounts: ['top', 'barrel'], rc: 1, builtIn: ['folding-stock'] } }),
|
|
72
|
-
row('uzi-iv', 'Uzi IV', 'RangedWeapon', 450, 4, 'An old name that still writes checks in three-round bursts.', { page: 'p.427', shape: 'smg', size: 'Medium', weight: 2.5, legality: 'R', stats: 'Acc 4 (5), DV 7P, AP --, BF, RC (1), 24 (c)', weapon: { skill: 'automatics', accuracy: 4, dv: 7, damageType: 'P', ap: 0, modes: ['BF'], ammo: { rounds: 24, feed: 'c' }, range: 'smg', mounts: ['top', 'barrel'], rc: 1, builtIn: ['folding-stock', 'laser-sight'] } }),
|
|
73
|
-
row('ingram-smartgun-x', 'Ingram Smartgun X', 'RangedWeapon', 800, 6, 'The runner\'s SMG: smartlink, gas vent, and a silencer already fitted.', { page: 'p.427', shape: 'smg', size: 'Medium', weight: 2.5, legality: 'R', stats: 'Acc 4 (6), DV 8P, AP --, BF/FA, RC 2, 32 (c)', weapon: { skill: 'automatics', accuracy: 4, dv: 8, damageType: 'P', ap: 0, modes: ['BF', 'FA'], ammo: { rounds: 32, feed: 'c' }, range: 'smg', mounts: ['top', 'barrel'], rc: 2, builtIn: ['gas-vent-2', 'smartgun-internal', 'silencer'] } }),
|
|
74
|
-
row('fn-p93-praetor', 'FN P93 Praetor', 'RangedWeapon', 900, 11, 'A bullpup SMG built for corp security. Forbidden, and it shows.', { page: 'p.427', shape: 'smg', size: 'Medium', weight: 3, legality: 'F', stats: 'Acc 6, DV 8P, AP --, SA/BF/FA, RC 1 (2), 50 (c)', weapon: { skill: 'automatics', accuracy: 6, dv: 8, damageType: 'P', ap: 0, modes: ['SA', 'BF', 'FA'], ammo: { rounds: 50, feed: 'c' }, range: 'smg', mounts: ['top', 'barrel'], rc: 1, builtIn: ['folding-stock', 'smartgun-internal', 'silencer'] } }),
|
|
75
|
-
row('ak-97', 'AK-97', 'RangedWeapon', 950, 4, 'A century of design maturity: it always, always fires.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 4, legality: 'R', stats: 'Acc 5, DV 10P, AP -2, SA/BF/FA, 38 (c)', weapon: { skill: 'automatics', accuracy: 5, dv: 10, damageType: 'P', ap: -2, modes: ['SA', 'BF', 'FA'], ammo: { rounds: 38, feed: 'c' }, range: 'assault-rifle', mounts: ['top', 'under', 'barrel'] } }),
|
|
76
|
-
row('colt-m23', 'Colt M23', 'RangedWeapon', 550, 4, 'Cheap, mass-produced, no frills -- the gangbanger\'s rifle and the gunsmith\'s canvas.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 4, legality: 'R', stats: 'Acc 4, DV 9P, AP -2, SA/BF/FA, 40 (c)', weapon: { skill: 'automatics', accuracy: 4, dv: 9, damageType: 'P', ap: -2, modes: ['SA', 'BF', 'FA'], ammo: { rounds: 40, feed: 'c' }, range: 'assault-rifle', mounts: ['top', 'under', 'barrel'] } }),
|
|
77
|
-
row('fn-har', 'FN HAR', 'RangedWeapon', 1500, 8, 'Corporate threat-response hardware: laser sight, gas-vent 2, no apologies.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 4.2, rating: 'Standard', legality: 'R', stats: 'Acc 5 (6), DV 10P, AP -2, SA/BF/FA, RC 2, 35 (c)', weapon: { skill: 'automatics', accuracy: 5, dv: 10, damageType: 'P', ap: -2, modes: ['SA', 'BF', 'FA'], ammo: { rounds: 35, feed: 'c' }, range: 'assault-rifle', mounts: ['top', 'under', 'barrel'], rc: 2, builtIn: ['laser-sight', 'gas-vent-2'] } }),
|
|
78
|
-
row('ares-alpha', 'Ares Alpha', 'RangedWeapon', 2650, 11, 'The assault rifle with the grenade launcher. Forbidden, and worth it.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 4.5, rating: 'MilitaryGrade', legality: 'F', stats: 'Acc 5 (7), DV 11P, AP -2, SA/BF/FA, RC 2, 42 (c) + grenade launcher', weapon: { skill: 'automatics', accuracy: 5, dv: 11, damageType: 'P', ap: -2, modes: ['SA', 'BF', 'FA'], ammo: { rounds: 42, feed: 'c' }, range: 'assault-rifle', mounts: ['top', 'under', 'barrel'], rc: 2, builtIn: ['smartgun-internal', 'grenade-launcher'] } }),
|
|
79
|
-
row('yamaha-raiden', 'Yamaha Raiden', 'RangedWeapon', 2600, 14, 'Electronic firing, state of the art, and utterly illegal to be caught with.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 4.5, rating: 'MilitaryGrade', legality: 'F', stats: 'Acc 6 (8), DV 11P, AP -2, BF/FA, RC 1, 60 (c)', weapon: { skill: 'automatics', accuracy: 6, dv: 11, damageType: 'P', ap: -2, modes: ['BF', 'FA'], ammo: { rounds: 60, feed: 'c' }, range: 'assault-rifle', mounts: ['top', 'under', 'barrel'], rc: 1, builtIn: ['silencer', 'smartgun-internal'] } }),
|
|
80
|
-
row('ruger-100', 'Ruger 100', 'RangedWeapon', 1300, 4, 'A hunting rifle that does not care what you are hunting.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 4.5, rating: 'Standard', legality: 'R', stats: 'Acc 6, DV 11P, AP -3, SA, RC (1), 8 (m)', weapon: { skill: 'longarms', accuracy: 6, dv: 11, damageType: 'P', ap: -3, modes: ['SA'], ammo: { rounds: 8, feed: 'm' }, range: 'sniper', mounts: ['top', 'under', 'barrel'], rc: 1, builtIn: ['imaging-scope', 'shock-pad'] } }),
|
|
81
|
-
row('ares-desert-strike', 'Ares Desert Strike', 'RangedWeapon', 17500, 10, 'A sniper rifle built to work after a week in the sand. Forbidden everywhere.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 6, rating: 'Legendary', legality: 'F', stats: 'Acc 7, DV 13P, AP -4, SA, RC (1), 14 (c)', weapon: { skill: 'longarms', accuracy: 7, dv: 13, damageType: 'P', ap: -4, modes: ['SA'], ammo: { rounds: 14, feed: 'c' }, range: 'sniper', mounts: ['top', 'under', 'barrel'], rc: 1, builtIn: ['shock-pad', 'imaging-scope'] } }),
|
|
82
|
-
row('ranger-arms-sm-5', 'Ranger Arms SM-5', 'RangedWeapon', 28000, 16, 'The assassin\'s rifle: silenced, scoped, and it breaks down into a briefcase.', { page: 'p.428', shape: 'rifle', size: 'Large', weight: 6, rating: 'Legendary', legality: 'F', stats: 'Acc 8, DV 14P, AP -5, SA, RC (1), 15 (c)', weapon: { skill: 'longarms', accuracy: 8, dv: 14, damageType: 'P', ap: -5, modes: ['SA'], ammo: { rounds: 15, feed: 'c' }, range: 'sniper', mounts: ['top', 'under', 'barrel'], rc: 1, builtIn: ['silencer', 'imaging-scope', 'shock-pad'] } }),
|
|
83
|
-
row('defiance-t-250', 'Defiance T-250', 'RangedWeapon', 450, 4, 'A pump shotgun with all the subtlety the name implies.', { page: 'p.429', shape: 'shotgun', size: 'Large', weight: 3.5, legality: 'R', stats: 'Acc 4, DV 10P, AP -1, SS/SA, 5 (m)', weapon: { skill: 'longarms', accuracy: 4, dv: 10, damageType: 'P', ap: -1, modes: ['SS', 'SA'], ammo: { rounds: 5, feed: 'm' }, range: 'shotgun', mounts: ['top', 'under', 'barrel'] } }),
|
|
84
|
-
row('enfield-as-7', 'Enfield AS-7', 'RangedWeapon', 1100, 12, 'A military assault shotgun. Universally feared, for excellent reasons.', { page: 'p.429', shape: 'shotgun', size: 'Large', weight: 4.5, rating: 'Standard', legality: 'F', stats: 'Acc 4 (5), DV 13P, AP -1, SA/BF, 10 (c) or 24 (d)', weapon: { skill: 'longarms', accuracy: 4, dv: 13, damageType: 'P', ap: -1, modes: ['SA', 'BF'], ammo: { rounds: 10, feed: 'c' }, range: 'shotgun', mounts: ['top', 'under', 'barrel'], builtIn: ['laser-sight'] } }),
|
|
85
|
-
row('stoner-ares-m202', 'Stoner-Ares M202', 'RangedWeapon', 7000, 12, 'A medium machine gun. If you are buying this, the plan already failed.', { page: 'p.430', shape: 'machine gun', size: 'Large', weight: 9, rating: 'MilitaryGrade', legality: 'F', stats: 'Acc 5, DV 10P, AP -3, FA, 50 (c) or 100 (belt)', weapon: { skill: 'heavy-weapons', accuracy: 5, dv: 10, damageType: 'P', ap: -3, modes: ['FA'], ammo: { rounds: 50, feed: 'c' }, range: 'mmg', mounts: ['top', 'under', 'barrel'] } }),
|
|
86
|
-
// ---- Firearm accessories (p.432) ----
|
|
87
|
-
row('silencer', 'Silencer/Suppressor', 'Electronics', 500, 9, 'The difference between a gunshot and a rumor.', { page: 'p.432', shape: 'tube', size: 'Tiny', weight: 0.4, legality: 'F', stats: 'Barrel mount', mod: { kind: 'weapon', mount: ['barrel'], excludes: ['shotgun', 'revolver'] } }),
|
|
88
|
-
row('smartgun-external', 'Smartgun System (external)', 'Electronics', 200, 4, 'The gun\'s half of a smartgun system, bolted on: with a smartlink in your eye it tells you where the round will land.', { page: 'p.432', shape: 'module', size: 'Tiny', weight: 0.3, legality: 'R', stats: 'Top or under mount', mod: { kind: 'weapon', mount: ['top', 'under'] }, effects: [{ type: 'flag', category: 'capability', property: 'smartgun', value: 1, when: 'fitted' }] }),
|
|
89
|
-
row('laser-sight', 'Laser Sight', 'Electronics', 125, 2, 'A red dot that argues with your shaking hands.', { page: 'p.432', shape: 'sight', size: 'Tiny', weight: 0.2, stats: 'Top or under mount, +1 Accuracy', mod: { kind: 'weapon', mount: ['top', 'under'] }, effects: [{ type: 'limit', category: 'limits', property: 'accuracy', value: 1, when: 'fitted' }] }),
|
|
90
|
-
row('quick-draw-holster', 'Quick-Draw Holster', 'Electronics', 175, 4, 'Spring-loaded rig for people whose first shot has to be first.', { page: 'p.432', shape: 'holster', size: 'Tiny', weight: 0.3, texture: 'synthleather' }),
|
|
91
|
-
row('hidden-arm-slide', 'Hidden Arm Slide', 'Electronics', 350, 4, 'A sleeve rig that puts a pistol in your palm mid-handshake.', { page: 'p.432', shape: 'slide', size: 'Tiny', weight: 0.3, legality: 'R' }),
|
|
92
|
-
row('spare-clip', 'Spare Clip', 'Ammunition', 5, 4, 'Because reloading from a box is how people die.', { page: 'p.432', shape: 'clip', size: 'Tiny', weight: 0.2, color: 'gunmetal' }),
|
|
93
|
-
// ---- Ammunition, per 10 rounds (p.433) ----
|
|
94
|
-
row('regular-ammo', 'Regular Ammo (box)', 'Ammunition', 20, 2, 'Ten clean rounds, serial numbers politely absent.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, color: 'brass', texture: 'metal', legality: 'R', stats: 'DV --, AP --', ammo: { dvMod: 0, apMod: 0 } }),
|
|
95
|
-
row('gel-rounds', 'Gel Rounds', 'Ammunition', 25, 2, 'Riot-control jelly slugs: they drop people who have to wake up later.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, legality: 'R', stats: 'DV +0S, AP +1, -2 target Physical limit vs knockdown', ammo: { dvMod: 0, apMod: 1, damageType: 'S' } }),
|
|
96
|
-
row('tracer-rounds', 'Tracer Rounds', 'Ammunition', 60, 6, 'Burning tails that walk your fire onto the target -- and back to you.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, legality: 'R', stats: 'DV --, AP --, +1 die on FA bursts', ammo: { dvMod: 0, apMod: 0, note: '+1 die on FA bursts (no burst model yet)' } }),
|
|
97
|
-
row('flechette-rounds', 'Flechette Rounds', 'Ammunition', 65, 6, 'A cloud of steel needles. Murder on flesh, useless on plate.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, legality: 'R', stats: 'DV +2, AP +5', ammo: { dvMod: 2, apMod: 5 } }),
|
|
98
|
-
row('hollow-points', 'Hollow Point Rounds', 'Ammunition', 70, 4, 'Rounds that open on impact. Forbidden for the obvious reason.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, legality: 'F', stats: 'DV +1, AP +2', ammo: { dvMod: 1, apMod: 2 } }),
|
|
99
|
-
row('injection-darts', 'Injection Darts', 'Ammunition', 75, 4, 'Delivery system in search of a payload. Bring your own chemistry.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.4, legality: 'R', stats: 'Payload: one dose, injection vector', ammo: { dvMod: 0, apMod: 0, note: 'delivers one dose' } }),
|
|
100
|
-
row('stick-n-shock', 'Stick-n-Shock Rounds', 'Ammunition', 80, 6, 'Taser slugs -- for when you want them down, not gone.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, legality: 'R', stats: 'DV -2S(e), AP -5', ammo: { dvMod: -2, apMod: -5, damageType: 'S', electric: true } }),
|
|
101
|
-
row('explosive-rounds', 'Explosive Rounds', 'Ammunition', 80, 9, 'Shaped charges in a casing. They misfire on a critical glitch. Enjoy.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, legality: 'F', stats: 'DV +1, AP -1', ammo: { dvMod: 1, apMod: -1 } }),
|
|
102
|
-
row('apds', 'APDS Rounds', 'Ammunition', 120, 12, 'Armor-piercing discarding sabot. Very forbidden. Very effective.', { page: 'p.433', shape: 'box', size: 'Tiny', weight: 0.5, rating: 'MilitaryGrade', legality: 'F', stats: 'DV --, AP -4', ammo: { dvMod: 0, apMod: -4 } }),
|
|
103
|
-
// ---- Grenades (p.435) ----
|
|
104
|
-
row('smoke-grenade', 'Smoke Grenade', 'Explosive', 40, 4, 'Portable weather for tactical withdrawals.', { page: 'p.435', shape: 'grenade', size: 'Tiny', weight: 0.3, legality: 'R', stats: '10m radius smoke' }),
|
|
105
|
-
row('thermal-smoke-grenade', 'Thermal Smoke Grenade', 'Explosive', 60, 6, 'Smoke that blinds thermographic eyes too. Worth the extra twenty.', { page: 'p.435', shape: 'grenade', size: 'Tiny', weight: 0.3, legality: 'R', stats: '10m radius, blocks thermographic' }),
|
|
106
|
-
row('flash-bang', 'Flash-Bang Grenade', 'Explosive', 100, 6, 'A very loud argument for leaving.', { page: 'p.435', shape: 'grenade', size: 'Tiny', weight: 0.3, legality: 'R', stats: 'DV 10S, AP -4, 10m radius', weapon: { skill: 'throwing-weapons', accuracy: 'physical', dv: 10, damageType: 'S', ap: -4, range: 'grenade' } }),
|
|
107
|
-
row('flash-pak', 'Flash-Pak', 'Explosive', 125, 4, 'A strobe that ruins low-light and thermo optics without hurting a soul.', { page: 'p.435', shape: 'strobe', size: 'Tiny', weight: 0.3, stats: 'Special: blinds vision enhancements' }),
|
|
108
|
-
row('frag-grenade', 'Fragmentation Grenade', 'Explosive', 100, 11, 'Steel rain in a can. Nothing subtle survives it, including you.', { page: 'p.435', shape: 'grenade', size: 'Tiny', weight: 0.4, legality: 'F', stats: 'DV 18P(f), AP +5, -1/m blast', weapon: { skill: 'throwing-weapons', accuracy: 'physical', dv: 18, damageType: 'P', ap: 5, range: 'grenade', blast: 1 } }),
|
|
109
|
-
row('he-grenade', 'High-Explosive Grenade', 'Explosive', 100, 11, 'The one that takes the wall with it.', { page: 'p.435', shape: 'grenade', size: 'Tiny', weight: 0.4, legality: 'F', stats: 'DV 16P, AP -2, -2/m blast', weapon: { skill: 'throwing-weapons', accuracy: 'physical', dv: 16, damageType: 'P', ap: -2, range: 'grenade', blast: 2 } }),
|
|
110
|
-
row('plastic-explosive', 'Plastic Explosive (Rating 10)', 'Explosive', 1000, 16, 'Grey putty that opens doors, vaults, and criminal careers.', { page: 'p.436', shape: 'brick', size: 'Tiny', weight: 1, rating: 'Rare', legality: 'F', stats: 'Rating 10, DV by rating', ratingValue: 10 }),
|
|
111
|
-
row('detonator-cap', 'Detonator Cap', 'Explosive', 75, 8, 'The small piece that makes the big piece matter.', { page: 'p.436', shape: 'cap', size: 'Tiny', weight: 0.1, legality: 'R' }),
|
|
112
|
-
// ---- Clothing (p.436) -- what fills the torso's `clothing` slot and
|
|
113
|
-
// the mundane-wear slots around it. Equipping keys on CATEGORY alone
|
|
114
|
-
// (Player.determineEquipmentSlot), so a jacket filed under Electronics
|
|
115
|
-
// is a jacket nobody can put on. The book prices mundane wear as ONE
|
|
116
|
-
// line -- Clothing, 20-100,000 nuyen, no availability test -- so the
|
|
117
|
-
// specific street pieces below cite p.436 and carry `approx` for the
|
|
118
|
-
// price point chosen within that range. None of them add soak: boots,
|
|
119
|
-
// gloves, and limb trim are deliberately 0 armor (getArmorValue).
|
|
120
|
-
row('street-clothing', 'Street Clothing', 'Clothing', 50, 0, 'Layers the sprawl stops looking at. The most useful thing you can wear.', { page: 'p.436', shape: 'clothing', size: 'Medium', weight: 1, color: 'faded black', texture: 'synthweave', stats: 'Armor 0', wearable: { armor: 0 } }),
|
|
121
|
-
row('synthleather-jacket', 'Synthleather Jacket', 'ArmorClothing', 200, 0, 'A jacket with enough hide in the weave to argue with a knife.', { page: 'p.436', shape: 'jacket', size: 'Medium', weight: 1.5, color: 'oxblood', texture: 'synthleather', stats: 'Armor 4', wearable: { armor: 4 } }),
|
|
122
|
-
row('electrochromic-clothing', 'Electrochromic Clothing', 'Clothing', 500, 2, 'Colour and pattern on command -- a different person leaves than the one who walked in.', { page: 'p.436', shape: 'clothing', size: 'Medium', weight: 1, color: 'whatever you tell it', rating: 'Standard', stats: 'Clothing modification, +2 avail' }),
|
|
123
|
-
row('feedback-clothing', 'Feedback Clothing', 'Clothing', 500, 8, 'Haptic weave that lets AR touch you back. Riggers and simsense junkies swear by it.', { page: 'p.436', shape: 'clothing', size: 'Medium', weight: 1, rating: 'Standard', stats: 'Clothing modification' }),
|
|
124
|
-
row('synthleather-boots', 'Synthleather Boots', 'Boots', 100, 0, 'Resoled twice, waterproof on the third try. They will outlast the job.', { page: 'p.436', approx: true, shape: 'boots', weight: 1, color: 'brown-black', texture: 'synthleather' }),
|
|
125
|
-
row('combat-boots', 'Combat Boots', 'Boots', 250, 4, 'Steel toes, ankle support, and tread that holds on wet rooftop gravel.', { page: 'p.436', approx: true, shape: 'boots', weight: 1.5, texture: 'ballistic nylon' }),
|
|
126
|
-
row('fingerless-gloves', 'Fingerless Gloves', 'Gloves', 40, 0, 'Grip where you need it, bare skin where the sensors want it.', { page: 'p.436', approx: true, shape: 'gloves', size: 'Tiny', weight: 0.2, texture: 'synthleather' }),
|
|
127
|
-
row('knit-cap', 'Knit Cap', 'Hat', 25, 0, 'Pulled low, it takes half your face out of every camera in the district.', { page: 'p.436', approx: true, shape: 'cap', size: 'Tiny', weight: 0.2, color: 'charcoal', texture: 'wool' }),
|
|
128
|
-
row('armored-pants', 'Armored Pants', 'LegArmor', 300, 4, 'Reinforced at the knee and thigh for people who take cover the hard way.', { page: 'p.436', approx: true, shape: 'pants', size: 'Medium', weight: 1.5, texture: 'ballistic weave' }),
|
|
129
|
-
row('forearm-guards', 'Forearm Guards', 'ArmArmor', 200, 4, 'Bracers under the sleeves -- what you raise when the blade is already moving.', { page: 'p.436', approx: true, shape: 'bracers', size: 'Small', weight: 1 }),
|
|
130
|
-
row('smartwatch', 'Smartwatch', 'Wristband', 200, 0, 'Wrist-worn commlink peripheral: time, vitals, and a very small screen of bad news.', { approx: true, shape: 'watch', size: 'Tiny', weight: 0.1, stats: 'Device Rating 2', device: { deviceRating: 2 } }),
|
|
131
|
-
// ---- Armor (p.436-p.438) ----
|
|
132
|
-
row('armor-clothing', 'Armor Clothing', 'ArmorClothing', 450, 2, 'Boardroom-passable protection.', { page: 'p.436', shape: 'clothing', size: 'Medium', weight: 2, stats: 'Armor 6', wearable: { armor: 6 } }),
|
|
133
|
-
row('armor-vest', 'Armor Vest', 'BodyArmor', 500, 4, 'Concealable ballistic weave. The difference between a bad night and a last one.', { page: 'p.437', shape: 'vest', size: 'Medium', weight: 3, stats: 'Armor 9', wearable: { armor: 9 } }),
|
|
134
|
-
row('urban-explorer', 'Urban Explorer Jumpsuit', 'ArmorClothing', 650, 8, 'Armored athletic wear for the parkour-inclined professional.', { page: 'p.436', shape: 'jumpsuit', size: 'Medium', weight: 2, stats: 'Armor 9', wearable: { armor: 9 } }),
|
|
135
|
-
row('lined-coat', 'Lined Coat', 'BodyArmor', 900, 4, 'Duster-length armor with room for everything underneath.', { page: 'p.437', shape: 'coat', size: 'Medium', weight: 3, stats: 'Armor 9, -2 Concealability for what is under it', wearable: { armor: 9, concealment: -2 } }),
|
|
136
|
-
row('armor-jacket', 'Armor Jacket', 'BodyArmor', 1000, 2, 'The runner standard: looks like a jacket, works like a wall.', { page: 'p.436', shape: 'jacket', size: 'Medium', weight: 3, texture: 'ballistic weave', stats: 'Armor 12', wearable: { armor: 12 } }),
|
|
137
|
-
row('actioneer-business-clothes', 'Actioneer Business Clothes', 'ArmorClothing', 1500, 8, 'A power suit with a concealable holster and a lawyer\'s alibi.', { page: 'p.437', shape: 'suit', size: 'Medium', weight: 2, color: 'charcoal', rating: 'Standard', stats: 'Armor 8, concealable holster', wearable: { armor: 8 } }),
|
|
138
|
-
row('chameleon-suit', 'Chameleon Suit', 'ArmorClothing', 1700, 10, 'Ruthenium weave that drinks the light around it.', { page: 'p.436', shape: 'suit', size: 'Medium', weight: 2, color: 'shifting gray', rating: 'Rare', legality: 'R', stats: 'Armor 9, +ruthenium polymer', wearable: { armor: 9 } }),
|
|
139
|
-
row('full-body-armor', 'Full Body Armor', 'BodyArmor', 2000, 14, 'Impossible to conceal, styled to intimidate, built for heavy ops.', { page: 'p.437', shape: 'hardsuit', size: 'Large', weight: 8, rating: 'Rare', legality: 'R', stats: 'Armor 15', wearable: { armor: 15 } }),
|
|
140
|
-
row('helmet', 'Helmet', 'Helmet', 100, 0, 'A hard shell for the soft parts that matter most.', { page: 'p.437', shape: 'helmet', weight: 1, stats: 'Armor +2, Capacity 6', wearable: { armorBonus: 2, capacity: 6, holds: ['vision', 'audio', 'trodes', 'armor'] } }),
|
|
141
|
-
row('full-helmet', 'Full Helmet', 'Helmet', 500, 0, 'Sealed faceplate. Nobody reads your expression, nobody reads your face.', { page: 'p.436', shape: 'helmet', weight: 1.5, rating: 'Standard', stats: 'Armor +3 (full body armor)', wearable: { armorBonus: 3 } }),
|
|
142
|
-
row('ballistic-shield', 'Ballistic Shield', 'Shield', 1200, 12, 'A door you carry into rooms that need one.', { page: 'p.438', shape: 'shield', size: 'Large', weight: 7, rating: 'Rare', legality: 'R', stats: 'Armor +6', wearable: { armorBonus: 6 } }),
|
|
143
|
-
// ---- Commlinks (p.438) ----
|
|
144
|
-
row('meta-link', 'Meta Link', 'Commlink', 100, 2, 'The squatter special. It makes calls. Usually.', { page: 'p.438', shape: 'slab', size: 'Tiny', weight: 0.2, stats: 'Device Rating 1', device: { deviceRating: 1 } }),
|
|
145
|
-
row('sony-emperor', 'Sony Emperor', 'Commlink', 700, 4, 'A solid mid-shelf commlink with a name bigger than its specs.', { page: 'p.438', shape: 'slab', size: 'Tiny', weight: 0.2, stats: 'Device Rating 2', device: { deviceRating: 2 } }),
|
|
146
|
-
row('renraku-sensei', 'Renraku Sensei', 'Commlink', 1000, 6, 'A businessman\'s link: discreet, capable, forgettable on purpose.', { page: 'p.438', shape: 'slab', size: 'Tiny', weight: 0.2, stats: 'Device Rating 3', device: { deviceRating: 3 } }),
|
|
147
|
-
row('erika-elite', 'Erika Elite', 'Commlink', 2500, 8, 'The decker\'s daily driver when the deck stays home.', { page: 'p.438', shape: 'slab', size: 'Tiny', weight: 0.2, rating: 'Standard', stats: 'Device Rating 4', device: { deviceRating: 4 } }),
|
|
148
|
-
row('hermes-ikon', 'Hermes Ikon', 'Commlink', 3000, 10, 'Serious hardware for people whose calls matter.', { page: 'p.438', shape: 'slab', size: 'Tiny', weight: 0.3, rating: 'Rare', stats: 'Device Rating 5', device: { deviceRating: 5 } }),
|
|
149
|
-
row('transys-avalon', 'Transys Avalon', 'Commlink', 5000, 12, 'Executive-grade signal discipline in a slab of brushed ceramic.', { page: 'p.438', shape: 'slab', size: 'Tiny', weight: 0.3, rating: 'Rare', stats: 'Device Rating 6', device: { deviceRating: 6 } }),
|
|
150
|
-
row('fairlight-caliban', 'Fairlight Caliban', 'Commlink', 8000, 14, 'The commlink executives get assassinated for.', { page: 'p.438', shape: 'slab', size: 'Tiny', weight: 0.3, rating: 'Legendary', stats: 'Device Rating 7', device: { deviceRating: 7 } }),
|
|
151
|
-
row('sim-module', 'Sim Module (hot-sim modified)', 'Electronics', 100, 0, 'The chip that turns a commlink into a doorway. Modified, of course.', { page: 'p.438', shape: 'chip', size: 'Tiny', weight: 0.1, stats: '+100 nuyen add-on; hot sim is the illegal part' }),
|
|
152
|
-
// ---- Cyberdecks (p.439) -- the aspirational end of the catalog: a
|
|
153
|
-
// Cyber-5 costs more than a Super-Platinum DocWagon year. Rating maps
|
|
154
|
-
// the book's Device Rating onto the engine's quality tiers (deck
|
|
155
|
-
// boxes and pools ride qualityBonus).
|
|
156
|
-
row('erika-mcd-1', 'Erika MCD-1', 'Cyberdeck', 49500, 3, 'The learner\'s cyberdeck -- "entry-level" meaning a year of rent.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 2, rating: 'Common', legality: 'R', stats: 'DR 1, A/S/D/F 4 3 2 1, 1 program', device: { deviceRating: 1, attack: 4, sleaze: 3, dataProcessing: 2, firewall: 1, programs: 1 } }),
|
|
157
|
-
row('microdeck-summit', 'Microdeck Summit', 'Cyberdeck', 58000, 3, 'Device Rating 1: a real deck, barely. Every decker\'s first love.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 2, rating: 'Common', legality: 'R', stats: 'DR 1, A/S/D/F 4 3 3 1, 1 program', device: { deviceRating: 1, attack: 4, sleaze: 3, dataProcessing: 3, firewall: 1, programs: 1 } }),
|
|
158
|
-
row('microtronica-azteca-200', 'Microtronica Azteca 200', 'Cyberdeck', 110250, 6, 'Aztechnology\'s starter deck. It works. Somebody is always watching it work.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 2, rating: 'Standard', legality: 'R', stats: 'DR 2, A/S/D/F 5 4 3 2, 2 programs', device: { deviceRating: 2, attack: 5, sleaze: 4, dataProcessing: 3, firewall: 2, programs: 2 } }),
|
|
159
|
-
row('hermes-chariot', 'Hermes Chariot', 'Cyberdeck', 123000, 6, 'Device Rating 2: the working professional\'s ride through the grid.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 2, rating: 'Standard', legality: 'R', stats: 'DR 2, A/S/D/F 5 4 4 2, 2 programs', device: { deviceRating: 2, attack: 5, sleaze: 4, dataProcessing: 4, firewall: 2, programs: 2 } }),
|
|
160
|
-
row('novatech-navigator', 'Novatech Navigator', 'Cyberdeck', 205750, 9, 'A deck that finds the seams in a host and remembers them.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 2.5, rating: 'Rare', legality: 'R', stats: 'DR 3, A/S/D/F 6 5 4 3, 3 programs', device: { deviceRating: 3, attack: 6, sleaze: 5, dataProcessing: 4, firewall: 3, programs: 3 } }),
|
|
161
|
-
row('renraku-tsurugi', 'Renraku Tsurugi', 'Cyberdeck', 214125, 9, 'Device Rating 3: a sword, as the name says -- corp-grade ice-cutting.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 2.5, rating: 'Rare', legality: 'R', stats: 'DR 3, A/S/D/F 6 5 5 3, 3 programs', device: { deviceRating: 3, attack: 6, sleaze: 5, dataProcessing: 5, firewall: 3, programs: 3 } }),
|
|
162
|
-
row('sony-ciy-720', 'Sony CIY-720', 'Cyberdeck', 345000, 12, 'The deck you buy when the job pays in corporate secrets.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 3, rating: 'Legendary', legality: 'R', stats: 'DR 4, A/S/D/F 7 6 5 4, 4 programs', device: { deviceRating: 4, attack: 7, sleaze: 6, dataProcessing: 5, firewall: 4, programs: 4 } }),
|
|
163
|
-
row('shiawase-cyber-5', 'Shiawase Cyber-5', 'Cyberdeck', 549375, 15, 'Device Rating 5: the deck legends retire on. Or die holding.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 3, rating: 'Legendary', legality: 'R', stats: 'DR 5, A/S/D/F 8 7 6 5, 5 programs', device: { deviceRating: 5, attack: 8, sleaze: 7, dataProcessing: 6, firewall: 5, programs: 5 } }),
|
|
164
|
-
row('fairlight-excalibur', 'Fairlight Excalibur', 'Cyberdeck', 823250, 18, 'Device Rating 6. There is no rung above this one, only rumors.', { page: 'p.439', shape: 'deck', size: 'Small', weight: 3, rating: 'Legendary', legality: 'R', stats: 'DR 6, A/S/D/F 9 8 7 6, 6 programs', device: { deviceRating: 6, attack: 9, sleaze: 8, dataProcessing: 7, firewall: 6, programs: 6 } }),
|
|
165
|
-
// ---- Deck software (p.442) -- "load <program>" runs a carried
|
|
166
|
-
// chip. Common programs are unrestricted at 80 nuyen; hacking
|
|
167
|
-
// programs are 250 nuyen at 6R; agents are rating x 2,000, avail
|
|
168
|
-
// rating x 3.
|
|
169
|
-
row('browse-program', 'Browse Program', 'Software', 80, 0, 'Purpose-built search routines: +2 dice on Matrix Search.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, stats: 'Common program', effects: [{ type: 'dice', category: 'skills', property: 'computer', value: 2, when: 'running', only: 'matrix-search' }] }),
|
|
170
|
-
row('toolbox-program', 'Toolbox Program', 'Software', 80, 0, 'Utility suite that keeps your persona thinking: +1 Data Processing.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, stats: 'Common program', effects: [{ type: 'attribute', category: 'matrix', property: 'dataProcessing', value: 1, when: 'running' }] }),
|
|
171
|
-
row('encryption-program', 'Encryption Program', 'Software', 80, 0, 'Wraps your traffic in ciphertext: +1 Firewall.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, stats: 'Common program', effects: [{ type: 'attribute', category: 'matrix', property: 'firewall', value: 1, when: 'running' }] }),
|
|
172
|
-
row('signal-scrub-program', 'Signal Scrub Program', 'Software', 80, 0, 'Cleans your noise floor: +1 die defending your PAN.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, stats: 'Common program', effects: [{ type: 'dice', category: 'pools', property: 'pan-defense', value: 1, when: 'running' }] }),
|
|
173
|
-
row('armor-program', 'Armor Program', 'Software', 250, 6, 'Structural integrity for your icon: +2 dice to resist Matrix damage.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, legality: 'R', stats: 'Hacking program', effects: [{ type: 'dice', category: 'pools', property: 'matrix-soak', value: 2, when: 'running' }] }),
|
|
174
|
-
row('biofeedback-filter-program', 'Biofeedback Filter Program', 'Software', 250, 6, 'A firewall for your sim module: +2 dice against biofeedback and dumpshock.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, legality: 'R', stats: 'Hacking program', effects: [{ type: 'dice', category: 'pools', property: 'biofeedback', value: 2, when: 'running' }] }),
|
|
175
|
-
row('exploit-program', 'Exploit Program', 'Software', 250, 6, 'Scans targets for Firewall weaknesses: +2 Sleaze when cracking.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, legality: 'R', stats: 'Hacking program', effects: [{ type: 'attribute', category: 'matrix', property: 'sleaze', value: 2, when: 'running' }] }),
|
|
176
|
-
row('sneak-program', 'Sneak Program', 'Software', 250, 6, 'Misroutes anyone hunting your icon: +2 dice defending a silent PAN.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, legality: 'R', stats: 'Hacking program', effects: [{ type: 'dice', category: 'pools', property: 'pan-defense', value: 2, when: 'running', only: 'silent' }] }),
|
|
177
|
-
row('hammer-program', 'Hammer Program', 'Software', 250, 6, 'Brute-force payload: +2 Matrix damage on your attack programs.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, legality: 'R', stats: 'Hacking program', effects: [{ type: 'attribute', category: 'matrix', property: 'damage', value: 2, when: 'running' }] }),
|
|
178
|
-
row('decryption-program', 'Decryption Program', 'Software', 250, 6, 'Rips ciphers apart in realtime: +2 Attack in Matrix combat.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, legality: 'R', stats: 'Hacking program', effects: [{ type: 'attribute', category: 'matrix', property: 'attack', value: 2, when: 'running' }] }),
|
|
179
|
-
row('agent-rating-4', 'Agent Rating 4', 'Software', 8000, 12, 'Autonomous pilot program, rating 4 -- a sharper mind for your deck than the bundled dog-brain ("agent" deploys it).', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, rating: 'Rare', stats: 'Agent 4: rating x 2,000 nuyen, avail rating x 3', ratingValue: 4 }),
|
|
180
|
-
row('agent-rating-6', 'Agent Rating 6', 'Software', 12000, 18, 'Top-shelf autonomous agent, rating 6 -- near-sapient, and priced like it knows.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, rating: 'Legendary', stats: 'Agent 6: rating x 2,000 nuyen, avail rating x 3', ratingValue: 6 }),
|
|
181
|
-
// SKILLSOFTS ARE OFF THE SHELF (2026-09-02): an Activesoft needs skillwires
|
|
182
|
-
// and a Knowsoft/Linguasoft a skilljack (p.442), and neither exists in the
|
|
183
|
-
// augmentation catalog yet -- a shop must not sell what nothing can run.
|
|
184
|
-
// Restore refunds one already bought (utilities/persistence.ts). Datasoft
|
|
185
|
-
// waits for a Knowledge test to land its Mental-limit bonus on.
|
|
186
|
-
row('mapsoft', 'Mapsoft', 'Software', 100, 4, 'Every alley, service tunnel, and dead end in the sprawl. Mostly current.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, stats: 'district map, no fog', effects: [{ type: 'flag', category: 'capability', property: 'no-fog', value: 1, when: 'stored' }] }),
|
|
187
|
-
row('shopsoft', 'Shopsoft', 'Software', 150, 4, 'Knows what a thing is worth before the fixer opens his mouth: +1 Social limit on haggle.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, effects: [{ type: 'limit', category: 'limits', property: 'social', value: 1, when: 'stored', only: 'haggle' }] }),
|
|
188
|
-
row('autosoft-3', 'Autosoft (Rating 3)', 'Software', 1500, 6, 'Drone brains in a chip: targeting, evasion, or clearsight, pick one.', { page: 'p.442', shape: 'chip', size: 'Tiny', weight: 0.1, rating: 'Standard', ratingValue: 3 }),
|
|
189
|
-
// ---- Comms & countermeasures (p.441) ----
|
|
190
|
-
row('microtransceiver', 'Microtransceiver', 'Electronics', 100, 2, 'Ear-canal comms for jobs where commlinks are too loud.', { page: 'p.441', shape: 'earpiece', size: 'Tiny', weight: 0.1 }),
|
|
191
|
-
row('subvocal-mic', 'Subvocal Microphone', 'Electronics', 50, 4, 'Stage-whisper at any range: -4 to anyone trying to overhear you.', { page: 'p.440', shape: 'patch', size: 'Tiny', weight: 0.1, stats: 'Device Rating 3', device: { deviceRating: 3 } }),
|
|
192
|
-
row('white-noise-generator', 'White Noise Generator (Rating 6)', 'Electronics', 300, 6, 'A bubble of privacy in a city of ears.', { page: 'p.441', shape: 'puck', size: 'Tiny', weight: 0.3, stats: 'Rating 6: rating x 50 nuyen, avail rating', ratingValue: 6 }),
|
|
193
|
-
row('data-tap', 'Data Tap', 'Electronics', 300, 6, 'Clamps a hardline and copies everything through it, quietly.', { page: 'p.441', shape: 'clamp', size: 'Tiny', weight: 0.2, legality: 'R' }),
|
|
194
|
-
row('tag-eraser', 'Tag Eraser', 'Electronics', 450, 6, 'Kills RFID at contact range: ten boxes of Matrix damage, one charge.', { page: 'p.441', shape: 'wand', size: 'Tiny', weight: 0.3, legality: 'R' }),
|
|
195
|
-
row('directional-jammer', 'Directional Jammer (Rating 6)', 'Electronics', 1200, 12, 'A cone of silence you can aim. Everything in front goes deaf.', { page: 'p.441', shape: 'horn', weight: 1, rating: 'Rare', legality: 'F', stats: 'Rating 6: rating x 200 nuyen, avail (rating x 2)F', ratingValue: 6 }),
|
|
196
|
-
row('area-jammer', 'Area Jammer (Rating 6)', 'Electronics', 1200, 18, 'Kills every wireless signal in the room, yours included.', { page: 'p.441', shape: 'box', weight: 1, rating: 'Rare', legality: 'F', stats: 'Rating 6: rating x 200 nuyen, avail (rating x 3)F', ratingValue: 6 }),
|
|
197
|
-
row('stealth-tags', 'Stealth RFID Tags (per 10)', 'Electronics', 10, 7, 'Tags that do not answer when the wrong people ask.', { page: 'p.440', shape: 'tags', size: 'Tiny', weight: 0.1, legality: 'R', stats: 'Device Rating 3', device: { deviceRating: 3 } }),
|
|
198
|
-
row('biometric-reader', 'Biometric Reader', 'Electronics', 200, 4, 'Prints, retinas, voice, tongue -- everything but DNA.', { page: 'p.440', shape: 'pad', size: 'Tiny', weight: 0.3, stats: 'Device Rating 3', device: { deviceRating: 3 } }),
|
|
199
|
-
row('trodes', 'Trodes', 'Electronics', 70, 0, 'A cheap headband doorway to VR. Everybody\'s first ride.', { page: 'p.440', shape: 'headband', size: 'Tiny', weight: 0.1, stats: 'Device Rating 3', device: { deviceRating: 3 }, effects: [{ type: 'flag', category: 'capability', property: 'dni', value: 1, when: 'worn' }] }),
|
|
200
|
-
// ---- Optics & audio (p.444-445) ----
|
|
201
|
-
row('goggles', 'Goggles (Capacity 4)', 'Glasses', 200, 0, 'Four slots of whatever you need your eyes to do tonight.', { page: 'p.444', shape: 'goggles', size: 'Tiny', weight: 0.3, stats: 'Capacity 4: capacity x 50 nuyen', ratingValue: 4, wearable: { capacity: 4, holds: ['vision'] } }),
|
|
202
|
-
row('glasses', 'Glasses (Capacity 3)', 'Glasses', 300, 0, 'Ordinary frames, extraordinary optics. Nobody looks twice.', { page: 'p.444', shape: 'glasses', size: 'Tiny', weight: 0.1, stats: 'Capacity 3: capacity x 100 nuyen', ratingValue: 3, wearable: { capacity: 3, holds: ['vision'] } }),
|
|
203
|
-
row('binoculars', 'Binoculars', 'Electronics', 50, 0, 'Distance, made someone else\'s problem.', { page: 'p.444', shape: 'binoculars', size: 'Tiny', weight: 0.5, stats: 'Built-in vision magnification' }),
|
|
204
|
-
row('micro-camera', 'Micro-Camera', 'Electronics', 100, 0, 'A lens the size of a coat button, and it never blinks.', { page: 'p.444', shape: 'lens', size: 'Tiny', weight: 0.1, stats: 'Capacity 1' }),
|
|
205
|
-
row('mage-sight-goggles', 'Mage Sight Goggles', 'Glasses', 3000, 12, 'Borrowed astral vision -- a mage sees what the lenses see.', { page: 'p.444', shape: 'goggles', size: 'Tiny', weight: 0.4, rating: 'Rare', legality: 'R' }),
|
|
206
|
-
row('smartlink', 'Smartlink (external)', 'Electronics', 2000, 4, 'The optics half of a smartgun system: +2 dice, and the gun knows it.', { page: 'p.444', shape: 'module', size: 'Tiny', weight: 0.1, rating: 'Standard', legality: 'R', stats: 'Vision enhancement, Capacity [1]', mod: { kind: 'vision', capacityCost: 1 }, effects: [{ type: 'flag', category: 'capability', property: 'smartlink', value: 1, when: 'fitted' }] }),
|
|
207
|
-
row('low-light-vision-mod', 'Low-Light Vision (mod)', 'Electronics', 500, 4, 'Turns a dark alley into a gray one.', { page: 'p.444', shape: 'module', size: 'Tiny', weight: 0.1, stats: 'Vision enhancement, Capacity [1]', mod: { kind: 'vision', capacityCost: 1 }, effects: [{ type: 'flag', category: 'capability', property: 'low-light', value: 1, when: 'fitted' }] }),
|
|
208
|
-
row('thermographic-vision-mod', 'Thermographic Vision (mod)', 'Electronics', 500, 6, 'Heat as a picture: bodies behind doors, engines still warm.', { page: 'p.444', shape: 'module', size: 'Tiny', weight: 0.1, stats: 'Vision enhancement, Capacity [1]', mod: { kind: 'vision', capacityCost: 1 }, effects: [{ type: 'flag', category: 'capability', property: 'thermographic', value: 1, when: 'fitted' }] }),
|
|
209
|
-
row('ear-buds', 'Ear Buds (Capacity 3)', 'Electronics', 150, 0, 'Hard to spot, harder to tell from the music kind.', { page: 'p.445', shape: 'earbuds', size: 'Tiny', weight: 0.1, stats: 'Capacity 3: capacity x 50 nuyen', ratingValue: 3, wearable: { capacity: 3, holds: ['audio'] } }),
|
|
210
|
-
// SENSORS (p.445), and only the four rows the book actually SELLS.
|
|
211
|
-
// The Sensor Functions table (camera, MAD scanner, ultrasound...) is a
|
|
212
|
-
// MAX RANGE reference with no price or availability column, and Sensor
|
|
213
|
-
// Housings is a max-rating-by-platform table -- neither is a price
|
|
214
|
-
// list, so neither becomes catalog rows. A housing is what you buy;
|
|
215
|
-
// the functions are what you put in it.
|
|
216
|
-
row('sensor-housing-handheld', 'Handheld Sensor Housing (Capacity 3)', 'Sensor', 300, 0, 'A palm case with three empty sockets and a hungry look.', { page: 'p.445', shape: 'case', size: 'Tiny', weight: 0.3, stats: 'Capacity 3: capacity x 100 nuyen; holds sensors up to Rating 3', ratingValue: 3 }),
|
|
217
|
-
row('sensor-housing-wall', 'Wall-Mounted Sensor Housing (Capacity 6)', 'Sensor', 1500, 0, 'Bolts to a wall and watches the room it is bolted to.', { page: 'p.445', shape: 'housing', size: 'Small', weight: 2, rating: 'Standard', stats: 'Capacity 6: capacity x 250 nuyen; holds sensors up to Rating 4', ratingValue: 6 }),
|
|
218
|
-
row('sensor-array-4', 'Sensor Array (Rating 4)', 'Sensor', 4000, 7, 'Six senses in one shell, and none of them blink.', { page: 'p.445', shape: 'array', size: 'Small', weight: 1.5, rating: 'Standard', stats: 'Rating 4: rating x 1,000 nuyen, avail 7; capacity [6]', ratingValue: 4 }),
|
|
219
|
-
row('single-sensor-4', 'Single Sensor (Rating 4)', 'Sensor', 400, 5, 'One sense, done properly, for when you only need the one.', { page: 'p.445', shape: 'module', size: 'Tiny', weight: 0.2, stats: 'Rating 4: rating x 100 nuyen, avail 5; capacity [1]', ratingValue: 4 }),
|
|
220
|
-
row('laser-mic', 'Laser Microphone (Capacity 3)', 'Electronics', 300, 6, 'Reads a conversation off the windowpane it happened behind.', { page: 'p.445', shape: 'mic', size: 'Tiny', weight: 0.4, legality: 'R', stats: 'Capacity 3: capacity x 100 nuyen', ratingValue: 3 }),
|
|
221
|
-
// ---- Security, B&E, and rope (p.447-p.450) ----
|
|
222
|
-
row('plasteel-restraints', 'Plasteel Restraints', 'Electronics', 50, 6, 'Cuffs that do not care how strong you think you are.', { page: 'p.447', shape: 'cuffs', size: 'Tiny', weight: 0.3, legality: 'R' }),
|
|
223
|
-
row('containment-manacles', 'Containment Manacles', 'Electronics', 250, 6, 'For prisoners with chrome, magic, or ideas.', { page: 'p.447', shape: 'manacles', size: 'Small', weight: 1.5, legality: 'R' }),
|
|
224
|
-
row('lockpick-set', 'Lockpick Set', 'Electronics', 250, 4, 'Manual picks and a shim set, wrapped like surgeon\'s tools.', { page: 'p.448', shape: 'roll', size: 'Tiny', weight: 0.3, legality: 'R', useHint: 'These aren\'t for admiring -- "pick <door>" while you\'re at the lock.' }),
|
|
225
|
-
row('sequencer-4', 'Sequencer (Rating 4)', 'Electronics', 1000, 12, 'Brute-forces a maglock\'s passcode while you stand there looking bored.', { page: 'p.448', shape: 'dongle', size: 'Tiny', weight: 0.2, rating: 'Standard', legality: 'F', stats: 'Rating 4: rating x 250 nuyen, avail (rating x 3)F', ratingValue: 4, effects: [{ type: 'flag', category: 'capability', property: 'maglock-opposed', value: 1, when: 'carried' }], useHint: 'It only earns its keep at a lock -- "pick <door>" while you\'re carrying it.' }),
|
|
226
|
-
row('maglock-passkey-4', 'Maglock Passkey (Rating 4)', 'Electronics', 8000, 12, 'A skeleton key for cardreaders. Expensive because it works.', { page: 'p.448', shape: 'card', size: 'Tiny', weight: 0.1, rating: 'Rare', legality: 'F', stats: 'Rating 4: rating x 2,000 nuyen, avail (rating x 3)F', ratingValue: 4, effects: [{ type: 'flag', category: 'capability', property: 'maglock-opposed', value: 1, when: 'carried' }], useHint: 'It only earns its keep at a lock -- "pick <door>" while you\'re carrying it.' }),
|
|
227
|
-
row('keycard-copier-4', 'Keycard Copier (Rating 4)', 'Electronics', 2400, 8, 'Swipe once, own the door. The forged card rolls Rating x 2.', { page: 'p.448', shape: 'reader', size: 'Tiny', weight: 0.3, rating: 'Standard', legality: 'F', stats: 'Rating 4: rating x 600 nuyen, avail 8F', ratingValue: 4, effects: [{ type: 'flag', category: 'capability', property: 'maglock-opposed', value: 1, when: 'carried' }], useHint: 'Reading a card is not the same as opening the door -- "pick <door>" once you\'re carrying it.' }),
|
|
228
|
-
// Rated rows follow the shipped convention (fake-sin-N, qi-focus-N):
|
|
229
|
-
// ONE row at a concrete rating with the price and availability already
|
|
230
|
-
// computed for it, and the FORMULA kept in `stats` so a player can
|
|
231
|
-
// read off any other rating. Note the two shapes in this table --
|
|
232
|
-
// autopicker/molder/copier have a FLAT availability and scale only on
|
|
233
|
-
// cost, while passkey and sequencer scale both.
|
|
234
|
-
row('autopicker-3', 'Autopicker (Rating 3)', 'Electronics', 1500, 8, 'Reads the tumblers and turns them for you, patiently, while you watch the corridor.', { page: 'p.447', shape: 'wand', size: 'Tiny', weight: 0.3, legality: 'R', stats: 'Rating 3: rating x 500 nuyen, avail 8R', ratingValue: 3, effects: [{ type: 'flag', category: 'capability', property: 'autopicker', value: 1, when: 'carried' }], useHint: 'It only earns its keep at a lock -- "pick <door>" while you\'re carrying it.' }),
|
|
235
|
-
row('cellular-glove-molder-2', 'Cellular Glove Molder (Rating 2)', 'Electronics', 1000, 12, 'Wears somebody else\'s fingerprints for as long as the scanner is looking.', { page: 'p.447', shape: 'glove', size: 'Tiny', weight: 0.2, legality: 'F', stats: 'Rating 2: rating x 500 nuyen, avail 12F', ratingValue: 2 }),
|
|
236
|
-
row('chisel-crowbar', 'Chisel/Crowbar', 'Tool', 20, 0, 'The oldest answer to a locked thing, and still the loudest.', { page: 'p.447', shape: 'bar', size: 'Small', weight: 1.5, texture: 'pitted steel' }),
|
|
237
|
-
row('miniwelder', 'Miniwelder', 'Electronics', 250, 2, 'Thirty minutes of arc: through a hinge, a bar, or a padlock.', { page: 'p.448', shape: 'torch', size: 'Small', weight: 1.5 }),
|
|
238
|
-
row('miniwelder-fuel-canister', 'Miniwelder Fuel Canister', 'Consumable', 80, 2, 'Another thirty minutes. Buy two -- doors come in pairs.', { page: 'p.447', shape: 'canister', size: 'Tiny', weight: 0.4 }),
|
|
239
|
-
row('glue-solvent', 'Glue Solvent', 'Consumable', 90, 2, 'Undoes a square metre of somebody else\'s bright idea.', { page: 'p.448', shape: 'spray can', size: 'Tiny', weight: 0.5 }),
|
|
240
|
-
row('glue-sprayer', 'Glue Sprayer', 'Consumable', 150, 2, 'A square metre of fast-drying superglue: enough to seal a door somebody else needs.', { page: 'p.448', shape: 'spray can', size: 'Tiny', weight: 0.5, stats: 'Sets in 1 Combat Turn; Body 5 / Strength 5 to force' }),
|
|
241
|
-
row('thermite-burning-bar', 'Thermite Burning Bar', 'Electronics', 500, 16, 'Burns through a vault door and everything behind it. Bring a hood.', { page: 'p.448', shape: 'bar', size: 'Medium', weight: 3, rating: 'Rare', legality: 'R' }),
|
|
242
|
-
row('monofilament-chainsaw', 'Monofilament Chainsaw', 'Electronics', 500, 8, 'A loop of monowire on a motor. It does not know what a wall is.', { page: 'p.448', shape: 'saw', size: 'Medium', weight: 3, rating: 'Standard', stats: 'Acc 3, Reach 1, DV 8P, AP -6 (Exotic Melee)', weapon: { skill: 'exotic-melee', accuracy: 3, dv: 8, damageType: 'P', ap: -6, reach: 1, range: 'melee' } }),
|
|
243
|
-
row('standard-rope', 'Standard Rope (100 m)', 'Electronics', 50, 0, 'A hundred meters of the least glamorous life insurance made.', { page: 'p.450', shape: 'coil', size: 'Medium', weight: 4, texture: 'braided' }),
|
|
244
|
-
row('stealth-rope', 'Stealth Rope (100 m)', 'Electronics', 85, 8, 'Rope that stiffens on command and goes limp when you leave it.', { page: 'p.450', shape: 'coil', size: 'Medium', weight: 3, legality: 'F' }),
|
|
245
|
-
row('myomeric-rope', 'Myomeric Rope (10 m)', 'Electronics', 200, 10, 'Rope that climbs for you. Ten meters of muscle in a coil.', { page: 'p.450', shape: 'coil', size: 'Small', weight: 2, rating: 'Standard' }),
|
|
246
|
-
// ---- Survival & entry (p.449-p.450) ----
|
|
247
|
-
row('climbing-gear', 'Climbing Gear', 'Electronics', 200, 0, 'Rope, harness, and hardware rated for your bad decisions.', { page: 'p.449', shape: 'kit', size: 'Medium', weight: 5, effects: [{ type: 'dice', category: 'pools', property: 'climbing', value: 2, when: 'carried' }] }),
|
|
248
|
-
row('flashlight', 'Flashlight', 'Electronics', 25, 0, 'Light where the city forgot to put any.', { page: 'p.449', shape: 'tube', size: 'Tiny', weight: 0.3 }),
|
|
249
|
-
row('light-stick', 'Light Stick', 'Electronics', 25, 0, 'Crack it, drop it, mark the way out.', { page: 'p.449', shape: 'stick', size: 'Tiny', weight: 0.1, color: 'chem green' }),
|
|
250
|
-
row('magnesium-torch', 'Magnesium Torch', 'Consumable', 5, 0, 'Burns white and does not care about the rain. Once.', { page: 'p.449', shape: 'torch', size: 'Tiny', weight: 0.2, color: 'grey' }),
|
|
251
|
-
row('micro-flare-launcher', 'Micro Flare Launcher', 'Electronics', 175, 0, 'Puts a hard little sun over the block for as long as anyone needs to see.', { page: 'p.449', shape: 'launcher', size: 'Small', weight: 0.6 }),
|
|
252
|
-
row('micro-flares', 'Micro Flares', 'Consumable', 25, 0, 'Reloads for the launcher. Sold by the handful, spent in seconds.', { page: 'p.449', shape: 'cartridge', size: 'Tiny', weight: 0.1 }),
|
|
253
|
-
row('gas-mask', 'Gas Mask', 'Mask', 200, 0, 'Filters the air the sprawl insists on selling you.', { page: 'p.449', shape: 'mask', size: 'Small', weight: 1 }),
|
|
254
|
-
row('respirator-4', 'Respirator (Rating 4)', 'Mask', 200, 0, 'A slim filter for smoke, dust, and whatever the plant is venting.', { page: 'p.449', shape: 'mask', size: 'Tiny', weight: 0.4, stats: 'Rating 4: rating x 50 nuyen', ratingValue: 4 }),
|
|
255
|
-
row('chemsuit-4', 'Chemsuit (Rating 4)', 'Clothing', 600, 8, 'A coverall that argues with chemistry for as long as it lasts.', { page: 'p.449', shape: 'coverall', size: 'Medium', weight: 2, rating: 'Standard', stats: 'Rating 4: rating x 150 nuyen, avail rating x 2', ratingValue: 4 }),
|
|
256
|
-
row('gecko-tape-gloves', 'Gecko Tape Gloves', 'Gloves', 250, 12, 'Walk up the wall. Forbidden for exactly that reason.', { page: 'p.449', shape: 'gloves', size: 'Tiny', weight: 0.3, rating: 'Rare' }),
|
|
257
|
-
row('rappelling-gloves', 'Rappelling Gloves', 'Gloves', 50, 0, 'Palms that let you go down fast without leaving skin behind.', { page: 'p.449', shape: 'gloves', size: 'Tiny', weight: 0.2, texture: 'reinforced leather' }),
|
|
258
|
-
row('survival-kit', 'Survival Kit', 'Electronics', 200, 4, 'Everything the barrens forgot to provide.', { page: 'p.449', shape: 'kit', size: 'Medium', weight: 3 }),
|
|
259
|
-
row('grapple-gun', 'Grapple Gun', 'Electronics', 500, 8, 'A rooftop in one pull of a trigger. Bring the descent kit.', { page: 'p.450', shape: 'launcher', size: 'Medium', weight: 2, legality: 'R', stats: 'Acc 3, DV 7S, AP -2, SS, 1 (ml)', weapon: { skill: 'exotic-ranged', accuracy: 3, dv: 7, damageType: 'S', ap: -2, modes: ['SS'], ammo: { rounds: 1, feed: 'ml' } } }),
|
|
260
|
-
// The p.443 Tools table, all three tiers. GENERIC rows, not one per
|
|
261
|
-
// skill: canon sells a kit/shop/facility per trade, but `tool-kit`
|
|
262
|
-
// already shipped as one row that says "buy the trade separately" in
|
|
263
|
-
// its description, and splitting only the two new tiers would leave a
|
|
264
|
-
// three-row canon table inconsistent with itself -- while splitting
|
|
265
|
-
// all three would rewrite an existing row and every chargen payload
|
|
266
|
-
// that grants it. Following the shipped precedent keeps this additive.
|
|
267
|
-
row('tool-kit', 'Tool Kit', 'Tool', 500, 0, 'One trade\'s worth of tools in a case. Buy the trade separately.', { page: 'p.443', shape: 'case', size: 'Medium', weight: 4 }),
|
|
268
|
-
row('tool-shop', 'Tool Shop', 'Tool', 5000, 8, 'A trade\'s worth of bench and press, and a van to move it in. Buy the trade separately.', { page: 'p.443', shape: 'bench', size: 'Large', weight: 120, rating: 'Standard', stats: 'Shop: transportable, advanced repairs and building' }),
|
|
269
|
-
row('tool-facility', 'Tool Facility', 'Tool', 50000, 12, 'A room that does not move, full of machines that do. Buy the trade separately.', { page: 'p.443', shape: 'workshop', size: 'VeryLarge', weight: 2000, rating: 'Rare', stats: 'Facility: immobile, advanced construction and modification' }),
|
|
270
|
-
// ---- Medical (p.450-p.451) ----
|
|
271
|
-
row('disposable-syringe', 'Disposable Syringe', 'Medical', 10, 3, 'One dose, one use, no questions afterward.', { page: 'p.450', shape: 'syringe', size: 'Tiny', weight: 0.1, color: 'clear' }),
|
|
272
|
-
row('biomonitor', 'Biomonitor', 'Medical', 300, 3, 'Reads your vitals and tells the world when they stop.', { page: 'p.450', shape: 'band', size: 'Tiny', weight: 0.2 }),
|
|
273
|
-
row('medkit-supplies', 'Medkit Supplies', 'Medical', 100, 0, 'Refills: sealant, patches, and the drugs that ran out last run.', { page: 'p.450', shape: 'pouch', size: 'Tiny', weight: 0.5, color: 'red' }),
|
|
274
|
-
row('medkit-3', 'Medkit (Rating 3)', 'Medical', 750, 3, 'Pocket trauma kit: sealant, stims, a diagnostic patch.', { page: 'p.450', shape: 'case', color: 'red', stats: 'Rating 3: rating x 250 nuyen, avail rating', ratingValue: 3, effects: [{ type: 'dice', category: 'skills', property: 'first-aid', value: 1, when: 'carried', scaleBy: 'rating' }] }),
|
|
275
|
-
row('medkit-6', 'Medkit (Rating 6)', 'Medical', 1500, 6, 'A clinic in a handheld case -- the good one.', { page: 'p.450', shape: 'case', size: 'Medium', weight: 2, color: 'red', stats: 'Rating 6: rating x 250 nuyen, avail rating', ratingValue: 6, effects: [{ type: 'dice', category: 'skills', property: 'first-aid', value: 1, when: 'carried', scaleBy: 'rating' }] }),
|
|
276
|
-
row('stim-patch', 'Stim Patch (Rating 4)', 'StimPatch', 100, 8, 'Slap-on chemical courage. The crash comes later.', { page: 'p.451', shape: 'patch', size: 'Tiny', weight: 0.1, color: 'yellow', stats: 'Rating 4: rating x 25 nuyen, avail rating x 2', ratingValue: 4 }),
|
|
277
|
-
row('antidote-patch-4', 'Antidote Patch (Rating 4)', 'SlapPatch', 200, 4, 'Argues with a toxin already in your blood. Sometimes it wins.', { page: 'p.451', shape: 'patch', size: 'Tiny', weight: 0.1, color: 'green', stats: 'Rating 4: rating x 50 nuyen, avail rating', ratingValue: 4 }),
|
|
278
|
-
row('tranq-patch-6', 'Tranq Patch (Rating 6)', 'SlapPatch', 120, 12, 'Puts someone under without putting them down.', { page: 'p.451', shape: 'patch', size: 'Tiny', weight: 0.1, color: 'blue', stats: 'Rating 6: rating x 20 nuyen, avail rating x 2', ratingValue: 6 }),
|
|
279
|
-
row('trauma-patch', 'Trauma Patch', 'Medical', 500, 6, 'The patch that argues with death itself. Once.', { page: 'p.451', shape: 'patch', size: 'Tiny', weight: 0.1, color: 'red', rating: 'Standard', stats: 'Stabilizes a dying patient on Body' }),
|
|
280
|
-
// ---- Magical goods (p.461) ----
|
|
281
|
-
row('reagents', 'Reagents (10 drams)', 'Focus', 200, 0, 'Alchemically potent odds and ends, jarred and labeled.', { page: 'p.461', shape: 'jar', size: 'Tiny', weight: 0.5, stats: '20 nuyen per dram' }),
|
|
282
|
-
row('lodge-materials-3', 'Magical Lodge Materials (Force 3)', 'Focus', 1500, 6, 'The candles, chalk, and silence a lodge is actually made of.', { page: 'p.461', shape: 'crate', size: 'Medium', weight: 6, rating: 'Standard', stats: 'Force 3: force x 500 nuyen, avail force x 2', ratingValue: 3 }),
|
|
283
|
-
row('qi-focus-1', 'Qi Focus (Force 1)', 'Focus', 3000, 3, 'Bound to the body, not the hand -- a tattoo that hums when you do.', { page: 'p.461', shape: 'tattoo', size: 'Tiny', weight: 0, rating: 'Standard', legality: 'R', stats: 'Force 1: force x 3,000 nuyen, avail (force x 3)R', ratingValue: 1 }),
|
|
284
|
-
row('spell-focus-1', 'Spell Focus (Force 1)', 'Focus', 4000, 3, 'A lens for one category of spell. Bond it or it is jewelry.', { page: 'p.461', shape: 'ring', size: 'Tiny', weight: 0.1, rating: 'Standard', legality: 'R', stats: 'Force 1: force x 4,000 nuyen, avail (force x 3)R', ratingValue: 1, effects: [{ type: 'dice', category: 'skills', property: 'spellcasting', value: 1, when: 'carried', scaleBy: 'rating' }] }),
|
|
285
|
-
row('spirit-focus-1', 'Spirit Focus (Force 1)', 'Focus', 4000, 3, 'Where a summoner keeps the leash.', { page: 'p.461', shape: 'talisman', size: 'Tiny', weight: 0.1, rating: 'Standard', legality: 'R', stats: 'Force 1: force x 4,000 nuyen, avail (force x 3)R', ratingValue: 1, effects: [{ type: 'dice', category: 'skills', property: 'summoning', value: 1, when: 'carried', scaleBy: 'rating' }] }),
|
|
286
|
-
row('weapon-focus-1', 'Weapon Focus (Force 1)', 'Focus', 7000, 4, 'A blade that cuts things that have never had a body.', { page: 'p.461', shape: 'blade', size: 'Medium', weight: 1.2, rating: 'Rare', legality: 'R', stats: 'Force 1: force x 7,000 nuyen, avail (force x 4)R', ratingValue: 1 }),
|
|
287
|
-
row('power-focus-1', 'Power Focus (Force 1)', 'Focus', 18000, 4, 'A bound anchor for living mana. The real investment.', { page: 'p.461', shape: 'amulet', size: 'Tiny', weight: 0.2, rating: 'Rare', legality: 'R', stats: 'Force 1: force x 18,000 nuyen, avail (force x 4)R', ratingValue: 1, effects: [{ type: 'dice', category: 'skills', property: 'spellcasting', value: 1, when: 'carried', scaleBy: 'rating' }] }),
|
|
288
|
-
// SPELL FORMULAE ARE GENERATED, one per spell, by formulaRows() below
|
|
289
|
-
// -- a formula is written for ONE spell and priced by that spell's
|
|
290
|
-
// category (p.461). The five category-named rows that used to sit
|
|
291
|
-
// here could never teach anything: knowsSpell looks for the spell
|
|
292
|
-
// name inside the item name, and "Combat Spell Formula" contains no
|
|
293
|
-
// spell's name.
|
|
294
|
-
// ---- Drones (p.466) ----
|
|
295
|
-
// ANTHROPOMORPHIC DRONES (Rigger 5.0 p.145-148) -- the FIRST rows in
|
|
296
|
-
// this catalog cited to a book other than the core rulebook, so the
|
|
297
|
-
// page cite names it. They are a different animal from the walkers
|
|
298
|
-
// above: two drone arms and two drone legs, a Physical monitor of
|
|
299
|
-
// 8 + (Body/2) rather than the usual, and enough metahuman shape to
|
|
300
|
-
// use metahuman clothing, weapons and tools. The 'G' on Speed is the
|
|
301
|
-
// book's own ground-speed notation and is kept verbatim.
|
|
302
|
-
row('horizon-little-buddy', 'Horizon Little Buddy', 'Drone', 2000, 4, 'A five-year-old sized nanny that never sleeps and never raises its voice.', { page: 'Rigger 5.0 p.146', shape: 'anthroform', size: 'Small', weight: 20, color: 'nursery yellow', stats: 'Handl 2, Spd 1G, Acc 1, Bod 1, Arm 0, Pilot 2, Sen 2; anthro: arms and legs, Physical 8 + (Bod/2)', vehicle: { handling: 2, speed: '1G', acceleration: 1, body: 1, armor: 0, pilot: 2, sensor: 2, anthro: true } }),
|
|
303
|
-
row('aztechnology-criado-juan', 'Aztechnology Criado Juan', 'Drone', 8000, 2, 'The cheap Azzie houseservant from the ad campaign nobody can unhear.', { page: 'Rigger 5.0 p.145', shape: 'anthroform', size: 'Medium', weight: 45, rating: 'Standard', stats: 'Handl 2, Spd 2G, Acc 1, Bod 2, Arm 0, Pilot 2, Sen 2; anthro: arms and legs, Physical 8 + (Bod/2)', vehicle: { handling: 2, speed: '2G', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 2, anthro: true } }),
|
|
304
|
-
row('mct-kenchiku-kikai', 'MCT Kenchiku-Kikai', 'Drone', 20000, 8, 'The oldest anthroform still on the job, and it has been on the job a long time.', { page: 'Rigger 5.0 p.146', shape: 'anthroform', size: 'Large', weight: 120, rating: 'Rare', legality: 'R', stats: 'Handl 2, Spd 2G, Acc 1, Bod 5, Arm 3, Pilot 2, Sen 2; anthro: arms and legs, Physical 8 + (Bod/2)', vehicle: { handling: 2, speed: '2G', acceleration: 1, body: 5, armor: 3, pilot: 2, sensor: 2, anthro: true } }),
|
|
305
|
-
row('shiawase-i-doll', 'Shiawase I-Doll', 'Drone', 20000, 4, 'A domestic servant built to be customised, and customised by everyone who buys one.', { page: 'Rigger 5.0 p.148', shape: 'anthroform', size: 'Medium', weight: 55, rating: 'Rare', stats: 'Handl 3, Spd 3G, Acc 1, Bod 3, Arm 0, Pilot 3, Sen 3; anthro: arms and legs, Physical 8 + (Bod/2)', vehicle: { handling: 3, speed: '3G', acceleration: 1, body: 3, armor: 0, pilot: 3, sensor: 3, anthro: true } }),
|
|
306
|
-
row('sk-direktionssekretar', 'S-K Direktionssekretar', 'Drone', 40000, 12, 'A corporate secretary that files, schedules, and is armoured for a reason.', { page: 'Rigger 5.0 p.148', shape: 'anthroform', size: 'Medium', weight: 60, rating: 'Rare', legality: 'R', stats: 'Handl 4, Spd 4G, Acc 2, Bod 4, Arm 3, Pilot 4, Sen 4; anthro: arms and legs, Physical 8 + (Bod/2)', vehicle: { handling: 4, speed: '4G', acceleration: 2, body: 4, armor: 3, pilot: 4, sensor: 4, anthro: true } }),
|
|
307
|
-
row('neonet-juggernaught', 'NeoNET Juggernaught', 'Drone', 100000, 14, 'Heavy artillery in a person-shaped chassis, sold to people who wanted exactly that.', { page: 'Rigger 5.0 p.147', shape: 'anthroform', size: 'Large', weight: 300, rating: 'Rare', legality: 'R', stats: 'Handl 3, Spd 4G, Acc 1, Bod 6, Arm 12, Pilot 3, Sen 3; anthro: arms and legs, Physical 8 + (Bod/2)', vehicle: { handling: 3, speed: '4G', acceleration: 1, body: 6, armor: 12, pilot: 3, sensor: 3, anthro: true } }),
|
|
308
|
-
// THE REST OF RIGGER 5.0 (p.126-148). The core p.466 table and the six
|
|
309
|
-
// anthroforms shipped earlier; this is the remaining lineup -- micro,
|
|
310
|
-
// mini, small, medium, large, huge, and one drone that is a missile.
|
|
311
|
-
//
|
|
312
|
-
// PAGE REFS COME FROM THE BOOK'S OWN COMPILED TABLES (p.188-190), not
|
|
313
|
-
// from page footers: two mechanical footer derivations disagreed by one
|
|
314
|
-
// page, and a spot check showed the footer rule is inconsistent (the
|
|
315
|
-
// Cheetah overshoots, the Sentry does not). The appendix is an index and
|
|
316
|
-
// is authoritative.
|
|
317
|
-
//
|
|
318
|
-
// Stats are the book's own line verbatim: Body carries its MOD POINTS in
|
|
319
|
-
// parentheses (Rigger p.122 -- "2(1)" is Body 2 with 1 point free), and
|
|
320
|
-
// Speed keeps its travel-mode letter (G ground, R rotor, J jet, W water,
|
|
321
|
-
// p.124). "P" is left unexpanded on purpose: the retrieval was explicit
|
|
322
|
-
// that it could not say what P stands for, and a guess in a stat line
|
|
323
|
-
// reads exactly like a fact.
|
|
324
|
-
row('horizon-noizquito', 'Horizon "Noizquito"', 'Drone', 2000, 10, 'A mosquito with a microphone, sold to people who want to hear a room they are not in.', { page: 'Rigger 5.0 p.128', shape: 'insect', size: 'Tiny', weight: 0.2, legality: 'R', stats: 'Handl 4, Spd 3R, Acc 2, Bod 1, Arm 0, Pilot 3, Sen 3', vehicle: { handling: 4, speed: '3R', acceleration: 2, body: 1, armor: 0, pilot: 3, sensor: 3 } }),
|
|
325
|
-
row('sony-goldfish', 'Sony Goldfish', 'Drone', 500, 6, 'A toy that swims, watches, and costs less than dinner.', { page: 'Rigger 5.0 p.128', shape: 'insect', size: 'Tiny', weight: 0.2, stats: 'Handl 2/4, Spd 1W, Acc 1, Bod 0, Arm 0, Pilot 2, Sen 2', vehicle: { handling: '2/4', speed: '1W', acceleration: 1, body: 0, armor: 0, pilot: 2, sensor: 2 } }),
|
|
326
|
-
row('aerodesigns-condor', 'Aerodesigns Condor', 'Drone', 4000, 6, 'A glider that rides thermals all day and reports what it saw at dusk.', { page: 'Rigger 5.0 p.129', shape: 'insect', size: 'Tiny', weight: 0.5, legality: 'R', stats: 'Handl 2, Spd 0R, Acc 0, Bod 1(1), Arm 0, Pilot 2, Sen 4', vehicle: { handling: 2, speed: '0R', acceleration: 0, body: 1, armor: 0, pilot: 2, sensor: 4 } }),
|
|
327
|
-
row('aztechnology-hedgehog', 'Aztechnology Hedgehog', 'Drone', 8000, 8, 'Small, spiny, and disinclined to be picked up by anyone it does not know.', { page: 'Rigger 5.0 p.129', shape: 'insect', size: 'Tiny', weight: 0.5, legality: 'F', stats: 'Handl 3, Spd 1G, Acc 1, Bod 1(0), Arm 0, Pilot 4, Sen 3', vehicle: { handling: 3, speed: '1G', acceleration: 1, body: 1, armor: 0, pilot: 4, sensor: 3 } }),
|
|
328
|
-
row('cd-dragonfly', 'CD Dragonfly', 'Drone', 4000, 12, 'Four wings, one camera, and a knack for hovering where nobody thinks to look.', { page: 'Rigger 5.0 p.129', shape: 'insect', size: 'Tiny', weight: 0.5, legality: 'R', stats: 'Handl 4, Spd 2P, Acc 1, Bod 1(0), Arm 3, Pilot 3, Sen 2', vehicle: { handling: 4, speed: '2P', acceleration: 1, body: 1, armor: 3, pilot: 3, sensor: 2 } }),
|
|
329
|
-
row('festo-pigeon-2-0', 'Festo Pigeon 2.0', 'Drone', 3000, 8, 'Indistinguishable from the real thing until it does not fly away.', { page: 'Rigger 5.0 p.129', shape: 'insect', size: 'Tiny', weight: 0.5, stats: 'Handl 4, Spd 2P, Acc 1, Bod 1(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: 4, speed: '2P', acceleration: 1, body: 1, armor: 0, pilot: 2, sensor: 2 } }),
|
|
330
|
-
row('horizon-cu-3', 'Horizon CU^3', 'Drone', 3000, 4, 'A cube that follows you and films you, which is apparently what people wanted.', { page: 'Rigger 5.0 p.130', shape: 'insect', size: 'Tiny', weight: 0.5, stats: 'Handl 4, Spd 1P, Acc 1, Bod 1(1), Arm 0, Pilot 2, Sen 3', vehicle: { handling: 4, speed: '1P', acceleration: 1, body: 1, armor: 0, pilot: 2, sensor: 3 } }),
|
|
331
|
-
row('renraku-gerbil', 'Renraku Gerbil', 'Drone', 2000, 4, 'Scurries under furniture and through ducts, cheerfully, for hours.', { page: 'Rigger 5.0 p.130', shape: 'insect', size: 'Tiny', weight: 0.5, stats: 'Handl 4/2, Spd 2G, Acc 1, Bod 1(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: '4/2', speed: '2G', acceleration: 1, body: 1, armor: 0, pilot: 2, sensor: 2 } }),
|
|
332
|
-
row('ares-sentry', 'Ares Sentry', 'Drone', 4000, 4, 'It does not move and it does not need to. It watches an arc and shoots what enters it.', { page: 'Rigger 5.0 p.130', shape: 'frame', size: 'Small', weight: 4, legality: 'R', stats: 'Handl 4/--, Spd 1G, Acc 1, Bod 2(0), Arm 6, Pilot 3, Sen 2', vehicle: { handling: '4/--', speed: '1G', acceleration: 1, body: 2, armor: 6, pilot: 3, sensor: 2 } }),
|
|
333
|
-
row('c-b-smoke-generator', 'C-B Smoke Generator', 'Drone', 4000, 8, 'Fills a room with cover on request. Everything after that is your problem.', { page: 'Rigger 5.0 p.130', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 1G, Acc 1, Bod 2(0), Arm 0, Pilot 2, Sen 2', vehicle: { handling: 3, speed: '1G', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
334
|
-
row('cd-wolfhound', 'CD Wolfhound', 'Drone', 30000, 12, 'A long-range hunter with a nose for signal and the patience to use it.', { page: 'Rigger 5.0 p.131', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 2J, Acc 1, Bod 2(1), Arm 0, Pilot 2, Sen 4', vehicle: { handling: 3, speed: '2J', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 4 } }),
|
|
335
|
-
row('evo-proletarian', 'Evo Proletarian', 'Drone', 4000, 6, 'The people\'s drone: cheap, rugged, and unbothered by dignity.', { page: 'Rigger 5.0 p.131', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 4/2, Spd 2G, Acc 1, Bod 2(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: '4/2', speed: '2G', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
336
|
-
row('ferret-rpd-5x', 'Ferret RPD-5X', 'Drone', 4000, 8, 'A guard dog that fits under a desk and takes the job seriously.', { page: 'Rigger 5.0 p.132', shape: 'frame', size: 'Small', weight: 4, legality: 'R', stats: 'Handl 4/2, Spd 1G, Acc 1, Bod 2(1), Arm 3, Pilot 3, Sen 3', vehicle: { handling: '4/2', speed: '1G', acceleration: 1, body: 2, armor: 3, pilot: 3, sensor: 3 } }),
|
|
337
|
-
row('festo-sewer-snake', 'Festo Sewer Snake', 'Drone', 6000, 10, 'Goes where the pipes go, which is everywhere nobody wants to follow.', { page: 'Rigger 5.0 p.132', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 1G/1W, Acc 1/1, Bod 2(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: 3, speed: '1G/1W', acceleration: '1/1', body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
338
|
-
row('horizon-mini-zep', 'Horizon Mini-Zep', 'Drone', 2000, 4, 'A little airship that loiters over a crowd for as long as the crowd lasts.', { page: 'Rigger 5.0 p.131-132', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 2, Spd 0P, Acc 0, Bod 2(4), Arm 0, Pilot 2, Sen 2', vehicle: { handling: 2, speed: '0P', acceleration: 0, body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
339
|
-
row('knight-errant-p5', 'Knight Errant P5', 'Drone', 8000, 10, 'Police pursuit in a small package. It is faster than you and it does not tire.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, legality: 'R', stats: 'Handl 4/2, Spd 6G, Acc 2, Bod 2(1), Arm 0, Pilot 3, Sen 2', vehicle: { handling: '4/2', speed: '6G', acceleration: 2, body: 2, armor: 0, pilot: 3, sensor: 2 } }),
|
|
340
|
-
row('ls-castle-guard', 'LS Castle Guard', 'Drone', 10000, 8, 'Bolted to a wall with a firing arc and no imagination whatsoever.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, legality: 'R', stats: 'Handl 4/2, Spd 1G, Acc 1, Bod 2(0), Arm 6, Pilot 3, Sen 2', vehicle: { handling: '4/2', speed: '1G', acceleration: 1, body: 2, armor: 6, pilot: 3, sensor: 2 } }),
|
|
341
|
-
row('mct-gun-turret', 'MCT Gun Turret', 'Drone', 4000, 4, 'It has no wheels because it is not going anywhere. Neither, ideally, are you.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, legality: 'R', stats: 'Handl --, Spd --, Acc --, Bod 2(0), Arm 6, Pilot 3, Sen 2', vehicle: { handling: '--', speed: '--', acceleration: '--', body: 2, armor: 6, pilot: 3, sensor: 2 } }),
|
|
342
|
-
row('mct-seven-wheelie', 'MCT Seven (Wheelie)', 'Drone', 2000, 0, 'The modular Seven on two wheels -- quick, cheap, and easily replaced.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 4/2, Spd 2G, Acc 1, Bod 1(3), Arm 0, Pilot 1, Sen 1', vehicle: { handling: '4/2', speed: '2G', acceleration: 1, body: 1, armor: 0, pilot: 1, sensor: 1 } }),
|
|
343
|
-
row('mct-seven-treads', 'MCT Seven (Treads)', 'Drone', 2000, 2, 'The modular Seven on treads, for ground that argues back.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 2G, Acc 1, Bod 1(3), Arm 0, Pilot 1, Sen 1', vehicle: { handling: 3, speed: '2G', acceleration: 1, body: 1, armor: 0, pilot: 1, sensor: 1 } }),
|
|
344
|
-
row('mct-seven-dirty', 'MCT Seven (Dirty)', 'Drone', 2000, 2, 'The modular Seven built for mud, dust, and the places between them.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 2/4, Spd 2G, Acc 1, Bod 1(3), Arm 0, Pilot 1, Sen 1', vehicle: { handling: '2/4', speed: '2G', acceleration: 1, body: 1, armor: 0, pilot: 1, sensor: 1 } }),
|
|
345
|
-
row('mct-seven-quad', 'MCT Seven (Quad)', 'Drone', 2000, 4, 'The modular Seven on four legs, picking its way over what wheels refuse.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 4, Spd 1G, Acc 1, Bod 1(3), Arm 0, Pilot 1, Sen 1', vehicle: { handling: 4, speed: '1G', acceleration: 1, body: 1, armor: 0, pilot: 1, sensor: 1 } }),
|
|
346
|
-
row('mct-seven-swims', 'MCT Seven (Swims)', 'Drone', 1000, 4, 'The modular Seven, waterproofed. The cheapest thing in the catalog that floats.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 2W, Acc 1, Bod 1(3), Arm 0, Pilot 1, Sen 1', vehicle: { handling: 3, speed: '2W', acceleration: 1, body: 1, armor: 0, pilot: 1, sensor: 1 } }),
|
|
347
|
-
row('mct-seven-hovers', 'MCT Seven (Hovers)', 'Drone', 4000, 6, 'The modular Seven on ducted fans, hovering a hand\'s width off the floor.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 4, Spd 1P, Acc 1, Bod 1(3), Arm 0, Pilot 1, Sen 1', vehicle: { handling: 4, speed: '1P', acceleration: 1, body: 1, armor: 0, pilot: 1, sensor: 1 } }),
|
|
348
|
-
row('mct-seven-soars', 'MCT Seven (Soars)', 'Drone', 4000, 8, 'The modular Seven with a jet where its sense of proportion should be.', { page: 'Rigger 5.0 p.133', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 2J, Acc 1, Bod 1(3), Arm 0, Pilot 1, Sen 1', vehicle: { handling: 3, speed: '2J', acceleration: 1, body: 1, armor: 0, pilot: 1, sensor: 1 } }),
|
|
349
|
-
row('nn-prairie-dog', 'NN Prairie Dog', 'Drone', 8000, 12, 'Pops up, looks around, drops back down. Sold to people who need exactly that.', { page: 'Rigger 5.0 p.134', shape: 'frame', size: 'Small', weight: 4, legality: 'F', stats: 'Handl 2/4, Spd 2G, Acc 1, Bod 2(0), Arm 3, Pilot 3, Sen 4', vehicle: { handling: '2/4', speed: '2G', acceleration: 1, body: 2, armor: 3, pilot: 3, sensor: 4 } }),
|
|
350
|
-
row('p-w-sundowner', 'P&W Sundowner', 'Drone', 10000, 8, 'A high-altitude loiterer that watches a district until its batteries give out.', { page: 'Rigger 5.0 p.134', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 4P, Acc 1, Bod 2(0), Arm 0, Pilot 2, Sen 2', vehicle: { handling: 3, speed: '4P', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
351
|
-
row('proteus-krake', 'Proteus \'Krake\'', 'Drone', 10000, 18, 'Built for deep water and pressure that would fold anything cheaper.', { page: 'Rigger 5.0 p.134', shape: 'frame', size: 'Small', weight: 4, legality: 'F', stats: 'Handl 5, Spd 3W, Acc 4, Bod 2(0), Arm 2, Pilot 4, Sen 3', vehicle: { handling: 5, speed: '3W', acceleration: 4, body: 2, armor: 2, pilot: 4, sensor: 3 } }),
|
|
352
|
-
row('s-t-bloodhound', 'S-T Bloodhound', 'Drone', 10000, 8, 'Follows a chemical trail long after a metahuman nose has given up.', { page: 'Rigger 5.0 p.136', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 1G, Acc 1, Bod 2(0), Arm 0, Pilot 2, Sen 4', vehicle: { handling: 3, speed: '1G', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 4 } }),
|
|
353
|
-
row('renraku-dove-4', 'Renraku Dove-4', 'Drone', 5000, 4, 'A courier that finds an address and does not ask what is in the package.', { page: 'Rigger 5.0 p.136', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 4, Spd 2P, Acc 1, Bod 2(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: 4, speed: '2P', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
354
|
-
row('renraku-jardinero', 'Renraku Jardinero', 'Drone', 2000, 4, 'A gardener drone. It trims hedges, and it has seen everything in the garden.', { page: 'Rigger 5.0 p.136', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 2/4, Spd 1G, Acc 1, Bod 2(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: '2/4', speed: '1G', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
355
|
-
row('renraku-job-a-mat', 'Renraku Job-A-Mat', 'Drone', 3000, 4, 'A fixed servicer that does one job forever without complaint or curiosity.', { page: 'Rigger 5.0 p.137', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl --, Spd --, Acc --, Bod 2(2), Arm 0, Pilot 2, Sen 2', vehicle: { handling: '--', speed: '--', acceleration: '--', body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
356
|
-
row('renraku-pelican', 'Renraku Pelican', 'Drone', 4000, 2, 'Carries more than it looks like it should, then puts it down gently.', { page: 'Rigger 5.0 p.137', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 4, Spd 2P, Acc 1, Bod 2(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: 4, speed: '2P', acceleration: 1, body: 2, armor: 0, pilot: 2, sensor: 2 } }),
|
|
357
|
-
row('telestrian-shamus', 'Telestrian Shamus', 'Drone', 30000, 10, 'A private investigator with eight sensor channels and no conscience to trouble.', { page: 'Rigger 5.0 p.137', shape: 'frame', size: 'Small', weight: 4, stats: 'Handl 3, Spd 3G, Acc 1, Bod 4(0), Arm 4, Pilot 3, Sen 8', vehicle: { handling: 3, speed: '3G', acceleration: 1, body: 4, armor: 4, pilot: 3, sensor: 8 } }),
|
|
358
|
-
row('ares-cheetah', 'Ares Cheetah', 'Drone', 14000, 12, 'Fast, armoured, and pointed at whatever is running away.', { page: 'Rigger 5.0 p.138', shape: 'frame', size: 'Medium', weight: 20, legality: 'R', stats: 'Handl 4, Spd 6G, Acc 2, Bod 2(0), Arm 6, Pilot 3, Sen 2', vehicle: { handling: 4, speed: '6G', acceleration: 2, body: 2, armor: 6, pilot: 3, sensor: 2 } }),
|
|
359
|
-
row('evo-krokodil', 'Evo Krokodil', 'Drone', 12000, 8, 'Equally at home on a riverbank and in the river, and unpleasant on both.', { page: 'Rigger 5.0 p.139', shape: 'frame', size: 'Medium', weight: 20, legality: 'R', stats: 'Handl 3, Spd 2G/3W, Acc 1, Bod 3(1), Arm 6, Pilot 2, Sen 2', vehicle: { handling: 3, speed: '2G/3W', acceleration: 1, body: 3, armor: 6, pilot: 2, sensor: 2 } }),
|
|
360
|
-
row('f-b-kull', 'F-B Kull', 'Drone', 10000, 4, 'A flying brick with a payload bay, sold on capacity rather than charm.', { page: 'Rigger 5.0 p.140', shape: 'frame', size: 'Medium', weight: 20, stats: 'Handl 3, Spd 4P, Acc 2, Bod 3(3), Arm 0, Pilot 3, Sen 2', vehicle: { handling: 3, speed: '4P', acceleration: 2, body: 3, armor: 0, pilot: 3, sensor: 2 } }),
|
|
361
|
-
row('mct-tunneler', 'MCT Tunneler', 'Drone', 10000, 8, 'Goes through walls the slow way, and does not care how long that takes.', { page: 'Rigger 5.0 p.140', shape: 'frame', size: 'Medium', weight: 20, legality: 'R', stats: 'Handl 3, Spd 0P, Acc 0, Bod 3(2), Arm 6, Pilot 2, Sen 2', vehicle: { handling: 3, speed: '0P', acceleration: 0, body: 3, armor: 6, pilot: 2, sensor: 2 } }),
|
|
362
|
-
row('renraku-lebd-2', 'Renraku LEBD-2', 'Drone', 20000, 12, 'Law enforcement in drone form: armoured, watchful, and unmistakably official.', { page: 'Rigger 5.0 p.140', shape: 'frame', size: 'Medium', weight: 20, legality: 'R', stats: 'Handl 4, Spd 2P, Acc 1, Bod 3(0), Arm 9, Pilot 4, Sen 4', vehicle: { handling: 4, speed: '2P', acceleration: 1, body: 3, armor: 9, pilot: 4, sensor: 4 } }),
|
|
363
|
-
row('transys-steed', 'Transys Steed', 'Drone', 4000, 2, 'A patient hauler that follows a rigger around like a well-trained animal.', { page: 'Rigger 5.0 p.140', shape: 'frame', size: 'Medium', weight: 20, stats: 'Handl 4/2, Spd 1G, Acc 1, Bod 3(1), Arm 0, Pilot 2, Sen 2', vehicle: { handling: '4/2', speed: '1G', acceleration: 1, body: 3, armor: 0, pilot: 2, sensor: 2 } }),
|
|
364
|
-
row('ares-matilda', 'Ares Matilda', 'Drone', 18000, 12, 'Slow, enormously tough, and built to still be there when the shooting stops.', { page: 'Rigger 5.0 p.141', shape: 'hull', size: 'Large', weight: 90, legality: 'R', stats: 'Handl 1, Spd 2G, Acc 1, Bod 8, Arm 8, Pilot 2, Sen 1', vehicle: { handling: 1, speed: '2G', acceleration: 1, body: 8, armor: 8, pilot: 2, sensor: 1 } }),
|
|
365
|
-
row('ares-mule', 'Ares Mule', 'Drone', 8000, 4, 'It carries what you cannot and complains less than anyone you could hire.', { page: 'Rigger 5.0 p.141', shape: 'hull', size: 'Large', weight: 90, stats: 'Handl 4, Spd 1G, Acc 1, Bod 4(3), Arm 6, Pilot 2, Sen 2', vehicle: { handling: 4, speed: '1G', acceleration: 1, body: 4, armor: 6, pilot: 2, sensor: 2 } }),
|
|
366
|
-
row('ares-paladin', 'Ares Paladin', 'Drone', 5000, 8, 'Armour eighteen deep on a chassis that costs less than the plating suggests.', { page: 'Rigger 5.0 p.142', shape: 'hull', size: 'Large', weight: 90, legality: 'R', stats: 'Handl 5, Spd 4G, Acc 1, Bod 5(0), Arm 18, Pilot 3, Sen 2', vehicle: { handling: 5, speed: '4G', acceleration: 1, body: 5, armor: 18, pilot: 3, sensor: 2 } }),
|
|
367
|
-
row('cc-medicart', 'CC \'MediCart\'', 'Drone', 10000, 6, 'A rolling clinic that reaches the wounded before the ambulance does.', { page: 'Rigger 5.0 p.142', shape: 'hull', size: 'Large', weight: 90, stats: 'Handl 5, Spd 5G, Acc 1, Bod 6(2), Arm 5, Pilot 4, Sen 4', vehicle: { handling: 5, speed: '5G', acceleration: 1, body: 6, armor: 5, pilot: 4, sensor: 4 } }),
|
|
368
|
-
row('gts-tower', 'GTS Tower', 'Drone', 10000, 8, 'A mast on wheels: raises a sensor package above the skyline and holds it there.', { page: 'Rigger 5.0 p.143', shape: 'hull', size: 'Large', weight: 90, stats: 'Handl 2, Spd 1P, Acc 1, Bod 4(0), Arm 6, Pilot 2, Sen 2', vehicle: { handling: 2, speed: '1P', acceleration: 1, body: 4, armor: 6, pilot: 2, sensor: 2 } }),
|
|
369
|
-
row('s-k-neptune', 'S-K Neptune', 'Drone', 17500, 10, 'A submersible with a corporate budget behind it and depth to prove it.', { page: 'Rigger 5.0 p.143', shape: 'hull', size: 'Large', weight: 90, legality: 'R', stats: 'Handl 2, Spd 3W, Acc 1, Bod 5(0), Arm 3, Pilot 4, Sen 3', vehicle: { handling: 2, speed: '3W', acceleration: 1, body: 5, armor: 3, pilot: 4, sensor: 3 } }),
|
|
370
|
-
row('mitsuhama-malakim', 'Mitsuhama Malakim', 'Drone', 40000, 20, 'An angel by name, a gunship by build, and forbidden almost everywhere.', { page: 'Rigger 5.0 p.143', shape: 'hull', size: 'Large', weight: 90, legality: 'F', stats: 'Handl 3, Spd 6P, Acc 2, Bod 4(0), Arm 9, Pilot 4, Sen 4', vehicle: { handling: 3, speed: '6P', acceleration: 2, body: 4, armor: 9, pilot: 4, sensor: 4 } }),
|
|
371
|
-
row('ares-kn-y2-deimos', 'Ares KN-Y2 (Deimos)', 'Drone', 220000, 20, 'A walking weapons platform named for a moon, and about as approachable.', { page: 'Rigger 5.0 p.143', shape: 'hull', size: 'VeryLarge', weight: 400, legality: 'F', stats: 'Handl 3, Spd 2G, Acc 1, Bod 6(0), Arm 18, Pilot 5, Sen 3', vehicle: { handling: 3, speed: '2G', acceleration: 1, body: 6, armor: 18, pilot: 5, sensor: 3 } }),
|
|
372
|
-
row('ares-kn-y4-eris', 'Ares KN-Y4 (Eris)', 'Drone', 270000, 24, 'The Deimos\'s bigger sibling: more of everything, including trouble.', { page: 'Rigger 5.0 p.143', shape: 'hull', size: 'VeryLarge', weight: 400, legality: 'F', stats: 'Handl 3, Spd 2G, Acc 1, Bod 6(0), Arm 18, Pilot 5, Sen 3', vehicle: { handling: 3, speed: '2G', acceleration: 1, body: 6, armor: 18, pilot: 5, sensor: 3 } }),
|
|
373
|
-
row('ares-kn-y1-phobos', 'Ares KN-Y1 (Phobos)', 'Drone', 250000, 16, 'The third Ares moon: same chassis, same eighteen points of plate, a slightly kinder price.', { page: 'Rigger 5.0 p.143', shape: 'hull', size: 'VeryLarge', weight: 400, legality: 'F', stats: 'Handl 3, Spd 2G, Acc 1, Bod 6(0), Arm 18, Pilot 5, Sen 3', vehicle: { handling: 3, speed: '2G', acceleration: 1, body: 6, armor: 18, pilot: 5, sensor: 3 } }),
|
|
374
|
-
row('mesametric-kodiak', 'Mesametric Kodiak', 'Drone', 40000, 12, 'A bear-sized hauler that goes over terrain rather than around it.', { page: 'Rigger 5.0 p.145', shape: 'hull', size: 'VeryLarge', weight: 400, legality: 'R', stats: 'Handl 2/4, Spd 2G, Acc 1, Bod 6(2), Arm 12, Pilot 2, Sen 2', vehicle: { handling: '2/4', speed: '2G', acceleration: 1, body: 6, armor: 12, pilot: 2, sensor: 2 } }),
|
|
375
|
-
row('neonet-avenging-angel', 'NeoNET Avenging Angel', 'Drone', 1000000, 40, 'A million nuyen of jet-driven opinion. Availability 40 is not a typo.', { page: 'Rigger 5.0 p.145', shape: 'hull', size: 'VeryLarge', weight: 400, legality: 'F', stats: 'Handl 3, Spd 6J, Acc 2, Bod 6(0), Arm 12, Pilot 6, Sen 6', vehicle: { handling: 3, speed: '6J', acceleration: 2, body: 6, armor: 12, pilot: 6, sensor: 6 } }),
|
|
376
|
-
row('ares-garuda', 'Ares \'Garuda\'', 'Drone', 8500, 20, 'A drone that is also a missile, which resolves any question about its lifespan.', { page: 'Rigger 5.0 p.149', shape: 'missile', size: 'Small', weight: 15, legality: 'F', stats: 'Handl 6, Spd 3J/6J, Acc 2/4, Bod 2, Arm 2, Pilot 4, Sen 3', vehicle: { handling: 6, speed: '3J/6J', acceleration: '2/4', body: 2, armor: 2, pilot: 4, sensor: 3 } }),
|
|
377
|
-
// The two microdrones that complete the p.466 table. The other nine
|
|
378
|
-
// rows were already held -- see the PR: nine of eleven, and the
|
|
379
|
-
// 'full drone list' request resolved to two rows plus one wrong stat.
|
|
380
|
-
row('shiawase-kanmushi', 'Shiawase Kanmushi', 'Drone', 1000, 8, 'A beetle the size of a thumbnail that walks up walls and listens.', { page: 'p.466', shape: 'insect', size: 'Tiny', weight: 0.2, color: 'chitin brown', stats: 'Handl 4, Spd 2, Acc 1, Bod 0, Arm 0, Pilot 3, Sen 3', vehicle: { handling: 4, speed: 2, acceleration: 1, body: 0, armor: 0, pilot: 3, sensor: 3 } }),
|
|
381
|
-
row('sb-microskimmer', 'S-B Microskimmer', 'Drone', 1000, 6, 'A saucer the width of a hand that hovers where nobody looks up.', { page: 'p.466', shape: 'disc', size: 'Tiny', weight: 0.3, color: 'dull grey', stats: 'Handl 3, Spd 3, Acc 1, Bod 0, Arm 0, Pilot 3, Sen 3', vehicle: { handling: 3, speed: 3, acceleration: 1, body: 0, armor: 0, pilot: 3, sensor: 3 } }),
|
|
382
|
-
row('fly-spy', 'MCT Fly-Spy', 'Drone', 2000, 8, 'A palm-sized dragonfly with a camera where its soul should be.', { page: 'p.466', shape: 'insect', size: 'Tiny', weight: 0.4, color: 'iridescent green', stats: 'Handl 4, Spd 3, Acc 2, Bod 1, Arm 0, Pilot 3, Sen 3', vehicle: { handling: 4, speed: 3, acceleration: 2, body: 1, armor: 0, pilot: 3, sensor: 3 } }),
|
|
383
|
-
row('horizon-flying-eye', 'Horizon Flying Eye', 'Drone', 2000, 8, 'A news drone that never asks whose story it is filming.', { page: 'p.466', shape: 'disc', size: 'Tiny', weight: 0.5, color: 'white', stats: 'Handl 4, Spd 3, Acc 2, Bod 1, Arm 0, Pilot 3, Sen 3', vehicle: { handling: 4, speed: 3, acceleration: 2, body: 1, armor: 0, pilot: 3, sensor: 3 } }),
|
|
384
|
-
row('aztechnology-crawler', 'Aztechnology Crawler', 'Drone', 4000, 4, 'A walker that goes where wheels give up and stairs begin.', { page: 'p.466', shape: 'walker', size: 'Small', weight: 8, rating: 'Standard', stats: 'Handl 4, Spd 3, Acc 1, Bod 3, Arm 3, Pilot 4, Sen 3', vehicle: { handling: 4, speed: 3, acceleration: 1, body: 3, armor: 3, pilot: 4, sensor: 3 } }),
|
|
385
|
-
row('ares-duelist', 'Ares Duelist', 'Drone', 4500, 5, 'A bodyguard drone with a monofilament arm and no sense of humor.', { page: 'p.466', shape: 'walker', size: 'Small', weight: 10, rating: 'Standard', legality: 'R', stats: 'Handl 3, Spd 3, Acc 1, Bod 4, Arm 4, Pilot 3, Sen 3', vehicle: { handling: 3, speed: 3, acceleration: 1, body: 4, armor: 4, pilot: 3, sensor: 3 } }),
|
|
386
|
-
row('gm-nissan-doberman', 'GM-Nissan Doberman', 'Drone', 5000, 4, 'A tracked weapons platform the size of a dog, with a dog\'s loyalty.', { page: 'p.466', shape: 'tracked', size: 'Medium', weight: 20, rating: 'Rare', legality: 'R', stats: 'Handl 5, Spd 3, Acc 1, Bod 4, Arm 4, Pilot 3, Sen 3, weapon mount', vehicle: { handling: 5, speed: 3, acceleration: 1, body: 4, armor: 4, pilot: 3, sensor: 3, mount: 'standard' } }),
|
|
387
|
-
row('mct-nissan-roto-drone', 'MCT-Nissan Roto-Drone', 'Drone', 5000, 6, 'The workhorse quadrotor: cargo, cameras, or something with a barrel.', { page: 'p.466', shape: 'rotary', size: 'Medium', weight: 15, rating: 'Rare', stats: 'Handl 4, Spd 4, Acc 2, Bod 4, Arm 4, Pilot 3, Sen 3, weapon mount', vehicle: { handling: 4, speed: 4, acceleration: 2, body: 4, armor: 4, pilot: 3, sensor: 3, mount: 'standard' } }),
|
|
388
|
-
row('cd-dalmatian', 'Cyberspace Designs Dalmatian', 'Drone', 10000, 6, 'A VTOL that carries a body -- yours, ideally still breathing.', { page: 'p.466', shape: 'vtol', size: 'Medium', weight: 25, rating: 'Rare', legality: 'R', stats: 'Handl 5, Spd 5, Acc 3, Bod 5, Arm 5, Pilot 3, Sen 3', vehicle: { handling: 5, speed: 5, acceleration: 3, body: 5, armor: 5, pilot: 3, sensor: 3 } }),
|
|
389
|
-
row('lockheed-optic-x2', 'Lockheed Optic-X2', 'Drone', 21000, 10, 'A high-altitude eye that watches a whole district and never blinks.', { page: 'p.466', shape: 'vstol', size: 'Medium', weight: 12, rating: 'Legendary', stats: 'Handl 4, Spd 4, Acc 3, Bod 2, Arm 2, Pilot 3, Sen 3', vehicle: { handling: 4, speed: 4, acceleration: 3, body: 2, armor: 2, pilot: 3, sensor: 3 } }),
|
|
390
|
-
row('steel-lynx', 'Steel Lynx', 'Drone', 25000, 10, 'A rolling gun emplacement. When it arrives, the run is already loud.', { page: 'p.466', shape: 'wheeled', size: 'Large', weight: 120, rating: 'Legendary', legality: 'R', stats: 'Handl 5, Spd 4, Acc 2, Bod 6, Arm 12, Pilot 3, Sen 3, heavy weapon mount', vehicle: { handling: 5, speed: 4, acceleration: 2, body: 6, armor: 12, pilot: 3, sensor: 3, mount: 'heavy' } }),
|
|
391
|
-
// ---- Identity, paper, and credit (p.443: fake SIN 2,500x per rating;
|
|
392
|
-
// a KE checkpoint's scanner beats the rating to BURN the fake -- see
|
|
393
|
-
// game.ts checkpointOnRideHome) ----
|
|
394
|
-
row('fake-sin-2', 'Fake SIN (Rating 2)', 'FakeSIN', 5000, 6, 'A life that holds up to a doorman scanner -- not to anyone paid to look twice.', { page: 'p.443', shape: 'credential', size: 'Tiny', weight: 0, legality: 'F', stats: 'Rating 2: rating x 2,500 nuyen, avail (rating x 3)F', ratingValue: 2 }),
|
|
395
|
-
row('fake-sin-4', 'Fake SIN (Rating 4)', 'FakeSIN', 10000, 12, 'A properly built identity: employment history, a tax trail, a face that checks out.', { page: 'p.443', shape: 'credential', size: 'Tiny', weight: 0, legality: 'F', stats: 'Rating 4: rating x 2,500 nuyen, avail (rating x 3)F', ratingValue: 4 }),
|
|
396
|
-
row('fake-sin-6', 'Fake SIN (Rating 6)', 'FakeSIN', 15000, 18, 'Artisan work -- a person who has always existed, right up until the day you burn them.', { page: 'p.443', shape: 'credential', size: 'Tiny', weight: 0, rating: 'Rare', legality: 'F', stats: 'Rating 6: rating x 2,500 nuyen, avail (rating x 3)F', ratingValue: 6 }),
|
|
397
|
-
row('fake-license-4', 'Fake License (Rating 4)', 'License', 800, 12, 'Paper that says the gun on your hip is a hobby.', { page: 'p.443', shape: 'credential', size: 'Tiny', weight: 0, legality: 'F', stats: 'Rating 4: rating x 200 nuyen, avail (rating x 3)F', ratingValue: 4 }),
|
|
398
|
-
row('credstick-silver', 'Certified Credstick (Silver)', 'Credstick', 20, 0, 'Anonymous money in a stick. Holds 20,000 and asks nothing.', { page: 'p.443', shape: 'stick', size: 'Tiny', weight: 0.1, color: 'silver', stats: 'Max 20,000 nuyen' }),
|
|
399
|
-
row('credstick-gold', 'Certified Credstick (Gold)', 'Credstick', 100, 5, 'Holds a hundred thousand. Carrying one says something about your night.', { page: 'p.443', shape: 'stick', size: 'Tiny', weight: 0.1, color: 'gold', stats: 'Max 100,000 nuyen' }),
|
|
400
|
-
row('credstick-platinum', 'Certified Credstick (Platinum)', 'Credstick', 500, 10, 'Half a million, certified. People have died for the empty ones.', { page: 'p.443', shape: 'stick', size: 'Tiny', weight: 0.1, color: 'platinum', rating: 'Standard', stats: 'Max 500,000 nuyen' }),
|
|
401
|
-
row('credstick-ebony', 'Certified Credstick (Ebony)', 'Credstick', 1000, 20, 'A million nuyen and a very short list of people who own one.', { page: 'p.443', shape: 'stick', size: 'Tiny', weight: 0.1, color: 'ebony', rating: 'Rare', stats: 'Max 1,000,000 nuyen' }),
|
|
402
|
-
];
|
|
403
|
-
/**
|
|
404
|
-
* THE NON-GEAR ROWS (catalog v14, user 2026-09-04: "I don't see any
|
|
405
|
-
* spells, or qualities there. The catalog should cover ALL things that
|
|
406
|
-
* can be obtained in the game, backed by canon").
|
|
407
|
-
*
|
|
408
|
-
* DERIVED, NEVER RETYPED. qualities.ts and augmentations.ts are the
|
|
409
|
-
* engine's own sources of truth -- the clinic charges from them, the
|
|
410
|
-
* creation ledger prices from them, the sheet prints from them -- so the
|
|
411
|
-
* catalog reads THOSE rather than carrying a second copy. A hand-copied
|
|
412
|
-
* list of something that already exists cannot stay right: that is
|
|
413
|
-
* exactly how the Conjurer shipped broken this morning, when a duplicate
|
|
414
|
-
* of MAGICAL_GROUP_SKILLS went stale the day the original moved.
|
|
415
|
-
*
|
|
416
|
-
* Every field here already existed on the source rows. Nothing is
|
|
417
|
-
* invented to fill the shape: `requiresMetatype` stays absent because
|
|
418
|
-
* this engine models no metatype and a gate it cannot check is a rule it
|
|
419
|
-
* cannot keep (qualities.ts says so in its own words), and `legality` /
|
|
420
|
-
* `canonEssence` stay absent on augmentations for the same reason --
|
|
421
|
-
* the source does not carry them.
|
|
422
|
-
*/
|
|
423
|
-
/**
|
|
424
|
-
* The restrictions a row declares, assembled from whichever per-kind
|
|
425
|
-
* fields its source happens to use. One shape out, so the server can
|
|
426
|
-
* enforce every kind in one pass; the sources keep the field names that
|
|
427
|
-
* read well where they live.
|
|
428
|
-
*
|
|
429
|
-
* Returns undefined rather than an empty object when a row restricts
|
|
430
|
-
* nothing, so "has restrictions" stays a truthiness check and 400 rows
|
|
431
|
-
* do not each grow an empty object.
|
|
432
|
-
*/
|
|
433
|
-
function restrictionsOf(src) {
|
|
434
|
-
const excludes = [
|
|
435
|
-
...(src.excludes ?? []),
|
|
436
|
-
...(src.excludesQuality !== undefined ? [src.excludesQuality] : []),
|
|
437
|
-
];
|
|
438
|
-
const out = {
|
|
439
|
-
...(excludes.length > 0 ? { excludes } : {}),
|
|
440
|
-
...(src.requiresQuality !== undefined ? { needs: [src.requiresQuality] } : {}),
|
|
441
|
-
...(src.requires !== undefined ? { path: src.requires } : {}),
|
|
442
|
-
};
|
|
443
|
-
return Object.keys(out).length > 0 ? out : undefined;
|
|
444
|
-
}
|
|
445
|
-
function qualityRows() {
|
|
446
|
-
return QUALITIES.map(q => ({
|
|
447
|
-
kind: 'quality',
|
|
448
|
-
slug: q.key,
|
|
449
|
-
name: q.name,
|
|
450
|
-
description: q.effect,
|
|
451
|
-
page: q.page,
|
|
452
|
-
// The mechanics, in the same vocabulary a weapon states its DV in,
|
|
453
|
-
// so a reader of the catalog gets a quality's NUMBERS and not just
|
|
454
|
-
// its sentence. Absent where SR5's effect is not a flat modifier
|
|
455
|
-
// (or where the engine implements it as its own rule) -- see the
|
|
456
|
-
// `effects` comment in qualities.ts, which says why that is the
|
|
457
|
-
// honest answer rather than a gap to be filled in.
|
|
458
|
-
...(q.effects !== undefined ? { effects: q.effects } : {}),
|
|
459
|
-
// On the ROW, not in the quality block -- ICatalogBase carries both,
|
|
460
|
-
// so chrome and spells declare them in the same place.
|
|
461
|
-
...(q.choice !== undefined ? { choice: q.choice } : {}),
|
|
462
|
-
...(restrictionsOf(q) !== undefined ? { restrictions: restrictionsOf(q) } : {}),
|
|
463
|
-
quality: {
|
|
464
|
-
polarity: q.kind,
|
|
465
|
-
karma: q.karma,
|
|
466
|
-
...(q.maxRating !== undefined ? { maxRating: q.maxRating } : {}),
|
|
467
|
-
...(q.retired !== undefined ? { retired: q.retired } : {}),
|
|
468
|
-
...(q.requires !== undefined ? { requires: q.requires } : {}),
|
|
469
|
-
...(q.requiresQuality !== undefined ? { requiresQuality: q.requiresQuality } : {}),
|
|
470
|
-
// WHAT KIND OF RULE this is, and whether the engine runs it yet.
|
|
471
|
-
// `family` is always present (qualities.ts requires it); `inert`
|
|
472
|
-
// is present only when the quality currently delivers nothing,
|
|
473
|
-
// and names the missing seat -- so a reader of the catalog can
|
|
474
|
-
// tell a finished rule from one that is still only priced.
|
|
475
|
-
family: q.family,
|
|
476
|
-
...(q.inert !== undefined ? { inert: q.inert } : {}),
|
|
477
|
-
// The pick chargen has to collect before the quality can work,
|
|
478
|
-
// and the quality it may not be held alongside (p.65-66).
|
|
479
|
-
...(q.excludesQuality !== undefined ? { excludesQuality: q.excludesQuality } : {}),
|
|
480
|
-
},
|
|
481
|
-
}));
|
|
482
|
-
}
|
|
483
|
-
function augmentationRows() {
|
|
484
|
-
return AUGMENTATIONS.map(a => ({
|
|
485
|
-
kind: 'augmentation',
|
|
486
|
-
slug: a.key,
|
|
487
|
-
name: a.name,
|
|
488
|
-
description: a.effect,
|
|
489
|
-
page: a.page,
|
|
490
|
-
// The dice, in the same vocabulary a weapon states its DV in. Chrome
|
|
491
|
-
// declared a `bonuses` map of its own until 2026-09-04, which is why
|
|
492
|
-
// this column read empty in the catalog while every piece of 'ware in
|
|
493
|
-
// the game was moving real dice.
|
|
494
|
-
...(a.effects !== undefined ? { effects: a.effects } : {}),
|
|
495
|
-
// 62 of the 69 restrictions in the catalog are these: the exclusions
|
|
496
|
-
// that stop Wired Reflexes I riding alongside a synaptic booster, or
|
|
497
|
-
// three vision enhancements stacking. Declared for a long time,
|
|
498
|
-
// enforced by nothing.
|
|
499
|
-
...(restrictionsOf(a) !== undefined ? { restrictions: restrictionsOf(a) } : {}),
|
|
500
|
-
augmentation: {
|
|
501
|
-
ware: a.kind,
|
|
502
|
-
essence: a.essence,
|
|
503
|
-
cost: a.cost,
|
|
504
|
-
wakeLine: a.wakeLine,
|
|
505
|
-
...(a.excludes !== undefined ? { excludes: a.excludes } : {}),
|
|
506
|
-
...(a.avail !== undefined ? { avail: a.avail } : {}),
|
|
507
|
-
...(a.canonCost !== undefined ? { canonCost: a.canonCost } : {}),
|
|
508
|
-
},
|
|
509
|
-
}));
|
|
510
|
-
}
|
|
511
|
-
/** THE WHOLE SEED, every kind: gear, qualities and augmentations. Spells
|
|
512
|
-
* and metatypes are still outstanding -- see the note above qualityRows.
|
|
513
|
-
* The loader (utilities/catalog.ts) weighs THIS against the server and
|
|
514
|
-
* the cache. */
|
|
515
|
-
/**
|
|
516
|
-
* THE SPELLS (SR5 p.283-295). Held out of the catalog until now because
|
|
517
|
-
* ICatalogSpell wants Type, Range and Duration and the engine stored none
|
|
518
|
-
* of them -- recorded at the time as a deliberate omission rather than an
|
|
519
|
-
* oversight. spells.ts carries all three since 2026-09-04, each read off
|
|
520
|
-
* the printed stat block, so the shape is satisfied by canon rather than
|
|
521
|
-
* by inference and the rows can ship.
|
|
522
|
-
*
|
|
523
|
-
* A spell has no PRICE: it is learned, not bought, which is why the row
|
|
524
|
-
* carries no availability or nuyen and the spell block carries the drain
|
|
525
|
-
* instead. What a formula costs on the street is a GEAR row, and there
|
|
526
|
-
* are five of those already (Category 'SpellFormula').
|
|
527
|
-
*/
|
|
528
|
-
/**
|
|
529
|
-
* A spell's line, composed from its own stat block.
|
|
530
|
-
*
|
|
531
|
-
* spells.ts carries no prose -- it never needed any, because cast.ts
|
|
532
|
-
* names the spell and rolls it -- and inventing twenty-one descriptions
|
|
533
|
-
* to fill a `description` field would be putting words in the book's
|
|
534
|
-
* mouth. So the line is DERIVED: the printed Type, Range, Duration and
|
|
535
|
-
* Drain, in a sentence, plus what resists it. Every word of it is data
|
|
536
|
-
* the row already carries.
|
|
537
|
-
*/
|
|
538
|
-
function spellLine(sp) {
|
|
539
|
-
const range = sp.range === 'touch' ? 'Touch' : sp.range === 'LOS(A)' ? 'line of sight, area' : 'line of sight';
|
|
540
|
-
const duration = sp.duration === 'I' ? 'instantaneous' : sp.duration === 'S' ? 'sustained' : 'permanent';
|
|
541
|
-
const drain = `Drain F${sp.drainOffset === 0 ? '' : sp.drainOffset > 0 ? ` + ${sp.drainOffset}` : ` - ${-sp.drainOffset}`}`;
|
|
542
|
-
const resist = sp.soak === 'willpower' ? '; resisted with Willpower'
|
|
543
|
-
: sp.soak === 'body' ? '; resisted with Body'
|
|
544
|
-
: sp.soak === 'armor' ? '; soaked in full, less AP' : '';
|
|
545
|
-
return `${sp.category} spell, ${sp.type}, ${range}, ${duration}. ${drain}${resist}.`;
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* WHAT A FORMULA COSTS, by the category of the spell it teaches (p.461,
|
|
549
|
-
* priced from the Magical Goods table). The formula is for ONE spell;
|
|
550
|
-
* the CATEGORY is only what sets the price, which is why these rows are
|
|
551
|
-
* generated per spell rather than per category.
|
|
552
|
-
*/
|
|
553
|
-
const FORMULA_PRICE = {
|
|
554
|
-
Detection: { price: 500, avail: 4 },
|
|
555
|
-
Health: { price: 500, avail: 4 },
|
|
556
|
-
Illusion: { price: 1000, avail: 8 },
|
|
557
|
-
Manipulation: { price: 1500, avail: 8 },
|
|
558
|
-
Combat: { price: 2000, avail: 8 },
|
|
559
|
-
};
|
|
560
|
-
/**
|
|
561
|
-
* ONE FORMULA PER SPELL, derived from SPELL_CATALOG.
|
|
562
|
-
*
|
|
563
|
-
* These are GEAR rows -- a scroll you buy from a talismonger and carry --
|
|
564
|
-
* and they are the first gear the engine reads for something other than
|
|
565
|
-
* a dice modifier: `teaches` names the spell, and Player.knowsSpell reads
|
|
566
|
-
* it. Generated rather than authored so a spell added tomorrow is
|
|
567
|
-
* purchasable the same day, with no second edit to forget.
|
|
568
|
-
*
|
|
569
|
-
* The Detection price sits in the table above and produces no rows,
|
|
570
|
-
* because this engine has no Detection spell yet. That is deliberate: a
|
|
571
|
-
* "Detection Spell Formula" WAS on sale here for 500 nuyen, for a
|
|
572
|
-
* category with nothing in it.
|
|
573
|
-
*/
|
|
574
|
-
function formulaRows() {
|
|
575
|
-
return SPELL_CATALOG.map(sp => {
|
|
576
|
-
const { price, avail } = FORMULA_PRICE[sp.category];
|
|
577
|
-
return row(`spell-formula-${sp.key}`, `Spell Formula (${sp.name})`, 'SpellFormula', price, avail, `${sp.name}, notated for study in somebody else's hand. Bring talent.`, {
|
|
578
|
-
page: 'p.461', shape: 'scroll', size: 'Tiny', weight: 0.1, legality: 'R',
|
|
579
|
-
teaches: sp.key,
|
|
580
|
-
stats: `${sp.category} formula: ${price} nuyen, avail ${avail}R`,
|
|
581
|
-
});
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
function spellRows() {
|
|
585
|
-
return SPELL_CATALOG.map(sp => ({
|
|
586
|
-
kind: 'spell',
|
|
587
|
-
slug: sp.key,
|
|
588
|
-
name: sp.name,
|
|
589
|
-
description: spellLine(sp),
|
|
590
|
-
page: sp.page,
|
|
591
|
-
// What it does to whoever it is held on, in the shared vocabulary.
|
|
592
|
-
// Absent on every Instantaneous spell -- a combat spell resolves at
|
|
593
|
-
// cast time -- and on the two barriers, whose effect is a wall in a
|
|
594
|
-
// room rather than a modifier on anybody.
|
|
595
|
-
...(sp.effects !== undefined ? { effects: sp.effects } : {}),
|
|
596
|
-
spell: {
|
|
597
|
-
cast: sp.cast,
|
|
598
|
-
category: sp.category,
|
|
599
|
-
type: sp.type,
|
|
600
|
-
range: sp.range,
|
|
601
|
-
duration: sp.duration,
|
|
602
|
-
drainOffset: sp.drainOffset,
|
|
603
|
-
...(sp.soak !== undefined ? { soak: sp.soak } : {}),
|
|
604
|
-
...(sp.stun !== undefined ? { stun: sp.stun } : {}),
|
|
605
|
-
...(sp.area !== undefined ? { area: sp.area } : {}),
|
|
606
|
-
...(sp.touch !== undefined ? { touch: sp.touch } : {}),
|
|
607
|
-
},
|
|
608
|
-
}));
|
|
609
|
-
}
|
|
610
|
-
function adeptPowerRows() {
|
|
611
|
-
return ADEPT_POWER_CATALOG.map(a => ({
|
|
612
|
-
kind: 'adept-power',
|
|
613
|
-
slug: a.key,
|
|
614
|
-
name: a.name,
|
|
615
|
-
description: a.effect,
|
|
616
|
-
page: a.page,
|
|
617
|
-
...(a.effects !== undefined ? { effects: a.effects } : {}),
|
|
618
|
-
adeptPower: {
|
|
619
|
-
levelCosts: a.levelCosts,
|
|
620
|
-
magicCapped: a.magicCapped,
|
|
621
|
-
...(a.costPerLevel !== undefined ? { costPerLevel: a.costPerLevel } : {}),
|
|
622
|
-
},
|
|
623
|
-
}));
|
|
624
|
-
}
|
|
625
|
-
function metamagicRows() {
|
|
626
|
-
return METAMAGICS.map(m => ({
|
|
627
|
-
kind: 'metamagic',
|
|
628
|
-
slug: m.key,
|
|
629
|
-
name: m.name,
|
|
630
|
-
description: m.effect,
|
|
631
|
-
page: m.page,
|
|
632
|
-
...(m.effects !== undefined ? { effects: m.effects } : {}),
|
|
633
|
-
metamagic: { path: m.path },
|
|
634
|
-
}));
|
|
635
|
-
}
|
|
636
|
-
/**
|
|
637
|
-
* THE METATYPES (p.66). Rows only: this engine models no metatype on a
|
|
638
|
-
* character and this pass does not change that -- what it does is put the
|
|
639
|
-
* table where it can be read, cited and priced, so the shape stops being
|
|
640
|
-
* an empty promise in the schema.
|
|
641
|
-
*/
|
|
642
|
-
function metatypeRows() {
|
|
643
|
-
return METATYPES.map(m => ({
|
|
644
|
-
kind: 'metatype',
|
|
645
|
-
slug: m.key,
|
|
646
|
-
name: m.name,
|
|
647
|
-
description: m.description,
|
|
648
|
-
page: m.page,
|
|
649
|
-
...(m.effects !== undefined ? { effects: m.effects } : {}),
|
|
650
|
-
metatype: {
|
|
651
|
-
attributes: m.attributes,
|
|
652
|
-
sprintMetersPerHit: m.sprintMetersPerHit,
|
|
653
|
-
...(m.lifestyleCostMult !== undefined ? { lifestyleCostMult: m.lifestyleCostMult } : {}),
|
|
654
|
-
},
|
|
655
|
-
}));
|
|
656
|
-
}
|
|
657
|
-
export const CATALOG_ROWS = [
|
|
658
|
-
...CATALOG_ITEMS,
|
|
659
|
-
...formulaRows(),
|
|
660
|
-
...qualityRows(),
|
|
661
|
-
...augmentationRows(),
|
|
662
|
-
...adeptPowerRows(),
|
|
663
|
-
...metamagicRows(),
|
|
664
|
-
...spellRows(),
|
|
665
|
-
...metatypeRows(),
|
|
666
|
-
];
|
|
667
33
|
//# sourceMappingURL=catalog-data.js.map
|