mnml/client/src/components/targeting.arrows.jsx
2019-06-30 16:43:43 +10:00

115 lines
3.8 KiB
JavaScript

const preact = require('preact');
const { Component } = require('preact');
const { connect } = require('preact-redux');
const throttle = require('lodash/throttle');
const addState = connect(
({ game, account, resolution }) => ({ game, account, resolution })
);
class TargetSvg extends Component {
constructor() {
super();
this.state = { width: 3000, height: 1000 };
this.onResize = throttle(() => {
const svg = document.getElementById('targeting');
const { width, height } = svg.getBoundingClientRect();
this.setState({ width, height });
}, 500);
}
render(props, state) {
const { game, account, resolution } = props;
const { width, height } = state;
const playerTeam = game.players.find(t => t.id === account.id);
const otherTeam = game.players.find(t => t.id !== account.id);
const playerTeamIds = playerTeam.constructs.map(c => c.id);
const outgoing = game.stack.filter(stack => playerTeamIds.includes(stack.source_construct_id));
function getPath(cast) {
const source = playerTeam.constructs.findIndex(c => c.id === cast.source_construct_id);
const defensive = playerTeamIds.includes(cast.target_construct_id);
const target = defensive
? playerTeam.constructs.findIndex(c => c.id === cast.target_construct_id)
: otherTeam.constructs.findIndex(c => c.id === cast.target_construct_id);
const pathOffset = [
[0, -1, -2],
[1, 0, -1],
[2, 1, 0],
][source][target];
const sourceY = height;
const sourceX = (source * width / 3) + width / 6;
const targetX = (target * width / 3) + width / 6
+ (defensive ? width / 64 : 0)
+ (pathOffset * width / 32);
const targetY = defensive ? height : 0;
const bendStart = height * (0.7 - 0.1 * source);
const bendEnd = height * 0.20;
if (defensive) {
const path = `
M${sourceX},${sourceY}
L${sourceX},${bendStart}
L${targetX},${bendStart}
L${targetX},${targetY}
L${targetX - (width * 0.005)},${height * 0.875}
M${targetX},${targetY}
L${targetX + (width * 0.005)},${height * 0.875}
`;
return <path d={path} />;
}
const path = `
M${sourceX},${sourceY}
L${sourceX},${bendStart}
L${targetX},${bendEnd}
L${targetX},${targetY}
L${targetX - (width * 0.005)},${height * 0.125}
M${targetX},${targetY}
L${targetX + (width * 0.005)},${height * 0.125}
`;
return <path d={path} />;
}
const arrows = resolution
? null
: outgoing.map(getPath);
let skill = '';
if (resolution) {
if (resolution.event[1]) ([, { skill }] = resolution.event);
}
const resolutionText = resolution
? <text x={`${(width / 2) - 50}`} y={`${(height / 2) + 16}`} font-family="Jura" font-size="2em"> {skill} </text>
: null;
return (
<svg id="targeting" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" class="targeting-arrows">
{arrows}
{resolutionText}
</svg>
);
}
componentDidMount() {
window.addEventListener('resize', this.onResize);
this.onResize();
setTimeout(this.onResize, 50);
}
componentWillUnmount() {
window.removeEventListener('resize', this.onResize);
}
}
module.exports = addState(TargetSvg);