250 lines
6.9 KiB
JavaScript
250 lines
6.9 KiB
JavaScript
const preact = require('preact');
|
|
const range = require('lodash/range');
|
|
|
|
const molecule = require('./molecule');
|
|
|
|
const { STATS } = require('../utils');
|
|
|
|
// const SKILL_HOT_KEYS = ['Q', 'W', 'E', 'R'];
|
|
|
|
function GamePanel(props) {
|
|
const {
|
|
game,
|
|
activeSkill,
|
|
setActiveSkill,
|
|
setActiveCryp,
|
|
selectSkillTarget,
|
|
activeCryp,
|
|
account,
|
|
showLog,
|
|
toggleLog,
|
|
quit,
|
|
} = props;
|
|
|
|
if (!game) return <div>...</div>;
|
|
if (showLog) {
|
|
const logs = game.log.map((l, i) => (<div key={i}>{l}</div>)).reverse();
|
|
return (
|
|
<main className="game">
|
|
<div className="instance-hdr">
|
|
<button
|
|
className="game-back-btn instance-btn instance-ui-btn left"
|
|
onClick={() => toggleLog(!showLog)}>
|
|
Game
|
|
</button>
|
|
<div className="spacer">
|
|
<div> </div>
|
|
</div>
|
|
</div>
|
|
<div className="logs">
|
|
{logs}
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
const header = (
|
|
<div className="instance-hdr">
|
|
<button
|
|
className="game-back-btn instance-btn instance-ui-btn left"
|
|
onClick={quit}>
|
|
Back
|
|
</button>
|
|
<div className="spacer">
|
|
<div> </div>
|
|
</div>
|
|
<button
|
|
className="game-back-btn instance-btn instance-ui-btn left"
|
|
onClick={() => toggleLog(!showLog)}>
|
|
Log
|
|
</button>
|
|
</div>
|
|
);
|
|
|
|
function findCryp(id) {
|
|
const team = game.teams.find(t => t.cryps.find(c => c.id === id));
|
|
if (team) return team.cryps.find(c => c.id === id);
|
|
return null;
|
|
}
|
|
|
|
const otherTeams = game.teams.filter(t => t.id !== account.id);
|
|
|
|
const playerTeam = game.teams.find(t => t.id === account.id);
|
|
|
|
function stackElement(c, i) {
|
|
let skills = game.stack.filter(s => s.source_cryp_id === c.id).map((s, j) => {
|
|
const target = findCryp(s.target_cryp_id);
|
|
return (
|
|
<div key={j}>{s.skill} -> {target.name}</div>
|
|
);
|
|
});
|
|
|
|
if (!skills.length) skills = (<div> </div>);
|
|
|
|
return (
|
|
<div
|
|
key={i}
|
|
className="stack-line">
|
|
{skills}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function Skill(cryp, i, mobile) {
|
|
const ko = cryp.green_life.value === 0 ? 'ko' : '';
|
|
|
|
const s = cryp.skills[i];
|
|
if (!s) {
|
|
return (
|
|
<button
|
|
disabled='true'
|
|
key={i}
|
|
className='cryp-skill-btn disabled'>
|
|
<span> </span>
|
|
</button>
|
|
);
|
|
}
|
|
|
|
const side = mobile
|
|
? 'top'
|
|
: 'right';
|
|
|
|
const cdText = cryp.skills[i].cd > 0
|
|
? `- ${s.cd}`
|
|
: '';
|
|
|
|
const highlight = activeSkill
|
|
? activeSkill.crypId === cryp.id && activeSkill.skill === s
|
|
: false;
|
|
|
|
function onClick(e) {
|
|
e.stopPropagation();
|
|
return setActiveSkill(cryp.id, s.skill);
|
|
}
|
|
|
|
return (
|
|
<button
|
|
key={i}
|
|
disabled={!!cdText || ko}
|
|
className={`cryp-skill-btn ${side} ${highlight ? 'active' : ''}`}
|
|
type="submit"
|
|
onClick={onClick}>
|
|
{s.skill} {cdText}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
function Cryp(cryp) {
|
|
const ko = cryp.green_life.value === 0 ? 'ko' : '';
|
|
|
|
const skills = range(0, 3).map(i => Skill(cryp, i));
|
|
|
|
const stats = [STATS.greenLife, STATS.redLife, STATS.blueLife].map((s, j) => (
|
|
<figure key={j} alt={s.stat}>
|
|
{s.svg(`stat-icon ${s.colour}`)}
|
|
<figcaption>{cryp[s.stat].value} / {cryp[s.stat].max}</figcaption>
|
|
</figure>
|
|
));
|
|
|
|
|
|
function onClick(e) {
|
|
e.stopPropagation();
|
|
return setActiveCryp(cryp);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
key={cryp.id}
|
|
style={ activeSkill ? { cursor: 'pointer' } : {}}
|
|
onClick={onClick}
|
|
className={`cryp-box ${ko}`} >
|
|
<div className="cryp-box-top">
|
|
<figure
|
|
className="img"
|
|
onClick={() => selectSkillTarget(cryp.id)} >
|
|
{molecule}
|
|
<figcaption>{cryp.name}</figcaption>
|
|
</figure>
|
|
<div className="skills">
|
|
{skills}
|
|
</div>
|
|
</div>
|
|
<div className="stats">
|
|
{stats}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function PlayerTeam(team) {
|
|
const cryps = team.cryps.map(c => Cryp(c));
|
|
|
|
return (
|
|
<div className="team-player cryp-list">
|
|
{cryps}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function OpponentCryp(cryp, i) {
|
|
const stats = [STATS.greenLife, STATS.redLife, STATS.blueLife].map((s, j) => (
|
|
<figure key={j} alt={s.stat}>
|
|
{s.svg(`stat-icon ${s.colour}`)}
|
|
<figcaption>{cryp[s.stat].value} / {cryp[s.stat].max}</figcaption>
|
|
</figure>
|
|
));
|
|
|
|
return (
|
|
<div
|
|
key={i}
|
|
className="cryp-box"
|
|
style={ activeSkill ? { cursor: 'pointer' } : {}}
|
|
onClick={() => selectSkillTarget(cryp.id)} >
|
|
<div className="cryp-box-top">
|
|
<figure className="img">
|
|
{molecule}
|
|
<figcaption>{cryp.name}</figcaption>
|
|
</figure>
|
|
</div>
|
|
<div className="stats">
|
|
{stats}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
|
|
function OpponentTeam(team) {
|
|
const cryps = team.cryps.map(OpponentCryp);
|
|
return (
|
|
<div className="cryp-list" >
|
|
{cryps}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const selectedSkills = playerTeam.cryps.map((c, i) => stackElement(c, i));
|
|
|
|
const mobileSkills = activeCryp
|
|
? range(0, 3).map(i => Skill(activeCryp, i, true))
|
|
: (<div/>);
|
|
|
|
return (
|
|
<main className="game" onClick={() => setActiveCryp(null)} >
|
|
{header}
|
|
{PlayerTeam(playerTeam, setActiveSkill)}
|
|
<div className="mobile-skills">
|
|
{mobileSkills}
|
|
</div>
|
|
<div className="selected-skills">
|
|
{selectedSkills}
|
|
</div>
|
|
<div className="team-opponent cryp-list">
|
|
{otherTeams.map(OpponentTeam)}
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
module.exports = GamePanel;
|