Character Development Tool

Character Development Tool

Build a rich, detailed character profile step-by-step.

Step 1: Core Identity

Step 2: Physical Appearance

Step 3: Personality & Traits

Step 4: History & Backstory

Step 5: Your Completed Character Profile

Your character's profile will be summarized here once you fill out the previous steps and click "Generate Profile".

Height/Build: ${characterData['char-height'] || 'N/A'}

Hair/Eyes: ${characterData['char-hair'] || 'N/A'}

Style: ${characterData['char-style'] || 'N/A'}

Personality

Positive Traits: ${characterData['char-traits'] || 'N/A'}

Flaws: ${characterData['char-flaws'] || 'N/A'}

Motivations: ${characterData['char-motivations'] || 'N/A'}

Backstory

${characterData['char-backstory'] || 'N/A'}

`; pdfButtonContainer.style.display = 'block'; showTab(tabs.length - 1); }; const downloadPDF = () => { try { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const fields = { name: document.getElementById('char-name')?.value || 'Unnamed Character', nickname: document.getElementById('char-nickname')?.value || 'N/A', age: document.getElementById('char-age')?.value || 'N/A', gender: document.getElementById('char-gender')?.value || 'N/A', occupation: document.getElementById('char-occupation')?.value || 'N/A', concept: document.getElementById('char-concept')?.value || 'N/A', height: document.getElementById('char-height')?.value || 'N/A', hair: document.getElementById('char-hair')?.value || 'N/A', features: document.getElementById('char-features')?.value || 'N/A', style: document.getElementById('char-style')?.value || 'N/A', traits: document.getElementById('char-traits')?.value || 'N/A', flaws: document.getElementById('char-flaws')?.value || 'N/A', motivations: document.getElementById('char-motivations')?.value || 'N/A', backstory: document.getElementById('char-backstory')?.value || 'N/A' }; const pageHeight = doc.internal.pageSize.getHeight(); const pageWidth = doc.internal.pageSize.getWidth(); const margin = 15; let cursorY = margin; // --- PDF Header --- doc.setFont('helvetica', 'bold'); doc.setFontSize(24); doc.setTextColor(45, 22, 82); // Dark Purple doc.text(fields.name, pageWidth / 2, cursorY, { align: 'center' }); cursorY += 8; doc.setFont('helvetica', 'normal'); doc.setFontSize(12); doc.setTextColor(128, 128, 128); doc.text(`Character Profile Sheet`, pageWidth / 2, cursorY, { align: 'center' }); cursorY += 12; doc.setDrawColor(221, 221, 221); doc.line(margin, cursorY, pageWidth - margin, cursorY); cursorY += 10; // --- Helper function for sections --- const addSection = (title, content, isLongText = false) => { if (cursorY > pageHeight - 30) { doc.addPage(); cursorY = margin; } doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.setTextColor(88, 28, 135); // Purple doc.text(title, margin, cursorY); cursorY += 6; doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.setTextColor(55, 65, 81); if(isLongText){ const textLines = doc.splitTextToSize(content, pageWidth - margin * 2); doc.text(textLines, margin, cursorY); cursorY += (textLines.length * 4.5) + 8; } else { doc.autoTable({ startY: cursorY, body: content, theme: 'plain', styles: { fontSize: 10, cellPadding: 2, textColor: [55, 65, 81] }, columnStyles: { 0: { fontStyle: 'bold', cellWidth: 50, textColor: [17, 24, 39] } } }); cursorY = doc.previousAutoTable.finalY + 8; } }; // --- Build PDF Sections --- const identityData = [ ['Nickname:', fields.nickname], ['Age:', fields.age], ['Gender:', fields.gender], ['Occupation:', fields.occupation] ]; addSection("Core Identity", identityData); addSection("Core Concept", fields.concept, true); const appearanceData = [ ['Height & Build:', fields.height], ['Hair & Eyes:', fields.hair], ['Features:', fields.features], ['Clothing Style:', fields.style] ]; addSection("Appearance", appearanceData); addSection("Positive Traits", fields.traits, true); addSection("Flaws & Vices", fields.flaws, true); addSection("Motivations & Goals", fields.motivations, true); addSection("Backstory", fields.backstory, true); // --- Footer --- const pageCount = doc.internal.getNumberOfPages(); for (let i = 1; i <= pageCount; i++) { doc.setPage(i); doc.setFontSize(9); doc.setTextColor(150); const footerText = `Page ${i} of ${pageCount} | ${fields.name} | Generated on: ${new Date().toLocaleDateString()}`; doc.text(footerText, pageWidth / 2, pageHeight - 10, { align: 'center' }); } doc.save(`${fields.name.replace(/\s+/g, '_')}-Profile.pdf`); } catch (error) { console.error("Failed to generate PDF:", error); const pdfButtonContainer = document.getElementById('pdf-button-container'); if (pdfButtonContainer && !pdfButtonContainer.querySelector('.error-msg')) { const errorMsg = document.createElement('p'); errorMsg.textContent = 'Sorry, an error occurred while creating the PDF.'; errorMsg.className = 'text-red-500 text-sm mt-2 error-msg'; pdfButtonContainer.appendChild(errorMsg); } } }; // Event Listeners prevButton.addEventListener('click', () => navigate(-1)); nextButton.addEventListener('click', () => navigate(1)); generateButton.addEventListener('click', generateProfile); downloadPdfButton.addEventListener('click', downloadPDF); // Initial setup showTab(0); });
Scroll to Top