Tracker made in React for keeping track of HP and MP and so on.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

128 lines
6.4 KiB

import React, {useEffect, useMemo, useState} from 'react';
import './App.css';
import {Col, Container, Row, Stack} from "react-bootstrap";
import {CharacterStatus} from "./CharacterStatus";
import {GameState} from "../model/GameState";
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
import Tooltip from "react-bootstrap/Tooltip";
import {TurnTimer} from "./TurnTimer";
import {CharacterSide} from "../model/Character";
import {evaluate} from "../grammar/interpreter";
function useJson<T>(url: string): T | null {
const [data, setData] = useState<T | null>(null);
useEffect(() => {
let ignore = false;
fetch(url)
.then(response => response.json() as T)
.then(json => {
if (!ignore) {
setData(json);
}
});
return () => {
ignore = true;
};
}, [url]);
return data as T | null;
}
function App() {
const origState = useJson<GameState>("/api/current.json")
const state = useMemo(() => {
try {
if (origState !== null) {
return evaluate(origState, Date.now(),
String.raw`Begin &echo @prandia: Lunch
&: 69/420 MP
&: -20 MP
@ HP: 35/70
@ HP: -30... water
@: ZP 5/6
@: ZP +1
&: 20 HP
gale, calor,gravitas HP: 3
&: ZP 5
&: ZP /7
&: /99 IP
& HP: /69
aelica IP: -
athetyz: - MP
linnet: HP -
&: Lv -
End`)
}
} catch (ex) {
console.log(ex)
}
}, [origState])
const startTime = Date.now()
const endTime = Date.now() + 2 * 60 * 1000
return <React.Fragment>
<Container fluid>
<Row>
<Col xs={{span: false}} xxl={{span: true}}>
<Stack direction="vertical">
<h1 className={"session-head"}>Session</h1>
<Row><Col xs={{span: true}} xxl={{span: false}}>
<Stack direction="horizontal">
<OverlayTrigger delay={{show: 750, hide: 0}} trigger={["hover", "click", "focus"]} overlay={
<Tooltip>
<div className={"appHelpHeader"}>
<span className={"appHelpName"}>Fabula Points spent</span>
<span className={"appHelpValue"}>{state?.session.usedSp.Fabula ?? 0}</span></div>
<div className={"appHelpDescription"}>
The party earns 1 EXP for each (#-players) Fabula Points spent during the session.
</div>
</Tooltip>
} placement={"right"}>
<div className={"totalFPSpent"}>{state?.session.usedSp.Fabula ?? 0}</div>
</OverlayTrigger>
<div className={"mx-auto totalSPSpent"}>Points Spent</div>
<OverlayTrigger delay={{show: 750, hide: 0}} trigger={["hover", "click", "focus"]} overlay={
<Tooltip>
<div className={"appHelpHeader"}>
<span className={"appHelpName"}>Ultima Points spent</span>
<span className={"appHelpValue"}>{state?.session.usedSp.Ultima ?? 0}</span></div>
<div className={"appHelpDescription"}>
The party earns 1 EXP for each Ultima Point spent during the session.
</div>
</Tooltip>
} placement={"left"}>
<div className={"totalUPSpent"}>{state?.session.usedSp.Ultima ?? 0}</div>
</OverlayTrigger>
</Stack>
</Col>
<Col xs={{span: true}} xxl={{span: false}}>
<TurnTimer title={"Timer"} startTime={startTime} endTime={endTime} />
</Col></Row>
</Stack>
</Col>
<Col xs={{span: true}} xxl={{span: true, order: "first"}}>
<Stack direction="vertical" className={"align-items-center"}>
<h1 className={"ally-head " + (state?.conflict?.activeSide === CharacterSide.Ally ? "active" : state?.conflict?.activeSide === CharacterSide.Enemy ? "inactive" : "")}>Allies</h1>
{state && state.characters.filter((character) => character.side === CharacterSide.Ally).map((character) =>
<CharacterStatus
key={character.id}
character={character}
statuses={state.statuses}
active={character.id === state.conflict?.activeCharacterId} />)}
</Stack>
</Col>
<Col xs={{span: true}} xxl={{span: true, order: "last"}}>
<Stack direction="vertical" className={"align-items-center"}>
<h1 className={"enemy-head " + (state?.conflict?.activeSide === CharacterSide.Enemy ? "active" : state?.conflict?.activeSide === CharacterSide.Ally ? "inactive" : "")}>Enemies</h1>
{state && state.characters.filter((character) => character.side === CharacterSide.Enemy).map((character) =>
<CharacterStatus
key={character.id}
character={character}
statuses={state.statuses}
active={character.id === state.conflict?.activeCharacterId} />)}
</Stack>
</Col>
</Row>
</Container>
</React.Fragment>;
}
export default App;