mnml/client/src/components/construct.jsx
2019-07-19 20:46:38 +10:00

176 lines
4.9 KiB
JavaScript

const preact = require('preact');
const { Component } = require('preact');
const { connect } = require('preact-redux');
// const { match } = require('./../utils');
const banish = require('./anims/banish');
const idleAnimation = require('./anims/idle');
const invert = require('./anims/invert');
const sourceCast = require('./anims/source.cast');
const addState = connect(
function receiveState(state) {
const { animSource, animTarget } = state;
return { animSource, animTarget };
}
);
class ConstructAvatar extends Component {
constructor(props) {
super();
// The animation ids are a check to ensure that animations are not repeated
// When a new construct animation is communicated with state it will have a corresponding Id
// which is a count of how many resoluttions have passed
this.animations = [];
this.resetAnimations = this.resetAnimations.bind(this);
}
render() {
return (
<div
class="avatar"
id={this.props.construct.id}
style={{ 'background-image': `url(/imgs/${this.props.construct.img}.svg)` }}
/>
);
}
componentDidMount() {
const { animSource, animTarget, construct } = this.props;
// back to idle
if (!animTarget && !animSource) {
if (!this.idle) {
this.idle = idleAnimation(this.props.construct.id);
this.animations.push(this.idle);
}
return this.idle.play();
}
const isSource = animSource && animSource.constructId === construct.id;
const selectAnim = () => {
if (isSource) {
console.warn(construct.name, animSource);
return sourceCast(animSource.constructId, animSource.direction);
}
switch (animTarget.skill) {
case 'banish': return banish(construct.id);
case 'invert': return invert(construct.id);
default: return null;
}
};
const anim = selectAnim();
if (!anim) return false;
this.idle.pause();
this.animations.push(anim);
return true;
}
componentDidUpdate(prevProps) {
const { animSource, animTarget, construct } = this.props;
// back to idle
if (!animTarget && !animSource) {
return this.idle.play();
}
const isSource = animSource && animSource.constructId === construct.id;
const selectAnim = () => {
if (isSource) {
return sourceCast(animSource.constructId, animSource.direction);
}
switch (animTarget.skill) {
case 'Banish': return banish(construct.id);
case 'Invert': return invert(construct.id);
default: return null;
}
};
const anim = selectAnim();
if (!anim) return false;
this.idle.pause();
this.animations.push(anim);
return true;
}
resetAnimations() {
for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset();
}
}
componentWillUnmount() {
this.resetAnimations();
}
shouldComponentUpdate({ animSource, animTarget, construct }) {
if (construct !== this.props.construct) {
return true;
}
if (animSource === this.props.animSource && animTarget === this.props.animTarget) {
// console.warn(construct.name, 'thinks its same props')
return false;
}
// something has changed
// what do?
// this is the source
if (animSource && animSource.constructId === construct.id) {
// console.warn(construct.name, 'should update')
return true;
}
// this is the target
if (animTarget && animTarget.constructId === construct.id) {
// console.warn(construct.name, 'should update')
return true;
}
// we were previously doing src anim
const prevSrc = this.props.animSource && this.props.animSource.constructId === construct.id;
if (prevSrc && !animSource) return true;
const prevTarget = this.props.animTarget && this.props.animTarget.constructId === construct.id;
if (prevTarget && !animTarget) return true;
// console.warn(construct.name, 'not updating');
return false;
}
}
const addStateText = connect(
function receiveState(state) {
const { animText } = state;
return { animText };
}
);
function constructText(props) {
const { construct, animText } = props;
if (!construct || !animText) return false;
const text = animText.constructId === construct.id
? animText.text
: null;
return <div class={'combat-text'}>{text}</div>;
}
module.exports = {
ConstructAvatar: addState(ConstructAvatar),
ConstructText: addStateText(constructText),
};