refactor game.construct

This commit is contained in:
Mashy 2019-12-05 17:25:54 +10:00
parent 8e90e6e0e3
commit af654cffc2
6 changed files with 213 additions and 174 deletions

View File

@ -0,0 +1,73 @@
const preact = require('preact');
const { connect } = require('preact-redux');
const anime = require('animejs').default;
const reactStringReplace = require('react-string-replace');
const shapes = require('./shapes');
const { removeTier } = require('../utils');
const { TIMES } = require('./../constants');
const addState = connect(({ animText, itemInfo }) => ({ animText, itemInfo }));
class AnimText extends preact.Component {
shouldComponentUpdate(newProps) {
if (newProps.animText !== this.props.animText) return true;
return false;
}
componentDidUpdate(prevProps) {
const { animText, construct } = this.props;
if (animText && animText !== prevProps.animText && animText.constructId === construct.id) {
anime({
targets: '.combat-text',
top: '40%',
duration: TIMES.POST_SKILL_DURATION_MS - 500,
easing: 'easeOutQuad',
});
}
}
render(props) {
const { construct, animText, itemInfo } = props;
if (animText && animText.constructId === construct.id) {
const itemSourceDescription = () => {
const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animText.skill));
const itemSourceInfo = itemSource.length
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
: false;
const itemRegEx = /(Red|Blue|Green)/;
return reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
};
const animationTextHtml = () => {
// monkaW hack to make red / blue recharge work nicely
if (animText.css === 'rb') {
const text = animText.text.split(' ');
return (
<h1>
<span class="red">{text[0]}</span>&nbsp;
<span class="blue">{text[1]}</span>
</h1>
);
}
return (
<h1 class={animText.css}>
<span>{animText.text}</span>
</h1>
);
};
return (
<div class="combat-text">
<h2><span>{animText.skill}</span></h2>
<span>{itemSourceDescription()}</span>
{animationTextHtml()}
</div>
);
}
return null;
}
}
module.exports = addState(AnimText);

View File

@ -0,0 +1,72 @@
const preact = require('preact');
const { connect } = require('preact-redux');
const reactStringReplace = require('react-string-replace');
const actions = require('../actions');
const shapes = require('./shapes');
const { INFO } = require('./../constants');
const addState = connect(
({ animText, itemInfo, gameSkillInfo }) => ({ animText, itemInfo, gameSkillInfo }),
function receiveDispatch(dispatch) {
function setGameEffectInfo(info) {
dispatch(actions.setGameEffectInfo(info));
}
return { setGameEffectInfo };
}
);
class GameConstructEffects extends preact.Component {
shouldComponentUpdate(newProps) {
if (newProps.animText !== this.props.animText) {
if (newProps.animText && newProps.animText.constructId === this.props.construct.id) return true;
}
if (newProps.construct !== this.props.construct) return true;
return false;
}
render() {
const {
animText,
construct,
gameSkillInfo,
setGameEffectInfo,
itemInfo,
} = this.props;
function hoverInfo(e, info) {
e.stopPropagation();
return setGameEffectInfo(info);
}
if (gameSkillInfo && gameSkillInfo.constructId === construct.id) {
const fullInfo = itemInfo.items.find(k => k.item === gameSkillInfo.skill) || INFO[gameSkillInfo.skill];
const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/;
const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]());
const speed = <span> Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}% </span>;
return (
<div class="skill-description">
<h2><span> {gameSkillInfo.skill} </span></h2>
<span>{infoDescription} </span> <br />
{speed}
</div>);
}
const effects = animText && animText.constructId === construct.id && animText.effects
? animText.effects
: construct.effects;
const renderEffects = effects.length
? effects.map(c =>
<div key={c.effect}>
<span key={c.effect} onMouseOver={e => hoverInfo(e, c)}
onMouseOut={e => hoverInfo(e, null)}> {c.effect} - {c.duration}T
</span>
</div>)
: null;
return (<div class="effects"> {renderEffects} </div>);
}
}
module.exports = addState(GameConstructEffects);

View File

@ -1,94 +1,23 @@
const preact = require('preact'); const preact = require('preact');
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const anime = require('animejs').default;
const range = require('lodash/range'); const range = require('lodash/range');
const reactStringReplace = require('react-string-replace');
const { STATS, removeTier } = require('../utils');
const { ConstructAvatar, ConstructText } = require('./construct'); const { ConstructAvatar, ConstructText } = require('./construct');
const shapes = require('./shapes');
const { INFO, TIMES } = require('./../constants');
const actions = require('../actions');
const SkillBtn = require('./skill.btn'); const SkillBtn = require('./game.construct.skill.btn');
const ConstructAnimationText = require('./game.construct.anim.text');
const addStateText = connect(({ animText, itemInfo }) => ({ animText, itemInfo })); const ConstructLife = require('./game.construct.life');
const ConstructEffectBox = require('./game.construct.effect.box');
class combatText extends preact.Component {
shouldComponentUpdate(newProps) {
if (newProps.animText !== this.props.animText) return true;
return false;
}
componentDidUpdate(prevProps) {
const { animText, construct } = this.props;
if (animText && animText !== prevProps.animText && animText.constructId === construct.id) {
anime({
targets: '.combat-text',
top: '40%',
duration: TIMES.POST_SKILL_DURATION_MS - 500,
easing: 'easeOutQuad',
});
}
}
render(props) {
const { construct, animText, itemInfo } = props;
if (animText && animText.constructId === construct.id) {
const itemSourceDescription = () => {
const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animText.skill));
const itemSourceInfo = itemSource.length
? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
: false;
const itemRegEx = /(Red|Blue|Green)/;
return reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
};
const animationTextHtml = () => {
// monkaW hack to make red / blue recharge work nicely
if (animText.css === 'rb') {
const text = animText.text.split(' ');
return (
<h1>
<span class="red">{text[0]}</span>&nbsp;
<span class="blue">{text[1]}</span>
</h1>
);
}
return (
<h1 class={animText.css}>
<span>{animText.text}</span>
</h1>
);
};
return (
<div class="combat-text">
<h2><span>{animText.skill}</span></h2>
<span>{itemSourceDescription()}</span>
{animationTextHtml()}
</div>
);
}
return null;
}
}
const ConstructAnimationText = addStateText(combatText);
const addState = connect( const addState = connect(
function receiveState(state) { function receiveState(state) {
const { const {
ws, ws,
game, game,
account,
activeSkill, activeSkill,
animFocus, animFocus,
animating,
animText, animText,
gameSkillInfo,
itemInfo,
} = state; } = state;
function selectSkillTarget(targetConstructId) { function selectSkillTarget(targetConstructId) {
@ -99,59 +28,20 @@ const addState = connect(
} }
return { return {
game, activeSkill,
account,
animating,
animFocus, animFocus,
animText, animText,
activeSkill,
selectSkillTarget, selectSkillTarget,
gameSkillInfo,
itemInfo,
}; };
},
function receiveDispatch(dispatch) {
function setGameEffectInfo(info) {
dispatch(actions.setGameEffectInfo(info));
} }
return { setGameEffectInfo };
}
); );
const eventClasses = (animating, animFocus, construct, postSkill) => {
if (!animating) return '';
if (!postSkill) {
if (animFocus.includes(construct.id)) return '';
return 'unfocus';
}
if (postSkill.constructId !== construct.id) {
if (animFocus.includes(construct.id)) return '';
return 'unfocus';
}
if (postSkill.effects) construct.effects = postSkill.effects;
construct.green_life.value = postSkill.life.green;
construct.red_life.value = postSkill.life.red;
construct.blue_life.value = postSkill.life.blue;
return postSkill.css;
};
class GameConstruct extends preact.Component { class GameConstruct extends preact.Component {
constructor() {
super();
this.resolvedLength = 0;
}
shouldComponentUpdate(newProps) { shouldComponentUpdate(newProps) {
if (newProps.activeSkill !== this.props.activeSkill) return true; if (newProps.activeSkill !== this.props.activeSkill) return true;
if (newProps.animFocus !== this.props.animFocus) return true; if (newProps.animFocus !== this.props.animFocus) return true;
if (newProps.animText !== this.props.animText) return true; if (newProps.animText !== this.props.animText) return true;
if (newProps.animating !== this.props.animating) return true;
if (newProps.construct !== this.props.construct) return true; if (newProps.construct !== this.props.construct) return true;
if (newProps.player !== this.props.player) return true;
if (newProps.gameSkillInfo !== this.props.gameSkillInfo) return true;
return false; return false;
} }
@ -161,78 +51,36 @@ class GameConstruct extends preact.Component {
activeSkill, activeSkill,
animFocus, animFocus,
animText, animText,
animating, selectSkillTarget,
construct, construct,
player, player,
gameSkillInfo,
// Constants
i,
itemInfo,
// Functions
selectSkillTarget,
setGameEffectInfo,
} = this.props; } = this.props;
const koEvent = animText ? animText.text === 'KO!' && animText.constructId === construct.id : false; const koEvent = animText && animText.text === 'KO!' && animText.constructId === construct.id;
const ko = construct.green_life.value === 0 && !koEvent ? 'ko' : ''; const ko = construct.green_life.value === 0 && !koEvent ? 'ko' : '';
const classes = eventClasses(animating, animFocus, construct, animText);
const cssClass = ['ko-transition', 'unfocus'].includes(classes) ? classes : null;
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => ( const cssClass = () => {
<div key={j} alt={STATS[s].stat}> if (koEvent) return 'ko-transition';
{shapes[s]()} if (animFocus && !animFocus.includes(construct.id)) return 'unfocus';
<div class="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div> return '';
<div class="value" >{construct[STATS[s].stat].value}</div>
</div>
));
const skills = range(0, 3)
.map(j => <SkillBtn key={j} construct={construct} i={j} j={i} animating={animating} />);
let crypSkills = <div></div>;
if (player) crypSkills = (<div class="skills"> {skills} </div>);
function hoverInfo(e, info) {
e.stopPropagation();
return setGameEffectInfo(info);
}
const effectBox = () => {
if (gameSkillInfo && gameSkillInfo.constructId === construct.id) {
const fullInfo = itemInfo.items.find(k => k.item === gameSkillInfo.skill) || INFO[gameSkillInfo.skill];
const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/;
const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]());
const speed = <span> Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}% </span>;
return (
<div class="skill-description">
<h2><span> {gameSkillInfo.skill} </span></h2>
<span>{infoDescription} </span> <br />
{speed}
</div>);
}
const effects = construct.effects.length
? construct.effects.map(c =>
<div key={c.effect}>
<span key={c.effect} onMouseOver={e => hoverInfo(e, c)}
onMouseOut={e => hoverInfo(e, null)}> {c.effect} - {c.duration}T
</span>
</div>)
: null;
return (<div class="effects"> {effects} </div>);
}; };
const crypSkills = player
? <div class="skills"> {range(0, 3).map(j => <SkillBtn key={j} construct={construct} i={j} />)} </div>
: <div></div>;
return ( return (
<div <div
onClick={() => { onClick={() => selectSkillTarget(construct.id)}
selectSkillTarget(construct.id);
}}
style={ activeSkill ? { cursor: 'pointer' } : {}} style={ activeSkill ? { cursor: 'pointer' } : {}}
class={`game-construct ${ko} ${cssClass}`}> class={`game-construct ${ko} ${cssClass()}`}>
<div class="left"> <div class="left">
{crypSkills} {crypSkills}
{effectBox()} <ConstructEffectBox construct={construct} />
</div> </div>
<div class="right"> <div class="right">
<div class="stats"> {stats} </div> <ConstructLife construct={construct} />
<ConstructAvatar construct={construct} /> <ConstructAvatar construct={construct} />
<ConstructText construct={construct} /> <ConstructText construct={construct} />
<ConstructAnimationText construct={construct} /> <ConstructAnimationText construct={construct} />

View File

@ -0,0 +1,44 @@
const preact = require('preact');
const { connect } = require('preact-redux');
const shapes = require('./shapes');
const addState = connect(({ animText }) => ({ animText }));
class GameConstructLife extends preact.Component {
shouldComponentUpdate(newProps) {
if (newProps.animText !== this.props.animText) {
if (newProps.animText && newProps.animText.constructId === this.props.construct.id) return true;
}
if (newProps.construct !== this.props.construct) return true;
return false;
}
render() {
const { construct, animText } = this.props;
// this will be cleaner in new update
const updateLife = animText && animText.constructId === construct.id;
const redLife = updateLife ? animText.life.red : construct.red_life.value;
const greenLife = updateLife ? animText.life.green : construct.green_life.value;
const blueLife = updateLife ? animText.life.blue : construct.blue_life.value;
return (
<div class="stats">
<div>
{shapes.RedLife()}
<div class="max" >{redLife} / {construct.red_life.max}</div>
</div>
<div>
{shapes.GreenLife()}
<div class="max" >{greenLife} / {construct.green_life.max}</div>
</div>
<div>
{shapes.BlueLife()}
<div class="max" >{blueLife} / {construct.blue_life.max}</div>
</div>
</div>
);
}
}
module.exports = addState(GameConstructLife);

View File

@ -10,11 +10,13 @@ const addState = connect(
const { const {
activeSkill, activeSkill,
game, game,
animating,
} = state; } = state;
return { return {
activeSkill, activeSkill,
game, game,
animating,
}; };
}, },

View File

@ -138,7 +138,7 @@ function registerEvents(store) {
store.dispatch(actions.setAnimText(null)); store.dispatch(actions.setAnimText(null));
store.dispatch(actions.setAnimating(false)); store.dispatch(actions.setAnimating(false));
store.dispatch(actions.setGameEffectInfo(null)); store.dispatch(actions.setGameEffectInfo(null));
store.dispatch(actions.setAnimFocus(null));
// set the game state so resolutions don't fire twice // set the game state so resolutions don't fire twice
store.dispatch(actions.setGame(game)); store.dispatch(actions.setGame(game));
ws.sendGameState(game.id); ws.sendGameState(game.id);