Create a renderer for Candela Obscura character sheets #275
|
@ -0,0 +1,14 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
build:
|
||||||
|
cmds:
|
||||||
|
- cargo build
|
||||||
|
|
||||||
|
test:
|
||||||
|
cmds:
|
||||||
|
- cargo watch -x test
|
||||||
|
|
||||||
|
server:
|
||||||
|
cmds:
|
||||||
|
- cargo watch -x run
|
|
@ -0,0 +1,7 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
dev:
|
||||||
|
cmds:
|
||||||
|
- npm run start
|
||||||
|
|
|
@ -16,4 +16,40 @@
|
||||||
width: 33%;
|
width: 33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-group {
|
||||||
|
position: relative;
|
||||||
|
border: 2px solid black;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-group:before {
|
||||||
|
content: " ";
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
top: 2px;
|
||||||
|
left: 2px;
|
||||||
|
right: 2px;
|
||||||
|
bottom: 2px;
|
||||||
|
border: 2px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-group > h1 {
|
||||||
|
margin: 4px;
|
||||||
|
margin-left: -4px;
|
||||||
|
padding-left: 4px;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-group__action {
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-group__dots {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ export type Guage = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Action = {
|
export type Action = {
|
||||||
guilded: boolean,
|
gilded: boolean,
|
||||||
score: number,
|
score: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ export type ActionGroup = {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Nerve = {
|
type Nerve = {
|
||||||
|
type_: "nerve",
|
||||||
drives: Guage,
|
drives: Guage,
|
||||||
resistances: Guage,
|
resistances: Guage,
|
||||||
move: Action,
|
move: Action,
|
||||||
|
@ -28,6 +29,7 @@ type Nerve = {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Cunning = {
|
type Cunning = {
|
||||||
|
type_: "cunning",
|
||||||
drives: Guage,
|
drives: Guage,
|
||||||
resistances: Guage,
|
resistances: Guage,
|
||||||
sway: Action,
|
sway: Action,
|
||||||
|
@ -36,6 +38,7 @@ type Cunning = {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Intuition = {
|
type Intuition = {
|
||||||
|
type_: "intuition",
|
||||||
drives: Guage,
|
drives: Guage,
|
||||||
resistances: Guage,
|
resistances: Guage,
|
||||||
survey: Action,
|
survey: Action,
|
||||||
|
@ -62,11 +65,6 @@ interface CharsheetProps {
|
||||||
sheet: Charsheet,
|
sheet: Charsheet,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActionDriveProps {
|
|
||||||
groupName: string,
|
|
||||||
group: Nerve | Cunning | Intuition,
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GuageProps {
|
interface GuageProps {
|
||||||
current: number,
|
current: number,
|
||||||
max: number,
|
max: number,
|
||||||
|
@ -76,15 +74,67 @@ const GuageElement = ({ current, max }: GuageProps) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActionDriveElement = ({ groupName, group }: ActionDriveProps) => {
|
function assertNever(value: never) {
|
||||||
|
throw new Error("Unexpected value: " + value);
|
||||||
|
}
|
||||||
|
|
||||||
if ("move" in group) {
|
interface ActionElementProps {
|
||||||
return <div> -- Nerve -- </div>;
|
name: string,
|
||||||
} else if ("sway" in group) {
|
gilded: boolean,
|
||||||
return <div> -- Cunning -- </div>;
|
value: number,
|
||||||
} else {
|
}
|
||||||
return <div> -- Intuition -- </div>;
|
|
||||||
|
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> Nerve </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> Cunning </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> Intuition </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">
|
||||||
|
<h1> {title} </h1>
|
||||||
|
{elements}
|
||||||
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CharsheetElement_ = ({ sheet }: CharsheetProps) => {
|
const CharsheetElement_ = ({ sheet }: CharsheetProps) => {
|
||||||
|
@ -104,9 +154,9 @@ const CharsheetElement_ = ({ sheet }: CharsheetProps) => {
|
||||||
</div >
|
</div >
|
||||||
<div className="charsheet__body">
|
<div className="charsheet__body">
|
||||||
<div>
|
<div>
|
||||||
<ActionDriveElement groupName="Nerve" group={sheet.nerve} />
|
<ActionGroupElement group={sheet.nerve} />
|
||||||
<ActionDriveElement groupName="Cunning" group={sheet.cunning} />
|
<ActionGroupElement group={sheet.cunning} />
|
||||||
<ActionDriveElement groupName="Intuition" group={sheet.intuition} />
|
<ActionGroupElement group={sheet.intuition} />
|
||||||
</div>
|
</div>
|
||||||
<div> Role and Specialty </div>
|
<div> Role and Specialty </div>
|
||||||
<div> Marks, Scars, Relationships </div>
|
<div> Marks, Scars, Relationships </div>
|
||||||
|
@ -125,26 +175,29 @@ export const CharsheetElement = () => {
|
||||||
question: 'What were the contents of that book?',
|
question: 'What were the contents of that book?',
|
||||||
role: 'Slink',
|
role: 'Slink',
|
||||||
nerve: {
|
nerve: {
|
||||||
|
type_: "nerve",
|
||||||
drives: { current: 2, max: 2 },
|
drives: { current: 2, max: 2 },
|
||||||
resistances: { current: 0, max: 3 },
|
resistances: { current: 0, max: 3 },
|
||||||
move: { guilded: false, score: 0 },
|
move: { gilded: false, score: 2 },
|
||||||
strike: { guilded: false, score: 0 },
|
strike: { gilded: false, score: 1 },
|
||||||
control: { guilded: true, score: 0 },
|
control: { gilded: true, score: 0 },
|
||||||
},
|
} as Nerve,
|
||||||
cunning: {
|
cunning: {
|
||||||
|
type_: "cunning",
|
||||||
drives: { current: 1, max: 1 },
|
drives: { current: 1, max: 1 },
|
||||||
resistances: { current: 0, max: 3 },
|
resistances: { current: 0, max: 3 },
|
||||||
sway: { guilded: false, score: 0 },
|
sway: { gilded: false, score: 0 },
|
||||||
read: { guilded: false, score: 0 },
|
read: { gilded: false, score: 0 },
|
||||||
hide: { guilded: false, score: 0 },
|
hide: { gilded: false, score: 0 },
|
||||||
},
|
} as Cunning,
|
||||||
intuition: {
|
intuition: {
|
||||||
|
type_: "intuition",
|
||||||
drives: { current: 0, max: 0 },
|
drives: { current: 0, max: 0 },
|
||||||
resistances: { current: 0, max: 3 },
|
resistances: { current: 0, max: 3 },
|
||||||
survey: { guilded: false, score: 0 },
|
survey: { gilded: false, score: 0 },
|
||||||
focus: { guilded: false, score: 0 },
|
focus: { gilded: false, score: 0 },
|
||||||
sense: { guilded: false, score: 0 },
|
sense: { gilded: false, score: 0 },
|
||||||
}
|
} as Intuition
|
||||||
};
|
};
|
||||||
|
|
||||||
return <CharsheetElement_ sheet={sheet} />
|
return <CharsheetElement_ sheet={sheet} />
|
||||||
|
|
Loading…
Reference in New Issue