Files
the-sunken-reach/frontend/src/lib/guide.ts
T
joshuaandClaude Opus 5.5 4a6a09bae8 V1.1.0: gear levels, encounter overhaul, guided builder, trading, docs
Characters
- Builder: pick-then-Next on every step with live preview, Back button,
  plain-language help throughout, and "Suggest for me" for ability scores
- Motivation is picked from a list; new steps for special abilities,
  background and appearance, all composed from fixed lists and DM-only
  to edit afterwards
- Copy a character to another campaign
- Characters can give gold, weapons, items and spells to each other
- Money tracker: gold only changes through a logged ledger
- Fixes: level/XP/location are DM-only, HP stays within 0..max, physical
  dice ability rolls, every die is rolled once

Gear
- DM-managed item pool; weapons, items and spells are handed out by the DM
- Starting-option flag per pool entry
- Gear levels 1-9 per held copy with a damage ladder, growth rate and
  starting level; spells gated by spell level with a fixed damage value
- Spell library carries default damage; damage is picked from a list

Encounters
- Battle and NPC quest modes, turn tracking, scene description, DM notes
- NPCs, richer combatant cards, conditions from a list
- Rewards (gold, weapons, items) lined up and awarded, with gold splitting
- Character HP is shared between the sheet and the encounter
- Monster stat blocks and NPC secrets are never sent to players

Other
- Dice roller on every page
- Docs for characters, weapons, spells, items, encounters, monsters and
  NPCs, with full lists generated from the data (npm run docs:lists)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:47:28 +02:00

230 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Ability, CharacterClass, Species } from '../api/types';
// Plain-language explanations for someone building their first character.
// Everything here describes what a choice does to the *numbers* — plus a line
// of flavour. The special abilities a species or class grants are listed
// separately, from the server's own lists (useBuildOptions).
export const SPECIES_SPEED: Record<Species, number> = {
HUMAN: 30,
HALF_ELF: 30,
ELF: 30,
GNOME: 25,
DWARF: 25,
HALFLING: 25,
DRAGONBORN: 30,
TIEFLING: 30,
HALF_ORC: 30,
ORC: 30,
};
export const SPECIES_GUIDE: Record<Species, { blurb: string; goodFor: string }> = {
HUMAN: {
blurb: 'Adaptable and ambitious, found in every corner of the world.',
goodFor: 'A little better at everything (+1 to all six abilities). A safe pick for any class.',
},
HALF_ELF: {
blurb: 'Walks between two worlds, with human drive and elven grace.',
goodFor: 'Very charming (+2 Charisma), and you choose two more abilities to raise by 1. Great for talkers and Charisma spellcasters.',
},
ELF: {
blurb: 'Graceful, long-lived and quick on their feet.',
goodFor: 'Nimble (+2 Dexterity): harder to hit, acts sooner in a fight, better with bows and light blades.',
},
GNOME: {
blurb: 'Small, curious tinkerers with sharp minds.',
goodFor: 'Clever (+2 Intelligence): ideal for Wizards and knowledge skills. A little slower on foot.',
},
DWARF: {
blurb: 'Stout, stubborn mountain folk who are hard to put down.',
goodFor: 'Tough (+2 Constitution): more hit points at every level. A little slower on foot.',
},
HALFLING: {
blurb: 'Small, cheerful and surprisingly brave.',
goodFor: 'Nimble (+2 Dexterity): harder to hit and good at sneaking. A little slower on foot.',
},
DRAGONBORN: {
blurb: 'Proud, scaled warriors with dragon blood.',
goodFor: 'Strong (+2 Strength) with presence (+1 Charisma): hits hard up close. Great for Paladins and Fighters.',
},
TIEFLING: {
blurb: 'Marked by an infernal bloodline, and used to being stared at.',
goodFor: 'Magnetic (+2 Charisma) and bright (+1 Intelligence): great for Warlocks, Sorcerers and Bards.',
},
HALF_ORC: {
blurb: 'Fierce and enduring, with something to prove.',
goodFor: 'Strong (+2 Strength) and hardy (+1 Constitution): hits hard and takes hits. Great for Barbarians and Fighters.',
},
ORC: {
blurb: 'Powerful and relentless, raised to survive.',
goodFor: 'Strong (+2 Strength) and hardy (+1 Constitution): built for the front line.',
},
};
export type Toughness = 'Fragile' | 'Average' | 'Sturdy' | 'Very tough';
export const CLASS_GUIDE: Record<
CharacterClass,
{ blurb: string; playsLike: string; keyAbilities: Ability[]; skillCount: number; difficulty: 'Easy' | 'Medium' | 'Tricky' }
> = {
FIGHTER: {
blurb: 'A trained warrior, at home with any weapon.',
playsLike: 'Stand at the front, hit things, take hits. The simplest class to play well.',
keyAbilities: ['STR', 'DEX', 'CON'],
skillCount: 2,
difficulty: 'Easy',
},
BARBARIAN: {
blurb: 'A fierce warrior driven by raw fury.',
playsLike: 'Charge in and soak up damage — you have the most hit points of any class.',
keyAbilities: ['STR', 'CON'],
skillCount: 2,
difficulty: 'Easy',
},
ROGUE: {
blurb: 'A sneak, scout and scoundrel who relies on cunning.',
playsLike: 'Strike from the shadows and solve problems with skills — you get more skills than anyone.',
keyAbilities: ['DEX'],
skillCount: 4,
difficulty: 'Medium',
},
RANGER: {
blurb: 'A hunter and tracker of the wild places.',
playsLike: 'Fight from range or up close, with a little nature magic and plenty of outdoor skills.',
keyAbilities: ['DEX', 'WIS'],
skillCount: 3,
difficulty: 'Medium',
},
WIZARD: {
blurb: 'A scholar who has studied magic from books.',
playsLike: 'Stay back and cast spells. Powerful but fragile — the fewest hit points of any class.',
keyAbilities: ['INT'],
skillCount: 2,
difficulty: 'Tricky',
},
SORCERER: {
blurb: 'Born with magic in the blood.',
playsLike: 'Stay back and cast spells through sheer force of personality. Powerful but fragile.',
keyAbilities: ['CHA'],
skillCount: 2,
difficulty: 'Tricky',
},
CLERIC: {
blurb: 'A priest who channels the power of a god.',
playsLike: 'Heal and protect the party, and hold your own in a fight. Every group is glad to have one.',
keyAbilities: ['WIS'],
skillCount: 2,
difficulty: 'Medium',
},
PALADIN: {
blurb: 'A holy knight sworn to an oath.',
playsLike: 'A front-line fighter with a little divine magic to back up the sword.',
keyAbilities: ['STR', 'CHA'],
skillCount: 2,
difficulty: 'Medium',
},
BARD: {
blurb: 'A performer whose words and music carry magic.',
playsLike: 'The party’s talker and helper: spells, skills, and a way out of trouble.',
keyAbilities: ['CHA'],
skillCount: 3,
difficulty: 'Medium',
},
WARLOCK: {
blurb: 'Made a pact with a powerful being in exchange for magic.',
playsLike: 'A spellcaster with a few strong tricks used often, rather than many used rarely.',
keyAbilities: ['CHA'],
skillCount: 2,
difficulty: 'Medium',
},
DRUID: {
blurb: 'A guardian of nature who draws magic from the wild.',
playsLike: 'A flexible spellcaster: healing, nature magic and control of the battlefield.',
keyAbilities: ['WIS'],
skillCount: 2,
difficulty: 'Tricky',
},
MONK: {
blurb: 'A martial artist who has trained body and mind.',
playsLike: 'Fast and precise: dart around the fight striking quickly, with little need for gear.',
keyAbilities: ['DEX', 'WIS'],
skillCount: 2,
difficulty: 'Medium',
},
};
export function hitDieToughness(hitDie: number): Toughness {
if (hitDie <= 6) return 'Fragile';
if (hitDie <= 8) return 'Average';
if (hitDie <= 10) return 'Sturdy';
return 'Very tough';
}
// What each ability changes on the sheet this app builds.
export const ABILITY_GUIDE: Record<Ability, { short: string; affects: string }> = {
STR: {
short: 'Physical power',
affects: 'Strength — hitting and damage with heavy melee weapons, the Athletics skill (climbing, jumping, grappling), and Strength saves.',
},
DEX: {
short: 'Agility and reflexes',
affects:
'Dexterity — your Armor Class (how hard you are to hit), your Initiative (how early you act), attacks with bows and light blades, and Acrobatics, Sleight of Hand and Stealth.',
},
CON: {
short: 'Health and stamina',
affects: 'Constitution — your hit points, at level 1 and again every level after. Also Constitution saves. Useful for everyone.',
},
INT: {
short: 'Memory and reasoning',
affects: 'Intelligence — the Arcana, History, Investigation, Nature and Religion skills, and a Wizard’s spells.',
},
WIS: {
short: 'Awareness and intuition',
affects:
'Wisdom — noticing things (Perception and Passive Perception), plus Insight, Medicine, Survival and Animal Handling, and the spells of Clerics, Druids and Rangers.',
},
CHA: {
short: 'Force of personality',
affects: 'Charisma — Persuasion, Deception, Intimidation and Performance, and the spells of Bards, Paladins, Sorcerers and Warlocks.',
},
};
export const SKILL_GUIDE: Record<string, { ability: Ability; what: string }> = {
ACROBATICS: { ability: 'DEX', what: 'Staying on your feet: balancing, tumbling, flips.' },
ANIMAL_HANDLING: { ability: 'WIS', what: 'Calming, controlling or reading the mood of an animal.' },
ARCANA: { ability: 'INT', what: 'Knowing about magic, spells and magical creatures.' },
ATHLETICS: { ability: 'STR', what: 'Climbing, jumping, swimming and wrestling.' },
DECEPTION: { ability: 'CHA', what: 'Lying convincingly and hiding the truth.' },
HISTORY: { ability: 'INT', what: 'Recalling past events, kingdoms, wars and legends.' },
INSIGHT: { ability: 'WIS', what: 'Reading people: spotting lies and sensing intentions.' },
INTIMIDATION: { ability: 'CHA', what: 'Getting your way through threats and menace.' },
INVESTIGATION: { ability: 'INT', what: 'Searching for clues and working out what they mean.' },
MEDICINE: { ability: 'WIS', what: 'Steadying the dying and diagnosing illness.' },
NATURE: { ability: 'INT', what: 'Knowing about plants, animals, weather and terrain.' },
PERCEPTION: { ability: 'WIS', what: 'Noticing things: hidden enemies, traps, faint sounds. Rolled more than any other skill.' },
PERFORMANCE: { ability: 'CHA', what: 'Entertaining a crowd with music, acting or storytelling.' },
PERSUASION: { ability: 'CHA', what: 'Winning people over with honest charm and good arguments.' },
RELIGION: { ability: 'INT', what: 'Knowing about gods, rites, holy symbols and cults.' },
SLEIGHT_OF_HAND: { ability: 'DEX', what: 'Picking pockets, palming objects, planting things unseen.' },
STEALTH: { ability: 'DEX', what: 'Moving quietly and staying hidden.' },
SURVIVAL: { ability: 'WIS', what: 'Tracking, finding food and shelter, not getting lost.' },
};
// One line under each step heading: what this step is and why it matters.
export const STEP_GUIDE = {
SPECIES: 'Your species is who your character was born as. It nudges a few ability scores up and sets how fast you move.',
CLASS: 'Your class is what your character does — warrior, spellcaster, sneak. It sets your hit points, which saves you are good at, your skills, and whether you cast spells.',
MOTIVATION: 'Why is your character out adventuring? This is pure story — it changes no numbers, but it gives you something to play.',
SCORES:
'Six numbers that describe your character. Higher is better: 10 is average, and every 2 points above 10 adds +1 to related rolls. You roll six scores, then decide which ability gets which.',
SKILLS: 'Skills are things your character is trained in. When you roll for one of these, you add your proficiency bonus on top.',
ABILITIES:
'Special abilities are the tricks that make your character more than numbers. Your species and class each grant some automatically, and you pick a couple of talents of your own. Your DM applies them at the table.',
BACKGROUND: 'Who was your character before the adventure began? Pick one answer to each question. It changes no numbers — it tells you and your DM who you are playing.',
APPEARANCE: 'What do people see when your character walks in? Pick from each list to build the description.',
EQUIPMENT: 'What you set out with. Your DM decides what is on offer here, and can hand out more as you play.',
} as const;
export const STEP_NAMES = ['Species', 'Class', 'Motivation', 'Scores', 'Skills', 'Abilities', 'Background', 'Appearance', 'Equipment'] as const;