A4 character sheet (summary and lobby), A4/wide switch, print to PDF
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJhXuLD2Z6hv3Wqeq9UL9K
This commit is contained in:
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { applyPreset, applyProfession, compute, effectiveRules, emptyCharacter, kitItems, normalize, resetStep, setProfessionPicks } from './calc.js'
|
||||
import SheetPanel from './SheetPanel.jsx'
|
||||
import Tip from './Tip.jsx'
|
||||
import PaperSheet from './PaperSheet.jsx'
|
||||
import { explainAttr, explainAttrPool, explainCapacity, explainCarry, explainDerived, explainProfPool, explainSkill, explainSkillPool } from './explain.js'
|
||||
|
||||
const STEPS = ['Concept', 'Attributes', 'Profession', 'Skills', 'Talents', 'Mutations', 'Equipment', 'Summary']
|
||||
@@ -433,47 +434,7 @@ export default function Creator({ rules: baseRules, user, loadRequest, clearLoad
|
||||
<>
|
||||
<h2>Summary</h2>
|
||||
{warnings.length > 0 && <ul className="warn">{warnings.map((w) => <li key={w}>{w}</li>)}</ul>}
|
||||
<div className="sheet card">
|
||||
<h3 className="sheet-name">{ch.name || 'Nameless'}</h3>
|
||||
<p className="muted">{ch.player && `Player: ${ch.player} · `}Profession: {prof?.name || '–'}{cls && ` · Class: ${[cls.name, sub?.name].filter(Boolean).join(' / ')}`}</p>
|
||||
<div className="sheet-cols">
|
||||
<div>
|
||||
<h4>Attributes</h4>
|
||||
<table><tbody>{rules.attributes.map((a) => <tr key={a.id}><td><Tip text={explainAttr(a, ctx)}>{a.name}</Tip></td><td>{c.attrs[a.id]}</td><td className="muted">Mod {c.mods[a.id]}</td></tr>)}</tbody></table>
|
||||
<h4>Derived stats</h4>
|
||||
<table><tbody>{rules.derived.map((d) => <tr key={d.id}><td><Tip text={explainDerived(d, ctx)}>{d.name}</Tip></td><td>{c.derived[d.id]}</td></tr>)}</tbody></table>
|
||||
</div>
|
||||
<div>
|
||||
<h4>Talents</h4>
|
||||
<ul className="desclist">{rules.talents.filter((t) => ch.talents.includes(t.id)).map((t) => <li key={t.id}><strong>{t.name}</strong><div className="rowdesc">{t.desc}</div></li>)}</ul>
|
||||
{!ch.talents.length && <p>–</p>}
|
||||
<h4><Tip text={explainCapacity(ctx)}>Mutations / implants ({c.capacityUsed}/{c.capacityMax})</Tip></h4>
|
||||
<ul className="desclist">{rules.augments.filter((a) => ch.augments.includes(a.id)).map((a) => <li key={a.id}><strong>{a.name}</strong> <span className="muted small">cost {a.cost}</span><div className="rowdesc">{a.desc}</div></li>)}</ul>
|
||||
{!ch.augments.length && <p>–</p>}
|
||||
<h4><Tip text={explainCarry(ctx)}>Equipment ({c.weight}/{c.carryMax} kg)</Tip></h4>
|
||||
<ul className="desclist">{gearLines.map((g) => <li key={g.item.id}><strong>{g.item.name}{g.qty > 1 ? ` x${g.qty}` : ''}</strong><div className="rowdesc">{[g.item.stat, `${Math.round(g.item.kg * g.qty * 10) / 10} kg`, g.item.note].filter(Boolean).join(' · ')}</div></li>)}</ul>
|
||||
{!gearLines.length && <p>–</p>}
|
||||
{ch.gear.other && <p className="small"><strong>Other:</strong> {ch.gear.other}</p>}
|
||||
</div>
|
||||
</div>
|
||||
<h4>Skills</h4>
|
||||
<div className="skillcols">
|
||||
{rules.skill_groups.map((g) => (
|
||||
<div key={g.id} className="skillgroup">
|
||||
<h5>{g.name}</h5>
|
||||
<table><tbody>
|
||||
{c.skills.filter((s) => s.group === g.id).map((s) => (
|
||||
<tr key={s.id} className={s.usable ? '' : 'dim'}>
|
||||
<td><Tip text={explainSkill(s, ctx)}>{s.name}</Tip>{s.type === 'advanced' && <span className="muted small"> (adv.)</span>}</td>
|
||||
<td>{s.total}</td>
|
||||
<td className="muted">{s.pips === 2 ? 'Expertise' : s.pips === 1 ? 'Proficient' : !s.usable ? 'Locked' : s.points ? `+${s.points}` : ''}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody></table>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<PaperSheet data={ch} baseRules={baseRules} />
|
||||
<div className="actions wrap">
|
||||
<button onClick={() => download('pdf')}>Download as PDF</button>
|
||||
<button onClick={() => download('docx')}>Download as Word</button>
|
||||
|
||||
Reference in New Issue
Block a user