- All 123 official subclasses (2014 books and the 2024 Player's Handbook), each with its book and features up to level 20; one file per class - The builder has a subclass step after the class: pick one, let a die suggest one, or decide later; its gifts arrive at the class's choice level - 2024 updates (Wild Heart, Warrior of the Elements) offer a one-click switch - The Road Ahead: a level 1-20 timeline on every sheet and in the builder - 33 new species (2024 Aasimar and Goliath, Monsters of the Multiverse) with chosen +2/+1 or +1/+1/+1 bonuses; species roll is now a d8 by family - The Artificer: class, half-caster slots from level 1, features, Flash of Genius - Class tables and counters run to level 20; a fifth Boon, Resolve Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
393 lines
24 KiB
JavaScript
393 lines
24 KiB
JavaScript
// What each class gains at each level after the first: the "Levelling-Up
|
||
// Checklist" tables of the Hollowcrown book (Rules Cheat Sheet) for levels 2
|
||
// to 10, carried on to level 20 in the same spirit. These are the features every member of the class gets; what a subclass
|
||
// adds is in subclasses.js. Level 1 features are in characterOptions.js and
|
||
// are written by the builder.
|
||
//
|
||
// Each entry becomes a line of the character's special abilities, "Name —
|
||
// text". An `upgrade` rewrites the line that already has that name (Sneak
|
||
// Attack growing a die); anything else is added as a new line. `{ boon: true }`
|
||
// is a Boon: the DM picks one from BOONS below.
|
||
//
|
||
// None of this feeds the calculation engine: like the level 1 features, these
|
||
// are table rules in plain words.
|
||
|
||
const BOON = { boon: true };
|
||
|
||
const rage = (uses, damage) => ({
|
||
name: 'Rage',
|
||
text: `${uses} per day, for one minute: +${damage} melee damage, advantage on Strength checks and saves, and physical damage against you is halved.`,
|
||
upgrade: true,
|
||
});
|
||
|
||
const sneakAttack = (dice) => ({
|
||
name: 'Sneak Attack',
|
||
text: `Once per turn, deal an extra ${dice} damage to a target you have advantage against, or that has one of your allies next to it.`,
|
||
upgrade: true,
|
||
});
|
||
|
||
const bardicInspiration = (die) => ({
|
||
name: 'Bardic Inspiration',
|
||
text: `A few times per day, as a bonus action, give an ally a ${die} to add to one attack, check or save.`,
|
||
upgrade: true,
|
||
});
|
||
|
||
const wildShape = (limit) => ({
|
||
name: 'Wild Shape',
|
||
text: `Twice per short rest, become a beast you have seen of ${limit}, for up to half your level in hours. Use the beast's HP; when it hits 0 you return to your own form.`,
|
||
upgrade: true,
|
||
});
|
||
|
||
const EXTRA_ATTACK = { name: 'Extra Attack', text: 'Attack twice when you take the Attack action.' };
|
||
const EVASION = { name: 'Evasion', text: 'On a Dexterity save for half damage, take none on a success and half on a failure.' };
|
||
const LANDS_STRIDE = { name: 'Land’s Stride', text: 'Ordinary difficult terrain and plants do not slow you.' };
|
||
|
||
const INVOCATIONS =
|
||
'Agonizing Blast (add your Charisma modifier to each Eldritch Blast hit), Devil’s Sight (see normally in darkness, even magical darkness, to 120 ft), Repelling Blast (Eldritch Blast hits push the target 10 ft away), Mask of Many Faces (cast Disguise Self at will), Beguiling Influence (proficiency in Deception and Persuasion, added by hand), Eyes of the Rune Keeper (read any writing)';
|
||
const invocations = (total) => ({
|
||
name: 'Eldritch Invocations',
|
||
text: `Choose one more with your DM (${total} in all). From level 5 the list adds Thirsting Blade (Pact of the Blade: attack twice with your pact weapon) and One with Shadows (become invisible while standing still in dim light or darkness).`,
|
||
});
|
||
|
||
const LEVEL_FEATURES = {
|
||
BARBARIAN: {
|
||
2: [
|
||
{ name: 'Reckless Attack', text: 'On your first attack each turn you may attack with advantage; attacks against you have advantage until your next turn.' },
|
||
{ name: 'Danger Sense', text: 'Advantage on Dexterity saves against effects you can see (traps, breath, spells).' },
|
||
],
|
||
3: [rage('Three times', 2)],
|
||
4: [BOON],
|
||
5: [EXTRA_ATTACK, { name: 'Fast Movement', text: '+10 ft speed when not in heavy armor (ask your DM to raise your speed).' }],
|
||
6: [rage('Four times', 2)],
|
||
7: [{ name: 'Feral Instinct', text: 'Advantage on initiative; you can act normally in a surprise round if you rage first.' }],
|
||
8: [BOON],
|
||
9: [{ name: 'Brutal Critical', text: 'Roll one extra weapon damage die on a critical hit.' }, rage('Four times', 3)],
|
||
11: [{ name: 'Relentless Rage', text: 'While raging, when you drop to 0 HP but are not killed outright, make a DC 10 Constitution save to drop to 1 HP instead. The DC rises by 5 each time, back to 10 after a rest.' }],
|
||
12: [BOON, rage('Five times', 3)],
|
||
13: [{ name: 'Brutal Critical', text: 'Roll two extra weapon damage dice on a critical hit.', upgrade: true }],
|
||
15: [{ name: 'Persistent Rage', text: 'Your rage only ends early if you fall unconscious or choose to end it.' }],
|
||
16: [BOON, rage('Five times', 4)],
|
||
17: [{ name: 'Brutal Critical', text: 'Roll three extra weapon damage dice on a critical hit.', upgrade: true }, rage('Six times', 4)],
|
||
18: [{ name: 'Indomitable Might', text: 'If a Strength check comes up lower than your Strength score, use the score instead.' }],
|
||
19: [BOON],
|
||
20: [
|
||
{ name: 'Primal Champion', text: 'Your Strength and Constitution each count 4 higher (to 24 at most): add +2 to those modifiers by hand.' },
|
||
{ name: 'Rage', text: 'As often as you like, for one minute: +4 melee damage, advantage on Strength checks and saves, and physical damage against you is halved.', upgrade: true },
|
||
],
|
||
},
|
||
BARD: {
|
||
2: [
|
||
{ name: 'Jack of All Trades', text: 'Add half your proficiency bonus (round down) to any check you are not proficient in.' },
|
||
{ name: 'Song of Rest', text: 'During a short rest, allies who spend Hit Dice heal an extra 1d6.' },
|
||
],
|
||
3: [
|
||
{ name: 'Expertise', text: 'Double proficiency on two proficient skills (add by hand).' },
|
||
],
|
||
4: [BOON],
|
||
5: [bardicInspiration('d8'), { name: 'Font of Inspiration', text: 'Regain Bardic Inspiration on a short rest.' }],
|
||
6: [
|
||
{ name: 'Countercharm', text: 'Action: allies within 30 ft get advantage on saves against fear and charm until your next turn.' },
|
||
],
|
||
8: [BOON],
|
||
9: [{ name: 'Song of Rest', text: 'During a short rest, allies who spend Hit Dice heal an extra 1d8.', upgrade: true }],
|
||
10: [
|
||
bardicInspiration('d10'),
|
||
{ name: 'Expertise', text: 'Double proficiency on four proficient skills (add by hand).', upgrade: true },
|
||
{ name: 'Magical Secrets', text: 'Learn two more spells from any class (the DM grants them within the unlock schedule).' },
|
||
],
|
||
12: [BOON],
|
||
13: [{ name: 'Song of Rest', text: 'During a short rest, allies who spend Hit Dice heal an extra 1d10.', upgrade: true }],
|
||
14: [{ name: 'Magical Secrets', text: 'Learn four spells from any class in all (the DM grants two more within the unlock schedule).', upgrade: true }],
|
||
15: [bardicInspiration('d12')],
|
||
16: [BOON],
|
||
17: [{ name: 'Song of Rest', text: 'During a short rest, allies who spend Hit Dice heal an extra 1d12.', upgrade: true }],
|
||
18: [{ name: 'Magical Secrets', text: 'Learn six spells from any class in all (the DM grants two more within the unlock schedule).', upgrade: true }],
|
||
19: [BOON],
|
||
20: [{ name: 'Superior Inspiration', text: 'When you roll initiative with no Bardic Inspiration left, you get one back.' }],
|
||
},
|
||
CLERIC: {
|
||
2: [
|
||
{ name: 'Channel Divinity', text: 'Once per short rest, use Turn Undead or your domain’s Channel Divinity.' },
|
||
{ name: 'Turn Undead', text: 'Channel Divinity. Action: undead within 30 ft make a Wisdom save or flee from you for 1 minute.' },
|
||
],
|
||
4: [BOON],
|
||
5: [{ name: 'Destroy Undead', text: 'Undead of CR 1/2 or lower that fail against your Turn Undead are destroyed.' }],
|
||
6: [
|
||
{ name: 'Channel Divinity', text: 'Twice per short rest, use Turn Undead or your domain’s Channel Divinity.', upgrade: true },
|
||
],
|
||
8: [
|
||
BOON,
|
||
{ name: 'Destroy Undead', text: 'Undead of CR 1 or lower that fail against your Turn Undead are destroyed.', upgrade: true },
|
||
],
|
||
10: [{ name: 'Divine Intervention', text: 'Once per week, call on your god: roll d100; if you roll your level or lower, the god helps (the DM decides how).' }],
|
||
11: [{ name: 'Destroy Undead', text: 'Undead of CR 2 or lower that fail against your Turn Undead are destroyed.', upgrade: true }],
|
||
12: [BOON],
|
||
14: [{ name: 'Destroy Undead', text: 'Undead of CR 3 or lower that fail against your Turn Undead are destroyed.', upgrade: true }],
|
||
16: [BOON],
|
||
17: [{ name: 'Destroy Undead', text: 'Undead of CR 4 or lower that fail against your Turn Undead are destroyed.', upgrade: true }],
|
||
18: [{ name: 'Channel Divinity', text: 'Three times per short rest, use Turn Undead or your domain’s Channel Divinity.', upgrade: true }],
|
||
19: [BOON],
|
||
20: [{ name: 'Divine Intervention', text: 'Once per week, call on your god and it answers: no roll needed (the DM decides how it helps).', upgrade: true }],
|
||
},
|
||
DRUID: {
|
||
2: [
|
||
wildShape('CR 1/4 or less (no flying or swimming)'),
|
||
],
|
||
4: [BOON, wildShape('CR 1/2 or less (it may swim, not fly)')],
|
||
8: [BOON, wildShape('CR 1 or less (it may swim or fly)')],
|
||
12: [BOON],
|
||
16: [BOON],
|
||
18: [
|
||
{ name: 'Timeless Body', text: 'You age one year for every ten that pass.' },
|
||
{ name: 'Beast Spells', text: 'You can cast spells while in Wild Shape (anything that needs no costly material).' },
|
||
],
|
||
19: [BOON],
|
||
20: [{ name: 'Archdruid', text: 'Wild Shape as often as you like, and cast druid spells without words, gestures or simple materials.' }],
|
||
},
|
||
FIGHTER: {
|
||
2: [{ name: 'Action Surge', text: 'Once per short rest, take one extra action on your turn.' }],
|
||
4: [BOON],
|
||
5: [EXTRA_ATTACK],
|
||
6: [BOON],
|
||
8: [BOON],
|
||
9: [{ name: 'Indomitable', text: 'Once per long rest, reroll a failed saving throw.' }],
|
||
11: [{ name: 'Extra Attack', text: 'Attack three times when you take the Attack action.', upgrade: true }],
|
||
12: [BOON],
|
||
13: [{ name: 'Indomitable', text: 'Twice per long rest, reroll a failed saving throw.', upgrade: true }],
|
||
14: [BOON],
|
||
16: [BOON],
|
||
17: [
|
||
{ name: 'Action Surge', text: 'Twice per short rest (but once per turn), take one extra action on your turn.', upgrade: true },
|
||
{ name: 'Indomitable', text: 'Three times per long rest, reroll a failed saving throw.', upgrade: true },
|
||
],
|
||
19: [BOON],
|
||
20: [{ name: 'Extra Attack', text: 'Attack four times when you take the Attack action.', upgrade: true }],
|
||
},
|
||
MONK: {
|
||
2: [
|
||
{ name: 'Ki', text: 'Points equal to your level; they come back on a short rest. Ki save DC is 8 + proficiency bonus + Wisdom modifier.' },
|
||
{ name: 'Flurry of Blows', text: '1 ki: two unarmed strikes as a bonus action.' },
|
||
{ name: 'Patient Defense', text: '1 ki: Dodge as a bonus action.' },
|
||
{ name: 'Step of the Wind', text: '1 ki: Dash or Disengage as a bonus action, jump distance doubled.' },
|
||
{ name: 'Unarmored Movement', text: '+10 ft speed without armor (ask your DM to raise your speed).' },
|
||
],
|
||
3: [
|
||
{ name: 'Deflect Missiles', text: 'Reaction: reduce ranged weapon damage by 1d10 + Dexterity modifier + your level.' },
|
||
],
|
||
4: [BOON, { name: 'Slow Fall', text: 'Reaction: reduce falling damage by 5 × your level.' }],
|
||
5: [
|
||
EXTRA_ATTACK,
|
||
{ name: 'Stunning Strike', text: '1 ki after a melee hit: the target makes a Constitution save or is stunned until your next turn.' },
|
||
{ name: 'Martial Arts', text: 'Your unarmed strikes deal 1d6 damage and can use Dexterity. After attacking, make one unarmed strike as a bonus action.', upgrade: true },
|
||
],
|
||
6: [
|
||
{ name: 'Ki-Empowered Strikes', text: 'Your unarmed strikes count as magical.' },
|
||
{ name: 'Unarmored Movement', text: '+15 ft speed without armor (ask your DM to raise your speed).', upgrade: true },
|
||
],
|
||
7: [EVASION, { name: 'Stillness of Mind', text: 'Action: end charm or fear on yourself.' }],
|
||
8: [BOON],
|
||
9: [{ name: 'Unarmored Movement', text: '+15 ft speed without armor (ask your DM to raise your speed). You can run along walls and across water during your move.', upgrade: true }],
|
||
10: [
|
||
{ name: 'Purity of Body', text: 'Immune to poison and disease.' },
|
||
{ name: 'Unarmored Movement', text: '+20 ft speed without armor (ask your DM to raise your speed). You can run along walls and across water during your move.', upgrade: true },
|
||
],
|
||
11: [{ name: 'Martial Arts', text: 'Your unarmed strikes deal 1d8 damage and can use Dexterity. After attacking, make one unarmed strike as a bonus action.', upgrade: true }],
|
||
12: [BOON],
|
||
13: [{ name: 'Tongue of the Sun and Moon', text: 'You understand every spoken language, and anyone who speaks one understands you.' }],
|
||
14: [
|
||
{ name: 'Diamond Soul', text: 'You are proficient in every saving throw (add the bonus by hand); 1 ki rerolls a failed save.' },
|
||
{ name: 'Unarmored Movement', text: '+25 ft speed without armor (ask your DM to raise your speed). You can run along walls and across water during your move.', upgrade: true },
|
||
],
|
||
15: [{ name: 'Timeless Body', text: 'You need no food or water and suffer none of the frailty of old age.' }],
|
||
16: [BOON],
|
||
17: [{ name: 'Martial Arts', text: 'Your unarmed strikes deal 1d10 damage and can use Dexterity. After attacking, make one unarmed strike as a bonus action.', upgrade: true }],
|
||
18: [
|
||
{ name: 'Empty Body', text: '4 ki: invisible for one minute, and all damage but force against you is halved. 8 ki: cast Astral Projection on yourself.' },
|
||
{ name: 'Unarmored Movement', text: '+30 ft speed without armor (ask your DM to raise your speed). You can run along walls and across water during your move.', upgrade: true },
|
||
],
|
||
19: [BOON],
|
||
20: [{ name: 'Perfect Self', text: 'When you roll initiative with no ki left, regain 4 ki.' }],
|
||
},
|
||
PALADIN: {
|
||
2: [
|
||
{ name: 'Divine Smite', text: 'After a melee hit, spend a spell slot to deal +2d8 radiant (+1d8 per slot level above 1st; +1d8 more against undead and fiends).' },
|
||
{ name: 'Fighting Style', text: 'Choose one with your DM: +1 AC in armor (the DM raises Extra AC by 1), +2 damage with a one-handed weapon, or protect an adjacent ally (impose disadvantage on an attack as a reaction).' },
|
||
{ name: 'Spellcasting', text: 'Paladin spells unlock: you now have spell slots.' },
|
||
],
|
||
3: [
|
||
{ name: 'Divine Health', text: 'Immune to disease.' },
|
||
],
|
||
4: [BOON],
|
||
5: [EXTRA_ATTACK],
|
||
6: [{ name: 'Aura of Protection', text: 'You and allies within 10 ft add your Charisma modifier to all saving throws while you are conscious.' }],
|
||
8: [BOON],
|
||
10: [{ name: 'Aura of Courage', text: 'You and allies within 10 ft can’t be frightened.' }],
|
||
11: [{ name: 'Improved Divine Smite', text: 'Every melee weapon hit deals an extra 1d8 radiant damage.' }],
|
||
12: [BOON],
|
||
14: [{ name: 'Cleansing Touch', text: 'A few times per day (your Charisma modifier, at least once), action: end one spell on yourself or a willing creature you touch.' }],
|
||
16: [BOON],
|
||
18: [
|
||
{ name: 'Aura of Protection', text: 'You and allies within 30 ft add your Charisma modifier to all saving throws while you are conscious.', upgrade: true },
|
||
{ name: 'Aura of Courage', text: 'You and allies within 30 ft can’t be frightened.', upgrade: true },
|
||
],
|
||
19: [BOON],
|
||
},
|
||
RANGER: {
|
||
2: [
|
||
{ name: 'Fighting Style', text: 'Choose one with your DM: +2 to ranged attacks, +1 AC in armor (the DM raises Extra AC by 1), or add your ability modifier again to a paired weapon’s damage (added by hand).' },
|
||
{ name: 'Spellcasting', text: 'Ranger spells unlock: you now have spell slots.' },
|
||
],
|
||
3: [
|
||
{ name: 'Primeval Awareness', text: 'Spend a spell slot: sense aberrations, dragons, fey, fiends, undead and elementals within 1 mile for 1 minute per slot level.' },
|
||
],
|
||
4: [BOON],
|
||
5: [EXTRA_ATTACK],
|
||
6: [
|
||
{ name: 'Favored Enemy', text: 'Choose a second favored enemy with your DM.' },
|
||
{ name: 'Natural Explorer', text: 'Choose a second favored terrain with your DM.' },
|
||
],
|
||
8: [BOON, LANDS_STRIDE],
|
||
10: [
|
||
{ name: 'Hide in Plain Sight', text: 'Spend 1 minute camouflaging: +10 to Stealth while you stay still.' },
|
||
{ name: 'Natural Explorer', text: 'Choose a third favored terrain with your DM.' },
|
||
],
|
||
12: [BOON],
|
||
14: [
|
||
{ name: 'Vanish', text: 'Hide as a bonus action, and you can’t be tracked by non-magical means unless you choose to leave a trail.' },
|
||
{ name: 'Favored Enemy', text: 'Choose a third favored enemy with your DM.', upgrade: true },
|
||
],
|
||
16: [BOON],
|
||
18: [{ name: 'Feral Senses', text: 'Within 30 ft, invisibility gives no advantage against you, and you know where invisible creatures are.' }],
|
||
19: [BOON],
|
||
20: [{ name: 'Foe Slayer', text: 'Once per turn, add your Wisdom modifier to the attack or damage roll against a favored enemy.' }],
|
||
},
|
||
ROGUE: {
|
||
2: [{ name: 'Cunning Action', text: 'Bonus action: Dash, Disengage or Hide.' }],
|
||
3: [sneakAttack('2d6')],
|
||
4: [BOON],
|
||
5: [sneakAttack('3d6'), { name: 'Uncanny Dodge', text: 'Reaction: halve the damage of an attack that hits you.' }],
|
||
6: [{ name: 'Expertise', text: 'Double proficiency on two more proficient skills (add by hand).' }],
|
||
7: [sneakAttack('4d6'), EVASION],
|
||
8: [BOON],
|
||
9: [sneakAttack('5d6')],
|
||
10: [BOON],
|
||
11: [sneakAttack('6d6'), { name: 'Reliable Talent', text: 'On a check with a skill you are proficient in, treat a d20 roll of 9 or lower as a 10.' }],
|
||
12: [BOON],
|
||
13: [sneakAttack('7d6')],
|
||
14: [{ name: 'Blindsense', text: 'If you can hear, you know where any hidden or invisible creature within 10 ft is.' }],
|
||
15: [sneakAttack('8d6'), { name: 'Slippery Mind', text: 'You are proficient in Wisdom saves (add the bonus by hand).' }],
|
||
16: [BOON],
|
||
17: [sneakAttack('9d6')],
|
||
18: [{ name: 'Elusive', text: 'No attack against you has advantage while you are not incapacitated.' }],
|
||
19: [BOON, sneakAttack('10d6')],
|
||
20: [{ name: 'Stroke of Luck', text: 'Once per short rest, turn a missed attack into a hit, or a failed check into a 20.' }],
|
||
},
|
||
SORCERER: {
|
||
2: [{ name: 'Font of Magic', text: 'Sorcery points equal to your level; they come back on a long rest. Bonus action: turn points into a spell slot (2 points = 1st, 3 = 2nd, 5 = 3rd, 6 = 4th, 7 = 5th), or a spell slot into points equal to its level.' }],
|
||
3: [{ name: 'Metamagic', text: 'Choose two with your DM: Quickened Spell (2 points: cast an action spell as a bonus action), Twinned Spell (points = spell level: hit a second target with a single-target spell), Careful Spell (1 point: allies auto-succeed on your spell’s save), Subtle Spell (1 point: cast without words or gestures), Extended Spell (1 point: double duration), Heightened Spell (3 points: one target has disadvantage on its first save).' }],
|
||
4: [BOON],
|
||
8: [BOON],
|
||
10: [{ name: 'Metamagic', text: 'Choose a third option with your DM.' }],
|
||
12: [BOON],
|
||
16: [BOON],
|
||
17: [{ name: 'Metamagic', text: 'Choose a fourth option with your DM.' }],
|
||
19: [BOON],
|
||
20: [{ name: 'Sorcerous Restoration', text: 'Regain 4 sorcery points after each short rest.' }],
|
||
},
|
||
WARLOCK: {
|
||
2: [{ name: 'Eldritch Invocations', text: `Choose two with your DM: ${INVOCATIONS}.` }],
|
||
3: [{ name: 'Pact Boon', text: 'Choose one with your DM: Pact of the Blade (summon a weapon of your choice as an action; it counts as magical), Pact of the Chain (gain a small familiar spirit: an imp, a sprite or a cat-shaped shadow), or Pact of the Tome (a book of three extra cantrips from any class, which the DM grants).' }],
|
||
4: [BOON],
|
||
5: [invocations('three')],
|
||
7: [invocations('four')],
|
||
8: [BOON],
|
||
9: [invocations('five')],
|
||
11: [{ name: 'Mystic Arcanum', text: 'Choose a 6th-level warlock spell with your DM: cast it once per long rest without a slot. One more spell is added at 13 (7th), 15 (8th) and 17 (9th).' }],
|
||
12: [BOON, invocations('six')],
|
||
13: [{ name: 'Mystic Arcanum', text: 'Choose a 7th-level spell too: each arcanum spell is cast once per long rest without a slot.', upgrade: true }],
|
||
15: [{ name: 'Mystic Arcanum', text: 'Choose an 8th-level spell too: each arcanum spell is cast once per long rest without a slot.', upgrade: true }, invocations('seven')],
|
||
16: [BOON],
|
||
17: [{ name: 'Mystic Arcanum', text: 'Choose a 9th-level spell too: each arcanum spell (6th to 9th) is cast once per long rest without a slot.', upgrade: true }],
|
||
18: [invocations('eight')],
|
||
19: [BOON],
|
||
20: [{ name: 'Eldritch Master', text: 'Once per long rest, spend a minute pleading with your patron to regain all your pact slots.' }],
|
||
},
|
||
WIZARD: {
|
||
4: [BOON],
|
||
8: [BOON],
|
||
12: [BOON],
|
||
16: [BOON],
|
||
18: [{ name: 'Spell Mastery', text: 'Choose a 1st- and a 2nd-level spell in your book with your DM: cast them at their lowest level without a slot.' }],
|
||
19: [BOON],
|
||
20: [{ name: 'Signature Spells', text: 'Choose two 3rd-level spells with your DM: each can be cast once per short rest without a slot.' }],
|
||
},
|
||
ARTIFICER: {
|
||
2: [{ name: 'Infuse Item', text: 'After a long rest, infuse up to two items with magic (you know four infusions; choose them with your DM): an enhanced weapon (+1 to hit and damage), enhanced armor (+1 AC), a bag of holding, a glowing focus (+1 spell attacks), and more.' }],
|
||
3: [{ name: 'The Right Tool for the Job', text: 'With an hour’s work and thieves’ or artisan’s tools, make any set of artisan’s tools you need.' }],
|
||
4: [BOON],
|
||
6: [
|
||
{ name: 'Tool Expertise', text: 'Double your proficiency bonus on any check that uses a tool (add it by hand).' },
|
||
{ name: 'Infuse Item', text: 'You know six infusions and keep up to three infused items at once.', upgrade: true },
|
||
],
|
||
7: [{ name: 'Flash of Genius', text: 'A few times per long rest (your Intelligence modifier, at least once), reaction: add your Intelligence modifier to a check or save made by you or a creature within 30 ft.' }],
|
||
8: [BOON],
|
||
10: [
|
||
{ name: 'Magic Item Adept', text: 'Attune to four magic items, and craft common or uncommon ones in a quarter of the time for half the gold.' },
|
||
{ name: 'Infuse Item', text: 'You know eight infusions and keep up to four infused items at once.', upgrade: true },
|
||
],
|
||
11: [{ name: 'Spell-Storing Item', text: 'After a long rest, store a 1st- or 2nd-level artificer spell in an item. Whoever holds it can cast it from the item, twice your Intelligence modifier times.' }],
|
||
12: [BOON],
|
||
14: [
|
||
{ name: 'Magic Item Savant', text: 'Attune to five magic items, and ignore class, species, spell and level requirements on them.' },
|
||
{ name: 'Infuse Item', text: 'You know ten infusions and keep up to five infused items at once.', upgrade: true },
|
||
],
|
||
16: [BOON],
|
||
18: [
|
||
{ name: 'Magic Item Master', text: 'Attune to six magic items.' },
|
||
{ name: 'Infuse Item', text: 'You know twelve infusions and keep up to six infused items at once.', upgrade: true },
|
||
],
|
||
19: [BOON],
|
||
20: [{ name: 'Soul of Artifice', text: '+1 to every saving throw for each magic item you are attuned to. When you drop to 0 HP, end one of your infusions to drop to 1 instead.' }],
|
||
},
|
||
};
|
||
|
||
// The class tables above go this far; so does a character.
|
||
const MAX_FEATURE_LEVEL = 20;
|
||
|
||
// From level 5 a damaging cantrip rolls twice the dice the site shows. Written
|
||
// onto the sheet of every class that casts, so nobody forgets.
|
||
const CANTRIP_LEVEL = 5;
|
||
const CANTRIP_FEATURE = {
|
||
name: 'Cantrips',
|
||
text: 'Double dice. Roll twice the damage dice the site shows for a damaging cantrip (Eldritch Blast becomes two beams, each with its own attack roll).',
|
||
};
|
||
|
||
// Boons stand in for ability score increases, which the site does not have
|
||
// (every number on the sheet comes from the scores rolled at the build). Each
|
||
// is worth what +2 to a best ability would be. `max` is how often one can be
|
||
// taken; `per` is what each taking adds, and `text` the line for that many.
|
||
const BOONS = [
|
||
{
|
||
key: 'WEAPON_MASTERY',
|
||
name: 'Weapon Mastery',
|
||
max: 2,
|
||
per: 1,
|
||
text: (amount) => `+${amount} to attack and damage rolls with weapons (add it to the numbers the site shows).`,
|
||
},
|
||
{
|
||
key: 'ARCANE_FOCUS',
|
||
name: 'Arcane Focus',
|
||
max: 2,
|
||
per: 1,
|
||
text: (amount) => `+${amount} to spell save DC and spell attack bonus (add it to the numbers the site shows).`,
|
||
},
|
||
// AC is the most powerful number in the game, so this one is taken once.
|
||
{ key: 'TOUGHENED', name: 'Toughened', max: 1, per: 1, text: (amount) => `+${amount} AC (counted in your Extra AC).` },
|
||
// The site works max HP out itself, so the extra lives in Temp HP.
|
||
{ key: 'HARDY', name: 'Hardy', max: 2, per: 5, text: (amount) => `+${amount} maximum HP: gain ${amount} Temp HP after each long rest.` },
|
||
// Past level 10 a class can have more Boons than the four above allow.
|
||
{ key: 'RESOLVE', name: 'Resolve', max: 2, per: 1, text: (amount) => `+${amount} to every saving throw (add it to the numbers the site shows).` },
|
||
];
|
||
|
||
module.exports = { LEVEL_FEATURES, MAX_FEATURE_LEVEL, CANTRIP_LEVEL, CANTRIP_FEATURE, BOONS };
|