diff --git a/client/src/animations.socket.jsx b/client/src/animations.socket.jsx
index 424114b1..881f1ea6 100644
--- a/client/src/animations.socket.jsx
+++ b/client/src/animations.socket.jsx
@@ -25,14 +25,18 @@ function createSocket(store) {
function onDevResolutions(newRes) {
const { game: currentGame } = store.getState();
+ let id = 0;
return eachSeries(newRes, (r, cb) => {
if (['Disable', 'TargetKo'].includes(r.event[0])) return cb();
// Create sub events for combat animations
const sequence = getCombatSequence(r);
+ id += 1;
+
return eachSeries(sequence, (stages, sCb) => {
const stagedR = Object.create(r);
stagedR.sequence = sequence;
stagedR.stages = stages;
+ stagedR.id = id;
let timeout = 0;
if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) {
@@ -45,11 +49,13 @@ function createSocket(store) {
return setTimeout(sCb, timeout);
}, err => {
if (err) console.error(err);
+ store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false }));
// Finished this resolution
return cb();
});
}, err => {
if (err) return console.error(err);
+ store.dispatch(actions.setAvatarAnimation({ id: -1, source: false, target: false }));
store.dispatch(actions.setResolution(null));
// stop skipping resolutions
store.dispatch(actions.setSkip(false));
diff --git a/client/src/components/animations.jsx b/client/src/components/animations.jsx
index 564070fc..a290c9eb 100644
--- a/client/src/components/animations.jsx
+++ b/client/src/components/animations.jsx
@@ -73,13 +73,20 @@ function animations(props) {
const sourceIsPlayer = playerTeamIds.includes(construct.id);
const targetIsPlayer = playerTeamIds.includes(resolution.target.id);
- if (resolution.source.id === construct.id && resolution.stages.includes('START_SKILL')) {
+ const skipSource = (resolution.source.id === resolution.target.id
+ && ['Invert', 'Banish'].includes(removeTier(event.skill)));
+
+ if (!skipSource && resolution.source.id === construct.id && resolution.stages.includes('START_SKILL')) {
const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer);
- const y = sameTeam
- ? 0
- : targetIsPlayer
- ? 1
- : -1;
+
+ let y = 0;
+ if (!sameTeam) y = targetIsPlayer ? 1 : -1;
+
+ // const y = sameTeam
+ // ? 0
+ // : targetIsPlayer
+ // ? 1
+ // : -1;
const i = sourceIsPlayer
? playerTeamIds.findIndex(c => c === construct.id)
@@ -90,8 +97,14 @@ function animations(props) {
: otherTeamIds.findIndex(c => c === resolution.target.id);
const x = j - i;
- if (avatarAnimation.id !== resolution.id) {
- setAvatarAnimation({ id: resolution.id, animTargetId: construct.id, x, y });
+ if (!avatarAnimation.source) {
+ setAvatarAnimation({
+ source: true,
+ target: avatarAnimation.target,
+ animTargetId: construct.id,
+ type: 'sourceCast',
+ params: { x, y },
+ });
}
}
const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds;
@@ -100,7 +113,6 @@ function animations(props) {
// target animation
const anim = text => {
- console.log(text);
if (!text || !resolution.sequence[0].includes('END_SKILL')) return false;
const skill = removeTier(text);
@@ -130,14 +142,34 @@ function animations(props) {
case 'Curse': return ;
case 'Decay': return ;
case 'DecayTick': return ;
- case 'Invert': return ;
+ case 'Invert': {
+ if (!avatarAnimation.target) {
+ setAvatarAnimation({
+ source: avatarAnimation.source,
+ target: true,
+ id: resolution.id,
+ animTargetId: construct.id,
+ type: 'invert',
+ });
+ } break;
+ }
case 'Purge': return ;
case 'Silence': return ;
case 'Restrict': return ;
// Stun Base
case 'Stun': return ;
- case 'Banish': return ;
+ case 'Banish': {
+ if (!avatarAnimation.target) {
+ setAvatarAnimation({
+ source: avatarAnimation.source,
+ target: true,
+ id: resolution.id,
+ animTargetId: construct.id,
+ type: 'banish',
+ });
+ } break;
+ }
case 'Bash': return ;
case 'Absorb': return ;
case 'Sleep': return ;
diff --git a/client/src/components/anims/banish.jsx b/client/src/components/anims/banish.jsx
index 081b5537..62d3096a 100644
--- a/client/src/components/anims/banish.jsx
+++ b/client/src/components/anims/banish.jsx
@@ -1,42 +1,17 @@
-const preact = require('preact');
-const { Component } = require('preact');
-
const anime = require('animejs').default;
+
const { TIMES } = require('../../constants');
-class Banish extends Component {
- constructor(props) {
- super();
- this.id = props.id;
- this.animations = [];
- }
-
- render() {
- // Need this so unmount triggers
- return ;
- }
-
- componentDidMount() {
- this.animations.push(anime({
- targets: [document.getElementById(this.id)],
- scaleY: 0,
- fill: '#fff',
- easing: 'easeOutElastic',
- delay: TIMES.TARGET_DELAY_MS,
- duration: TIMES.TARGET_DURATION_MS * 0.5,
- direction: 'alternate',
- }));
- }
-
- // 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();
- }
- }
+function Banish(id) {
+ return anime({
+ targets: [document.getElementById(id)],
+ scaleY: 0,
+ fill: '#fff',
+ easing: 'easeOutElastic',
+ delay: TIMES.TARGET_DELAY_MS,
+ duration: TIMES.TARGET_DURATION_MS * 0.45,
+ direction: 'alternate',
+ });
}
module.exports = Banish;
diff --git a/client/src/components/anims/idle.jsx b/client/src/components/anims/idle.jsx
new file mode 100644
index 00000000..0972b4ac
--- /dev/null
+++ b/client/src/components/anims/idle.jsx
@@ -0,0 +1,18 @@
+const anime = require('animejs').default;
+
+function idle(id) {
+ const duration = anime.random(2000, 18000);
+ const target = document.getElementById(id);
+ return anime({
+ targets: target,
+ translateX: () => anime.random(-20, 20),
+ translateY: () => anime.random(0, -40),
+ rotate: () => anime.random(-15, 15),
+ duration,
+ direction: 'alternate',
+ easing: 'linear',
+ loop: true,
+ });
+}
+
+module.exports = idle;
diff --git a/client/src/components/anims/invert.jsx b/client/src/components/anims/invert.jsx
index 34d383cc..57a787d8 100644
--- a/client/src/components/anims/invert.jsx
+++ b/client/src/components/anims/invert.jsx
@@ -1,41 +1,16 @@
-const preact = require('preact');
-const { Component } = require('preact');
-
const anime = require('animejs').default;
+
const { TIMES } = require('../../constants');
-class Invert extends Component {
- constructor(props) {
- super();
- this.id = props.id;
- this.animations = [];
- }
-
- render() {
- // Need this so unmount triggers
- return ;
- }
-
- componentDidMount() {
- this.animations.push(anime({
- targets: [document.getElementById(this.id)],
- rotate: 180,
- delay: TIMES.TARGET_DELAY_MS,
- duration: TIMES.TARGET_DURATION_MS * 0.45,
- easing: 'easeInOutElastic',
- direction: 'alternate',
- }));
- }
-
- // 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();
- }
- }
+function Invert(id) {
+ return anime({
+ targets: [document.getElementById(id)],
+ rotate: 180,
+ delay: TIMES.TARGET_DELAY_MS,
+ duration: TIMES.TARGET_DURATION_MS * 0.45,
+ easing: 'easeInOutElastic',
+ direction: 'alternate',
+ });
}
module.exports = Invert;
diff --git a/client/src/components/anims/source.cast.jsx b/client/src/components/anims/source.cast.jsx
new file mode 100644
index 00000000..c6690ca9
--- /dev/null
+++ b/client/src/components/anims/source.cast.jsx
@@ -0,0 +1,17 @@
+const anime = require('animejs').default;
+
+const { TIMES } = require('../../constants');
+
+function sourceCast(id, params) {
+ const { x, y } = params;
+ return anime({
+ targets: [document.getElementById(id)],
+ translateX: x * 200,
+ translateY: y * 200,
+ easing: 'easeInOutElastic',
+ direction: 'alternate',
+ duration: TIMES.SOURCE_DURATION_MS,
+ });
+}
+
+module.exports = sourceCast;
diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx
index b70f0161..3419ca5b 100644
--- a/client/src/components/construct.jsx
+++ b/client/src/components/construct.jsx
@@ -3,7 +3,11 @@ const { Component } = require('preact');
const { connect } = require('preact-redux');
const anime = require('animejs').default;
-const { TIMES } = require('../constants');
+const banish = require('./anims/banish');
+const idleAnimation = require('./anims/idle');
+const invert = require('./anims/invert');
+const sourceCast = require('./anims/source.cast');
+
const genAvatar = name => {
let hash = 0;
@@ -17,28 +21,6 @@ const genAvatar = name => {
return `${hash}`;
};
-const animations = {};
-function animateConstruct(id) {
- if (animations[id]) return false;
- animations[id] = true;
- const duration = anime.random(2000, 18000);
- const target = document.getElementById(id);
- return anime({
- targets: target,
- translateX: () => anime.random(-20, 20),
- translateY: () => anime.random(0, -40),
- rotate: () => anime.random(-15, 15),
- duration,
- direction: 'alternate',
- easing: 'linear',
- loop: true,
- complete: () => animations[id] = false,
- });
-}
-
-function clearAnimation(id) {
- animations[id] = false;
-}
const addState = connect(
function receiveState(state) {
@@ -48,10 +30,15 @@ const addState = connect(
);
class ConstructAvatar extends Component {
- constructor() {
+ 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.animId = 0;
+ this.source = false;
this.animations = [];
+ this.avatar = genAvatar(props.name);
}
render() {
@@ -59,61 +46,45 @@ class ConstructAvatar extends Component {
);
}
componentDidMount() {
- this.idle = animateConstruct(this.props.id);
+ this.idle = idleAnimation(this.props.id);
+ this.animations.push(this.idle);
}
componentWillReceiveProps(nextProps) {
- if (nextProps.avatarAnimation.id !== this.animId && nextProps.avatarAnimation.animTargetId === this.props.id) {
+ const animations = nextProps.avatarAnimation;
+ if (animations.id === -1) this.animId = 0; // The current set of resolutions ended reset to 0
+ if (animations.id !== this.animId && animations.animTargetId === this.props.id) {
this.animId = nextProps.avatarAnimation.id;
- this.idle.pause();
- const anim = anime({
- targets: [document.getElementById(this.props.id)],
- translateY: nextProps.avatarAnimation.y * 200,
- translateX: nextProps.avatarAnimation.x * 200,
- easing: 'easeInOutElastic',
- direction: 'alternate',
- duration: TIMES.SOURCE_DURATION_MS,
- });
- anim.finished.then(this.idle.play);
+ const selectAnim = () => {
+ switch (animations.type) {
+ case 'banish': return banish(this.props.id);
+ case 'invert': return invert(this.props.id);
+ case 'sourceCast': return sourceCast(this.props.id, animations.params);
+ default: return null;
+ }
+ };
+ const anim = selectAnim();
+ if (anim) {
+ this.idle.pause();
+ this.animations.push(anim);
+ anim.finished.then(this.idle.play);
+ }
}
- // console.log(this.props);
- // console.log(nextProps);
}
componentWillUnmount() {
- clearAnimation(this.props.id);
- }
-}
-
-class ConstructImg extends Component {
- render() {
- return (
-
event.target.setAttribute('src', '/molecules/726.svg')}
- />
- );
- }
-
- componentDidMount() {
- animateConstruct(this.props.id);
- }
-
- componentWillUnmount() {
- clearAnimation(this.props.id);
+ for (let i = this.animations.length - 1; i >= 0; i--) {
+ this.animations[i].reset();
+ }
}
}
module.exports = {
ConstructAvatar: addState(ConstructAvatar),
- ConstructImg,
};
diff --git a/client/src/events.jsx b/client/src/events.jsx
index ec20bef3..392dda99 100644
--- a/client/src/events.jsx
+++ b/client/src/events.jsx
@@ -84,12 +84,13 @@ function registerEvents(store) {
if (err) console.error(err);
// Clear the anim classes
store.dispatch(actions.setResolution('clear'));
+ store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false }));
// Finished this resolution small delay for reset
return setTimeout(cb, 5);
});
}, err => {
if (err) return console.error(err);
- store.dispatch(actions.setAvatarAnimation({ id: -1 }));
+ store.dispatch(actions.setAvatarAnimation({ id: -1, source: false, target: false }));
store.dispatch(actions.setResolution(null));
// stop skipping resolutions
store.dispatch(actions.setSkip(false));
diff --git a/client/src/reducers.jsx b/client/src/reducers.jsx
index abd7ad03..9a154c51 100644
--- a/client/src/reducers.jsx
+++ b/client/src/reducers.jsx
@@ -15,7 +15,7 @@ module.exports = {
activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'),
activeItem: createReducer(null, 'SET_ACTIVE_VAR'),
activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'),
- avatarAnimation: createReducer({ id: -1 }, 'SET_AVATAR_ANIMATION'),
+ avatarAnimation: createReducer({ id: -1, source: false, target: false }, 'SET_AVATAR_ANIMATION'),
combiner: createReducer([null, null, null], 'SET_COMBINER'),
constructs: createReducer([], 'SET_CONSTRUCTS'),
constructDeleteId: createReducer(null, 'SET_CONSTRUCT_DELETE_ID'),