182 lines
6.1 KiB
JavaScript
Executable File
182 lines
6.1 KiB
JavaScript
Executable File
const preact = require('preact');
|
|
const key = require('keymaster');
|
|
|
|
const SKILL_HOT_KEYS = ['Q', 'W', 'E', 'R'];
|
|
|
|
function GamePanel(props) {
|
|
const {
|
|
game,
|
|
activeSkill,
|
|
activeIncoming,
|
|
setActiveSkill,
|
|
setActiveIncoming,
|
|
selectSkillTarget,
|
|
selectIncomingTarget,
|
|
account,
|
|
} = props;
|
|
|
|
if (!game) return <div>...</div>;
|
|
|
|
const otherTeams = game.teams.filter(t => t.id !== account.id);
|
|
|
|
const playerTeam = game.teams.find(t => t.id === account.id);
|
|
|
|
const incoming = game.stack.filter(s => s.target_team_id === playerTeam.id).map((inc) => {
|
|
key.unbind('1');
|
|
key('1', () => setActiveIncoming(inc.id));
|
|
return (
|
|
<div className="tile is-child" key={inc.id}>
|
|
<div>{JSON.stringify(inc)}</div>
|
|
<button
|
|
className="button is-dark is-fullwidth"
|
|
type="submit"
|
|
onClick={() => setActiveIncoming(inc.id)}>
|
|
(1) Block skill: {inc.skill}
|
|
</button>
|
|
</div>
|
|
);
|
|
});
|
|
|
|
function PlayerCrypCard(cryp) {
|
|
const skills = cryp.skills.map((skill, i) => {
|
|
const hotkey = SKILL_HOT_KEYS[i];
|
|
key.unbind(hotkey);
|
|
key(hotkey, () => setActiveSkill(cryp.id, skill));
|
|
|
|
return (
|
|
<button
|
|
key={i}
|
|
className="button is-dark"
|
|
type="submit"
|
|
onClick={() => setActiveSkill(cryp.id, skill)}
|
|
>
|
|
({hotkey}) {skill.skill} {skill.cd && `(${skill.cd}T)`}
|
|
</button>
|
|
);
|
|
});
|
|
|
|
const statuses = cryp.statuses.map((status, i) => (
|
|
<div key={i}>{status} for {status.turns}T</div>
|
|
));
|
|
|
|
return (
|
|
<div
|
|
key={cryp.id}
|
|
style={ activeIncoming ? { cursor: 'pointer' } : {}}
|
|
onClick={() => selectIncomingTarget(cryp.id)}
|
|
className="tile is-vertical">
|
|
<div className="tile is-child">
|
|
<div className="columns" >
|
|
<div className="column is-10">
|
|
<p className="title">{cryp.name}</p>
|
|
<p className="subtitle">Level {cryp.lvl}</p>
|
|
</div>
|
|
<div className="column">
|
|
<figure className="image">
|
|
<svg width="40" height="40" data-jdenticon-value={cryp.name} />
|
|
</figure>
|
|
</div>
|
|
|
|
</div>
|
|
<div className="has-text-centered">{cryp.hp.value} / {cryp.stam.value} HP </div>
|
|
<progress className="progress is-dark" value={cryp.hp.value} max={cryp.stam.value}></progress>
|
|
|
|
<div className="has-text-centered">{cryp.xp} / {Math.pow(2, cryp.lvl + 1)} XP </div>
|
|
<progress className="progress is-dark" value={cryp.xp} max={Math.pow(2, cryp.lvl + 1)}></progress>
|
|
</div>
|
|
{statuses}
|
|
{skills}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function PlayerTeam(team) {
|
|
const cryps = team.cryps.map(c => PlayerCrypCard(c, setActiveSkill));
|
|
|
|
return (
|
|
<div className="tile">
|
|
{cryps}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function OpponentCrypCard(cryp) {
|
|
const statuses = cryp.statuses.map((status, i) => (
|
|
<div key={i}>{status.status} for {status.turns}T</div>
|
|
));
|
|
|
|
return (
|
|
<div key={cryp.id} className="tile is-vertical">
|
|
<div className="tile is-child">
|
|
<div className="columns" >
|
|
<div className="column is-10">
|
|
<p className="title">{cryp.name}</p>
|
|
<p className="subtitle">Level {cryp.lvl}</p>
|
|
</div>
|
|
<div className="column">
|
|
<figure className="image">
|
|
<svg width="40" height="40" data-jdenticon-value={cryp.name} />
|
|
</figure>
|
|
</div>
|
|
|
|
</div>
|
|
<div className="has-text-centered">{cryp.hp.value} / {cryp.stam.value} HP </div>
|
|
<progress className="progress is-dark" value={cryp.hp.value} max={cryp.stam.value}></progress>
|
|
|
|
<div className="has-text-centered">{cryp.xp} / {Math.pow(2, cryp.lvl + 1)} XP </div>
|
|
<progress className="progress is-dark" value={cryp.xp} max={Math.pow(2, cryp.lvl + 1)}></progress>
|
|
|
|
</div>
|
|
{statuses}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function OpponentTeam(team) {
|
|
const cryps = team.cryps.map(OpponentCrypCard);
|
|
return (
|
|
<div
|
|
className="tile"
|
|
style={activeSkill ? { cursor: 'pointer' } : {}}
|
|
onClick={() => selectSkillTarget(team.id)} >
|
|
{cryps}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// style={{ "min-height": "100%" }}
|
|
function phaseText(phase) {
|
|
switch (phase) {
|
|
case 'Skill':
|
|
return 'Choose abilities';
|
|
case 'Target':
|
|
return 'Block abilities';
|
|
case 'Finish':
|
|
return 'Game over';
|
|
}
|
|
}
|
|
return (
|
|
<section className="columns">
|
|
<div className="column is-2 title is-1">
|
|
{phaseText(game.phase)}
|
|
</div>
|
|
<div className="column is-4">
|
|
{PlayerTeam(playerTeam, setActiveSkill)}
|
|
</div>
|
|
<div className="column is-4">
|
|
<div>
|
|
{otherTeams.map(OpponentTeam)}
|
|
</div>
|
|
<div>
|
|
{incoming}
|
|
</div>
|
|
</div>
|
|
<div className="column is-2">
|
|
<div className="title is-4">log</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
module.exports = GamePanel;
|