Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Mashy 2019-07-23 18:07:39 +10:00
commit 2dc929de40
15 changed files with 252 additions and 180 deletions

View File

@ -1,6 +1,6 @@
require('./assets/styles/styles.css'); require('./assets/styles/styles.css');
require('./assets/styles/styles.mobile.css'); require('./assets/styles/styles.mobile.css');
require('./assets/styles/instance.css'); require('./assets/styles/instance.less');
require('./assets/styles/instance.mobile.css'); require('./assets/styles/instance.mobile.css');
require('./assets/styles/game.css'); require('./assets/styles/game.css');

View File

@ -234,65 +234,54 @@
*/} */}
.game-construct.red-damage { .game-construct.red-damage {
/* filter: drop-shadow(0 0 0.2em red); color: #a52a2a;
*/ color: red;
/*ensure construct doesn't get opacity lowered because of being KO before the KO animation*/ /*ensure construct doesn't get opacity lowered because of being KO before the KO animation*/
opacity: 1; opacity: 1;
/*border-color: red;*/
} }
.red-damage button { .red-damage button {
/*border: 1px solid red;*/ color: #a52a2a;
color: red;
} }
.red-damage text { .red-damage text {
fill: red; fill: #a52a2a;
} }
.red-damage .stats { .red-damage .stats {
/*border-top: 1px solid red;*/ /*border-top: 1px solid #a52a2a;*/
} }
.game-construct.blue-damage { .game-construct.blue-damage {
/* filter: drop-shadow(0 0 0.2em blue); color: #3498db;
*/ color: blue;
opacity: 1; opacity: 1;
/*border-color: blue;*/
} }
.blue-damage button { .blue-damage button {
/*border: 1px solid blue;*/ color: #3498db;
color: blue;
} }
.blue-damage text { .blue-damage text {
fill: blue; fill: #3498db;
} }
.blue-damage .stats { .blue-damage .stats {
/*border-top: 1px solid blue;*/
} }
.game-construct.green-damage { .game-construct.green-damage {
/* filter: drop-shadow(0 0 0.2em green); color: #1FF01F;
*/ color: green;
opacity: 1; opacity: 1;
/*border-color: green;*/
} }
.green-damage button { .green-damage button {
/*border: 1px solid green;*/ color: #1FF01F;
color: green;
} }
.green-damage text { .green-damage text {
fill: green; fill: #1FF01F;
} }
.green-damage .stats { .green-damage .stats {
/*border-top: 1px solid green;*/ /*border-top: 1px solid #1FF01F;*/
} }
.game-construct.purple-damage { .game-construct.purple-damage {

View File

@ -287,66 +287,80 @@
flex: 1 0 100%; flex: 1 0 100%;
} }
// .equipping {
// position: relative;
// }
// .equipping::before {
// content: '';
// position: absolute;
// top: 2px;
// left: 50%;
// width: 100%;
// height: 2px;
// transform-origin: center;
// background-color: whitesmoke;
// animation: equipping-skill 2s infinite ease-out alternate;
// opacity: 0;
// }
// .equipping::after {
// content: '';
// position: absolute;
// bottom: 2px;
// left: 50%;
// width: 100%;
// height: 2px;
// transform-origin: center;
// background-color: whitesmoke;
// animation: equipping-skill 2s infinite ease-out alternate;
// opacity: 0;
// animation-delay: 0.75s
// }
// @keyframes equipping-skill {
// from {
// transform: translate(-50%, 0) scaleX(0);
// }
// to {
// transform: translate(-50%, 0) scaleX(0.75);
// opacity: 1;
// }
// }
// .equip-spec {
// position: relative;
// stroke: #333;
// }
// .equip-spec::after {
// content: '';
// position: absolute;
// bottom: 2px;
// left: 50%;
// width: 100%;
// height: 2px;
// transform-origin: center;
// background-color: whitesmoke;
// animation: equipping-skill 2s infinite ease-out alternate;
// opacity: 0;
// }
.equipping { .equipping {
position: relative; animation: equipping 2s infinite ease-in-out alternate;
} }
.equipping::before { @keyframes equipping {
content: '';
position: absolute;
top: 2px;
left: 50%;
width: 100%;
height: 2px;
transform-origin: center;
background-color: whitesmoke;
animation: equipping-skill 2s infinite ease-out alternate;
opacity: 0;
}
.equipping::after {
content: '';
position: absolute;
bottom: 2px;
left: 50%;
width: 100%;
height: 2px;
transform-origin: center;
background-color: whitesmoke;
animation: equipping-skill 2s infinite ease-out alternate;
opacity: 0;
animation-delay: 0.75s
}
@keyframes equipping-skill {
from { from {
transform: translate(-50%, 0) scaleX(0); border-color: #444;
} }
to { to {
transform: translate(-50%, 0) scaleX(0.75); border-color: whitesmoke;
opacity: 1;
} }
} }
.equip-spec {
position: relative;
stroke: #333;
}
.equip-spec::after {
content: '';
position: absolute;
bottom: 2px;
left: 50%;
width: 100%;
height: 2px;
transform-origin: center;
background-color: whitesmoke;
animation: equipping-skill 2s infinite ease-out alternate;
opacity: 0;
}
.thresholds { .thresholds {
display: flex; display: flex;
flex-flow: column; flex-flow: column;

View File

@ -78,9 +78,18 @@
background: @white; background: @white;
border: 1px solid @white; border: 1px solid @white;
// overwrite the classes on white svg elements
ellipse.white { ellipse.white {
stroke: black; stroke: black;
} }
rect.white {
stroke: black;
}
polygon.white {
stroke: black;
}
} }
} }

View File

@ -5,7 +5,7 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "parcel watch index.html --out-dir /var/lib/mnml/public/current", "start": "parcel watch index.html --out-dir /var/lib/mnml/public/current",
"anims": "parcel watch animations.html --out-dir /var/lib/mnml/public/current", "anims": "parcel watch animations.html --no-hmr --out-dir /var/lib/mnml/public/current",
"build": "parcel build index.html", "build": "parcel build index.html",
"scss": "node-sass --watch assets/scss -o assets/styles", "scss": "node-sass --watch assets/scss -o assets/styles",
"lint": "eslint --fix --ext .jsx src/", "lint": "eslint --fix --ext .jsx src/",

View File

@ -28,12 +28,9 @@ function createSocket(store) {
if (animating) return false; if (animating) return false;
store.dispatch(actions.setAnimating(true)); store.dispatch(actions.setAnimating(true));
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();
store.dispatch(actions.setResolution(r));
// convert server enum into anims keywords // convert server enum into anims keywords
// todo make serersideonly // todo make serersideonly
const sequence = animations.getSequence(r); const sequence = animations.getSequence(r);
@ -41,23 +38,29 @@ function createSocket(store) {
const anims = animations.getObjects(r, sequence, game, account); const anims = animations.getObjects(r, sequence, game, account);
const text = animations.getText(r, sequence); const text = animations.getText(r, sequence);
store.dispatch(actions.setAnimFocus(animations.getFocusTargets(r)));
if (sequence.includes('START_SKILL')) store.dispatch(actions.setAnimSource(anims.animSource)); if (sequence.includes('START_SKILL')) store.dispatch(actions.setAnimSource(anims.animSource));
if (sequence.includes('END_SKILL')) store.dispatch(actions.setAnimTarget(anims.animTarget)); if (sequence.includes('END_SKILL')) {
store.dispatch(actions.setAnimTarget(anims.animTarget));
if (!['Banish', 'Invert'].includes(anims.animTarget.skill)) store.dispatch(actions.setAnimCb(cb));
}
if (sequence.includes('POST_SKILL')) { if (sequence.includes('POST_SKILL')) {
// timeout to prevent text classes from being added too soon // timeout to prevent text classes from being added too soon
setTimeout( setTimeout(
() => store.dispatch(actions.setAnimText(text)), () => store.dispatch(actions.setAnimText(text)),
timeout - 1000, timeout - TIMES.POST_SKILL_DURATION_MS
); );
} }
return setTimeout(() => { return setTimeout(() => {
store.dispatch(actions.setAnimSource(null)); store.dispatch(actions.setAnimSource(null));
store.dispatch(actions.setAnimTarget(null)); store.dispatch(actions.setAnimTarget(null));
store.dispatch(actions.setAnimText(null)); store.dispatch(actions.setAnimText(null));
return setTimeout(cb, 50); store.dispatch(actions.setAnimFocus([]));
if (!sequence.includes('END_SKILL')
|| ['Banish', 'Invert'].includes(anims.animTarget.skill)) return cb();
return true;
}, timeout); }, timeout);
}, err => { }, err => {
if (err) return console.error(err); if (err) return console.error(err);
// clear animation state // clear animation state

View File

@ -69,48 +69,48 @@ document.fonts.load('16pt "Jura"').then(() => {
}); });
const SKILLS = [ const SKILLS = [
'AbsorbI', 'Absorb',
'AbsorptionI', 'Absorption',
'AmplifyI', 'Amplify',
'Attack', 'Attack',
'BanishI', 'Banish',
'BashI', 'Bash',
'BlastI', 'Blast',
'Block', 'Block',
'BreakI', 'Break',
'Buff', 'Buff',
'ChaosI', 'Chaos',
'CounterAttackI', 'CounterAttack',
'CounterI', 'Counter',
'CurseI', 'Curse',
'Debuff', 'Debuff',
'DecayI', 'Decay',
'DecayTickI', 'DecayTick',
'ElectrifyI', 'Electrify',
'ElectrocuteI', 'Electrocute',
'ElectrocuteTickI', 'ElectrocuteTick',
'HasteI', 'Haste',
'HasteStrike', 'HasteStrike',
'HealI', 'Heal',
'HybridBlast', 'HybridBlast',
'HybridI', 'Hybrid',
'InterceptI', 'Intercept',
'InvertI', 'Invert',
'LinkI', 'Link',
'PurgeI', 'Purge',
'PurifyI', 'Purify',
'RechargeI', 'Recharge',
'ReflectI', 'Reflect',
'RestrictI', 'Restrict',
'RuinI', 'Ruin',
'SilenceI', 'Silence',
'SiphonI', 'Siphon',
'SiphonTickI', 'SiphonTick',
'SlayI', 'Slay',
'SleepI', 'Sleep',
'StrikeI', 'Strike',
'Stun', 'Stun',
'SustainI', 'Sustain',
'TriageI', 'Triage',
'TriageTickI', 'TriageTick',
]; ];

View File

@ -3,6 +3,7 @@ const { Component } = require('preact');
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const Amplify = require('./anims/amplify'); const Amplify = require('./anims/amplify');
const Attack = require('./anims/attack');
const Absorb = require('./anims/absorb'); const Absorb = require('./anims/absorb');
const Bash = require('./anims/bash'); const Bash = require('./anims/bash');
const Blast = require('./anims/blast'); const Blast = require('./anims/blast');
@ -69,7 +70,7 @@ class ConstructAnimation extends Component {
const chooseAnim = (skill) => { const chooseAnim = (skill) => {
switch (skill) { switch (skill) {
// Attack base // Attack base
case 'Attack': return <Strike colour={'#f5f5f5'} direction={direction}/>; case 'Attack': return <Attack direction={direction}/>;
case 'Blast': return <Blast direction={direction}/>; case 'Blast': return <Blast direction={direction}/>;
case 'Siphon': return <Siphon />; case 'Siphon': return <Siphon />;
case 'SiphonTick': return <SiphonTick />; case 'SiphonTick': return <SiphonTick />;

View File

@ -0,0 +1,67 @@
const preact = require('preact');
const { Component } = require('preact');
const { connect } = require('preact-redux');
const anime = require('animejs').default;
const { TIMES, COLOURS } = require('../../constants');
const addState = connect(
function receiveState(state) {
const { animCb } = state;
return { animCb };
}
);
class Attack extends Component {
constructor(props) {
super();
this.props = props;
this.animations = [];
}
render() {
return (
<svg
class='attack-anim'
version="1.1"
id="attack"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 400 400">
<g>
<rect x="0" y="400" transform="skewX(45)"
width="12" height="100" stroke-width="0" fill={COLOURS.RED}/>
<rect x="200" y="400"
width="12" height="100" stroke-width="0" fill={COLOURS.RED}/>
<rect x="400" y="400" transform="skewX(-45)"
width="12" height="100" stroke-width="0" fill={COLOURS.RED}/>
</g>
</svg>
);
}
componentDidMount() {
this.animations.push(anime({
targets: ['#attack rect'],
easing: 'easeOutExpo',
y: [400, 200],
height: [100, 10, 0],
width: [12, 5, 0],
delay: () => anime.random(TIMES.TARGET_DELAY_MS, TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS / 2),
duration: TIMES.TARGET_DURATION_MS,
}));
}
// this is necessary because
// skipping / timing / unmounting race conditions
// can cause the animations to cut short, this will ensure the values are reset
// because preact will recycle all these components
componentWillUnmount() {
for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset();
}
this.props.animCb();
}
}
module.exports = addState(Attack);

View File

@ -2,9 +2,9 @@ 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 times = require('lodash/times');
const { TIMES } = require('../../constants'); const { TIMES, COLOURS } = require('../../constants');
const { randomPoints } = require('../../utils');
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
@ -30,76 +30,65 @@ function projectile(x, y, radius, colour) {
class Blast extends Component { class Blast extends Component {
constructor(props) { constructor(props) {
super(); super();
this.team = props.team;
this.animations = []; this.animations = [];
const points = randomPoints(8, 60, { x: 0, y: 0, width: 300, height: 400 });
this.charges = points.map(coord => projectile(coord[0], coord[1], 20, '#00aabb'));
} }
render() { render() {
return ( return (
<svg <svg
class={'skill-animation'} id='blast'
class="skill-animation"
version="1.1" version="1.1"
id="blast" transform-box='fill-box'
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 300 400"> viewBox="0 0 300 300">
// {this.charges}
<defs> <defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="70%" fx="50%" fy="50%"> <filter id="blastFilter">
<stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:0.6" /> <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
<stop offset="100%" style={'stop-color:#00aabb;stop-opacity:1'} /> <feMerge>
</radialGradient> <feMergeNode />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs> </defs>
<filter id="explosion"> <g>
<feGaussianBlur stdDeviation="4"/> {times(50, () => (
<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="3" result="turbulence"/> <g>
<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="1" xChannelSelector="A" yChannelSelector="A"/> <rect filter="url(#blastFilter)" class="blue" x="150" y="200" width="3" height="5" />
<rect filter="url(#blastFilter)" class="white" x="150" y="200" width="1" height="3" />
</filter> </g>
{this.charges} ))}
</g>
</svg> </svg>
); );
} }
componentDidMount() { componentDidMount() {
anime.set('#blast', {
translateX: -200 * this.props.direction.x,
translateY: -300 * this.props.direction.y,
});
this.animations.push(anime({ this.animations.push(anime({
targets: '#blast', targets: ['#blast'],
opacity: [ opacity: [
{ value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.3 }, { value: 1, delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS * 0.2 },
{ value: 0, delay: TIMES.TARGET_DURATION_MS * 0.7, duration: TIMES.POST_SKILL_DURATION_MS }, { value: 0, delay: TIMES.TARGET_DURATION_MS * 0.5, duration: TIMES.TARGET_DURATION_MS * 0.2 },
], ],
easing: 'easeInOutSine',
})); }));
anime.set('#explosion feDisplacementMap', {
scale: 1,
});
this.animations.push(anime({ this.animations.push(anime({
targets: '#blast', targets: ['#blast g'],
translateY: 0, transform: () => `
translateX: 0, translate(${anime.random(-100, 100)} ${anime.random(-100, 100)})
loop: false, `,
style: { rotate: anime.random(-180, 180) },
easing: 'easeOutCubic',
delay: TIMES.TARGET_DELAY_MS, delay: TIMES.TARGET_DELAY_MS,
duration: (TIMES.TARGET_DURATION_MS * 1 / 2), duration: TIMES.TARGET_DURATION_MS,
easing: 'easeInQuad',
}));
this.animations.push(anime({
targets: '#explosion feDisplacementMap',
scale: 200,
loop: false,
delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS * 1 / 2,
duration: TIMES.TARGET_DURATION_MS * 1 / 2,
easing: 'easeInQuad',
})); }));
} }
// this is necessary because
// skipping / timing / unmounting race conditions
// can cause the animations to cut short, this will ensure the values are reset
// because preact will recycle all these components
componentWillUnmount() { componentWillUnmount() {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();

View File

@ -106,7 +106,8 @@ class Break extends Component {
componentWillUnmount() { componentWillUnmount() {
for (let i = this.animations.length - 1; i >= 0; i--) { for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset(); this.animations[i].reset();
} this.props.animCb(); }
this.props.animCb();
} }
} }

View File

@ -144,7 +144,7 @@ function Construct(props) {
if (!s) { if (!s) {
const equipping = specList.includes(vbox.bound[itemEquip]); const equipping = specList.includes(vbox.bound[itemEquip]);
const classes = `${equipping ? 'equip-spec' : 'gray'} empty`; const classes = `${equipping ? 'equipping' : 'gray'} empty`;
return ( return (
<button key={i} class={classes} disabled={!equipping} > <button key={i} class={classes} disabled={!equipping} >
{shapes.None()} {shapes.None()}

View File

@ -33,7 +33,7 @@ module.exports = {
RedPower: () => circle(['red']), RedPower: () => circle(['red']),
GreenPower: () => circle(['green']), GreenPower: () => circle(['green']),
BluePower: () => circle(['blue']), BluePower: () => circle(['blue']),
Speed: () => triangle(['white']), SpeedStat: () => triangle(['white']),
// specs // specs
@ -58,12 +58,11 @@ module.exports = {
<figcaption>Life</figcaption> <figcaption>Life</figcaption>
</figure>, </figure>,
// Speed: Speed: () =>
// <figure> <figure>
// {triangle(['white'])} {triangle(['white'])}
// <figcaption>Speed</figcaption> <figcaption>Speed</figcaption>
// </figure>, </figure>,
// Lifes Upgrades // Lifes Upgrades
LifeGG: () => LifeGG: () =>

View File

@ -4,9 +4,9 @@ module.exports = function triangle(classes) {
return ( return (
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 200 200" class={classes} transform="rotate(45)" > viewBox="0 0 200 200" class={classes} transform="rotate(45)" >
<rect x="10" y="10" width="180" height="180"/> <rect x="25" y="25" width="175" height="175"/>
<rect x="40" y="40" width="120" height="120"/> <rect x="55" y="55" width="115" height="115"/>
<rect x="70" y="70" width="60" height="60"/> <rect x="85" y="85" width="55" height="55"/>
</svg> </svg>
); );
}; };

View File

@ -63,7 +63,7 @@ const STATS = {
colour: 'blue', colour: 'blue',
svg: shapes.circle, svg: shapes.circle,
}, },
Speed: { SpeedStat: {
stat: 'speed', stat: 'speed',
colour: 'white', colour: 'white',
svg: shapes.triangle, svg: shapes.triangle,