123 lines
3.6 KiB
JavaScript
123 lines
3.6 KiB
JavaScript
const { connect } = require('react-redux');
|
|
const preact = require('preact');
|
|
const range = require('lodash/range');
|
|
|
|
const actions = require('../actions');
|
|
const { STATS, eventClasses, getCombatText, constructAvatar } = require('../utils');
|
|
const { animationDivs } = require('../animations');
|
|
const shapes = require('./shapes');
|
|
|
|
const SkillBtn = require('./skill.btn');
|
|
|
|
const addState = connect(
|
|
function receiveState(state) {
|
|
const {
|
|
ws,
|
|
game,
|
|
account,
|
|
resolution,
|
|
activeSkill,
|
|
} = state;
|
|
|
|
function selectSkillTarget(targetConstructId) {
|
|
if (activeSkill) {
|
|
return ws.sendGameSkill(game.id, activeSkill.constructId, targetConstructId, activeSkill.skill);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// intercept self casting skills
|
|
if (activeSkill && activeSkill.skill.self_targeting) {
|
|
ws.sendGameSkill(game.id, activeSkill.constructId, null, activeSkill.skill.skill);
|
|
}
|
|
|
|
return {
|
|
game,
|
|
account,
|
|
resolution,
|
|
activeSkill,
|
|
selectSkillTarget,
|
|
};
|
|
},
|
|
);
|
|
|
|
function GameConstruct(props) {
|
|
const {
|
|
game,
|
|
account,
|
|
construct,
|
|
resolution,
|
|
activeSkill,
|
|
setActiveConstruct,
|
|
selectSkillTarget,
|
|
} = props;
|
|
|
|
const ko = construct.green_life.value === 0 ? 'ko' : '';
|
|
const classes = eventClasses(resolution, construct);
|
|
|
|
const skills = range(0, 3)
|
|
.map(i => <SkillBtn key={i} construct={construct} i={i} />);
|
|
|
|
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
|
|
<div key={j} alt={STATS[s].stat}>
|
|
{shapes[s]()}
|
|
<div className="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div>
|
|
<div className="value" >{construct[STATS[s].stat].value}</div>
|
|
</div>
|
|
));
|
|
|
|
const [combatText, combatClass] = getCombatText(construct, resolution);
|
|
const combatTextClass = `combat-text ${combatClass}`;
|
|
const combatTextEl = combatText
|
|
? <div className={combatTextClass}>{combatText}</div>
|
|
: null;
|
|
|
|
const effects = construct.effects.length
|
|
? construct.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>)
|
|
: <div> </div>;
|
|
|
|
const playerTeam = game.players.find(t => t.id === account.id);
|
|
const playerTeamIds = playerTeam.constructs.map(c => c.id);
|
|
|
|
const targeting = game.stack
|
|
.filter(s => playerTeamIds.includes(s.source_construct_id) && s.target_construct_id === construct.id)
|
|
.map((s, i) => <h3 key={i}>{`< ${s.skill}`}</h3>);
|
|
|
|
const anim = (
|
|
<div className="anim-container">
|
|
{animationDivs(combatClass)}
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<div
|
|
style={ activeSkill ? { cursor: 'pointer' } : {}}
|
|
className={`game-construct ${ko} ${classes}`} >
|
|
<h3 className="name">
|
|
{construct.name}
|
|
</h3>
|
|
<div className="skills">
|
|
{skills}
|
|
</div>
|
|
<div className="targeting">
|
|
{targeting}
|
|
</div>
|
|
<figure
|
|
className="img"
|
|
onClick={() => selectSkillTarget(construct.id)} >
|
|
{constructAvatar(construct.name, construct.id)}
|
|
{combatTextEl}
|
|
{anim}
|
|
</figure>
|
|
<div className="effects">
|
|
{effects}
|
|
</div>
|
|
<div className="stats">
|
|
{stats}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
module.exports = addState(GameConstruct);
|