From 028606e80488e84b97bb1446d67f8deea78dd04b Mon Sep 17 00:00:00 2001 From: ntr Date: Thu, 18 Jul 2019 22:41:29 +1000 Subject: [PATCH 01/17] wip --- client/src/actions.jsx | 3 +- client/src/animations.utils.jsx | 108 ++++++++++ client/src/components/animations.jsx | 208 +++++++++----------- client/src/components/anims/source.cast.jsx | 4 +- client/src/components/construct.jsx | 50 ++--- client/src/components/game.construct.jsx | 119 ++++++----- client/src/components/game.jsx | 1 - client/src/components/targeting.arrows.jsx | 49 ++--- client/src/events.jsx | 54 +++-- client/src/reducers.jsx | 3 +- client/src/utils.jsx | 31 ++- 11 files changed, 371 insertions(+), 259 deletions(-) create mode 100644 client/src/animations.utils.jsx diff --git a/client/src/actions.jsx b/client/src/actions.jsx index e4f6fb2b..556b6643 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -1,6 +1,7 @@ export const setAccount = value => ({ type: 'SET_ACCOUNT', value }); export const setActiveConstruct = value => ({ type: 'SET_ACTIVE_CONSTRUCT', value }); -export const setAvatarAnimation = value => ({ type: 'SET_AVATAR_ANIMATION', value }); +export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value }); +export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value }); export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value }); export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null }); export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) }); diff --git a/client/src/animations.utils.jsx b/client/src/animations.utils.jsx new file mode 100644 index 00000000..06eb8225 --- /dev/null +++ b/client/src/animations.utils.jsx @@ -0,0 +1,108 @@ +const { removeTier } = require('./utils'); +const { TIMES } = require('./constants'); + +function none() { + return { + animSource: null, + animTarget: null, + }; +} + +function getObjects(resolution, stages, game, account) { + if (!resolution) return none(); + if (!resolution.target) return none(); + + const [, event] = resolution.event; + if (!event || !event.skill) return none(); + + const playerTeam = game.players.find(t => t.id === account.id); + const playerTeamIds = playerTeam.constructs.map(c => c.id); + const otherTeam = game.players.find(t => t.id !== account.id); + const otherTeamIds = otherTeam.constructs.map(c => c.id); + const sourceIsPlayer = playerTeamIds.includes(resolution.source.id); + const targetIsPlayer = playerTeamIds.includes(resolution.target.id); + + const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer); + let y = 0; + if (!sameTeam) y = targetIsPlayer ? 1 : -1; + + const i = sourceIsPlayer + ? playerTeamIds.findIndex(c => c === resolution.source.id) + : otherTeamIds.findIndex(c => c === resolution.source.id); + + const j = targetIsPlayer + ? playerTeamIds.findIndex(c => c === resolution.target.id) + : otherTeamIds.findIndex(c => c === resolution.target.id); + const x = j - i; + const direction = { x, y }; + // const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds; + + const createSourceAnim = () => { + return { + animation: 'sourceCast', + constructId: resolution.source.id, + direction, + }; + }; + + const skipSource = !stages.includes('START_SKILL') + || resolution.source.id === resolution.target.id; + + const animSource = skipSource + ? null + : createSourceAnim(); + + const skill = removeTier(event.skill); + + const animTarget = { + skill, + constructId: resolution.target.id, + player: playerTeamIds.includes(resolution.target.id), + direction, + }; + + return { + animSource, + animTarget, + }; +} + +function getSequence(resolution) { + if (!resolution.event) return false; + if (resolution.event[0] === 'Inversion') return false; + if (['Skill', 'AoeSkill'].includes(resolution.event[0])) return ['START_SKILL', 'END_SKILL']; + if (resolution.event[0] === 'Ko') return ['POST_SKILL']; + + switch (resolution.stages) { + case 1: return ['START_SKILL', 'END_SKILL']; + case 2: return ['START_SKILL', 'POST_SKILL']; + case 3: return ['START_SKILL']; + case 4: return ['END_SKILL', 'POST_SKILL']; + case 5: return ['END_SKILL']; + case 6: return ['POST_SKILL']; + case 7: return []; + default: return ['START_SKILL', 'END_SKILL', 'POST_SKILL']; + } +} + +function getTime(stages) { + if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) { + return TIMES.SOURCE_AND_TARGET_TOTAL_DURATION; + } + + if (stages.includes('START_SKILL')) return TIMES.SOURCE_DURATION_MS; + if (stages.includes('END_SKILL')) return TIMES.TARGET_DURATION_MS; + if (stages.includes('POST_SKILL')) return TIMES.POST_SKILL_DURATION_MS; + + return 0; +} + +module.exports = { + getObjects, + getTime, + getSequence, +}; + + + // if (!(resolution.target.id === construct.id) + // && !(resolution.event[0] === 'AoeSkill' && targetTeam.includes(construct.id))) return false; diff --git a/client/src/components/animations.jsx b/client/src/components/animations.jsx index bab9c2a6..7768812f 100644 --- a/client/src/components/animations.jsx +++ b/client/src/components/animations.jsx @@ -1,4 +1,6 @@ const preact = require('preact'); +const { Component } = require('preact'); +const { connect } = require('preact-redux'); const Amplify = require('./anims/amplify'); const Absorb = require('./anims/absorb'); @@ -36,130 +38,108 @@ const Stun = require('./anims/stun'); const Triage = require('./anims/triage'); const TriageTick = require('./anims/triage.tick'); -// const Test = require('./anims/test'); +const actions = require('../actions'); -const { removeTier } = require('../utils'); +const addState = connect( + function receiveState(state) { + const { animTarget } = state; + return { animTarget }; + }, +); -function animations(props) { - const { game, account, resolution, player, construct, avatarAnimation, setAvatarAnimation } = props; - if (!resolution || resolution === 'clear') return false; - const [, event] = resolution.event; - if (!event || !event.skill) return false; - if (!resolution.target) return false; +class ConstructAnimation extends Component { + render(props) { + const { + animTarget, + construct, + } = props; - // source animation - const playerTeam = game.players.find(t => t.id === account.id); - const playerTeamIds = playerTeam.constructs.map(c => c.id); - const otherTeam = game.players.find(t => t.id !== account.id); - const otherTeamIds = otherTeam.constructs.map(c => c.id); + if (!animTarget) return false; - const sourceIsPlayer = playerTeamIds.includes(resolution.source.id); - const targetIsPlayer = playerTeamIds.includes(resolution.target.id); + const { + skill, + player, + direction, + constructId, + } = animTarget; - const getDirection = () => { - const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer); - let y = 0; - if (!sameTeam) y = targetIsPlayer ? 1 : -1; + if (construct.id !== constructId) return false; - const i = sourceIsPlayer - ? playerTeamIds.findIndex(c => c === resolution.source.id) - : otherTeamIds.findIndex(c => c === resolution.source.id); + // find target animation + const chooseAnim = (skill) => { + switch (skill) { + // Attack base + case 'Attack': return ; + case 'Blast': return ; + case 'Siphon': return ; + case 'SiphonTick': return ; + case 'Strike': return ; + case 'Chaos': return ; + case 'Slay': return ; + case 'Heal': return ; - const j = targetIsPlayer - ? playerTeamIds.findIndex(c => c === resolution.target.id) - : otherTeamIds.findIndex(c => c === resolution.target.id); - const x = j - i; - return { x, y }; - }; + // Buff Base + case 'Buff': return ; + case 'Amplify': return ; + case 'Haste': return ; + case 'Triage': return ; + case 'TriageTick': return ; + case 'Link': return ; + case 'Hybrid': return ; + case 'Intercept': return ; - const skipSource = (resolution.source.id === resolution.target.id - && ['Invert', 'Banish'].includes(removeTier(event.skill))); + // Debuff base + case 'Debuff': return ; + case 'Curse': return ; + case 'Decay': return ; + case 'DecayTick': return ; + // case 'Invert': return setAvatarAnimation(true, true, resolution.id, construct.id, 'invert', null); + case 'Purge': return ; + case 'Silence': return ; + case 'Restrict': return ; - // Play Source Animation - if (!skipSource && resolution.source.id === construct.id && resolution.stages.includes('START_SKILL')) { - if (!avatarAnimation.source) { - setAvatarAnimation(true, avatarAnimation.target, resolution.id, - construct.id, 'sourceCast', getDirection()); - } + // Stun Base + case 'Stun': return ; + // case 'Banish': return setAvatarAnimation(true, true, resolution.id, construct.id, 'banish', null); + case 'Bash': return ; + case 'Absorb': return ; + case 'Sleep': return ; + case 'Break': return ; + case 'Ruin': return ; + + // Block Base + case 'Block': return ; + case 'Sustain': return ; + case 'Electrify': return ; + case 'Electrocute': return ; + case 'ElectrocuteTick': return ; + case 'Counter': return ; + case 'Purify': return ; + case 'Recharge': return ; + case 'Reflect': return ; + + default: return false; + }; + }; + + const anim = chooseAnim(skill); + console.log(anim); + if (!anim) return false; + + return ( +
+ {anim} +
+ ); } - const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds; - if (!(resolution.target.id === construct.id) - && !(resolution.event[0] === 'AoeSkill' && targetTeam.includes(construct.id))) return false; - // Play Target animation - const anim = text => { - if (!text || !resolution.sequence[0].includes('END_SKILL')) return false; - const skill = removeTier(text); - switch (skill) { - // Attack base - case 'Attack': return ; - case 'Blast': return ; - case 'Siphon': return ; - case 'SiphonTick': return ; - case 'Strike': return ; - case 'Chaos': return ; - case 'Slay': return ; - case 'Heal': return ; - - // Buff Base - case 'Buff': return ; - case 'Amplify': return ; - case 'Haste': return ; - case 'Triage': return ; - case 'TriageTick': return ; - case 'Link': return ; - case 'Hybrid': return ; - case 'Intercept': return ; - - // Debuff base - case 'Debuff': return ; - case 'Curse': return ; - case 'Decay': return ; - case 'DecayTick': return ; - case 'Invert': { - if (!avatarAnimation.target) { - setAvatarAnimation(avatarAnimation.source, true, resolution.id, construct.id, 'invert', null); - } return false; - } - case 'Purge': return ; - case 'Silence': return ; - case 'Restrict': return ; - - // Stun Base - case 'Stun': return ; - case 'Banish': { - if (!avatarAnimation.target) { - setAvatarAnimation(avatarAnimation.source, true, resolution.id, construct.id, 'banish', null); - } return false; - } - case 'Bash': return ; - case 'Absorb': return ; - case 'Sleep': return ; - case 'Break': return ; - case 'Ruin': return ; - - // Block Base - case 'Block': return ; - case 'Sustain': return ; - case 'Electrify': return ; - case 'Electrocute': return ; - case 'ElectrocuteTick': return ; - case 'Counter': return ; - case 'Purify': return ; - case 'Recharge': return ; - case 'Reflect': return ; - - default: return false; - } - }; - - const combatAnim = anim(event.skill); - if (!combatAnim) return false; - return ( -
- {combatAnim} -
- ); + // never update, wait til it gets nuked by parent + shouldComponentUpdate({ animTarget }) { + return animTarget === this.props.animTarget; + } } -module.exports = animations; + +module.exports = { + ConstructAnimation: addState(ConstructAnimation), +}; diff --git a/client/src/components/anims/source.cast.jsx b/client/src/components/anims/source.cast.jsx index c6690ca9..deb96df1 100644 --- a/client/src/components/anims/source.cast.jsx +++ b/client/src/components/anims/source.cast.jsx @@ -2,8 +2,8 @@ const anime = require('animejs').default; const { TIMES } = require('../../constants'); -function sourceCast(id, params) { - const { x, y } = params; +function sourceCast(id, direction) { + const { x, y } = direction; return anime({ targets: [document.getElementById(id)], translateX: x * 200, diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 9c669810..eddaacf5 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -1,7 +1,8 @@ const preact = require('preact'); const { Component } = require('preact'); const { connect } = require('preact-redux'); -const anime = require('animejs').default; + +const { match } = require('./../utils'); const banish = require('./anims/banish'); const idleAnimation = require('./anims/idle'); @@ -10,8 +11,8 @@ const sourceCast = require('./anims/source.cast'); const addState = connect( function receiveState(state) { - const { avatarAnimation } = state; - return { avatarAnimation }; + const { animSource, animTarget } = state; + return { animSource, animTarget }; } ); @@ -21,8 +22,6 @@ class ConstructAvatar extends Component { // 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 = []; } @@ -41,25 +40,27 @@ class ConstructAvatar extends Component { this.animations.push(this.idle); } - componentWillReceiveProps(nextProps) { - if (nextProps.avatarAnimation.id === -1) this.animId = 0; // The current set of resolutions ended reset to 0 - if (nextProps.avatarAnimation.id !== this.animId && nextProps.avatarAnimation.animTargetId === this.props.construct.id) { - this.animId = nextProps.avatarAnimation.id; - const selectAnim = () => { - switch (nextProps.avatarAnimation.type) { - case 'banish': return banish(this.props.construct.id); - case 'invert': return invert(this.props.construct.id); - case 'sourceCast': return sourceCast(this.props.construct.id, nextProps.avatarAnimation.params); - default: return null; - } - }; - const anim = selectAnim(); - if (anim) { - this.idle.pause(); - this.animations.push(anim); - anim.finished.then(this.idle.play); + componentWillReceiveProps({ animSource, animTarget }) { + const avatarAnim = () => { + if (animSource && animSource.constructId === this.props.construct.id) { + return sourceCast(animSource.constructId, animSource.direction); } + + // if (!animTarget) return false; + // match(animTarget.skill, [ + // ['banish', () => banish(this.props.construct.id)], + // ['invert', () => invert(this.props.construct.id)], + // ]); + }; + + const anim = avatarAnim(); + if (anim) { + this.idle.pause(); + this.animations.push(anim); + anim.finished.then(this.idle.play); } + + return true; } componentWillUnmount() { @@ -67,6 +68,11 @@ class ConstructAvatar extends Component { this.animations[i].reset(); } } + + // never update, wait til it gets nuked by parent + shouldComponentUpdate({ animTarget, sourceTarget }) { + return (animTarget === this.props.animTarget) && (sourceTarget === this.props.sourceTarget); + } } module.exports = { diff --git a/client/src/components/game.construct.jsx b/client/src/components/game.construct.jsx index 4ed97b38..064cfbd8 100644 --- a/client/src/components/game.construct.jsx +++ b/client/src/components/game.construct.jsx @@ -1,10 +1,11 @@ const { connect } = require('preact-redux'); +const { Component } = require('preact'); const preact = require('preact'); const range = require('lodash/range'); const { STATS, eventClasses, getCombatText } = require('../utils'); const { ConstructAvatar } = require('./construct'); -const animations = require('./animations'); +const { ConstructAnimation } = require('./animations'); const shapes = require('./shapes'); @@ -58,57 +59,83 @@ const addState = connect( ); -function GameConstruct(props) { - const { - i, - game, - account, - construct, - player, - resolution, - activeSkill, - avatarAnimation, - setAvatarAnimation, - selectSkillTarget, - } = props; +class GameConstruct extends Component { + constructor() { + super(); + this.resolvedLength = 0; + } + render() { + const { + i, + game, + account, + construct, + player, + resolution, + activeSkill, + selectSkillTarget, + } = this.props; - const ko = construct.green_life.value === 0 ? 'ko' : ''; - const classes = eventClasses(game, account, resolution, construct); + const ko = construct.green_life.value === 0 ? 'ko' : ''; + const classes = eventClasses(game, account, resolution, construct); - const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => ( -
- {shapes[s]()} -
{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}
-
{construct[STATS[s].stat].value}
-
- )); + const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => ( +
+ {shapes[s]()} +
{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}
+
{construct[STATS[s].stat].value}
+
+ )); - const skills = range(0, 3) - .map(j => ); + const skills = range(0, 3) + .map(j => ); - let crypSkills =
 
; - if (player) crypSkills = (
{skills}
); + let crypSkills =
 
; + if (player) crypSkills = (
{skills}
); - const effects = construct.effects.length - ? construct.effects.map(c =>
{c.effect} - {c.duration}T
) - :
 
; - const combatAnim = animations({ game, account, resolution, player, construct, avatarAnimation, setAvatarAnimation }); - const combatText = getCombatText(resolution, construct); - return ( -
selectSkillTarget(construct.id)} - style={ activeSkill ? { cursor: 'pointer' } : {}} - class={`game-construct ${ko} ${classes}`} > -

{construct.name}

- {crypSkills} -
{stats}
- - {combatAnim} -
{combatText}
-
{effects}
-
- ); + const effects = construct.effects.length + ? construct.effects.map(c =>
{c.effect} - {c.duration}T
) + :
 
; + const combatText = getCombatText(resolution, construct); + return ( +
selectSkillTarget(construct.id)} + style={ activeSkill ? { cursor: 'pointer' } : {}} + class={`game-construct ${ko} ${classes}`} > +

{construct.name}

+ {crypSkills} +
{stats}
+ + +
{combatText}
+
{effects}
+
+ ); + } + + shouldComponentUpdate(nextProps) { + const allProps = JSON.stringify(nextProps) === JSON.stringify(this.props); + // console.log(allProps, 'allProps'); + + // const resProps = JSON.stringify(nextProps.resolution) === JSON.stringify(this.props.resolution); + // console.log(resProps, 'resProps'); + + // if (!resProps) console.log(JSON.stringify(nextProps.resolution), JSON.stringify(this.props.resolution)) + return !(allProps); + // if (!nextProps) return false; + // if (nextProps.activeSkill !== this.props.activeSkill) return true; + // if (!nextProps.game) return false; + // if (nextProps.game.resolved.length !== this.resolvedLength) { + // this.resolvedLength = nextProps.game.resolved.length; + // return true; + // } + // return false; + } + + componentWillUnmount() { + console.log('WTF!!!'); + } } module.exports = addState(GameConstruct); diff --git a/client/src/components/game.jsx b/client/src/components/game.jsx index 9c00c291..eddde654 100644 --- a/client/src/components/game.jsx +++ b/client/src/components/game.jsx @@ -65,7 +65,6 @@ function Game(props) { if (!game) return
...
; - console.log('running game'); const otherTeams = game.players.filter(t => t.id !== account.id); const playerTeam = game.players.find(t => t.id === account.id); diff --git a/client/src/components/targeting.arrows.jsx b/client/src/components/targeting.arrows.jsx index 33a49f92..83041e46 100644 --- a/client/src/components/targeting.arrows.jsx +++ b/client/src/components/targeting.arrows.jsx @@ -1,12 +1,13 @@ const preact = require('preact'); const { Component } = require('preact'); const { connect } = require('preact-redux'); -const anime = require('animejs').default; +// const anime = require('animejs').default; const throttle = require('lodash/throttle'); const addState = connect( - ({ game, account, resolution }) => ({ game, account, resolution }) + ({ game, account, animSource, animTarget }) => + ({ game, account, animSource, animTarget }) ); class TargetSvg extends Component { @@ -23,9 +24,25 @@ class TargetSvg extends Component { } render(props, state) { - const { game, account, resolution } = props; + const { game, account, animSource, animTarget } = props; const { width, height } = state; + // resolutions happening + // just put skill name up + if (animSource || animTarget) { + return ( + + + {animTarget.skill} + + + ); + } + const playerTeam = game.players.find(t => t.id === account.id); const otherTeam = game.players.find(t => t.id !== account.id); @@ -81,29 +98,13 @@ class TargetSvg extends Component { return ; } - if (resolution === 'clear') return false; - if (!resolution) { - return ( - - {outgoing.map(getPath)} - - ); - } - let skill = ''; - if (resolution.event[1]) ([, { skill }] = resolution.event); return ( - - - {skill} - + + {outgoing.map(getPath)} ); } diff --git a/client/src/events.jsx b/client/src/events.jsx index 69d8ec4a..cd848b0c 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -3,7 +3,7 @@ const eachSeries = require('async/eachSeries'); const actions = require('./actions'); const { TIMES } = require('./constants'); -const { getCombatSequence } = require('./utils'); +const animations = require('./animations.utils'); function registerEvents(store) { function setPing(ping) { @@ -42,44 +42,40 @@ function registerEvents(store) { } function setGame(game) { - const { game: currentGame, ws } = store.getState(); + const { game: currentGame, account, ws } = store.getState(); if (game && currentGame) { if (game.resolved.length !== currentGame.resolved.length) { // stop fetching the game state til animations are done const newRes = game.resolved.slice(currentGame.resolved.length); - let id = game.resolved.length - currentGame.resolved.length; 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')) { - timeout = TIMES.SOURCE_AND_TARGET_TOTAL_DURATION; - } else if (stages.includes('START_SKILL')) timeout = TIMES.SOURCE_DURATION_MS; - else if (stages.includes('END_SKILL')) timeout = TIMES.TARGET_DURATION_MS; - else if (stages.includes('POST_SKILL')) timeout = TIMES.POST_SKILL_DURATION_MS; - store.dispatch(actions.setResolution(stagedR)); - return setTimeout(sCb, timeout); - }, err => { - 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); - }); + // convert server enum into anims keywords + // todo make serersideonly + const sequence = animations.getSequence(r); + const timeout = animations.getTime(sequence); + const anims = animations.getObjects(r, sequence, game, account); + + console.log(sequence, timeout, anims); + + store.dispatch(actions.setAnimSource(anims.animSource)); + store.dispatch(actions.setAnimTarget(anims.animTarget)); + return setTimeout(cb, timeout); + + // return setTimeout(sCb, timeout); + // }, err => { + // if (err) console.error(err); + // // Clear the anim classes + // store.dispatch(actions.setResolution(null)); + // // 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, source: false, target: false })); - store.dispatch(actions.setResolution(null)); + store.dispatch(actions.setAnimSource(null)); + store.dispatch(actions.setAnimTarget(null)); // stop skipping resolutions store.dispatch(actions.setSkip(false)); // update the game diff --git a/client/src/reducers.jsx b/client/src/reducers.jsx index 288fca18..defd5e63 100644 --- a/client/src/reducers.jsx +++ b/client/src/reducers.jsx @@ -15,7 +15,8 @@ module.exports = { activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'), activeItem: createReducer(null, 'SET_ACTIVE_VAR'), activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'), - avatarAnimation: createReducer({ id: -1, source: false, target: false }, 'SET_AVATAR_ANIMATION'), + animSource: createReducer(null, 'SET_ANIM_SOURCE'), + animTarget: createReducer(null, 'SET_ANIM_TARGET'), combiner: createReducer([null, null, null], 'SET_COMBINER'), constructs: createReducer([], 'SET_CONSTRUCTS'), constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'), diff --git a/client/src/utils.jsx b/client/src/utils.jsx index 6a3bb804..f50dc7a3 100644 --- a/client/src/utils.jsx +++ b/client/src/utils.jsx @@ -4,6 +4,17 @@ const toast = require('izitoast'); const shapes = require('./components/shapes'); +function match(value, patterns) { + for (let i = 0; i < patterns.length; i++) { + if (value === patterns[i][0]) { + return patterns[i][1](); + } + } + + console.warn('default match - return null', value, patterns); + return null; +} + const stringSort = (k, desc) => { if (desc) { return (a, b) => { @@ -158,24 +169,6 @@ function eventClasses(game, account, resolution, construct) { return ''; } -function getCombatSequence(resolution) { - if (!resolution.event) return false; - if (resolution.event[0] === 'Inversion') return false; - if (['Skill', 'AoeSkill'].includes(resolution.event[0])) return [['START_SKILL', 'END_SKILL']]; - if (resolution.event[0] === 'Ko') return [['POST_SKILL']]; - - switch (resolution.stages) { - case 1: return [['START_SKILL', 'END_SKILL']]; - case 2: return [['START_SKILL'], ['POST_SKILL']]; - case 3: return [['START_SKILL']]; - case 4: return [['END_SKILL'], ['POST_SKILL']]; - case 5: return [['END_SKILL']]; - case 6: return [['POST_SKILL']]; - case 7: return false; - default: return [['START_SKILL', 'END_SKILL'], ['POST_SKILL']]; - } -} - function getCombatText(resolution, construct) { if (!resolution || resolution === 'clear') return false; if (!resolution.stages.includes('POST_SKILL')) return false; @@ -385,7 +378,6 @@ module.exports = { convertItem, numSort, eventClasses, - getCombatSequence, getCombatText, postData, errorToast, @@ -395,4 +387,5 @@ module.exports = { TARGET_COLOURS, randomPoints, removeTier, + match, }; From 47b9d496dc5602caadcc8da7c0b8c29c05d85b6c Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 14:47:48 +1000 Subject: [PATCH 02/17] update anims test --- client/package.json | 2 +- client/src/animations.socket.jsx | 62 ++++++++++++++--------------- client/src/components/construct.jsx | 26 ++++++++---- client/src/test.game.js | 6 +++ 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/client/package.json b/client/package.json index 2182bf77..1b7ef7c6 100644 --- a/client/package.json +++ b/client/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "start": "parcel watch index.html --out-dir /var/lib/mnml/public/current", - "anims": "parcel animations.html --host 0.0.0.0 --port 40080 --no-source-maps", + "anims": "parcel watch animations.html --out-dir /var/lib/mnml/public/current", "build": "parcel build index.html", "scss": "node-sass --watch assets/scss -o assets/styles", "lint": "eslint --fix --ext .jsx src/", diff --git a/client/src/animations.socket.jsx b/client/src/animations.socket.jsx index b1a10305..215c71ba 100644 --- a/client/src/animations.socket.jsx +++ b/client/src/animations.socket.jsx @@ -5,7 +5,7 @@ const eachSeries = require('async/eachSeries'); const actions = require('./actions'); const { TIMES } = require('./constants'); -const { getCombatSequence } = require('./utils'); +const animations = require('./animations.utils'); const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'wss://mnml.gg/api/ws' : 'ws://localhost/api/ws'; @@ -20,46 +20,39 @@ function createSocket(store) { } function sendDevResolve(a, b, skill) { - send({ method: 'dev_game_resolve', params: { a, b, skill } }); + send(['DevResolve', { a, b, skill }]); } function onDevResolutions(newRes) { - const { game: currentGame } = store.getState(); - let id = 0; + const { game: currentGame, account } = store.getState(); 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; + // convert server enum into anims keywords + // todo make serersideonly + const sequence = animations.getSequence(r); + const timeout = animations.getTime(sequence); + const anims = animations.getObjects(r, sequence, currentGame, account); - let timeout = 0; - if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) { - timeout = TIMES.SOURCE_AND_TARGET_TOTAL_DURATION; - } else if (stages.includes('START_SKILL')) timeout = TIMES.SOURCE_DURATION_MS; - else if (stages.includes('END_SKILL')) timeout = TIMES.TARGET_DURATION_MS; - else if (stages.includes('POST_SKILL')) timeout = TIMES.POST_SKILL_DURATION_MS; - store.dispatch(actions.setResolution(stagedR)); + console.log(sequence, timeout, anims); - return setTimeout(sCb, timeout); - }, err => { - if (err) console.error(err); - store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false })); - // Finished this resolution - return cb(); - }); + store.dispatch(actions.setAnimSource(anims.animSource)); + store.dispatch(actions.setAnimTarget(anims.animTarget)); + return setTimeout(cb, timeout); + + // return setTimeout(sCb, timeout); + // }, err => { + // if (err) console.error(err); + // // Clear the anim classes + // store.dispatch(actions.setResolution(null)); + // // 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, source: false, target: false })); - store.dispatch(actions.setResolution(null)); - // stop skipping resolutions - store.dispatch(actions.setSkip(false)); - // update the game + store.dispatch(actions.setAnimSource(null)); + store.dispatch(actions.setAnimTarget(null)); store.dispatch(actions.setGame(currentGame)); return true; }); @@ -75,8 +68,13 @@ function createSocket(store) { // decode binary msg from server const blob = new Uint8Array(event.data); const res = cbor.decode(blob); + // if (res.err) return errHandler(res.err); + const [msgType, params] = res; - if (!handlers[msgType]) return false; + if (msgType !== 'Pong') console.log(res); + + // check for error and split into response type and data + if (!handlers[msgType]) return console.error(`${msgType} handler missing`); return handlers[msgType](params); } diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index eddaacf5..f8ec172b 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -36,28 +36,38 @@ class ConstructAvatar extends Component { } componentDidMount() { - this.idle = idleAnimation(this.props.construct.id); - this.animations.push(this.idle); - } + const { animSource, animTarget, construct } = this.props; + + const isSource = animSource && animSource.constructId === construct.id; + const isTarget = animTarget && animTarget.constructId === construct.id; + + console.log(isSource, isTarget); + + if (!isSource || !isTarget) { + return this.animations.push(idleAnimation(construct.id)); + } - componentWillReceiveProps({ animSource, animTarget }) { const avatarAnim = () => { - if (animSource && animSource.constructId === this.props.construct.id) { + console.log(isSource); + if (isSource) { return sourceCast(animSource.constructId, animSource.direction); } // if (!animTarget) return false; // match(animTarget.skill, [ - // ['banish', () => banish(this.props.construct.id)], + // ['banish', () => banish(construct.id)], // ['invert', () => invert(this.props.construct.id)], // ]); }; const anim = avatarAnim(); if (anim) { - this.idle.pause(); + console.log(anim); this.animations.push(anim); - anim.finished.then(this.idle.play); + anim.finished.then(() => { + console.log('anim finished'); + return this.animations.push(idleAnimation(construct.id)); + }); } return true; diff --git a/client/src/test.game.js b/client/src/test.game.js index c36174ed..e17cb8e0 100644 --- a/client/src/test.game.js +++ b/client/src/test.game.js @@ -35,6 +35,7 @@ function testGame(uuid) { "constructs": [ { "id": "82e8b940-411c-42a1-8fc2-484ec7207734", + "img": "8446736d-d682-4588-b8a0-5b7ba53bdb55", "account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1", "red_damage": { "base": 256, @@ -108,6 +109,7 @@ function testGame(uuid) { }, { "id": "96ca4a0e-fed2-4ea2-9ec5-ae308f8dde4b", + "img": "8446736d-d682-4588-b8a0-5b7ba53bdb55", "account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1", "red_damage": { "base": 256, @@ -184,6 +186,7 @@ function testGame(uuid) { { "id": "ea302c35-d326-475c-a867-8ad5b162165a", "account": "8552e0bf-340d-4fc8-b6fc-3d56b68fe2a1", + "img": "8446736d-d682-4588-b8a0-5b7ba53bdb55", "red_damage": { "base": 256, "value": Math.floor(Math.random() * 10000), @@ -299,6 +302,7 @@ function testGame(uuid) { { "id": "3aa0f284-1e1b-4054-b38a-b2d50db471bd", "account": uuid, + "img": "8446736d-d682-4588-b8a0-5b7ba53bdb55", "red_damage": { "base": 256, "value": Math.floor(Math.random() * 10000), @@ -385,6 +389,7 @@ function testGame(uuid) { { "id": "50e5d94e-8ebe-495c-a916-3eb509ff4683", "account": uuid, + "img": "8446736d-d682-4588-b8a0-5b7ba53bdb55", "red_damage": { "base": 256, "value": Math.floor(Math.random() * 10000), @@ -465,6 +470,7 @@ function testGame(uuid) { { "id": "5d49fe65-27f0-4372-90a3-334ef906a0f5", "account": uuid, + "img": "8446736d-d682-4588-b8a0-5b7ba53bdb55", "red_damage": { "base": 256, "value": Math.floor(Math.random() * 10000), From 18ac22000678f7e73b8d8bac62b71bbe1f2d7ab8 Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 16:19:44 +1000 Subject: [PATCH 03/17] nearly there --- client/src/components/construct.jsx | 61 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index f8ec172b..378e735d 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -23,6 +23,7 @@ class ConstructAvatar extends Component { // 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() { @@ -36,52 +37,62 @@ class ConstructAvatar extends Component { } componentDidMount() { - const { animSource, animTarget, construct } = this.props; + console.log(this.props.construct.name, 'mounted'); + this.idle = idleAnimation(this.props.construct.id); + this.animations.push(this.idle); + } - const isSource = animSource && animSource.constructId === construct.id; - const isTarget = animTarget && animTarget.constructId === construct.id; + componentDidUpdate(newProps) { + const { animSource, animTarget, construct } = newProps; - console.log(isSource, isTarget); - - if (!isSource || !isTarget) { - return this.animations.push(idleAnimation(construct.id)); + // back to idle + if (!animTarget || !animSource) { + return this.idle.play(); } - const avatarAnim = () => { - console.log(isSource); + const isSource = animSource && animSource.constructId === construct.id; + + const selectAnim = () => { if (isSource) { + console.log(construct.name, 'source anim'); return sourceCast(animSource.constructId, animSource.direction); } - // if (!animTarget) return false; - // match(animTarget.skill, [ - // ['banish', () => banish(construct.id)], - // ['invert', () => invert(this.props.construct.id)], - // ]); + switch (animTarget.skill) { + case 'banish': return banish(construct.id); + case 'invert': return invert(construct.id); + default: return null; + } }; - const anim = avatarAnim(); + const anim = selectAnim(); if (anim) { - console.log(anim); + this.idle.pause(); this.animations.push(anim); - anim.finished.then(() => { - console.log('anim finished'); - return this.animations.push(idleAnimation(construct.id)); - }); + return true; } - return true; + return false; } - componentWillUnmount() { + resetAnimations() { for (let i = this.animations.length - 1; i >= 0; i--) { this.animations[i].reset(); } } - // never update, wait til it gets nuked by parent - shouldComponentUpdate({ animTarget, sourceTarget }) { - return (animTarget === this.props.animTarget) && (sourceTarget === this.props.sourceTarget); + componentWillUnmount() { + this.resetAnimations(); + } + + shouldComponentUpdate({ animTarget, animSource, construct }) { + const updated = (animTarget !== this.props.animTarget) || (animSource !== this.props.animSource); + if (!updated) return false; + + const isSource = animSource && animSource.constructId === construct.id; + const isTarget = animTarget && animTarget.constructId === construct.id; + + return isSource || isTarget; } } From 8d8a79c712b150cbd0b5ba00943638f42069cbf4 Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 18:24:46 +1000 Subject: [PATCH 04/17] good --- client/src/actions.jsx | 1 + client/src/animations.socket.jsx | 32 ++++---- client/src/animations.test.jsx | 4 +- client/src/animations.utils.jsx | 4 +- client/src/app.jsx | 3 +- client/src/components/animations.jsx | 1 - client/src/components/anims/source.cast.jsx | 4 +- client/src/components/construct.jsx | 86 ++++++++++++++++----- client/src/components/targeting.arrows.jsx | 10 ++- client/src/constants.jsx | 5 +- client/src/events.jsx | 30 ++++--- client/src/reducers.jsx | 1 + 12 files changed, 114 insertions(+), 67 deletions(-) diff --git a/client/src/actions.jsx b/client/src/actions.jsx index 556b6643..8b23cfa1 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -1,5 +1,6 @@ export const setAccount = value => ({ type: 'SET_ACCOUNT', value }); export const setActiveConstruct = value => ({ type: 'SET_ACTIVE_CONSTRUCT', value }); +export const setAnimating = value => ({ type: 'SET_ANIMATING', value }); export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value }); export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value }); export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value }); diff --git a/client/src/animations.socket.jsx b/client/src/animations.socket.jsx index 215c71ba..231a54b6 100644 --- a/client/src/animations.socket.jsx +++ b/client/src/animations.socket.jsx @@ -24,7 +24,11 @@ function createSocket(store) { } function onDevResolutions(newRes) { - const { game: currentGame, account } = store.getState(); + const { game, account, animating } = store.getState(); + + if (animating) return false; + store.dispatch(actions.setAnimating(true)); + return eachSeries(newRes, (r, cb) => { if (['Disable', 'TargetKo'].includes(r.event[0])) return cb(); @@ -32,28 +36,26 @@ function createSocket(store) { // todo make serersideonly const sequence = animations.getSequence(r); const timeout = animations.getTime(sequence); - const anims = animations.getObjects(r, sequence, currentGame, account); - - console.log(sequence, timeout, anims); + const anims = animations.getObjects(r, sequence, game, account); store.dispatch(actions.setAnimSource(anims.animSource)); store.dispatch(actions.setAnimTarget(anims.animTarget)); - return setTimeout(cb, timeout); - // return setTimeout(sCb, timeout); - // }, err => { - // if (err) console.error(err); - // // Clear the anim classes - // store.dispatch(actions.setResolution(null)); - // // store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false })); - // // Finished this resolution small delay for reset - // return setTimeout(cb, 5); - // }); + return setTimeout(() => { + store.dispatch(actions.setAnimSource(null)); + store.dispatch(actions.setAnimTarget(null)); + return setTimeout(cb, 50); + }, 3000); }, err => { if (err) return console.error(err); store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); - store.dispatch(actions.setGame(currentGame)); + store.dispatch(actions.setAnimating(false)); + + // stop skipping resolutions + store.dispatch(actions.setSkip(false)); + + // ws.sendGameState(currentGame.id); return true; }); } diff --git a/client/src/animations.test.jsx b/client/src/animations.test.jsx index 203e3976..3704c4f6 100644 --- a/client/src/animations.test.jsx +++ b/client/src/animations.test.jsx @@ -20,10 +20,10 @@ const testAccount = { // Redux Store const store = createStore( - combineReducers(reducers) + combineReducers(reducers), + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), ); -store.subscribe(() => console.log(store.getState())); store.dispatch(actions.setAccount(testAccount)); store.dispatch(actions.setGame(testGame)); diff --git a/client/src/animations.utils.jsx b/client/src/animations.utils.jsx index 06eb8225..49fe19ee 100644 --- a/client/src/animations.utils.jsx +++ b/client/src/animations.utils.jsx @@ -68,8 +68,8 @@ function getObjects(resolution, stages, game, account) { } function getSequence(resolution) { - if (!resolution.event) return false; - if (resolution.event[0] === 'Inversion') return false; + if (!resolution.event) return []; + if (resolution.event[0] === 'Inversion') return []; if (['Skill', 'AoeSkill'].includes(resolution.event[0])) return ['START_SKILL', 'END_SKILL']; if (resolution.event[0] === 'Ko') return ['POST_SKILL']; diff --git a/client/src/app.jsx b/client/src/app.jsx index 20586dc7..2e64724f 100644 --- a/client/src/app.jsx +++ b/client/src/app.jsx @@ -15,7 +15,8 @@ const Mnml = require('./components/mnml'); // Redux Store const store = createStore( - combineReducers(reducers) + combineReducers(reducers), + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), ); document.fonts.load('16pt "Jura"').then(() => { diff --git a/client/src/components/animations.jsx b/client/src/components/animations.jsx index 7768812f..7e0ad94a 100644 --- a/client/src/components/animations.jsx +++ b/client/src/components/animations.jsx @@ -123,7 +123,6 @@ class ConstructAnimation extends Component { }; const anim = chooseAnim(skill); - console.log(anim); if (!anim) return false; return ( diff --git a/client/src/components/anims/source.cast.jsx b/client/src/components/anims/source.cast.jsx index deb96df1..25cb8ae8 100644 --- a/client/src/components/anims/source.cast.jsx +++ b/client/src/components/anims/source.cast.jsx @@ -6,8 +6,8 @@ function sourceCast(id, direction) { const { x, y } = direction; return anime({ targets: [document.getElementById(id)], - translateX: x * 200, - translateY: y * 200, + translateX: [0, x * 200], + translateY: [0, y * 200], easing: 'easeInOutElastic', direction: 'alternate', duration: TIMES.SOURCE_DURATION_MS, diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 378e735d..7cd8899d 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -2,7 +2,7 @@ const preact = require('preact'); const { Component } = require('preact'); const { connect } = require('preact-redux'); -const { match } = require('./../utils'); +// const { match } = require('./../utils'); const banish = require('./anims/banish'); const idleAnimation = require('./anims/idle'); @@ -37,16 +37,15 @@ class ConstructAvatar extends Component { } componentDidMount() { - console.log(this.props.construct.name, 'mounted'); - this.idle = idleAnimation(this.props.construct.id); - this.animations.push(this.idle); - } - - componentDidUpdate(newProps) { - const { animSource, animTarget, construct } = newProps; + const { animSource, animTarget, construct } = this.props; // back to idle - if (!animTarget || !animSource) { + if (!animTarget && !animSource) { + if (!this.idle) { + this.idle = idleAnimation(this.props.construct.id); + this.animations.push(this.idle); + } + return this.idle.play(); } @@ -54,7 +53,7 @@ class ConstructAvatar extends Component { const selectAnim = () => { if (isSource) { - console.log(construct.name, 'source anim'); + console.warn(construct.name, animSource); return sourceCast(animSource.constructId, animSource.direction); } @@ -66,13 +65,41 @@ class ConstructAvatar extends Component { }; const anim = selectAnim(); - if (anim) { - this.idle.pause(); - this.animations.push(anim); - return true; + 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(); } - return false; + 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() { @@ -85,14 +112,31 @@ class ConstructAvatar extends Component { this.resetAnimations(); } - shouldComponentUpdate({ animTarget, animSource, construct }) { - const updated = (animTarget !== this.props.animTarget) || (animSource !== this.props.animSource); - if (!updated) return false; + shouldComponentUpdate({ animSource, construct }) { + if (animSource === this.props.animSource) { + // console.warn(construct.name, 'thinks its same props') + return false; + } - const isSource = animSource && animSource.constructId === construct.id; - const isTarget = animTarget && animTarget.constructId === construct.id; + // something has changed + // what do? - return isSource || isTarget; + // 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) return true; + + // we were previously doing src anim + const prevSrc = this.props.animSource && this.props.animSource.constructId === construct.id; + if (prevSrc && !animSource) return true; + + // console.warn(construct.name, 'not updating'); + + return false; } } diff --git a/client/src/components/targeting.arrows.jsx b/client/src/components/targeting.arrows.jsx index 83041e46..d5bdd9eb 100644 --- a/client/src/components/targeting.arrows.jsx +++ b/client/src/components/targeting.arrows.jsx @@ -6,8 +6,8 @@ const { connect } = require('preact-redux'); const throttle = require('lodash/throttle'); const addState = connect( - ({ game, account, animSource, animTarget }) => - ({ game, account, animSource, animTarget }) + ({ game, account, animTarget, animating }) => + ({ game, account, animTarget, animating }) ); class TargetSvg extends Component { @@ -24,12 +24,14 @@ class TargetSvg extends Component { } render(props, state) { - const { game, account, animSource, animTarget } = props; + const { game, account, animating, animTarget } = props; const { width, height } = state; // resolutions happening // just put skill name up - if (animSource || animTarget) { + if (animating) { + if (!animTarget) return false; + return ( { @@ -57,30 +61,23 @@ function registerEvents(store) { const timeout = animations.getTime(sequence); const anims = animations.getObjects(r, sequence, game, account); - console.log(sequence, timeout, anims); - store.dispatch(actions.setAnimSource(anims.animSource)); store.dispatch(actions.setAnimTarget(anims.animTarget)); - return setTimeout(cb, timeout); - // return setTimeout(sCb, timeout); - // }, err => { - // if (err) console.error(err); - // // Clear the anim classes - // store.dispatch(actions.setResolution(null)); - // // store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false })); - // // Finished this resolution small delay for reset - // return setTimeout(cb, 5); - // }); + return setTimeout(() => { + store.dispatch(actions.setAnimSource(null)); + store.dispatch(actions.setAnimTarget(null)); + return setTimeout(cb, 50); + }, 3000); }, err => { if (err) return console.error(err); store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); + store.dispatch(actions.setAnimating(false)); + // stop skipping resolutions store.dispatch(actions.setSkip(false)); - // update the game - store.dispatch(actions.setGame(game)); - // get the latest state and restart polling + ws.sendGameState(currentGame.id); return true; }); @@ -88,7 +85,6 @@ function registerEvents(store) { } return store.dispatch(actions.setGame(game)); - return console.log('EVENT ->', 'game', game); } function setAccount(account) { diff --git a/client/src/reducers.jsx b/client/src/reducers.jsx index defd5e63..9a36cccf 100644 --- a/client/src/reducers.jsx +++ b/client/src/reducers.jsx @@ -15,6 +15,7 @@ module.exports = { activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'), activeItem: createReducer(null, 'SET_ACTIVE_VAR'), activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'), + animating: createReducer(false, 'SET_ANIMATING'), animSource: createReducer(null, 'SET_ANIM_SOURCE'), animTarget: createReducer(null, 'SET_ANIM_TARGET'), combiner: createReducer([null, null, null], 'SET_COMBINER'), From 52b42b772abd68e592d922fb278cb424ad763bad Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 18:31:37 +1000 Subject: [PATCH 05/17] yes baybee --- client/src/components/animations.jsx | 5 ----- client/src/components/game.construct.jsx | 23 ----------------------- 2 files changed, 28 deletions(-) diff --git a/client/src/components/animations.jsx b/client/src/components/animations.jsx index 7e0ad94a..1a4e3ee6 100644 --- a/client/src/components/animations.jsx +++ b/client/src/components/animations.jsx @@ -131,11 +131,6 @@ class ConstructAnimation extends Component { ); } - - // never update, wait til it gets nuked by parent - shouldComponentUpdate({ animTarget }) { - return animTarget === this.props.animTarget; - } } diff --git a/client/src/components/game.construct.jsx b/client/src/components/game.construct.jsx index 064cfbd8..5e284e07 100644 --- a/client/src/components/game.construct.jsx +++ b/client/src/components/game.construct.jsx @@ -113,29 +113,6 @@ class GameConstruct extends Component { ); } - - shouldComponentUpdate(nextProps) { - const allProps = JSON.stringify(nextProps) === JSON.stringify(this.props); - // console.log(allProps, 'allProps'); - - // const resProps = JSON.stringify(nextProps.resolution) === JSON.stringify(this.props.resolution); - // console.log(resProps, 'resProps'); - - // if (!resProps) console.log(JSON.stringify(nextProps.resolution), JSON.stringify(this.props.resolution)) - return !(allProps); - // if (!nextProps) return false; - // if (nextProps.activeSkill !== this.props.activeSkill) return true; - // if (!nextProps.game) return false; - // if (nextProps.game.resolved.length !== this.resolvedLength) { - // this.resolvedLength = nextProps.game.resolved.length; - // return true; - // } - // return false; - } - - componentWillUnmount() { - console.log('WTF!!!'); - } } module.exports = addState(GameConstruct); From c94fc46f349784dfb7f449ece4147a381f62405b Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 18:35:31 +1000 Subject: [PATCH 06/17] pow --- client/src/events.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/events.jsx b/client/src/events.jsx index 044e7372..3843ea0c 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -71,14 +71,14 @@ function registerEvents(store) { }, 3000); }, err => { if (err) return console.error(err); + // clear animation state store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); store.dispatch(actions.setAnimating(false)); - // stop skipping resolutions - store.dispatch(actions.setSkip(false)); - - ws.sendGameState(currentGame.id); + // set the game state so resolutions don't fire twice + store.dispatch(actions.setGame(game)); + ws.sendGameState(game.id); return true; }); } From bd517a1926391005de499ae12a2fdbc4a71dd6f2 Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 19:03:22 +1000 Subject: [PATCH 07/17] text back --- client/src/actions.jsx | 3 + client/src/animations.utils.jsx | 84 ++++++++++++++++++++++-- client/src/components/construct.jsx | 20 ++++++ client/src/components/game.construct.jsx | 32 ++++----- client/src/events.jsx | 15 ++++- client/src/reducers.jsx | 3 + client/src/utils.jsx | 74 ++------------------- 7 files changed, 137 insertions(+), 94 deletions(-) diff --git a/client/src/actions.jsx b/client/src/actions.jsx index 8b23cfa1..8eb1697f 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -1,8 +1,11 @@ export const setAccount = value => ({ type: 'SET_ACCOUNT', value }); export const setActiveConstruct = value => ({ type: 'SET_ACTIVE_CONSTRUCT', value }); + export const setAnimating = value => ({ type: 'SET_ANIMATING', value }); export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value }); export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value }); +export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value }); + export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value }); export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null }); export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) }); diff --git a/client/src/animations.utils.jsx b/client/src/animations.utils.jsx index 49fe19ee..6a773ab8 100644 --- a/client/src/animations.utils.jsx +++ b/client/src/animations.utils.jsx @@ -85,22 +85,98 @@ function getSequence(resolution) { } } +const SOURCE_DURATION_MS = 1000; +const TARGET_DELAY_MS = 500; +const TARGET_DURATION_MS = 1500; +const POST_SKILL_DELAY_MS = 2000; +const POST_SKILL_DURATION_MS = 1000; +const SOURCE_AND_TARGET_TOTAL_DURATION = TARGET_DELAY_MS + TARGET_DURATION_MS + POST_SKILL_DURATION_MS; + function getTime(stages) { if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) { return TIMES.SOURCE_AND_TARGET_TOTAL_DURATION; } - if (stages.includes('START_SKILL')) return TIMES.SOURCE_DURATION_MS; - if (stages.includes('END_SKILL')) return TIMES.TARGET_DURATION_MS; - if (stages.includes('POST_SKILL')) return TIMES.POST_SKILL_DURATION_MS; + let time = 0; - return 0; + if (stages.includes('START_SKILL')) time += TIMES.SOURCE_DURATION_MS; + if (stages.includes('END_SKILL')) time += TIMES.TARGET_DURATION_MS; + if (stages.includes('POST_SKILL')) time += TIMES.POST_SKILL_DURATION_MS; + + return time; +} + +function getText(resolution, sequence) { + if (!resolution) return { text: null, constructId: null }; + if (!sequence.includes('POST_SKILL')) return { text: null, constructId: null }; + + function generateText() { + const [type, event] = resolution.event; + if (type === 'Ko') { + return 'KO!'; + } + + if (type === 'Disable') { + const { disable } = event; + return `${disable}`; + } + + if (type === 'Immunity') { + return 'IMMUNE'; + } + + if (type === 'Damage') { + const { mitigation, colour } = event; + let { amount } = event; + if (colour === 'Green') amount *= -1; + const mitigationText = mitigation + ? `(${mitigation})` + : ''; + return `${amount} ${mitigationText}`; + } + + if (type === 'Healing') { + const { amount, overhealing } = event; + return `${amount} (${overhealing} OH)`; + } + + if (type === 'Inversion') { + return 'INVERT'; + } + + if (type === 'Reflection') { + return 'REFLECT'; + } + + if (type === 'Effect') { + const { effect, duration } = event; + return `+ ${effect} ${duration}T`; + } + + if (type === 'Recharge') { + const { red, blue } = event; + return [`+${red}R ${blue}B`, '']; + } + + if (type === 'Removal') { + const { effect } = event; + return `-${effect}`; + } + + return false; + } + + return { + text: generateText(), + constructId: resolution.target.id, + }; } module.exports = { getObjects, getTime, getSequence, + getText, }; diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 7cd8899d..6eb08e69 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -140,6 +140,26 @@ class ConstructAvatar extends Component { } } + +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
{text}
; +} + module.exports = { ConstructAvatar: addState(ConstructAvatar), + ConstructText: addStateText(constructText), }; diff --git a/client/src/components/game.construct.jsx b/client/src/components/game.construct.jsx index 5e284e07..4569b4a1 100644 --- a/client/src/components/game.construct.jsx +++ b/client/src/components/game.construct.jsx @@ -3,8 +3,8 @@ const { Component } = require('preact'); const preact = require('preact'); const range = require('lodash/range'); -const { STATS, eventClasses, getCombatText } = require('../utils'); -const { ConstructAvatar } = require('./construct'); +const { STATS, eventClasses } = require('../utils'); +const { ConstructAvatar, ConstructText } = require('./construct'); const { ConstructAnimation } = require('./animations'); const shapes = require('./shapes'); @@ -20,9 +20,10 @@ const addState = connect( ws, game, account, - resolution, activeSkill, - avatarAnimation, + resolution, + + animText, } = state; function selectSkillTarget(targetConstructId) { @@ -40,22 +41,11 @@ const addState = connect( game, account, resolution, + animText, activeSkill, - avatarAnimation, selectSkillTarget, }; }, - - function receiveDispatch(dispatch) { - function setAvatarAnimation(source, target, id, animTargetId, type, params) { - return dispatch(actions.setAvatarAnimation({ source, target, id, animTargetId, type, params })); - } - - return { - setAvatarAnimation, - }; - } - ); @@ -72,9 +62,13 @@ class GameConstruct extends Component { account, construct, player, - resolution, activeSkill, selectSkillTarget, + + // todo remove dep + resolution, + + animText, } = this.props; const ko = construct.green_life.value === 0 ? 'ko' : ''; @@ -97,7 +91,7 @@ class GameConstruct extends Component { const effects = construct.effects.length ? construct.effects.map(c =>
{c.effect} - {c.duration}T
) :
 
; - const combatText = getCombatText(resolution, construct); + return (
selectSkillTarget(construct.id)} @@ -108,7 +102,7 @@ class GameConstruct extends Component {
{stats}
-
{combatText}
+
{effects}
); diff --git a/client/src/events.jsx b/client/src/events.jsx index 3843ea0c..074acd29 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -55,27 +55,36 @@ function registerEvents(store) { 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); const timeout = animations.getTime(sequence); const anims = animations.getObjects(r, sequence, game, account); + const text = animations.getText(r, sequence); - store.dispatch(actions.setAnimSource(anims.animSource)); - store.dispatch(actions.setAnimTarget(anims.animTarget)); + 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')) store.dispatch(actions.setAnimText(text)); return setTimeout(() => { store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); + store.dispatch(actions.setAnimText(null)); return setTimeout(cb, 50); - }, 3000); + }, timeout); }, err => { if (err) return console.error(err); // clear animation state store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); + store.dispatch(actions.setAnimText(null)); store.dispatch(actions.setAnimating(false)); + store.dispatch(actions.setSkip(false)); + store.dispatch(actions.setResolution(null)); + // set the game state so resolutions don't fire twice store.dispatch(actions.setGame(game)); ws.sendGameState(game.id); diff --git a/client/src/reducers.jsx b/client/src/reducers.jsx index 9a36cccf..398e3721 100644 --- a/client/src/reducers.jsx +++ b/client/src/reducers.jsx @@ -15,9 +15,12 @@ module.exports = { activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'), activeItem: createReducer(null, 'SET_ACTIVE_VAR'), activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'), + animating: createReducer(false, 'SET_ANIMATING'), animSource: createReducer(null, 'SET_ANIM_SOURCE'), animTarget: createReducer(null, 'SET_ANIM_TARGET'), + animText: createReducer(null, 'SET_ANIM_TEXT'), + combiner: createReducer([null, null, null], 'SET_COMBINER'), constructs: createReducer([], 'SET_CONSTRUCTS'), constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'), diff --git a/client/src/utils.jsx b/client/src/utils.jsx index f50dc7a3..58340adf 100644 --- a/client/src/utils.jsx +++ b/client/src/utils.jsx @@ -86,8 +86,7 @@ const STATS = { }; function eventClasses(game, account, resolution, construct) { - if (!resolution || resolution === 'clear') return ''; - const postSkill = resolution.stages.includes('POST_SKILL'); + if (!resolution) return ''; const source = construct.id === resolution.source.id; const target = construct.id === resolution.target.id; // not involved at all. blur them @@ -113,7 +112,7 @@ function eventClasses(game, account, resolution, construct) { if (type === 'Damage') { const { colour } = event; - if (target && postSkill) { + if (target) { construct.green_life.value = resolution.target.green; if (colour === 'Red') { construct.red_life.value = resolution.target.red; @@ -131,7 +130,7 @@ function eventClasses(game, account, resolution, construct) { } if (type === 'Healing') { - if (target && postSkill) { + if (target) { construct.green_life.value = resolution.target.green; return 'green-damage'; } @@ -139,17 +138,17 @@ function eventClasses(game, account, resolution, construct) { if (type === 'Effect') { const { construct_effects: constructEffects } = event; - if (target && postSkill) construct.effects = constructEffects; + if (target) construct.effects = constructEffects; } if (type === 'Removal') { const { construct_effects: constructEffects } = event; - if (target && postSkill) construct.effects = constructEffects; + if (target) construct.effects = constructEffects; } if (type === 'Recharge') { const { red, blue } = event; - if (target && postSkill) { + if (target) { if (red > 0 && blue > 0) { construct.red_life.value = resolution.target.red; construct.blue_life.value = resolution.target.blue; @@ -169,66 +168,6 @@ function eventClasses(game, account, resolution, construct) { return ''; } -function getCombatText(resolution, construct) { - if (!resolution || resolution === 'clear') return false; - if (!resolution.stages.includes('POST_SKILL')) return false; - if (construct.id !== resolution.target.id) return false; - - const [type, event] = resolution.event; - if (type === 'Ko') { - return 'KO!'; - } - - if (type === 'Disable') { - const { disable } = event; - return `${disable}`; - } - - if (type === 'Immunity') { - return 'IMMUNE'; - } - - if (type === 'Damage') { - const { mitigation, colour } = event; - let { amount } = event; - if (colour === 'Green') amount *= -1; - const mitigationText = mitigation - ? `(${mitigation})` - : ''; - return `${amount} ${mitigationText}`; - } - - if (type === 'Healing') { - const { amount, overhealing } = event; - return `${amount} (${overhealing} OH)`; - } - - if (type === 'Inversion') { - return 'INVERT'; - } - - if (type === 'Reflection') { - return 'REFLECT'; - } - - if (type === 'Effect') { - const { effect, duration } = event; - return `+ ${effect} ${duration}T`; - } - - if (type === 'Recharge') { - const { red, blue } = event; - return [`+${red}R ${blue}B`, '']; - } - - if (type === 'Removal') { - const { effect } = event; - return `-${effect}`; - } - - return false; -} - function convertItem(v) { if (['Red', 'Green', 'Blue'].includes(v)) { return ( @@ -378,7 +317,6 @@ module.exports = { convertItem, numSort, eventClasses, - getCombatText, postData, errorToast, NULL_UUID, From adf6700049aee25dd7c15b1cd5c911c7530d016f Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 19:07:03 +1000 Subject: [PATCH 08/17] ganba --- client/src/components/game.construct.jsx | 2 +- client/src/events.jsx | 7 ++++++- client/src/utils.jsx | 10 +++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/client/src/components/game.construct.jsx b/client/src/components/game.construct.jsx index 4569b4a1..41c30b8b 100644 --- a/client/src/components/game.construct.jsx +++ b/client/src/components/game.construct.jsx @@ -72,7 +72,7 @@ class GameConstruct extends Component { } = this.props; const ko = construct.green_life.value === 0 ? 'ko' : ''; - const classes = eventClasses(game, account, resolution, construct); + const classes = eventClasses(game, account, resolution, construct, animText); const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
diff --git a/client/src/events.jsx b/client/src/events.jsx index 074acd29..0c883262 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -66,7 +66,12 @@ function registerEvents(store) { 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')) store.dispatch(actions.setAnimText(text)); + if (sequence.includes('POST_SKILL')) { + setTimeout( + () => store.dispatch(actions.setAnimText(text)), + timeout - 1000, + ); + } return setTimeout(() => { store.dispatch(actions.setAnimSource(null)); diff --git a/client/src/utils.jsx b/client/src/utils.jsx index 58340adf..ad99728f 100644 --- a/client/src/utils.jsx +++ b/client/src/utils.jsx @@ -85,7 +85,7 @@ const STATS = { }, }; -function eventClasses(game, account, resolution, construct) { +function eventClasses(game, account, resolution, construct, postSkill) { if (!resolution) return ''; const source = construct.id === resolution.source.id; const target = construct.id === resolution.target.id; @@ -130,7 +130,7 @@ function eventClasses(game, account, resolution, construct) { } if (type === 'Healing') { - if (target) { + if (target && postSkill) { construct.green_life.value = resolution.target.green; return 'green-damage'; } @@ -138,17 +138,17 @@ function eventClasses(game, account, resolution, construct) { if (type === 'Effect') { const { construct_effects: constructEffects } = event; - if (target) construct.effects = constructEffects; + if (target && postSkill) construct.effects = constructEffects; } if (type === 'Removal') { const { construct_effects: constructEffects } = event; - if (target) construct.effects = constructEffects; + if (target && postSkill) construct.effects = constructEffects; } if (type === 'Recharge') { const { red, blue } = event; - if (target) { + if (target && postSkill) { if (red > 0 && blue > 0) { construct.red_life.value = resolution.target.red; construct.blue_life.value = resolution.target.blue; From 4ea3adcff3ea5afa6df6a283fba95bc4bef19e24 Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 19:10:44 +1000 Subject: [PATCH 09/17] comments --- client/src/events.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/events.jsx b/client/src/events.jsx index 0c883262..0b1b4fcd 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -67,6 +67,7 @@ function registerEvents(store) { 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, @@ -79,6 +80,7 @@ function registerEvents(store) { store.dispatch(actions.setAnimText(null)); return setTimeout(cb, 50); }, timeout); + }, err => { if (err) return console.error(err); // clear animation state From 2026530370396b8b1ad18a02b62f40a78eb334db Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 19:58:08 +1000 Subject: [PATCH 10/17] fix banish and invert --- client/assets/styles/game.css | 3 ++- client/src/animations.socket.jsx | 26 +++++++++++++++++++++----- client/src/components/anims/hybrid.jsx | 13 ++++++++----- client/src/components/construct.jsx | 16 +++++++++++----- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/client/assets/styles/game.css b/client/assets/styles/game.css index f0935718..f4898539 100644 --- a/client/assets/styles/game.css +++ b/client/assets/styles/game.css @@ -185,7 +185,7 @@ .game-construct.ko { animation: none; - opacity: 0.35; + opacity: 0.20; /* filter: grayscale(100%); */} @@ -199,6 +199,7 @@ */} .game-construct.unfocus.ko { + opacity: 0.20; /* filter: blur(5px) grayscale(100%); */} diff --git a/client/src/animations.socket.jsx b/client/src/animations.socket.jsx index 231a54b6..a7213957 100644 --- a/client/src/animations.socket.jsx +++ b/client/src/animations.socket.jsx @@ -32,30 +32,46 @@ function createSocket(store) { 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); const timeout = animations.getTime(sequence); const anims = animations.getObjects(r, sequence, game, account); + const text = animations.getText(r, sequence); - store.dispatch(actions.setAnimSource(anims.animSource)); - store.dispatch(actions.setAnimTarget(anims.animTarget)); + 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, + ); + } return setTimeout(() => { store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); + store.dispatch(actions.setAnimText(null)); return setTimeout(cb, 50); - }, 3000); + }, timeout); + }, err => { if (err) return console.error(err); + // clear animation state store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); + store.dispatch(actions.setAnimText(null)); store.dispatch(actions.setAnimating(false)); - // stop skipping resolutions store.dispatch(actions.setSkip(false)); + store.dispatch(actions.setResolution(null)); - // ws.sendGameState(currentGame.id); + // set the game state so resolutions don't fire twice + store.dispatch(actions.setGame(game)); + ws.sendGameState(game.id); return true; }); } diff --git a/client/src/components/anims/hybrid.jsx b/client/src/components/anims/hybrid.jsx index 5b0bce31..ddcb8a9e 100644 --- a/client/src/components/anims/hybrid.jsx +++ b/client/src/components/anims/hybrid.jsx @@ -33,7 +33,7 @@ class Hybrid extends Component { class="green-one" cx='50' cy='150' - r='10' + r="15" fill={COLOURS.GREEN} stroke="none" /> @@ -41,7 +41,7 @@ class Hybrid extends Component { class="green-two" cx='250' cy='150' - r='10' + r="15" fill={COLOURS.GREEN} stroke="none" /> @@ -49,7 +49,7 @@ class Hybrid extends Component { class="bluewhite-one" cx='150' cy='50' - r='10' + r="15" fill={COLOURS.BLUE} stroke="none" /> @@ -65,7 +65,7 @@ class Hybrid extends Component { class="bluewhite-two" cx='150' cy='250' - r='10' + r="15" fill={COLOURS.BLUE} stroke="none" /> @@ -77,7 +77,6 @@ class Hybrid extends Component { fill={COLOURS.WHITE} stroke="none" /> - ); @@ -100,6 +99,7 @@ class Hybrid extends Component { })); this.animations.push(anime({ + r: [10, anime.random(10, 30)], targets: ['#hybrid circle.green-one'], cx: [50, 250, 50, 250], delay: TIMES.TARGET_DELAY_MS, @@ -109,6 +109,7 @@ class Hybrid extends Component { })); this.animations.push(anime({ + r: [10, anime.random(10, 30)], targets: ['#hybrid circle.green-two'], cy: [250, 50, 250, 50], delay: TIMES.TARGET_DELAY_MS, @@ -118,6 +119,7 @@ class Hybrid extends Component { })); this.animations.push(anime({ + r: [10, anime.random(10, 30)], targets: ['#hybrid circle.bluewhite-one'], fill: [COLOURS.WHITE, COLOURS.BLUE], cy: [50, 250, 50, 250], @@ -128,6 +130,7 @@ class Hybrid extends Component { })); this.animations.push(anime({ + r: [10, anime.random(10, 30)], targets: ['#hybrid circle.bluewhite-two'], cx: [250, 50, 250, 50], fill: [COLOURS.WHITE, COLOURS.BLUE], diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 6eb08e69..7c3306c1 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -88,8 +88,8 @@ class ConstructAvatar extends Component { } switch (animTarget.skill) { - case 'banish': return banish(construct.id); - case 'invert': return invert(construct.id); + case 'Banish': return banish(construct.id); + case 'Invert': return invert(construct.id); default: return null; } }; @@ -112,8 +112,8 @@ class ConstructAvatar extends Component { this.resetAnimations(); } - shouldComponentUpdate({ animSource, construct }) { - if (animSource === this.props.animSource) { + shouldComponentUpdate({ animSource, animTarget, construct }) { + if (animSource === this.props.animSource && animTarget === this.props.animTarget) { // console.warn(construct.name, 'thinks its same props') return false; } @@ -128,12 +128,18 @@ class ConstructAvatar extends Component { } // this is the target - // if (animTarget && animTarget.constructId === construct.id) return true; + 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; From 9f0c21264302049e3f4703a8e76b7eeefa861354 Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 20:16:27 +1000 Subject: [PATCH 11/17] serialize stages as strings --- client/src/animations.utils.jsx | 15 ++++--- server/src/skill.rs | 80 ++++++++++++++++----------------- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/client/src/animations.utils.jsx b/client/src/animations.utils.jsx index 6a773ab8..70d4cc68 100644 --- a/client/src/animations.utils.jsx +++ b/client/src/animations.utils.jsx @@ -74,13 +74,14 @@ function getSequence(resolution) { if (resolution.event[0] === 'Ko') return ['POST_SKILL']; switch (resolution.stages) { - case 1: return ['START_SKILL', 'END_SKILL']; - case 2: return ['START_SKILL', 'POST_SKILL']; - case 3: return ['START_SKILL']; - case 4: return ['END_SKILL', 'POST_SKILL']; - case 5: return ['END_SKILL']; - case 6: return ['POST_SKILL']; - case 7: return []; + case 'AllStages': return ['START_SKILL', 'END_SKILL', 'POST_SKILL']; + case 'StartEnd': return ['START_SKILL', 'END_SKILL']; + case 'StartPost': return ['START_SKILL', 'POST_SKILL']; + case 'StartOnly': return ['START_SKILL']; + case 'EndPost': return ['END_SKILL', 'POST_SKILL']; + case 'EndOnly': return ['END_SKILL']; + case 'PostOnly': return ['POST_SKILL']; + case 'None': return []; default: return ['START_SKILL', 'END_SKILL', 'POST_SKILL']; } } diff --git a/server/src/skill.rs b/server/src/skill.rs index 3b9f180f..206a3f83 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -405,15 +405,15 @@ pub struct EventConstruct { } #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] -pub enum LogStages { - AllStages, // 0 Anim Anim Anim - StartEnd, // 1 Anim Anim Skip - StartPost, // 2 Anim Skip Anim - StartOnly, // 3 Anim Skip Skip - EndPost, // 4 Skip Anim Anim - EndOnly, // 5 Skip Anim Skip - PostOnly, // 6 Skip Skip Anim - None, // 7 Skip Skip Skip +pub enum EventStages { + AllStages, // Anim Anim Anim + StartEnd, // Anim Anim Skip + StartPost, // Anim Skip Anim + StartOnly, // Anim Skip Skip + EndPost, // Skip Anim Anim + EndOnly, // Skip Anim Skip + PostOnly, // Skip Skip Anim + None, // Skip Skip Skip } #[derive(Debug,Clone,PartialEq,Serialize,Deserialize)] @@ -421,7 +421,7 @@ pub struct Resolution { pub source: EventConstruct, pub target: EventConstruct, pub event: Event, - pub stages: u8, + pub stages: EventStages, } impl Resolution { @@ -440,7 +440,7 @@ impl Resolution { blue: target.blue_life(), }, event: Event::Incomplete, - stages: LogStages::AllStages as u8, + stages: EventStages::AllStages, } } @@ -449,8 +449,8 @@ impl Resolution { self } - fn stages(mut self, s: LogStages) -> Resolution { - self.stages = s as u8; + fn stages(mut self, s: EventStages) -> Resolution { + self.stages = s; self } } @@ -1268,7 +1268,7 @@ fn bash(source: &mut Construct, target: &mut Construct, mut results: Resolutions let amount = source.red_power().pct(skill.multiplier().pct(100 + 45u64.saturating_mul(cds))); target.deal_red_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly))); } return results; @@ -1282,7 +1282,7 @@ fn sleep(source: &mut Construct, target: &mut Construct, mut results: Resolution let amount = source.green_power().pct(skill.multiplier()); target.deal_green_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly))); return results; } @@ -1298,7 +1298,7 @@ fn intercept(source: &mut Construct, target: &mut Construct, mut results: Resolu results.push(Resolution::new(source, target).event(target.recharge(skill, red_amount, 0))); let intercept = skill.effect()[0]; - results.push(Resolution::new(source, target).event(target.add_effect(skill, intercept)).stages(LogStages::PostOnly)); + results.push(Resolution::new(source, target).event(target.add_effect(skill, intercept)).stages(EventStages::PostOnly)); return results; } @@ -1306,7 +1306,7 @@ fn break_(source: &mut Construct, target: &mut Construct, mut results: Resolutio let stun = skill.effect()[0]; results.push(Resolution::new(source, target).event(target.add_effect(skill, stun))); let vuln = skill.effect()[1]; - results.push(Resolution::new(source, target).event(target.add_effect(skill, vuln)).stages(LogStages::PostOnly)); + results.push(Resolution::new(source, target).event(target.add_effect(skill, vuln)).stages(EventStages::PostOnly)); return results; } @@ -1314,7 +1314,7 @@ fn break_(source: &mut Construct, target: &mut Construct, mut results: Resolutio fn block(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { results.push(Resolution::new(source, target) .event(target.add_effect(skill, skill.effect()[0])) - .stages(LogStages::StartEnd)); + .stages(EventStages::StartEnd)); return results; } @@ -1328,11 +1328,11 @@ fn counter(source: &mut Construct, target: &mut Construct, mut results: Resoluti let red_amount = source.red_power().pct(skill.multiplier()); results.push(Resolution::new(source, target) .event(target.recharge(skill, red_amount, 0)) - .stages(LogStages::StartEnd)); + .stages(EventStages::StartEnd)); results.push(Resolution::new(source, target) .event(target.add_effect(skill, skill.effect()[0])) - .stages(LogStages::PostOnly)); + .stages(EventStages::PostOnly)); return results; } @@ -1341,7 +1341,7 @@ fn riposte(source: &mut Construct, target: &mut Construct, mut results: Resoluti let amount = source.red_power().pct(skill.multiplier()); target.deal_red_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::StartPost))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::StartPost))); return results; } @@ -1360,7 +1360,7 @@ fn restrict(source: &mut Construct, target: &mut Construct, mut results: Resolut let amount = source.red_power().pct(skill.multiplier()).pct(s_multi); target.deal_red_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly))); return results; @@ -1376,7 +1376,7 @@ fn slay(source: &mut Construct, target: &mut Construct, mut results: Resolutions results.push(Resolution::new(source, target).event(e)); let heal = source.deal_green_damage(skill, amount); for h in heal { - results.push(Resolution::new(source, source).event(h).stages(LogStages::PostOnly)); + results.push(Resolution::new(source, source).event(h).stages(EventStages::PostOnly)); }; }, _ => results.push(Resolution::new(source, target).event(e)), @@ -1409,7 +1409,7 @@ fn triage_tick(source: &mut Construct, target: &mut Construct, mut results: Reso let amount = source.green_power().pct(skill.multiplier()); target.deal_green_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost))); return results; } @@ -1424,7 +1424,7 @@ fn chaos(source: &mut Construct, target: &mut Construct, mut results: Resolution let amount = source.red_power().pct(skill.multiplier()).pct(r_rng); target.deal_red_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly))); return results; } @@ -1464,7 +1464,7 @@ fn decay(source: &mut Construct, target: &mut Construct, mut results: Resolution let decay = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill)); results.push(Resolution::new(source, target) .event(target.add_effect(skill, decay)) - .stages(LogStages::PostOnly)); + .stages(EventStages::PostOnly)); return decay_tick(source, target, results, tick_skill); } @@ -1473,7 +1473,7 @@ fn decay_tick(source: &mut Construct, target: &mut Construct, mut results: Resol let amount = source.blue_power().pct(skill.multiplier()); target.deal_blue_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost))); return results; } @@ -1495,7 +1495,7 @@ fn electrocute(source: &mut Construct, target: &mut Construct, mut results: Reso let electrocute = ConstructEffect::new(effect, duration).set_tick(Cast::new_tick(source, target, tick_skill)); results.push(Resolution::new(source, target) .event(target.add_effect(skill, electrocute)) - .stages(LogStages::StartPost)); + .stages(EventStages::StartPost)); return electrocute_tick(source, target, results, tick_skill); } @@ -1503,14 +1503,14 @@ fn electrocute_tick(source: &mut Construct, target: &mut Construct, mut results: let amount = source.blue_power().pct(skill.multiplier()); target.deal_blue_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost))); return results; } fn ruin(source: &mut Construct, target: &mut Construct, mut results: Resolutions, skill: Skill) -> Resolutions { results.push(Resolution::new(source, target) .event(target.add_effect(skill, skill.effect()[0])) - .stages(LogStages::PostOnly)); + .stages(EventStages::PostOnly)); return results;; } @@ -1529,7 +1529,7 @@ fn absorption(source: &mut Construct, target: &mut Construct, mut results: Resol let absorb = skill.effect()[0].set_meta(EffectMeta::AddedDamage(amount)); results.push(Resolution::new(source, target) .event(target.add_effect(reflect_skill, absorb)) - .stages(LogStages::PostOnly)); + .stages(EventStages::PostOnly)); return results;; } @@ -1554,7 +1554,7 @@ fn reflect(source: &mut Construct, target: &mut Construct, mut results: Resoluti let blue_amount = source.blue_power().pct(skill.multiplier()); results.push(Resolution::new(source, target) .event(target.recharge(skill, 0, blue_amount)) - .stages(LogStages::PostOnly)); + .stages(EventStages::PostOnly)); return results;; } @@ -1586,13 +1586,13 @@ fn siphon_tick(source: &mut Construct, target: &mut Construct, mut results: Reso for e in siphon_events { match e { Event::Damage { amount, mitigation: _, colour: _, skill: _ } => { - results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)); + results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost)); let heal = source.deal_green_damage(skill, amount); for h in heal { - results.push(Resolution::new(source, source).event(h).stages(LogStages::PostOnly)); + results.push(Resolution::new(source, source).event(h).stages(EventStages::PostOnly)); }; }, - _ => results.push(Resolution::new(source, target).event(e).stages(LogStages::EndPost)), + _ => results.push(Resolution::new(source, target).event(e).stages(EventStages::EndPost)), } } @@ -1604,7 +1604,7 @@ fn link(source: &mut Construct, target: &mut Construct, mut results: Resolutions results.push(Resolution::new(source, target).event(target.recharge(skill, 0, blue_amount))); let link = skill.effect()[0].set_meta(EffectMeta::LinkTarget(target.id)); - results.push(Resolution::new(source, target).event(source.add_effect(skill, link)).stages(LogStages::PostOnly)); + results.push(Resolution::new(source, target).event(source.add_effect(skill, link)).stages(EventStages::PostOnly)); return results; } @@ -1625,7 +1625,7 @@ fn link_hit(source: &Construct, target: &Construct, mut results: Resolutions, ga results.push(Resolution::new(target, link_target).event(Event::Skill { skill: Skill::LinkI })); res.into_iter().for_each(|e| results.push(Resolution::new(&source, &link_target) - .event(e).stages(LogStages::EndPost))); + .event(e).stages(EventStages::EndPost))); } else { panic!("not a link target {:?}", link); } @@ -1649,7 +1649,7 @@ fn silence(source: &mut Construct, target: &mut Construct, mut results: Resoluti let amount = source.blue_power().pct(skill.multiplier()).pct(s_multi); target.deal_blue_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly))); return results; } @@ -1700,10 +1700,10 @@ fn purify(source: &mut Construct, target: &mut Construct, mut results: Resolutio let ce = target.effects.remove(i); results.push(Resolution::new(source, target) .event(Event::Removal { effect: ce.effect, construct_effects: target.effects.clone() }) - .stages(LogStages::PostOnly)); + .stages(EventStages::PostOnly)); target.deal_green_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(LogStages::PostOnly))); + .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::PostOnly))); } return results; From 3f1367172d653a71acef5428bb0695a21deedc12 Mon Sep 17 00:00:00 2001 From: ntr Date: Fri, 19 Jul 2019 20:46:38 +1000 Subject: [PATCH 12/17] fix construct img reloads --- client/src/animations.socket.jsx | 1 - client/src/components/anims/sleep.jsx | 4 ---- client/src/components/construct.jsx | 4 ++++ client/src/events.jsx | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/client/src/animations.socket.jsx b/client/src/animations.socket.jsx index a7213957..fb0666b4 100644 --- a/client/src/animations.socket.jsx +++ b/client/src/animations.socket.jsx @@ -71,7 +71,6 @@ function createSocket(store) { // set the game state so resolutions don't fire twice store.dispatch(actions.setGame(game)); - ws.sendGameState(game.id); return true; }); } diff --git a/client/src/components/anims/sleep.jsx b/client/src/components/anims/sleep.jsx index f426d83b..a7d6be6b 100644 --- a/client/src/components/anims/sleep.jsx +++ b/client/src/components/anims/sleep.jsx @@ -70,10 +70,6 @@ class Sleep extends Component { } componentDidMount() { - anime.set('#sleep', { - translateY: 75, - }); - this.animations.push(anime({ targets: ['#sleep'], opacity: [ diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 7c3306c1..b6793d82 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -113,6 +113,10 @@ class ConstructAvatar extends Component { } 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; diff --git a/client/src/events.jsx b/client/src/events.jsx index 0b1b4fcd..f0a93581 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -78,7 +78,7 @@ function registerEvents(store) { store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimTarget(null)); store.dispatch(actions.setAnimText(null)); - return setTimeout(cb, 50); + return cb(); }, timeout); }, err => { From 145f8e6a3589be3c9e7fbc92986e19c0c7890cdb Mon Sep 17 00:00:00 2001 From: ntr Date: Sat, 20 Jul 2019 18:04:08 +1000 Subject: [PATCH 13/17] wip" --- client/assets/styles/game.css | 4 + client/assets/styles/instance.css | 4 +- client/assets/styles/vbox.less | 49 +++++++ client/index.js | 1 + client/package.json | 3 +- client/src/components/instance.constructs.jsx | 2 +- client/src/components/nav.jsx | 7 - client/src/components/shapes.jsx | 3 +- client/src/components/svgs/vbox.colour.jsx | 15 ++ client/src/components/vbox.component.jsx | 128 +++++++++--------- server/src/construct.rs | 2 +- server/src/names.rs | 11 +- 12 files changed, 151 insertions(+), 78 deletions(-) create mode 100644 client/assets/styles/vbox.less create mode 100644 client/src/components/svgs/vbox.colour.jsx diff --git a/client/assets/styles/game.css b/client/assets/styles/game.css index f4898539..d6ccd3d8 100644 --- a/client/assets/styles/game.css +++ b/client/assets/styles/game.css @@ -454,4 +454,8 @@ #mnml .game .skills button, #mnml .game .stats { font-size: 75%; } + + .game-construct .name { + display: none; + } } \ No newline at end of file diff --git a/client/assets/styles/instance.css b/client/assets/styles/instance.css index d1b666b5..759454ab 100644 --- a/client/assets/styles/instance.css +++ b/client/assets/styles/instance.css @@ -164,7 +164,7 @@ } } -.vbox button { +.vbox-btn { width: 100%; margin: 0; background-color: #333; @@ -179,7 +179,7 @@ cursor: pointer; } -.vbox-table td:active { +.vbox-table td:active, .vbox-table td:focus { background: whitesmoke; color: black; } diff --git a/client/assets/styles/vbox.less b/client/assets/styles/vbox.less new file mode 100644 index 00000000..6da095e6 --- /dev/null +++ b/client/assets/styles/vbox.less @@ -0,0 +1,49 @@ +@green: #1FF01F; +@red: #a52a2a; +@blue: #3498db; +@white: #f5f5f5; // whitesmoke +@purple: #9355b5; // 6lack - that far cover + +.vbox-vbox { + grid-area: vbox; + + display: flex; + flex-flow: column; + + .vbox-colours { + display: grid; + grid-template-columns: repeat(6, 1fr); + grid-gap: 1em; + align-items: center; + margin: 1em 0; + + svg { + width: 100%; + stroke: none; + border: 2px solid #222; + } + + svg.red { + fill: @red; + } + + svg.green { + fill: @green; + } + + .blue { + fill: @blue; + } + } + + .vbox-skills, .vbox-specs { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 1em; + align-items: center; + + button { + width: 100%; + } + } +} diff --git a/client/index.js b/client/index.js index 8f409800..636aa1df 100644 --- a/client/index.js +++ b/client/index.js @@ -1,6 +1,7 @@ require('./assets/styles/styles.css'); require('./assets/styles/styles.mobile.css'); require('./assets/styles/instance.css'); +require('./assets/styles/vbox.less'); require('./assets/styles/instance.mobile.css'); require('./assets/styles/game.css'); diff --git a/client/package.json b/client/package.json index 1b7ef7c6..842310a9 100644 --- a/client/package.json +++ b/client/package.json @@ -40,7 +40,8 @@ "eslint-config-airbnb-base": "^13.1.0", "eslint-plugin-import": "^2.14.0", "eslint-plugin-react": "^7.11.1", - "jest": "^18.0.0" + "jest": "^18.0.0", + "less": "^3.9.0" }, "alias": { "react": "preact-compat", diff --git a/client/src/components/instance.constructs.jsx b/client/src/components/instance.constructs.jsx index a7eb6b53..9b79cb4a 100644 --- a/client/src/components/instance.constructs.jsx +++ b/client/src/components/instance.constructs.jsx @@ -140,7 +140,7 @@ function Construct(props) { ); }); - const specs = range(0, 6).map(i => { + const specs = range(0, 3).map(i => { const s = construct.specs[i]; if (!s) { diff --git a/client/src/components/nav.jsx b/client/src/components/nav.jsx index 30fd9981..d658a6de 100644 --- a/client/src/components/nav.jsx +++ b/client/src/components/nav.jsx @@ -26,10 +26,6 @@ const addState = connect( return ws.sendInstanceState(instance.id); } - function sendAccountInstances() { - return ws.sendAccountInstances(); - } - function sendInstanceList() { return ws.sendInstanceList(); } @@ -41,7 +37,6 @@ const addState = connect( game, ping, sendInstanceState, - sendAccountInstances, sendInstanceList, }; }, @@ -90,7 +85,6 @@ function Nav(args) { team, sendInstanceState, - sendAccountInstances, sendInstanceList, setTestGame, @@ -102,7 +96,6 @@ function Nav(args) { function navTo(p) { if (p === 'list') { sendInstanceList(); - sendAccountInstances(); } return setNav(p); } diff --git a/client/src/components/shapes.jsx b/client/src/components/shapes.jsx index 1693937a..954bcb46 100644 --- a/client/src/components/shapes.jsx +++ b/client/src/components/shapes.jsx @@ -6,7 +6,8 @@ const saw = require('./svgs/saw'); const square = require('./svgs/square'); const squircle = require('./svgs/squircle'); const triangle = require('./svgs/triangle'); -const vboxColour = require('./svgs/colour'); +// const vboxColour = require('./svgs/colour'); +const vboxColour = require('./svgs/vbox.colour'); module.exports = { circle, diff --git a/client/src/components/svgs/vbox.colour.jsx b/client/src/components/svgs/vbox.colour.jsx new file mode 100644 index 00000000..575d0c77 --- /dev/null +++ b/client/src/components/svgs/vbox.colour.jsx @@ -0,0 +1,15 @@ +const preact = require('preact'); + +module.exports = function vboxColour(colour) { + return ( + + + + ); +}; diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index df097afd..62cee0af 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -124,15 +124,15 @@ function Vbox(args) { // // VBOX // - const free = []; + // const free = []; - // Colours - free.push([vbox.free[0][0], vbox.free[0][1], vbox.free[0][2]]); - free.push([vbox.free[0][3], vbox.free[0][4], vbox.free[0][5]]); - // Skills - free.push([vbox.free[1][0], vbox.free[1][1], vbox.free[1][2]]); - // Specs - free.push([vbox.free[2][0], vbox.free[2][1], vbox.free[2][2]]); + // // Colours + // free.push([vbox.free[0][0], vbox.free[0][1], vbox.free[0][2]]); + // free.push([vbox.free[0][3], vbox.free[0][4], vbox.free[0][5]]); + // // Skills + // free.push([vbox.free[1][0], vbox.free[1][1], vbox.free[1][2]]); + // // Specs + // free.push([vbox.free[2][0], vbox.free[2][1], vbox.free[2][2]]); let vboxTimer; const LONG_TOUCH_TIME = 500; @@ -165,32 +165,65 @@ function Vbox(args) { return true; } - const freeRows = free.map((row, i) => { - const cells = row.map((c, j) => { - const highlighted = c && vboxHighlight.includes(c); - // First two rows are colours - const sendItemType = i > 1 ? i - 1 : 0; - const sendItemIndex = i === 1 ? j + 3 : j; - return vboxTouchStart(e, i, j)} - onTouchEnd={e => vboxTouchEnd(e, i, j)} - onTouchMove={e => vboxTouchMove(e)} + const vboxBtn = v => ( + + ); - // onClick={freeClick} - onDblClick={() => sendVboxAccept(sendItemType, sendItemIndex) } - onMouseOver={e => vboxHover(e, c)} - > - {convertItem(c)} - ; - }); + function vboxElement() { return ( - - {cells} - +
setReclaiming(false)} + onMouseOver={e => hoverInfo(e, 'vbox')}> +
+

e.target.scrollIntoView(true)}>VBOX

+
hoverInfo(e, 'bits')} >{vbox.bits}b
+
+
+ {vbox.free[0].map(shapes.vboxColour)} +
+
+ {vbox.free[1].map(vboxBtn)} +
+
+ {vbox.free[2].map(vboxBtn)} +
+ + +
); - }); + } + + // const freeRows = free.map((row, i) => { + // const cells = row.map((c, j) => { + // const highlighted = c && vboxHighlight.includes(c); + // // First two rows are colours + // const sendItemType = i > 1 ? i - 1 : 0; + // const sendItemIndex = i === 1 ? j + 3 : j; + // return vboxTouchStart(e, i, j)} + // onTouchEnd={e => vboxTouchEnd(e, i, j)} + // onTouchMove={e => vboxTouchMove(e)} + + // // onClick={freeClick} + // onDblClick={() => sendVboxAccept(sendItemType, sendItemIndex) } + // onMouseOver={e => vboxHover(e, c)} + // > + // {convertItem(c)} + // ; + // }); + // return ( + // + // {cells} + // + // ); + // }); // // INVENTORY @@ -293,37 +326,7 @@ function Vbox(args) { return (
-
setReclaiming(false)} - onMouseOver={e => hoverInfo(e, 'vbox')}> -
-

e.target.scrollIntoView(true)}>VBOX

-
hoverInfo(e, 'bits')} >{vbox.bits}b
-
-
Colours
- - - {freeRows.slice(0, 2)} - -
-
Skills
- - - {freeRows[2]} - -
-
Specs
- - - {freeRows[3]} - -
- -
+ {vboxElement()}
hoverInfo(e, 'combiner')} > {combinerElement}
- {vbox.free[0].map(shapes.vboxColour)} + {range(0, 6).map(i => boundBtn(vbox.free[0][i], 0, i))}
-
- {vbox.free[1].map(vboxBtn)} +
+ {range(0, 3).map(i => boundBtn(vbox.free[1][i], 1, i))} + {range(0, 3).map(i => boundBtn(vbox.free[2][i], 2, i))}
-
- {vbox.free[2].map(vboxBtn)} -
-
); @@ -240,72 +234,70 @@ function Vbox(args) { return false; } - const boundTds = range(0, 9).map(i => { - const value = vbox.bound[i]; - if (combiner.indexOf(i) > -1) { + // const boundTds = range(0, 9).map(i => { + // const value = vbox.bound[i]; + // if (combiner.indexOf(i) > -1) { + // return ( + // + //   + // + // ); + // } + + // const highlighted = value && vboxHighlight.includes(value); + + // return ( + // vboxHover(e, value)} + // onClick={e => boundClick(e, i, highlighted) }> + // {convertItem(value)} + // + // ); + // }); + + function inventoryBtn(v, i) { + if (!v) return ; + + if (['Red', 'Green', 'Blue'].includes(v)) { return ( - -   - + ); } - const highlighted = value && vboxHighlight.includes(value); - - return ( - vboxHover(e, value)} - onClick={e => boundClick(e, i, highlighted) }> - {convertItem(value)} - - ); - }); - - const boundRows = [ - - {boundTds[0]} - {boundTds[1]} - {boundTds[2]} - , - - {boundTds[3]} - {boundTds[4]} - {boundTds[5]} - , - - {boundTds[6]} - {boundTds[7]} - {boundTds[8]} - , - ]; - - // - // COMBINER - // - function combinerRmv(i) { - combiner[i] = null; - return combinerChange(combiner); + return ; + } + + + function inventoryElement() { + return ( +
setReclaiming(false)} + onMouseOver={e => hoverInfo(e, 'inventory')}> +
+

e.target.scrollIntoView(true)}>INVENTORY

+ +
+
+ {range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))} +
+ +
+ ); } - const combinerElement = ( - - - - - - - - -
combinerRmv(0)}> - {combiner[0] !== null ? convertItem(vbox.bound[combiner[0]]) : shapes.vboxColour('gray')} - combinerRmv(1)}> - {combiner[1] !== null ? convertItem(vbox.bound[combiner[1]]) : shapes.vboxColour('gray')} - combinerRmv(2)}> - {convertItem(vbox.bound[combiner[2]])} -
- ); // // EVERYTHING @@ -321,42 +313,14 @@ function Vbox(args) { return setInfo(info); } - const classes = "vbox"; + const classes = 'vbox'; const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`; return (
{vboxElement()}
-
-
setReclaiming(false)} - onMouseOver={e => hoverInfo(e, 'inventory')}> -
-

e.target.scrollIntoView(true)}>INVENTORY

- -
- - - {boundRows} - -
-
-
e.target.scrollIntoView(true)}>⮟⮝
-
hoverInfo(e, 'combiner')} > - {combinerElement} - -
+ {inventoryElement()}
); } diff --git a/client/src/reducers.jsx b/client/src/reducers.jsx index 398e3721..3366bcaa 100644 --- a/client/src/reducers.jsx +++ b/client/src/reducers.jsx @@ -44,5 +44,8 @@ module.exports = { shop: createReducer(false, 'SET_SHOP'), team: createReducer([null, null, null], 'SET_SELECTED_CONSTRUCTS'), vboxHighlight: createReducer([], 'SET_VBOX_HIGHLIGHT'), + + vboxSelected: createReducer([], 'SET_VBOX_SELECTED'), + ws: createReducer(null, 'SET_WS'), }; diff --git a/client/src/utils.jsx b/client/src/utils.jsx index ad99728f..9dbf20d2 100644 --- a/client/src/utils.jsx +++ b/client/src/utils.jsx @@ -168,20 +168,6 @@ function eventClasses(game, account, resolution, construct, postSkill) { return ''; } -function convertItem(v) { - if (['Red', 'Green', 'Blue'].includes(v)) { - return ( - shapes.vboxColour(v.toLowerCase()) - ); - } - return v ||  ; - // uncomment for double borders in vbox; - // if (v) { - // return
{v}
; - // } - // return; -} - const COLOURS = [ '#a52a2a', '#1FF01F', @@ -314,7 +300,6 @@ function errorToast(message) { module.exports = { stringSort, - convertItem, numSort, eventClasses, postData, diff --git a/server/src/names.rs b/server/src/names.rs index c972cf8c..67c6e918 100644 --- a/server/src/names.rs +++ b/server/src/names.rs @@ -1,12 +1,14 @@ use rand::prelude::*; use rand::{thread_rng}; -const FIRSTS: [&'static str; 28] = [ +const FIRSTS: [&'static str; 33] = [ "artificial", + "ambient", "borean", "brewing", "bristling", "compressed", + "chromatic", "concave", "convex", "distorted", @@ -18,8 +20,11 @@ const FIRSTS: [&'static str; 28] = [ "metallic", "mossy", "mighty", + "modulated", "nocturnal", + "noisy", "nutritious", + "powerful", "obscure", "organic", "piscine", @@ -32,16 +37,19 @@ const FIRSTS: [&'static str; 28] = [ "weary", ]; -const LASTS: [&'static str; 36] = [ +const LASTS: [&'static str; 41] = [ "artifact", "assembly", "console", "construct", "design", + "drone", + "energy", "entropy", "foilage", "forest", "form", + "fossil", "frequency", "function", "information", @@ -52,19 +60,21 @@ const LASTS: [&'static str; 36] = [ "mountain", "nectar", "oak", + "pattern", "plant", "poseidon", "problem", + "receiver", "replicant", "river", "river", + "scaffold", "shape", "signal", + "synthesiser", + "system", "tower", "transmitter", - "scaffold", - "pattern", - "receiver", "traveller", "warning", "wildlife", From c69182b94e4345d9a826678f067864c3660c0b5b Mon Sep 17 00:00:00 2001 From: ntr Date: Sat, 20 Jul 2019 22:30:03 +1000 Subject: [PATCH 15/17] new combiner --- client/assets/styles/vbox.less | 35 +++--- client/src/components/vbox.component.jsx | 140 +++++++++++++---------- client/src/utils.jsx | 14 +++ 3 files changed, 116 insertions(+), 73 deletions(-) diff --git a/client/assets/styles/vbox.less b/client/assets/styles/vbox.less index 7cbb9073..42c6999b 100644 --- a/client/assets/styles/vbox.less +++ b/client/assets/styles/vbox.less @@ -71,27 +71,34 @@ button { height: 3em; margin: 0; - } - button.empty { - border-style: dashed; + &.empty { + border-style: dashed; + } + + &.highlight { + color: black; + background: @white; + border: 1px solid @white; + } } svg { stroke: none; margin: 0 auto; display: block; + + &.red { + fill: @red; + } + + &.green { + fill: @green; + } + + &.blue { + fill: @blue; + } } - svg.red { - fill: @red; - } - - svg.green { - fill: @green; - } - - .blue { - fill: @blue; - } } diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index af2664dd..3f8b9fa4 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -1,5 +1,6 @@ const preact = require('preact'); const range = require('lodash/range'); +const without = require('lodash/without'); const { connect } = require('preact-redux'); const shapes = require('./shapes'); @@ -142,7 +143,7 @@ function Vbox(args) { return true; } - function boundBtn(v, group, index) { + function availableBtn(v, group, index) { if (!v) return ; function onClick() { @@ -158,11 +159,21 @@ function Vbox(args) { if (['Red', 'Green', 'Blue'].includes(v)) { return ( - + ); } - return ; + return ( + + ); } @@ -176,11 +187,11 @@ function Vbox(args) {
hoverInfo(e, 'bits')} >{vbox.bits}b
- {range(0, 6).map(i => boundBtn(vbox.free[0][i], 0, i))} + {range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))}
- {range(0, 3).map(i => boundBtn(vbox.free[1][i], 1, i))} - {range(0, 3).map(i => boundBtn(vbox.free[2][i], 2, i))} + {range(0, 3).map(i => availableBtn(vbox.free[1][i], 1, i))} + {range(0, 3).map(i => availableBtn(vbox.free[2][i], 2, i))}
; + function onClick(e) { + if (reclaiming) return sendVboxReclaim(i); + + const combinerIndex = combiner.indexOf(i); + if (combinerIndex > -1) { + return combinerChange(without(combiner, i)); + } + + combiner.push(i); + return combinerChange(combiner); + } + + const highlighted = combiner.indexOf(i) > -1; + const classes = `${highlighted ? 'highlight' : ''}`; + if (['Red', 'Green', 'Blue'].includes(v)) { return ( - + ); } - return ; + return ( + + ); } + function combinerBtn() { + const dots = combiner.filter(v => v).length; + let text = ''; + + if (dots < 3) { + for (let i = 0; i < 3; i++) { + if (dots > i) { + text += '■ '; + } else { + text += '▫ '; + } + } + } else { + text = 'combine' + } + + return ( + + ); + } function inventoryElement() { return ( @@ -288,13 +322,7 @@ function Vbox(args) {
{range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))}
- + {combinerBtn()}
); } @@ -303,10 +331,6 @@ function Vbox(args) { // EVERYTHING // - function reclaimClick(e) { - e.stopPropagation(); - return setReclaiming(!reclaiming); - } function hoverInfo(e, info) { e.stopPropagation(); @@ -314,8 +338,6 @@ function Vbox(args) { } const classes = 'vbox'; - const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`; - return (
{vboxElement()} diff --git a/client/src/utils.jsx b/client/src/utils.jsx index 9dbf20d2..bb0717ab 100644 --- a/client/src/utils.jsx +++ b/client/src/utils.jsx @@ -297,12 +297,26 @@ function errorToast(message) { }); } +function convertItem(v) { + if (['Red', 'Green', 'Blue'].includes(v)) { + return ( + shapes.vboxColour(v.toLowerCase()) + ); + } + return v ||  ; + // uncomment for double borders in vbox; + // if (v) { + // return
{v}
; + // } + // return; +} module.exports = { stringSort, numSort, eventClasses, postData, + convertItem, errorToast, NULL_UUID, STATS, From 4ab8e99f1d52dbdfc02e536012dbe5c993c2165e Mon Sep 17 00:00:00 2001 From: ntr Date: Sat, 20 Jul 2019 22:44:36 +1000 Subject: [PATCH 16/17] fix boolean 0 check bullshit --- client/src/components/vbox.component.jsx | 11 +++++------ client/src/events.jsx | 4 ++-- client/src/keyboard.jsx | 2 +- client/src/reducers.jsx | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 3f8b9fa4..2633d593 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -240,7 +240,7 @@ function Vbox(args) { const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`; function inventoryBtn(v, i) { - if (!v) return ; + if (!v && v !== 0) return ; function onClick(e) { if (reclaiming) return sendVboxReclaim(i); @@ -279,25 +279,24 @@ function Vbox(args) { } function combinerBtn() { - const dots = combiner.filter(v => v).length; let text = ''; - if (dots < 3) { + if (combiner.length < 3) { for (let i = 0; i < 3; i++) { - if (dots > i) { + if (combiner.length > i) { text += '■ '; } else { text += '▫ '; } } } else { - text = 'combine' + text = 'combine'; } return (