monorepo/visions/ui/src/plugins/Candela/Charsheet.tsx

165 lines
5.9 KiB
TypeScript

import React from 'react';
import { assertNever } from '../../utils';
import './Charsheet.css';
import { DriveGuage } from './DriveGuage/DriveGuage';
import { Charsheet, Nerve, Cunning, Intuition } from './types';
interface CharsheetProps {
sheet: Charsheet,
}
interface ActionElementProps {
name: string,
gilded: boolean,
value: number,
}
const ActionElement = ({ name, gilded, value }: ActionElementProps) => {
let dots = [];
for (let i = 0; i < value; i++) {
dots.push("\u25ef");
}
let diamond = gilded ? "\u25c6" : "\u25c7";
return (<div>
<h2 className="action-group__action"> {diamond} {name} </h2>
<div className="action-group__dots"> {dots} </div>
</div>);
}
interface ActionGroupElementProps {
group: Nerve | Cunning | Intuition;
}
const ActionGroupElement = ({ group }: ActionGroupElementProps) => {
var title;
var elements = [];
switch (group.type_) {
case "nerve": {
title = <div className="action-group__header"> Nerve <DriveGuage current={group.drives.current} max={group.drives.max} /> </div>
elements.push(<ActionElement name="Move" gilded={group.move.gilded} value={group.move.score} />);
elements.push(<ActionElement name="Strike" gilded={group.strike.gilded} value={group.strike.score} />);
elements.push(<ActionElement name="Control" gilded={group.control.gilded} value={group.control.score} />);
break
}
case "cunning": {
title = <div className="action-group__header"> Cunning <DriveGuage current={group.drives.current} max={group.drives.max} /> </div>
elements.push(<ActionElement name="Sway" gilded={group.sway.gilded} value={group.sway.score} />);
elements.push(<ActionElement name="Read" gilded={group.read.gilded} value={group.read.score} />);
elements.push(<ActionElement name="Hide" gilded={group.hide.gilded} value={group.hide.score} />);
break
}
case "intuition": {
title = <div className="action-group__header"> Intuition <DriveGuage current={group.drives.current} max={group.drives.max} /> </div>
elements.push(<ActionElement name="Survey" gilded={group.survey.gilded} value={group.survey.score} />);
elements.push(<ActionElement name="Focus" gilded={group.focus.gilded} value={group.focus.score} />);
elements.push(<ActionElement name="Sense" gilded={group.sense.gilded} value={group.sense.score} />);
break
}
default: {
assertNever(group);
}
}
return (<div className="action-group">
{title}
{elements}
</div>)
}
interface AbilitiesElementProps {
role: string
role_abilities: string[]
specialty: string
specialty_abilities: string[]
}
const AbilitiesElement = ({ role, role_abilities, specialty, specialty_abilities }: AbilitiesElementProps) => {
return (<div>
<h1> ROLE: {role} </h1>
<ul>
{role_abilities.map((ability) => <li>{ability}</li>)}
</ul>
<h1> SPECIALTY: {role} </h1>
<ul>
{specialty_abilities.map((ability) => <li>{ability}</li>)}
</ul>
</div>
);
}
export const CharsheetElement = ({ sheet }: CharsheetProps) => {
return (<div>
<div className="charsheet__header">
<div> Candela Obscura </div>
<div>
<p> {sheet.name} </p>
<p> {sheet.pronouns} </p>
<p> {sheet.circle} </p>
</div>
<div>
<p> {sheet.style} </p>
<p> {sheet.catalyst} </p>
<p> {sheet.question} </p>
</div>
</div >
<div className="charsheet__body">
<div>
<ActionGroupElement group={sheet.nerve} />
<ActionGroupElement group={sheet.cunning} />
<ActionGroupElement group={sheet.intuition} />
</div>
<div> <AbilitiesElement {...sheet} /> </div>
<div> Marks, Scars, Relationships </div>
</div>
</div>);
}
/*
export const CharsheetElement = () => {
const sheet = {
type_: 'Candela',
name: "Soren Jensen",
pronouns: 'he/him',
circle: 'Circle of the Bluest Sky',
style: 'dapper gentleman',
catalyst: 'a cursed book',
question: 'What were the contents of that book?',
nerve: {
type_: "nerve",
drives: { current: 1, max: 2 },
resistances: { current: 0, max: 3 },
move: { gilded: false, score: 2 },
strike: { gilded: false, score: 1 },
control: { gilded: true, score: 0 },
} as Nerve,
cunning: {
type_: "cunning",
drives: { current: 1, max: 1 },
resistances: { current: 0, max: 3 },
sway: { gilded: false, score: 0 },
read: { gilded: false, score: 0 },
hide: { gilded: false, score: 0 },
} as Cunning,
intuition: {
type_: "intuition",
drives: { current: 0, max: 0 },
resistances: { current: 0, max: 3 },
survey: { gilded: false, score: 0 },
focus: { gilded: false, score: 0 },
sense: { gilded: false, score: 0 },
} as Intuition,
role: 'Slink',
role_abilities: [
'Scout: If you have time to observe a location, you can spend 1 Intuition to ask a question: What do I notice here that others do not see? What in this place might be of use to us? What path should we follow?',
],
specialty: 'Detective',
specialty_abilities: [
"Mind Palace: When you want to figure out how two clues might relate or what path they should point you towards, burn 1 Intution resistance. The GM will give you the information you've deduced.",
],
};
return <CharsheetElement_ sheet={sheet} />
}
*/