diff --git a/client/animations.test.js b/client/animations.test.js index 11f0a948..96a91b4e 100644 --- a/client/animations.test.js +++ b/client/animations.test.js @@ -1,6 +1,6 @@ require('./assets/styles/styles.css'); require('./assets/styles/styles.mobile.css'); -require('./assets/styles/instance.css'); +require('./assets/styles/instance.less'); require('./assets/styles/instance.mobile.css'); require('./assets/styles/game.css'); diff --git a/client/src/animations.socket.jsx b/client/src/animations.socket.jsx index fb0666b4..ce2e883e 100644 --- a/client/src/animations.socket.jsx +++ b/client/src/animations.socket.jsx @@ -28,12 +28,9 @@ function createSocket(store) { if (animating) return false; store.dispatch(actions.setAnimating(true)); - return eachSeries(newRes, (r, cb) => { if (['Disable', 'TargetKo'].includes(r.event[0])) return cb(); - store.dispatch(actions.setResolution(r)); - // convert server enum into anims keywords // todo make serersideonly const sequence = animations.getSequence(r); @@ -41,13 +38,15 @@ function createSocket(store) { const anims = animations.getObjects(r, sequence, game, account); const text = animations.getText(r, sequence); + store.dispatch(actions.setAnimFocus(animations.getFocusTargets(r))); + if (sequence.includes('START_SKILL')) store.dispatch(actions.setAnimSource(anims.animSource)); if (sequence.includes('END_SKILL')) store.dispatch(actions.setAnimTarget(anims.animTarget)); if (sequence.includes('POST_SKILL')) { // timeout to prevent text classes from being added too soon setTimeout( () => store.dispatch(actions.setAnimText(text)), - timeout - 1000, + timeout - TIMES.POST_SKILL_DURATION_MS ); } @@ -55,9 +54,11 @@ function createSocket(store) { store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); store.dispatch(actions.setAnimText(null)); - return setTimeout(cb, 50); + store.dispatch(actions.setAnimFocus([])); + // We currently need another small timeout so that everything can properly dismount / unload + // Otherwise 3 x Attack on same target will only render the first time + return setTimeout(cb, 200); }, timeout); - }, err => { if (err) return console.error(err); // clear animation state diff --git a/client/src/animations.test.jsx b/client/src/animations.test.jsx index 3704c4f6..2127ab35 100644 --- a/client/src/animations.test.jsx +++ b/client/src/animations.test.jsx @@ -69,48 +69,48 @@ document.fonts.load('16pt "Jura"').then(() => { }); const SKILLS = [ - 'AbsorbI', - 'AbsorptionI', - 'AmplifyI', + 'Absorb', + 'Absorption', + 'Amplify', 'Attack', - 'BanishI', - 'BashI', - 'BlastI', + 'Banish', + 'Bash', + 'Blast', 'Block', - 'BreakI', + 'Break', 'Buff', - 'ChaosI', - 'CounterAttackI', - 'CounterI', - 'CurseI', + 'Chaos', + 'CounterAttack', + 'Counter', + 'Curse', 'Debuff', - 'DecayI', - 'DecayTickI', - 'ElectrifyI', - 'ElectrocuteI', - 'ElectrocuteTickI', - 'HasteI', + 'Decay', + 'DecayTick', + 'Electrify', + 'Electrocute', + 'ElectrocuteTick', + 'Haste', 'HasteStrike', - 'HealI', + 'Heal', 'HybridBlast', - 'HybridI', - 'InterceptI', - 'InvertI', - 'LinkI', - 'PurgeI', - 'PurifyI', - 'RechargeI', - 'ReflectI', - 'RestrictI', - 'RuinI', - 'SilenceI', - 'SiphonI', - 'SiphonTickI', - 'SlayI', - 'SleepI', - 'StrikeI', + 'Hybrid', + 'Intercept', + 'Invert', + 'Link', + 'Purge', + 'Purify', + 'Recharge', + 'Reflect', + 'Restrict', + 'Ruin', + 'Silence', + 'Siphon', + 'SiphonTick', + 'Slay', + 'Sleep', + 'Strike', 'Stun', - 'SustainI', - 'TriageI', - 'TriageTickI', + 'Sustain', + 'Triage', + 'TriageTick', ]; diff --git a/client/src/components/animations.jsx b/client/src/components/animations.jsx index 1a4e3ee6..5e0cd1c9 100644 --- a/client/src/components/animations.jsx +++ b/client/src/components/animations.jsx @@ -3,6 +3,7 @@ const { Component } = require('preact'); const { connect } = require('preact-redux'); const Amplify = require('./anims/amplify'); +const Attack = require('./anims/attack'); const Absorb = require('./anims/absorb'); const Bash = require('./anims/bash'); const Blast = require('./anims/blast'); @@ -69,7 +70,7 @@ class ConstructAnimation extends Component { const chooseAnim = (skill) => { switch (skill) { // Attack base - case 'Attack': return ; + case 'Attack': return ; case 'Blast': return ; case 'Siphon': return ; case 'SiphonTick': return ; diff --git a/client/src/components/anims/attack.jsx b/client/src/components/anims/attack.jsx index e851a7f2..f49798ac 100644 --- a/client/src/components/anims/attack.jsx +++ b/client/src/components/anims/attack.jsx @@ -2,81 +2,57 @@ const preact = require('preact'); const { Component } = require('preact'); const anime = require('animejs').default; -const dagger = require('../svgs/dagger'); -const { TIMES } = require('../../constants'); - -const duration = TIMES.TARGET_DURATION_MS; +const { TIMES, COLOURS } = require('../../constants'); class Attack extends Component { constructor(props) { super(); this.props = props; + this.animations = []; } render() { return ( - {dagger(10, 250, 40, 150)} - {dagger(50, 250, 40, 150)} - {dagger(90, 250, 40, 150)} - {dagger(130, 250, 40, 150)} - {dagger(170, 250, 40, 150)} - {dagger(210, 250, 40, 150)} - {dagger(250, 250, 40, 150)} + viewBox="0 0 400 400"> + + + + + ); } componentDidMount() { - let y = 0; - const daggers = document.querySelectorAll('.attack-anim .dagger'); - anime.set(daggers, { - y: 250, - }); - y = -150; - if (!this.props.team) { - anime.set('.attack-anim', { - rotate: 180, - }); - } else { - anime.set('.attack-anim', { - rotate: 0, - }); - } - - // if (this.props.stage === 'END_SKILL') { - // anime.set(daggers, { - // y: 400, - // }); - // y = -150; - // if (!this.props.team) { - // anime.set('.attack-anim', { - // rotate: 0, - // }); - // } else { - // anime.set('.attack-anim', { - // rotate: 180, - // }); - // } - // } - - anime({ - targets: daggers, - delay: anime.stagger(250, { - start: 250, - grid: [1, 7], - from: 'center', - easing: 'linear', - }), - y, - duration, - }); + this.animations.push(anime({ + targets: ['#attack rect'], + easing: 'easeOutExpo', + y: [400, 200], + height: [100, 10, 0], + width: [12, 5, 0], + delay: () => anime.random(TIMES.TARGET_DELAY_MS, TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS / 2), + duration: TIMES.TARGET_DURATION_MS, + })); } + + // this is necessary because + // skipping / timing / unmounting race conditions + // can cause the animations to cut short, this will ensure the values are reset + // because preact will recycle all these components + componentWillUnmount() { + for (let i = this.animations.length - 1; i >= 0; i--) { + this.animations[i].reset(); + } + } + } module.exports = Attack;