This commit is contained in:
ntr 2019-07-18 22:41:29 +10:00
parent 860c70c4a1
commit 028606e804
11 changed files with 371 additions and 259 deletions

View File

@ -1,6 +1,7 @@
export const setAccount = value => ({ type: 'SET_ACCOUNT', value }); export const setAccount = value => ({ type: 'SET_ACCOUNT', value });
export const setActiveConstruct = value => ({ type: 'SET_ACTIVE_CONSTRUCT', 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 setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value });
export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null }); 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) }); export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) });

View File

@ -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;

View File

@ -1,4 +1,6 @@
const preact = require('preact'); const preact = require('preact');
const { Component } = require('preact');
const { connect } = require('preact-redux');
const Amplify = require('./anims/amplify'); const Amplify = require('./anims/amplify');
const Absorb = require('./anims/absorb'); const Absorb = require('./anims/absorb');
@ -36,130 +38,108 @@ const Stun = require('./anims/stun');
const Triage = require('./anims/triage'); const Triage = require('./anims/triage');
const TriageTick = require('./anims/triage.tick'); 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) { class ConstructAnimation extends Component {
const { game, account, resolution, player, construct, avatarAnimation, setAvatarAnimation } = props; render(props) {
if (!resolution || resolution === 'clear') return false; const {
const [, event] = resolution.event; animTarget,
if (!event || !event.skill) return false; construct,
if (!resolution.target) return false; } = props;
// source animation if (!animTarget) return false;
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 {
const targetIsPlayer = playerTeamIds.includes(resolution.target.id); skill,
player,
direction,
constructId,
} = animTarget;
const getDirection = () => { if (construct.id !== constructId) return false;
const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer);
let y = 0;
if (!sameTeam) y = targetIsPlayer ? 1 : -1;
const i = sourceIsPlayer // find target animation
? playerTeamIds.findIndex(c => c === resolution.source.id) const chooseAnim = (skill) => {
: otherTeamIds.findIndex(c => c === resolution.source.id); switch (skill) {
// Attack base
case 'Attack': return <Strike colour={'#f5f5f5'} direction={direction}/>;
case 'Blast': return <Blast direction={direction}/>;
case 'Siphon': return <Siphon />;
case 'SiphonTick': return <SiphonTick />;
case 'Strike': return <Strike colour={'#a52a2a'} direction={direction}/>;
case 'Chaos': return <Chaos direction={direction}/>;
case 'Slay': return <Slay direction={direction}/>;
case 'Heal': return <Heal />;
const j = targetIsPlayer // Buff Base
? playerTeamIds.findIndex(c => c === resolution.target.id) case 'Buff': return <Buff />;
: otherTeamIds.findIndex(c => c === resolution.target.id); case 'Amplify': return <Amplify />;
const x = j - i; case 'Haste': return <Haste />;
return { x, y }; case 'Triage': return <Triage />;
}; case 'TriageTick': return <TriageTick />;
case 'Link': return <Link player={player} />;
case 'Hybrid': return <Hybrid />;
case 'Intercept': return <Intercept player={player} />;
const skipSource = (resolution.source.id === resolution.target.id // Debuff base
&& ['Invert', 'Banish'].includes(removeTier(event.skill))); case 'Debuff': return <Debuff />;
case 'Curse': return <Curse />;
case 'Decay': return <Decay />;
case 'DecayTick': return <Decay />;
// case 'Invert': return setAvatarAnimation(true, true, resolution.id, construct.id, 'invert', null);
case 'Purge': return <Purge />;
case 'Silence': return <Silence />;
case 'Restrict': return <Restrict />;
// Play Source Animation // Stun Base
if (!skipSource && resolution.source.id === construct.id && resolution.stages.includes('START_SKILL')) { case 'Stun': return <Stun />;
if (!avatarAnimation.source) { // case 'Banish': return setAvatarAnimation(true, true, resolution.id, construct.id, 'banish', null);
setAvatarAnimation(true, avatarAnimation.target, resolution.id, case 'Bash': return <Bash />;
construct.id, 'sourceCast', getDirection()); case 'Absorb': return <Absorb />;
} case 'Sleep': return <Sleep />;
case 'Break': return <Break />;
case 'Ruin': return <Ruin />;
// Block Base
case 'Block': return <Block />;
case 'Sustain': return <Sustain player={player} />;
case 'Electrify': return <Electrify />;
case 'Electrocute': return <Electrocute />;
case 'ElectrocuteTick': return <Electrocute />;
case 'Counter': return <Counter player={player} />;
case 'Purify': return <Purify player={player} />;
case 'Recharge': return <Recharge player={player} />;
case 'Reflect': return <Refl player={player} />;
default: return false;
};
};
const anim = chooseAnim(skill);
console.log(anim);
if (!anim) return false;
return (
<div class={'combat-anim'}>
{anim}
</div>
);
} }
const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds;
if (!(resolution.target.id === construct.id)
&& !(resolution.event[0] === 'AoeSkill' && targetTeam.includes(construct.id))) return false;
// Play Target animation // never update, wait til it gets nuked by parent
const anim = text => { shouldComponentUpdate({ animTarget }) {
if (!text || !resolution.sequence[0].includes('END_SKILL')) return false; return animTarget === this.props.animTarget;
const skill = removeTier(text); }
switch (skill) {
// Attack base
case 'Attack': return <Strike colour={'#f5f5f5'} direction={getDirection()}/>;
case 'Blast': return <Blast direction={getDirection()}/>;
case 'Siphon': return <Siphon />;
case 'SiphonTick': return <SiphonTick />;
case 'Strike': return <Strike colour={'#a52a2a'} direction={getDirection()}/>;
case 'Chaos': return <Chaos direction={getDirection()}/>;
case 'Slay': return <Slay direction={getDirection()}/>;
case 'Heal': return <Heal />;
// Buff Base
case 'Buff': return <Buff />;
case 'Amplify': return <Amplify />;
case 'Haste': return <Haste />;
case 'Triage': return <Triage />;
case 'TriageTick': return <TriageTick />;
case 'Link': return <Link player={player} />;
case 'Hybrid': return <Hybrid />;
case 'Intercept': return <Intercept player={player} />;
// Debuff base
case 'Debuff': return <Debuff />;
case 'Curse': return <Curse />;
case 'Decay': return <Decay />;
case 'DecayTick': return <Decay />;
case 'Invert': {
if (!avatarAnimation.target) {
setAvatarAnimation(avatarAnimation.source, true, resolution.id, construct.id, 'invert', null);
} return false;
}
case 'Purge': return <Purge />;
case 'Silence': return <Silence />;
case 'Restrict': return <Restrict />;
// Stun Base
case 'Stun': return <Stun />;
case 'Banish': {
if (!avatarAnimation.target) {
setAvatarAnimation(avatarAnimation.source, true, resolution.id, construct.id, 'banish', null);
} return false;
}
case 'Bash': return <Bash />;
case 'Absorb': return <Absorb />;
case 'Sleep': return <Sleep />;
case 'Break': return <Break />;
case 'Ruin': return <Ruin />;
// Block Base
case 'Block': return <Block />;
case 'Sustain': return <Sustain team={player} />;
case 'Electrify': return <Electrify />;
case 'Electrocute': return <Electrocute />;
case 'ElectrocuteTick': return <Electrocute />;
case 'Counter': return <Counter team={player} />;
case 'Purify': return <Purify team={player} />;
case 'Recharge': return <Recharge team={player} />;
case 'Reflect': return <Refl team={player} />;
default: return false;
}
};
const combatAnim = anim(event.skill);
if (!combatAnim) return false;
return (
<div class={'combat-anim'}>
{combatAnim}
</div>
);
} }
module.exports = animations;
module.exports = {
ConstructAnimation: addState(ConstructAnimation),
};

View File

@ -2,8 +2,8 @@ const anime = require('animejs').default;
const { TIMES } = require('../../constants'); const { TIMES } = require('../../constants');
function sourceCast(id, params) { function sourceCast(id, direction) {
const { x, y } = params; const { x, y } = direction;
return anime({ return anime({
targets: [document.getElementById(id)], targets: [document.getElementById(id)],
translateX: x * 200, translateX: x * 200,

View File

@ -1,7 +1,8 @@
const preact = require('preact'); const preact = require('preact');
const { Component } = require('preact'); const { Component } = require('preact');
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const anime = require('animejs').default;
const { match } = require('./../utils');
const banish = require('./anims/banish'); const banish = require('./anims/banish');
const idleAnimation = require('./anims/idle'); const idleAnimation = require('./anims/idle');
@ -10,8 +11,8 @@ const sourceCast = require('./anims/source.cast');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { avatarAnimation } = state; const { animSource, animTarget } = state;
return { avatarAnimation }; return { animSource, animTarget };
} }
); );
@ -21,8 +22,6 @@ class ConstructAvatar extends Component {
// The animation ids are a check to ensure that animations are not repeated // 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 // 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 // which is a count of how many resoluttions have passed
this.animId = 0;
this.source = false;
this.animations = []; this.animations = [];
} }
@ -41,25 +40,27 @@ class ConstructAvatar extends Component {
this.animations.push(this.idle); this.animations.push(this.idle);
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps({ animSource, animTarget }) {
if (nextProps.avatarAnimation.id === -1) this.animId = 0; // The current set of resolutions ended reset to 0 const avatarAnim = () => {
if (nextProps.avatarAnimation.id !== this.animId && nextProps.avatarAnimation.animTargetId === this.props.construct.id) { if (animSource && animSource.constructId === this.props.construct.id) {
this.animId = nextProps.avatarAnimation.id; return sourceCast(animSource.constructId, animSource.direction);
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);
} }
// 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() { componentWillUnmount() {
@ -67,6 +68,11 @@ class ConstructAvatar extends Component {
this.animations[i].reset(); 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 = { module.exports = {

View File

@ -1,10 +1,11 @@
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const { Component } = require('preact');
const preact = require('preact'); const preact = require('preact');
const range = require('lodash/range'); const range = require('lodash/range');
const { STATS, eventClasses, getCombatText } = require('../utils'); const { STATS, eventClasses, getCombatText } = require('../utils');
const { ConstructAvatar } = require('./construct'); const { ConstructAvatar } = require('./construct');
const animations = require('./animations'); const { ConstructAnimation } = require('./animations');
const shapes = require('./shapes'); const shapes = require('./shapes');
@ -58,57 +59,83 @@ const addState = connect(
); );
function GameConstruct(props) { class GameConstruct extends Component {
const { constructor() {
i, super();
game, this.resolvedLength = 0;
account, }
construct,
player,
resolution,
activeSkill,
avatarAnimation,
setAvatarAnimation,
selectSkillTarget,
} = props;
render() {
const {
i,
game,
account,
construct,
player,
resolution,
activeSkill,
selectSkillTarget,
} = this.props;
const ko = construct.green_life.value === 0 ? 'ko' : ''; const ko = construct.green_life.value === 0 ? 'ko' : '';
const classes = eventClasses(game, account, resolution, construct); const classes = eventClasses(game, account, resolution, construct);
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => ( const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
<div key={j} alt={STATS[s].stat}> <div key={j} alt={STATS[s].stat}>
{shapes[s]()} {shapes[s]()}
<div class="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div> <div class="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div>
<div class="value" >{construct[STATS[s].stat].value}</div> <div class="value" >{construct[STATS[s].stat].value}</div>
</div> </div>
)); ));
const skills = range(0, 3) const skills = range(0, 3)
.map(j => <SkillBtn key={j} construct={construct} i={j} j={i} />); .map(j => <SkillBtn key={j} construct={construct} i={j} j={i} />);
let crypSkills = <div> &nbsp; </div>; let crypSkills = <div> &nbsp; </div>;
if (player) crypSkills = (<div class="skills"> {skills} </div>); if (player) crypSkills = (<div class="skills"> {skills} </div>);
const effects = construct.effects.length const effects = construct.effects.length
? construct.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>) ? construct.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>)
: <div>&nbsp;</div>; : <div>&nbsp;</div>;
const combatAnim = animations({ game, account, resolution, player, construct, avatarAnimation, setAvatarAnimation }); const combatText = getCombatText(resolution, construct);
const combatText = getCombatText(resolution, construct); return (
return ( <div
<div onClick={() => selectSkillTarget(construct.id)}
onClick={() => selectSkillTarget(construct.id)} style={ activeSkill ? { cursor: 'pointer' } : {}}
style={ activeSkill ? { cursor: 'pointer' } : {}} class={`game-construct ${ko} ${classes}`} >
class={`game-construct ${ko} ${classes}`} > <h3 class="name"> {construct.name} </h3>
<h3 class="name"> {construct.name} </h3> {crypSkills}
{crypSkills} <div class="stats"> {stats} </div>
<div class="stats"> {stats} </div> <ConstructAvatar construct={construct} />
<ConstructAvatar construct={construct} /> <ConstructAnimation construct={construct} />
{combatAnim} <div class={'combat-text'}> {combatText} </div>
<div class={'combat-text'}> {combatText} </div> <div class="effects"> {effects} </div>
<div class="effects"> {effects} </div> </div>
</div> );
); }
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); module.exports = addState(GameConstruct);

View File

@ -65,7 +65,6 @@ function Game(props) {
if (!game) return <div>...</div>; if (!game) return <div>...</div>;
console.log('running game');
const otherTeams = game.players.filter(t => t.id !== account.id); const otherTeams = game.players.filter(t => t.id !== account.id);
const playerTeam = game.players.find(t => t.id === account.id); const playerTeam = game.players.find(t => t.id === account.id);

View File

@ -1,12 +1,13 @@
const preact = require('preact'); const preact = require('preact');
const { Component } = require('preact'); const { Component } = require('preact');
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const anime = require('animejs').default; // const anime = require('animejs').default;
const throttle = require('lodash/throttle'); const throttle = require('lodash/throttle');
const addState = connect( const addState = connect(
({ game, account, resolution }) => ({ game, account, resolution }) ({ game, account, animSource, animTarget }) =>
({ game, account, animSource, animTarget })
); );
class TargetSvg extends Component { class TargetSvg extends Component {
@ -23,9 +24,25 @@ class TargetSvg extends Component {
} }
render(props, state) { render(props, state) {
const { game, account, resolution } = props; const { game, account, animSource, animTarget } = props;
const { width, height } = state; const { width, height } = state;
// resolutions happening
// just put skill name up
if (animSource || animTarget) {
return (
<svg id="targeting" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" class="targeting-arrows">
<text
x={`${(width / 2) - 50}`}
y={`${(height / 2) + 16}`}
font-family="Jura"
font-size="2em">
{animTarget.skill}
</text>
</svg>
);
}
const playerTeam = game.players.find(t => t.id === account.id); const playerTeam = game.players.find(t => t.id === account.id);
const otherTeam = 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 <path d={path} />; return <path d={path} />;
} }
if (resolution === 'clear') return false;
if (!resolution) {
return (
<svg id="targeting"
viewBox={`0 0 ${width} ${height}`}
preserveAspectRatio="none"
class="targeting-arrows">
{outgoing.map(getPath)}
</svg>
);
}
let skill = '';
if (resolution.event[1]) ([, { skill }] = resolution.event);
return ( return (
<svg id="targeting" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" class="targeting-arrows"> <svg id="targeting"
<text viewBox={`0 0 ${width} ${height}`}
x={`${(width / 2) - 50}`} preserveAspectRatio="none"
y={`${(height / 2) + 16}`} class="targeting-arrows">
font-family="Jura" {outgoing.map(getPath)}
font-size="2em">
{skill}
</text>
</svg> </svg>
); );
} }

View File

@ -3,7 +3,7 @@ const eachSeries = require('async/eachSeries');
const actions = require('./actions'); const actions = require('./actions');
const { TIMES } = require('./constants'); const { TIMES } = require('./constants');
const { getCombatSequence } = require('./utils'); const animations = require('./animations.utils');
function registerEvents(store) { function registerEvents(store) {
function setPing(ping) { function setPing(ping) {
@ -42,44 +42,40 @@ function registerEvents(store) {
} }
function setGame(game) { function setGame(game) {
const { game: currentGame, ws } = store.getState(); const { game: currentGame, account, ws } = store.getState();
if (game && currentGame) { if (game && currentGame) {
if (game.resolved.length !== currentGame.resolved.length) { if (game.resolved.length !== currentGame.resolved.length) {
// stop fetching the game state til animations are done // stop fetching the game state til animations are done
const newRes = game.resolved.slice(currentGame.resolved.length); const newRes = game.resolved.slice(currentGame.resolved.length);
let id = game.resolved.length - currentGame.resolved.length;
return eachSeries(newRes, (r, cb) => { return eachSeries(newRes, (r, cb) => {
if (['Disable', 'TargetKo'].includes(r.event[0])) return 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); // convert server enum into anims keywords
}, err => { // todo make serersideonly
if (err) console.error(err); const sequence = animations.getSequence(r);
// Clear the anim classes const timeout = animations.getTime(sequence);
store.dispatch(actions.setResolution('clear')); const anims = animations.getObjects(r, sequence, game, account);
store.dispatch(actions.setAvatarAnimation({ id, source: false, target: false }));
// Finished this resolution small delay for reset console.log(sequence, timeout, anims);
return setTimeout(cb, 5);
}); 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 => { }, err => {
if (err) return console.error(err); if (err) return console.error(err);
store.dispatch(actions.setAvatarAnimation({ id: -1, source: false, target: false })); store.dispatch(actions.setAnimSource(null));
store.dispatch(actions.setResolution(null)); store.dispatch(actions.setAnimTarget(null));
// stop skipping resolutions // stop skipping resolutions
store.dispatch(actions.setSkip(false)); store.dispatch(actions.setSkip(false));
// update the game // update the game

View File

@ -15,7 +15,8 @@ module.exports = {
activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'), activeConstruct: createReducer(null, 'SET_ACTIVE_CONSTRUCT'),
activeItem: createReducer(null, 'SET_ACTIVE_VAR'), activeItem: createReducer(null, 'SET_ACTIVE_VAR'),
activeSkill: createReducer(null, 'SET_ACTIVE_SKILL'), 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'), combiner: createReducer([null, null, null], 'SET_COMBINER'),
constructs: createReducer([], 'SET_CONSTRUCTS'), constructs: createReducer([], 'SET_CONSTRUCTS'),
constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'), constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'),

View File

@ -4,6 +4,17 @@ const toast = require('izitoast');
const shapes = require('./components/shapes'); 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) => { const stringSort = (k, desc) => {
if (desc) { if (desc) {
return (a, b) => { return (a, b) => {
@ -158,24 +169,6 @@ function eventClasses(game, account, resolution, construct) {
return ''; 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) { function getCombatText(resolution, construct) {
if (!resolution || resolution === 'clear') return false; if (!resolution || resolution === 'clear') return false;
if (!resolution.stages.includes('POST_SKILL')) return false; if (!resolution.stages.includes('POST_SKILL')) return false;
@ -385,7 +378,6 @@ module.exports = {
convertItem, convertItem,
numSort, numSort,
eventClasses, eventClasses,
getCombatSequence,
getCombatText, getCombatText,
postData, postData,
errorToast, errorToast,
@ -395,4 +387,5 @@ module.exports = {
TARGET_COLOURS, TARGET_COLOURS,
randomPoints, randomPoints,
removeTier, removeTier,
match,
}; };