Dragons Beyond Character Generator

1. Roll Traits

Roll 3d6 for each of your six personality traits:

2. Choose Race

3. Choose Class

4. Adjust Traits (Optional)

You may swap traits 2-for-1 based on your class:
Fighting-Man: Take 2 from Int/Cunning → add 1 to Strength
Cleric: Take 2 from Int/Strength → add 1 to Cunning
Magic-User: Take 2 from Cunning → add 1 to Intelligence (NOT from Strength)

5. Choose Alignment

6. Roll Starting Resources

7. Final Character Sheet

// Character data let character = { race: '', class: '', alignment: '', traits: { strength: 0, intelligence: 0, cunning: 0, ego: 0, health: 0, appearance: 0 }, gold: 0, hitPoints: 0, level: 1 }; // Race/Class restrictions const raceInfo = { human: { classes: ['fighting-man', 'magic-user', 'cleric'], info: 'Humans may play any class and advance without restriction.' }, dwarf: { classes: ['fighting-man'], info: 'Dwarves may only be Fighting-Men, max 6th level. +10% EP advancement (modified by Str/Int/Cunning average). Save vs magic as if 3 levels higher. See in dark 90\'. +2-in-6 detect secret doors.' }, elf: { classes: ['fighting-man', 'magic-user'], info: 'Elves may be Fighting-Man OR Magic-User and can switch classes. Max 5th level FM, 8th level MU. 90% base bow accuracy. See in dark 90\'. +1-in-6 detect secret doors.' }, halfling: { classes: ['fighting-man'], info: 'Halflings may only be Fighting-Men, max 4th level. -10% EP advancement (modified by Str/Int/Cunning average). Save vs magic as if 4 levels higher. 97% sling accuracy. Move silently. +2-in-6 detect secret doors (if Cunning 13+).' } }; const classInfo = { 'fighting-man': 'Prime Requisite: Strength. May use any weapon and armor.', 'magic-user': 'Prime Requisite: Intelligence. Casts arcane spells. Armor interferes with casting.', 'cleric': 'Prime Requisite: Cunning. Casts divine spells. No edged weapons (except Holy Sword). Turns undead.' }; const alignmentRestrictions = { human: { 'fighting-man': ['law', 'neutral', 'chaos'], 'magic-user': ['law', 'neutral', 'chaos'], 'cleric': ['law', 'chaos'] // Clerics cannot be Neutral }, dwarf: { 'fighting-man': ['law', 'neutral', 'chaos'] }, elf: { 'fighting-man': ['law', 'neutral'], // Elves may be Lawful or Neutral 'magic-user': ['law', 'neutral'] }, halfling: { 'fighting-man': ['law'] // Halflings must be Lawful } }; function roll3d6() { return Math.floor(Math.random() * 6) + 1 + Math.floor(Math.random() * 6) + 1 + Math.floor(Math.random() * 6) + 1; } function roll1d6() { return Math.floor(Math.random() * 6) + 1; } function updateClassOptions() { const race = document.getElementById('race').value; const classSelect = document.getElementById('class'); const raceInfoDiv = document.getElementById('raceInfo'); character.race = race; classSelect.innerHTML = ''; classSelect.disabled = !race; if (race) { raceInfo[race].classes.forEach(cls => { const option = document.createElement('option'); option.value = cls; option.textContent = cls.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('-'); classSelect.appendChild(option); }); raceInfoDiv.textContent = raceInfo[race].info; raceInfoDiv.style.display = 'block'; } else { raceInfoDiv.style.display = 'none'; } updateAlignmentOptions(); } function updateAlignmentOptions() { const race = document.getElementById('race').value; const cls = document.getElementById('class').value; const alignmentSelect = document.getElementById('alignment'); const classInfoDiv = document.getElementById('classInfo'); character.class = cls; alignmentSelect.innerHTML = ''; alignmentSelect.disabled = !cls; if (cls && classInfo[cls]) { classInfoDiv.textContent = classInfo[cls]; classInfoDiv.style.display = 'block'; } else { classInfoDiv.style.display = 'none'; } if (race && cls && alignmentRestrictions[race] && alignmentRestrictions[race][cls]) { alignmentRestrictions[race][cls].forEach(align => { const option = document.createElement('option'); option.value = align; option.textContent = align.charAt(0).toUpperCase() + align.slice(1); alignmentSelect.appendChild(option); }); } } function rollTraits() { if (!character.race || !character.class) { alert('Please select race and class first!'); return; } character.traits.strength = roll3d6(); character.traits.intelligence = roll3d6(); character.traits.cunning = roll3d6(); character.traits.ego = roll3d6(); character.traits.health = roll3d6(); character.traits.appearance = roll3d6(); displayTraits(); displayAdjustmentControls(); } function displayTraits() { const output = document.getElementById('traitsOutput'); output.innerHTML = `
Strength: ${character.traits.strength} ${getModifierText('strength')}
Intelligence: ${character.traits.intelligence} ${getModifierText('intelligence')}
Cunning: ${character.traits.cunning} ${getModifierText('cunning')}
Ego: ${character.traits.ego} ${getModifierText('ego')}
Health: ${character.traits.health} ${getHealthModifier()}
Appearance: ${character.traits.appearance}
`; } function getModifierText(trait) { const value = character.traits[trait]; let prime = ''; if (character.class === 'fighting-man' && trait === 'strength') prime = ' (Prime Requisite)'; if (character.class === 'magic-user' && trait === 'intelligence') prime = ' (Prime Requisite)'; if (character.class === 'cleric' && trait === 'cunning') prime = ' (Prime Requisite)'; if (value <= 6) return `Very Low${prime}`; if (value <= 8) return `Low${prime}`; if (value <= 12) return `Average${prime}`; if (value <= 14) return `Above Average${prime}`; return `Exceptional${prime}`; } function getHealthModifier() { const health = character.traits.health; if (health <= 6) return 'HP: -2 (min 1/die)'; if (health <= 8) return 'HP: -1 (min 1/die)'; if (health <= 12) return 'HP: No modifier'; if (health <= 14) return 'HP: +1 (min 3/die)'; return 'HP: +2 (min 4/die)'; } function displayAdjustmentControls() { const controls = document.getElementById('adjustmentControls'); if (character.class === 'fighting-man') { controls.innerHTML = ` `; } else if (character.class === 'cleric') { controls.innerHTML = ` `; } else if (character.class === 'magic-user') { controls.innerHTML = ` `; } else { controls.innerHTML = '

No adjustments available for this class.

'; } } function adjustTrait(from, to) { if (character.traits[from] >= 2) { character.traits[from] -= 2; character.traits[to] += 1; displayTraits(); } else { alert(`Not enough ${from} to adjust!`); } } function rollResources() { if (!character.race || !character.class || character.traits.strength === 0) { alert('Please select race, class, and roll traits first!'); return; } // Roll starting gold (3d6 × 10) character.gold = (roll3d6()) * 10; // Roll hit points (1d6, +1 for Fighting-Men and similar) let hpRoll = roll1d6(); // Fighting-Men bonus if (character.class === 'fighting-man' || (character.race === 'elf' && character.class === 'fighting-man') || character.race === 'halfling' || character.race === 'dwarf') { hpRoll += 1; } // Apply Health modifier const health = character.traits.health; let modifier = 0; let floor = 1; if (health <= 6) { modifier = -2; floor = 1; } else if (health <= 8) { modifier = -1; floor = 1; } else if (health <= 12) { modifier = 0; floor = 1; } else if (health <= 14) { modifier = 1; floor = 3; } else { modifier = 2; floor = 4; } character.hitPoints = Math.max(floor, hpRoll + modifier); const output = document.getElementById('resourcesOutput'); output.innerHTML = `
Starting Gold: ${character.gold} gp Hit Points: ${character.hitPoints} (rolled ${hpRoll}${modifier >= 0 ? '+' : ''}${modifier}, min ${floor})
`; } function getPrimeRequisiteModifier() { let primeValue = 0; if (character.class === 'fighting-man') { primeValue = character.traits.strength; } else if (character.class === 'magic-user') { primeValue = character.traits.intelligence; } else if (character.class === 'cleric') { primeValue = character.traits.cunning; } // Special handling for Dwarves and Halflings if (character.race === 'dwarf' || character.race === 'halfling') { const avg = Math.ceil((character.traits.strength + character.traits.intelligence + character.traits.cunning) / 3); primeValue = avg; } if (primeValue <= 6) return '-25%'; if (primeValue <= 8) return '-10%'; if (primeValue <= 12) return 'No modifier'; if (primeValue <= 14) return '+5%'; return '+10%'; } function getTitle() { const titles = { 'fighting-man': 'Veteran', 'magic-user': 'Medium', 'cleric': 'Acolyte' }; return titles[character.class] || 'Adventurer'; } function getLanguages() { const intel = character.traits.intelligence; let langs = ['Common']; // Check if character doesn't know Common (low Intelligence) if (intel <= 8) { const chance = (9 - intel) * 15; langs[0] = `Common (${100-chance}% chance to know)`; } // Additional languages based on Intelligence if (intel >= 11) { const additional = intel - 10; langs.push(`+${additional} additional language${additional > 1 ? 's' : ''}`); } // Magic-Users know Magi if (character.class === 'magic-user') { const readChance = Math.min(90, 15 + (intel - 3) * 5); langs.push(`Magi (${readChance}% to read)`); } // Racial languages if (character.race === 'dwarf') { langs.push('Dwarvish, Goblin, Kobold, Gnomish, Orc'); } else if (character.race === 'elf') { langs.push('Elvish'); } return langs.join(', '); } function getSavingThrows() { const saves = { 'fighting-man': { deathRay: 12, poison: 12, paralyzation: 15, stone: 16, breath: 15, spells: 16 }, 'magic-user': { deathRay: 15, poison: 14, paralyzation: 14, stone: 13, breath: 15, spells: 15 }, 'cleric': { deathRay: 11, poison: 13, paralyzation: 14, stone: 14, breath: 16, spells: 12 } }; let baseSaves = saves[character.class]; // Racial modifiers if (character.race === 'dwarf') { return `Death Ray: ${baseSaves.deathRay-3}, Poison: ${baseSaves.poison-3}, Paralyzation: ${baseSaves.paralyzation-3}, Stone: ${baseSaves.stone-3}, Breath: ${baseSaves.breath-3}, Spells: ${baseSaves.spells-3} (as 4th level)`; } else if (character.race === 'halfling') { return `Death Ray: ${baseSaves.deathRay-4}, Poison: ${baseSaves.poison-4}, Paralyzation: ${baseSaves.paralyzation-4}, Stone: ${baseSaves.stone-4}, Breath: ${baseSaves.breath-4}, Spells: ${baseSaves.spells-4} (as 5th level)`; } return `Death Ray: ${baseSaves.deathRay}, Poison: ${baseSaves.poison}, Paralyzation: ${baseSaves.paralyzation}, Stone: ${baseSaves.stone}, Breath: ${baseSaves.breath}, Spells: ${baseSaves.spells}`; } function generateCharacter() { const alignment = document.getElementById('alignment').value; if (!character.race || !character.class || !alignment || character.traits.strength === 0 || character.gold === 0) { alert('Please complete all previous steps first!'); return; } character.alignment = alignment; const output = document.getElementById('characterOutput'); const raceDisplay = character.race.charAt(0).toUpperCase() + character.race.slice(1); const classDisplay = character.class.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('-'); const alignDisplay = alignment.charAt(0).toUpperCase() + alignment.slice(1); output.innerHTML = `
╔═══════════════════════════════════════════════════════════╗ ║ DRAGONS BEYOND CHARACTER SHEET ║ ╠═══════════════════════════════════════════════════════════╣ Name: ______________________ Player: ______________________ Race: ${raceDisplay} Class: ${classDisplay} Level: 1 (${getTitle()}) Alignment: ${alignDisplay} TRAITS: Strength: ${character.traits.strength} ${character.class === 'fighting-man' ? '★ Prime Requisite' : ''} Intelligence: ${character.traits.intelligence} ${character.class === 'magic-user' ? '★ Prime Requisite' : ''} Cunning: ${character.traits.cunning} ${character.class === 'cleric' ? '★ Prime Requisite' : ''} Ego: ${character.traits.ego} Health: ${character.traits.health} Appearance: ${character.traits.appearance} COMBAT: Hit Points: ${character.hitPoints} Armor Class: 9 (unarmored) Movement: 12" (unencumbered) To Hit (AC 9): ${character.class === 'cleric' || character.class === 'magic-user' ? '10' : '9'} EXPERIENCE: Current XP: 0 Next Level: ${character.class === 'fighting-man' ? '1,000' : character.class === 'magic-user' ? '1,000' : '500'} Prime Requisite Modifier: ${getPrimeRequisiteModifier()} SAVING THROWS (3d6): ${getSavingThrows()} LANGUAGES: ${getLanguages()} EQUIPMENT & TREASURE: Starting Gold: ${character.gold} gp Armor: None (consider purchasing) Weapons: None (consider purchasing) Equipment: None (consider purchasing) Current Weight: 0 cns / 0 slots SPECIAL ABILITIES: ${getSpecialAbilities()} ╚═══════════════════════════════════════════════════════════╝ Next Steps: 1. Choose a name for your character 2. Purchase equipment with your starting gold 3. Calculate final Armor Class and movement rate 4. Begin your adventure!
`; } function getSpecialAbilities() { let abilities = []; if (character.class === 'cleric') { abilities.push(' • Turn Undead (see table)'); abilities.push(' • Spells: Can cast divine spells (none at 1st level)'); } else if (character.class === 'magic-user') { abilities.push(' • Spells: Can cast 1 first-level spell per day'); abilities.push(' • Read Magi: Use Read Magic spell to decipher scrolls'); } if (character.race === 'dwarf') { abilities.push(' • Darkvision 90\''); abilities.push(' • Detect sloping passages'); abilities.push(' • 2-in-6 detect secret doors'); abilities.push(' • 1-in-6 force doors with crowbar'); abilities.push(' • 2-in-6 hear noise at doors'); } else if (character.race === 'elf') { abilities.push(' • Darkvision 90\''); abilities.push(' • Cannot get lost in natural forest'); abilities.push(' • Bow: 90% base hit chance, can split move and fire'); abilities.push(' • 1-in-6 detect secret doors'); abilities.push(' • 1-in-6 force doors with crowbar'); abilities.push(' • 2-in-6 hear noise at doors'); if (character.class === 'magic-user') { abilities.push(' • Can switch to Fighting-Man class at max level (with 13+ Strength)'); } } else if (character.race === 'halfling') { abilities.push(' • Move silently (not heard by opponents)'); abilities.push(' • Sling: 97% base hit chance, 90% called shots'); abilities.push(' • 2-in-6 detect secret doors (if Cunning 13+)'); abilities.push(' • 1-in-6 force doors with crowbar'); abilities.push(' • 2-in-6 hear noise at doors'); } else { // human abilities.push(' • 1-in-6 detect secret doors'); abilities.push(' • 2-in-6 force doors with crowbar'); abilities.push(' • 1-in-6 hear noise at doors'); } return abilities.length > 0 ? abilities.join('\n') : ' None'; }