mnml/client/src/components/game.component.jsx
2019-05-06 20:21:28 +10:00

187 lines
5.4 KiB
JavaScript

const preact = require('preact');
const range = require('lodash/range');
const { STATS, eventClasses, getCombatText, crypAvatar } = require('../utils');
const GameCryp = require('./game.cryp');
const TargetingArrows = require('./targeting.arrows');
function GamePanel(props) {
const {
game,
resolution,
activeSkill,
setActiveSkill,
setActiveCryp,
selectSkillTarget,
sendInstanceState,
sendGameReady,
account,
showLog,
toggleLog,
quit,
} = props;
if (!game) return <div>...</div>;
console.log(showLog);
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-btn instance-btn instance-ui-btn left"
onClick={() => toggleLog(!showLog)}>
Game
</button>
<div className="spacer">
<div>&nbsp;</div>
</div>
</div>
<div className="logs">
{logs}
</div>
</main>
);
}
function backClick() {
if (game.phase === 'Finish') sendInstanceState(game.instance);
return quit();
}
const header = (
<div className="instance-hdr">
<button
className="game-btn instance-btn instance-ui-btn left"
onClick={backClick}>
Back
</button>
<button
className="game-btn instance-btn instance-ui-btn left"
onClick={() => toggleLog(!showLog)}>
Log
</button>
<div className="spacer">
<div>&nbsp;</div>
</div>
<button
className="game-btn instance-btn instance-ui-btn right"
onClick={() => sendGameReady()}>
Ready
</button>
</div>
);
function findCryp(id) {
const team = game.players.find(t => t.cryps.find(c => c.id === id));
if (team) return team.cryps.find(c => c.id === id);
return null;
}
const otherTeams = game.players.filter(t => t.id !== account.id);
const playerTeam = game.players.find(t => t.id === account.id);
const zero = Date.parse(game.phase_end) - (1000 * 60);
const now = Date.now();
const end = Date.parse(game.phase_end);
const timerPct = ((now - zero) / (end - zero) * 100);
const displayPct = resolution
? 0
: Math.min(timerPct, 100);
const displayColour = playerTeam.ready
? 'forestgreen'
: timerPct > 80
? 'red'
: 'whitesmoke';
const timerStyles = {
width: `${displayPct}%`,
background: displayColour,
};
const timer = (
<div className="timer-container">
<div className="timer" style={timerStyles} >&nbsp;</div>
</div>
);
function PlayerTeam(team) {
const cryps = team.cryps.map((c, i) => <GameCryp key={c.id} cryp={c} />);
return (
<div className="team-player cryp-list">
{cryps}
</div>
);
}
function OpponentCryp(cryp, i) {
const ko = cryp.green_life.value === 0 ? 'ko' : '';
const classes = eventClasses(resolution, cryp);
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>
));
const combatText = getCombatText(cryp, resolution);
const combatTextEl = combatText
? <div className="combat-text">{combatText}</div>
: null;
const effects = cryp.effects.length
? cryp.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>)
: <div>&nbsp;</div>;
return (
<div
key={i}
className={`game-cryp ${ko} ${classes}`}
style={ activeSkill ? { cursor: 'pointer' } : {}}
onClick={() => selectSkillTarget(cryp.id)} >
<figure
className="img"
onClick={() => selectSkillTarget(cryp.id)} >
{crypAvatar(cryp.name)}
{combatTextEl}
</figure>
<div className="effects">
{effects}
</div>
<div className="stats">
{stats}
</div>
</div>
);
}
function OpponentTeam(team) {
const cryps = team.cryps.map(OpponentCryp);
return (
<div className="team-opponent cryp-list">
{cryps}
</div>
);
}
const gameClasses = `game ${resolution ? 'resolving': ''}`;
return (
<main className={gameClasses} onClick={() => setActiveCryp(null)} >
{header}
{timer}
{PlayerTeam(playerTeam, setActiveSkill)}
<TargetingArrows />
{otherTeams.map(OpponentTeam)}
</main>
);
}
module.exports = GamePanel;