Merge branch 'vbox-rework' into develop
This commit is contained in:
@@ -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,102 @@ 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 <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
|
||||
? 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 <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} />;
|
||||
|
||||
const skipSource = (resolution.source.id === resolution.target.id
|
||||
&& ['Invert', 'Banish'].includes(removeTier(event.skill)));
|
||||
// Debuff base
|
||||
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
|
||||
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 <Stun />;
|
||||
// case 'Banish': return setAvatarAnimation(true, true, resolution.id, construct.id, 'banish', null);
|
||||
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 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);
|
||||
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
|
||||
const anim = text => {
|
||||
if (!text || !resolution.sequence[0].includes('END_SKILL')) return false;
|
||||
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),
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
@@ -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],
|
||||
|
||||
@@ -70,10 +70,6 @@ class Sleep extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
anime.set('#sleep', {
|
||||
translateY: 75,
|
||||
});
|
||||
|
||||
this.animations.push(anime({
|
||||
targets: ['#sleep'],
|
||||
opacity: [
|
||||
|
||||
@@ -2,12 +2,12 @@ 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,
|
||||
translateY: y * 200,
|
||||
translateX: [0, x * 200],
|
||||
translateY: [0, y * 200],
|
||||
easing: 'easeInOutElastic',
|
||||
direction: 'alternate',
|
||||
duration: TIMES.SOURCE_DURATION_MS,
|
||||
|
||||
@@ -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,9 +22,8 @@ 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 = [];
|
||||
this.resetAnimations = this.resetAnimations.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -37,38 +37,139 @@ class ConstructAvatar extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.idle = idleAnimation(this.props.construct.id);
|
||||
this.animations.push(this.idle);
|
||||
}
|
||||
const { animSource, animTarget, construct } = this.props;
|
||||
|
||||
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);
|
||||
// back to idle
|
||||
if (!animTarget && !animSource) {
|
||||
if (!this.idle) {
|
||||
this.idle = idleAnimation(this.props.construct.id);
|
||||
this.animations.push(this.idle);
|
||||
}
|
||||
|
||||
return this.idle.play();
|
||||
}
|
||||
|
||||
const isSource = animSource && animSource.constructId === construct.id;
|
||||
|
||||
const selectAnim = () => {
|
||||
if (isSource) {
|
||||
console.warn(construct.name, animSource);
|
||||
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;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
componentDidUpdate(prevProps) {
|
||||
const { animSource, animTarget, construct } = this.props;
|
||||
|
||||
// back to idle
|
||||
if (!animTarget && !animSource) {
|
||||
return this.idle.play();
|
||||
}
|
||||
|
||||
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() {
|
||||
for (let i = this.animations.length - 1; i >= 0; i--) {
|
||||
this.animations[i].reset();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.resetAnimations();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// something has changed
|
||||
// what do?
|
||||
|
||||
// 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) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 <div class={'combat-text'}>{text}</div>;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ConstructAvatar: addState(ConstructAvatar),
|
||||
ConstructText: addStateText(constructText),
|
||||
};
|
||||
|
||||
@@ -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 { STATS, eventClasses } = require('../utils');
|
||||
const { ConstructAvatar, ConstructText } = require('./construct');
|
||||
const { ConstructAnimation } = require('./animations');
|
||||
const shapes = require('./shapes');
|
||||
|
||||
|
||||
@@ -19,9 +20,10 @@ const addState = connect(
|
||||
ws,
|
||||
game,
|
||||
account,
|
||||
resolution,
|
||||
activeSkill,
|
||||
avatarAnimation,
|
||||
resolution,
|
||||
|
||||
animText,
|
||||
} = state;
|
||||
|
||||
function selectSkillTarget(targetConstructId) {
|
||||
@@ -39,76 +41,72 @@ 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,
|
||||
};
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
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,
|
||||
activeSkill,
|
||||
selectSkillTarget,
|
||||
|
||||
const ko = construct.green_life.value === 0 ? 'ko' : '';
|
||||
const classes = eventClasses(game, account, resolution, construct);
|
||||
// todo remove dep
|
||||
resolution,
|
||||
|
||||
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
|
||||
<div key={j} alt={STATS[s].stat}>
|
||||
{shapes[s]()}
|
||||
<div class="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div>
|
||||
<div class="value" >{construct[STATS[s].stat].value}</div>
|
||||
</div>
|
||||
));
|
||||
animText,
|
||||
} = this.props;
|
||||
|
||||
const skills = range(0, 3)
|
||||
.map(j => <SkillBtn key={j} construct={construct} i={j} j={i} />);
|
||||
const ko = construct.green_life.value === 0 ? 'ko' : '';
|
||||
const classes = eventClasses(game, account, resolution, construct, animText);
|
||||
|
||||
let crypSkills = <div> </div>;
|
||||
if (player) crypSkills = (<div class="skills"> {skills} </div>);
|
||||
const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
|
||||
<div key={j} alt={STATS[s].stat}>
|
||||
{shapes[s]()}
|
||||
<div class="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div>
|
||||
<div class="value" >{construct[STATS[s].stat].value}</div>
|
||||
</div>
|
||||
));
|
||||
|
||||
const effects = construct.effects.length
|
||||
? construct.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>)
|
||||
: <div> </div>;
|
||||
const combatAnim = animations({ game, account, resolution, player, construct, avatarAnimation, setAvatarAnimation });
|
||||
const combatText = getCombatText(resolution, construct);
|
||||
return (
|
||||
<div
|
||||
onClick={() => selectSkillTarget(construct.id)}
|
||||
style={ activeSkill ? { cursor: 'pointer' } : {}}
|
||||
class={`game-construct ${ko} ${classes}`} >
|
||||
<h3 class="name"> {construct.name} </h3>
|
||||
{crypSkills}
|
||||
<div class="stats"> {stats} </div>
|
||||
<ConstructAvatar construct={construct} />
|
||||
{combatAnim}
|
||||
<div class={'combat-text'}> {combatText} </div>
|
||||
<div class="effects"> {effects} </div>
|
||||
</div>
|
||||
);
|
||||
const skills = range(0, 3)
|
||||
.map(j => <SkillBtn key={j} construct={construct} i={j} j={i} />);
|
||||
|
||||
let crypSkills = <div> </div>;
|
||||
if (player) crypSkills = (<div class="skills"> {skills} </div>);
|
||||
|
||||
const effects = construct.effects.length
|
||||
? construct.effects.map(c => <div key={c.effect}>{c.effect} - {c.duration}T</div>)
|
||||
: <div> </div>;
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => selectSkillTarget(construct.id)}
|
||||
style={ activeSkill ? { cursor: 'pointer' } : {}}
|
||||
class={`game-construct ${ko} ${classes}`} >
|
||||
<h3 class="name"> {construct.name} </h3>
|
||||
{crypSkills}
|
||||
<div class="stats"> {stats} </div>
|
||||
<ConstructAvatar construct={construct} />
|
||||
<ConstructAnimation construct={construct} />
|
||||
<ConstructText construct={construct} />
|
||||
<div class="effects"> {effects} </div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = addState(GameConstruct);
|
||||
|
||||
@@ -65,7 +65,6 @@ function Game(props) {
|
||||
|
||||
if (!game) return <div>...</div>;
|
||||
|
||||
console.log('running game');
|
||||
const otherTeams = game.players.filter(t => t.id !== account.id);
|
||||
const playerTeam = game.players.find(t => t.id === account.id);
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ function Instance(args) {
|
||||
<main class={instanceClasses} onMouseOver={() => setInfo(null)} >
|
||||
<Vbox />
|
||||
<InfoContainer />
|
||||
<EquipmentContainer />
|
||||
<InstanceConstructsContainer />
|
||||
</main>
|
||||
);
|
||||
|
||||
@@ -81,11 +81,15 @@ function Construct(props) {
|
||||
sendUnequip,
|
||||
} = props;
|
||||
|
||||
const fullInfo = itemInfo.items.find(i => i.item === itemEquip);
|
||||
const isSkill = fullInfo && fullInfo.skill;
|
||||
const isSpec = fullInfo && fullInfo.spec;
|
||||
const equipping = itemEquip && (isSkill || isSpec);
|
||||
|
||||
function onClick(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
console.log('const click eA')
|
||||
if (itemEquip !== null) sendVboxApply(construct.id, itemEquip);
|
||||
if (equipping) sendVboxApply(construct.id, itemEquip);
|
||||
setItemEquip(null);
|
||||
return setActiveConstruct(construct);
|
||||
}
|
||||
@@ -124,13 +128,11 @@ function Construct(props) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// const action = skill ? '' : 'action';
|
||||
const equip = skillList.includes(vbox.bound[itemEquip]) && !skill ? 'equipping' : '';
|
||||
const classes = `${equip}`;
|
||||
const classes = `${equipping ? 'equipping' : ''}`;
|
||||
return (
|
||||
<button
|
||||
key={i}
|
||||
disabled={!skill && itemEquip === null}
|
||||
disabled={!skill && !equipping}
|
||||
class={classes}
|
||||
onClick={skillClick}
|
||||
onDblClick={skillDblClick}
|
||||
@@ -140,7 +142,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) {
|
||||
@@ -153,8 +155,6 @@ function Construct(props) {
|
||||
);
|
||||
}
|
||||
|
||||
const specInfo = itemInfo.items.find(i => i.item === s);
|
||||
|
||||
function specClick(e) {
|
||||
e.stopPropagation();
|
||||
setItemUnequip(s);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
},
|
||||
@@ -57,7 +52,7 @@ const addState = connect(
|
||||
function setNav(place) {
|
||||
dispatch(actions.setGame(null));
|
||||
dispatch(actions.setInstance(null));
|
||||
dispatch(actions.setCombiner([null, null, null]));
|
||||
dispatch(actions.setCombiner([]));
|
||||
dispatch(actions.setReclaiming(false));
|
||||
dispatch(actions.setActiveSkill(null));
|
||||
dispatch(actions.setActiveConstruct(null));
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
const preact = require('preact');
|
||||
|
||||
module.exports = function vboxColour(colour) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" class={colour} >
|
||||
<circle
|
||||
cx={50}
|
||||
cy={50}
|
||||
r={50}
|
||||
// stroke-width="2"
|
||||
// stroke={colour}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -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, animTarget, animating }) =>
|
||||
({ game, account, animTarget, animating })
|
||||
);
|
||||
|
||||
class TargetSvg extends Component {
|
||||
@@ -23,9 +24,27 @@ class TargetSvg extends Component {
|
||||
}
|
||||
|
||||
render(props, state) {
|
||||
const { game, account, resolution } = props;
|
||||
const { game, account, animating, animTarget } = props;
|
||||
const { width, height } = state;
|
||||
|
||||
// resolutions happening
|
||||
// just put skill name up
|
||||
if (animating) {
|
||||
if (!animTarget) return false;
|
||||
|
||||
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 otherTeam = game.players.find(t => t.id !== account.id);
|
||||
|
||||
@@ -81,29 +100,13 @@ class TargetSvg extends Component {
|
||||
|
||||
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 (
|
||||
<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">
|
||||
{skill}
|
||||
</text>
|
||||
<svg id="targeting"
|
||||
viewBox={`0 0 ${width} ${height}`}
|
||||
preserveAspectRatio="none"
|
||||
class="targeting-arrows">
|
||||
{outgoing.map(getPath)}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const preact = require('preact');
|
||||
const range = require('lodash/range');
|
||||
const without = require('lodash/without');
|
||||
const { connect } = require('preact-redux');
|
||||
|
||||
const shapes = require('./shapes');
|
||||
const { convertItem } = require('./../utils');
|
||||
const actions = require('../actions');
|
||||
|
||||
const addState = connect(
|
||||
@@ -15,6 +15,7 @@ const addState = connect(
|
||||
combiner,
|
||||
reclaiming,
|
||||
vboxHighlight,
|
||||
vboxSelected,
|
||||
itemInfo,
|
||||
} = state;
|
||||
|
||||
@@ -44,6 +45,7 @@ const addState = connect(
|
||||
sendVboxDiscard,
|
||||
sendVboxReclaim,
|
||||
vboxHighlight,
|
||||
vboxSelected,
|
||||
itemInfo,
|
||||
};
|
||||
},
|
||||
@@ -65,11 +67,21 @@ const addState = connect(
|
||||
return dispatch(actions.setVboxHighlight(v));
|
||||
}
|
||||
|
||||
function setVboxSelected(v) {
|
||||
return dispatch(actions.setVboxSelected(v));
|
||||
}
|
||||
|
||||
function setItemEquip(v) {
|
||||
return dispatch(actions.setItemEquip(v));
|
||||
}
|
||||
|
||||
return {
|
||||
setCombiner,
|
||||
setReclaiming,
|
||||
setInfo,
|
||||
setVboxHighlight,
|
||||
setVboxSelected,
|
||||
setItemEquip,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,6 +102,12 @@ function Vbox(args) {
|
||||
|
||||
setCombiner,
|
||||
setInfo,
|
||||
|
||||
vboxSelected,
|
||||
setVboxSelected,
|
||||
|
||||
setItemEquip,
|
||||
|
||||
setReclaiming,
|
||||
setVboxHighlight,
|
||||
} = args;
|
||||
@@ -105,6 +123,13 @@ function Vbox(args) {
|
||||
|
||||
function combinerChange(newCombiner) {
|
||||
setCombiner(newCombiner);
|
||||
|
||||
if (combiner.length === 1) {
|
||||
setItemEquip(newCombiner[0]);
|
||||
} else {
|
||||
setItemEquip(null);
|
||||
}
|
||||
|
||||
if (newCombiner.every(c => c === null)) return setVboxHighlight([]);
|
||||
|
||||
const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv);
|
||||
@@ -124,39 +149,6 @@ function Vbox(args) {
|
||||
//
|
||||
// VBOX
|
||||
//
|
||||
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]]);
|
||||
|
||||
let vboxTimer;
|
||||
const LONG_TOUCH_TIME = 500;
|
||||
function vboxTouchStart(e, i, j) {
|
||||
vboxTimer = (setTimeout(() => {
|
||||
sendVboxAccept(j, i);
|
||||
vboxTimer = null;
|
||||
}, LONG_TOUCH_TIME));
|
||||
return true;
|
||||
}
|
||||
|
||||
function vboxTouchEnd(e, i, j) {
|
||||
if (vboxTimer) {
|
||||
clearTimeout(vboxTimer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function vboxTouchMove(e) {
|
||||
if (vboxTimer) clearTimeout(vboxTimer);
|
||||
e.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
function vboxHover(e, v) {
|
||||
if (v) {
|
||||
setInfo(v);
|
||||
@@ -165,168 +157,170 @@ 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 <td
|
||||
key={j}
|
||||
class={`${highlighted ? 'highlight' : ''}`}
|
||||
onTouchStart={e => vboxTouchStart(e, i, j)}
|
||||
onTouchEnd={e => vboxTouchEnd(e, i, j)}
|
||||
onTouchMove={e => vboxTouchMove(e)}
|
||||
function availableBtn(v, group, index) {
|
||||
if (!v) return <button disabled class='empty' > </button>;
|
||||
|
||||
// onClick={freeClick}
|
||||
onDblClick={() => sendVboxAccept(sendItemType, sendItemIndex) }
|
||||
onMouseOver={e => vboxHover(e, c)}
|
||||
>
|
||||
{convertItem(c)}
|
||||
</td>;
|
||||
});
|
||||
return (
|
||||
<tr key={i}>
|
||||
{cells}
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
function onClick() {
|
||||
// double clicked
|
||||
if (vboxSelected[0] === group && vboxSelected[1] === index) {
|
||||
document.activeElement.blur();
|
||||
setVboxSelected([]);
|
||||
return sendVboxAccept(group, index);
|
||||
}
|
||||
|
||||
//
|
||||
// INVENTORY
|
||||
//
|
||||
function boundClick(e, i) {
|
||||
const value = vbox.bound[i];
|
||||
if (reclaiming && value) return sendVboxReclaim(i);
|
||||
if (value) {
|
||||
const insert = combiner.findIndex(j => j === null);
|
||||
if (insert === -1) return combinerChange([i, null, null]);
|
||||
combiner[insert] = i;
|
||||
return combinerChange(combiner);
|
||||
return setVboxSelected([group, index]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const boundTds = range(0, 9).map(i => {
|
||||
const value = vbox.bound[i];
|
||||
if (combiner.indexOf(i) > -1) {
|
||||
if (['Red', 'Green', 'Blue'].includes(v)) {
|
||||
return (
|
||||
<td
|
||||
key={i}>
|
||||
|
||||
</td>
|
||||
<button
|
||||
onMouseOver={e => vboxHover(e, v)}
|
||||
onClick={onClick}>
|
||||
{shapes.vboxColour(v.toLowerCase())}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
const highlighted = value && vboxHighlight.includes(value);
|
||||
|
||||
return (
|
||||
<td
|
||||
key={i}
|
||||
class={`${highlighted ? 'highlight' : ''}`}
|
||||
onMouseOver={(e) => vboxHover(e, value)}
|
||||
onClick={e => boundClick(e, i, highlighted) }>
|
||||
{convertItem(value)}
|
||||
</td>
|
||||
<button
|
||||
onClick={onClick}
|
||||
onMouseOver={e => vboxHover(e, v)}>
|
||||
{v}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
const boundRows = [
|
||||
<tr key={0} >
|
||||
{boundTds[0]}
|
||||
{boundTds[1]}
|
||||
{boundTds[2]}
|
||||
</tr>,
|
||||
<tr key={1}>
|
||||
{boundTds[3]}
|
||||
{boundTds[4]}
|
||||
{boundTds[5]}
|
||||
</tr>,
|
||||
<tr key={2}>
|
||||
{boundTds[6]}
|
||||
{boundTds[7]}
|
||||
{boundTds[8]}
|
||||
</tr>,
|
||||
];
|
||||
|
||||
//
|
||||
// COMBINER
|
||||
//
|
||||
function combinerRmv(i) {
|
||||
combiner[i] = null;
|
||||
return combinerChange(combiner);
|
||||
}
|
||||
const combinerElement = (
|
||||
<table class="vbox-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td onClick={() => combinerRmv(0)}>
|
||||
{combiner[0] !== null ? convertItem(vbox.bound[combiner[0]]) : shapes.vboxColour('gray')}
|
||||
</td>
|
||||
<td onClick={() => combinerRmv(1)}>
|
||||
{combiner[1] !== null ? convertItem(vbox.bound[combiner[1]]) : shapes.vboxColour('gray')}
|
||||
</td>
|
||||
<td onClick={() => combinerRmv(2)}>
|
||||
{convertItem(vbox.bound[combiner[2]])}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
|
||||
//
|
||||
// EVERYTHING
|
||||
//
|
||||
|
||||
function reclaimClick(e) {
|
||||
e.stopPropagation();
|
||||
return setReclaiming(!reclaiming);
|
||||
}
|
||||
|
||||
function hoverInfo(e, info) {
|
||||
e.stopPropagation();
|
||||
return setInfo(info);
|
||||
}
|
||||
|
||||
const classes = "vbox";
|
||||
const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`;
|
||||
|
||||
return (
|
||||
<div class={classes}>
|
||||
<div class='vbox-box'
|
||||
function vboxElement() {
|
||||
return (
|
||||
<div class='vbox-vbox'
|
||||
onClick={() => setReclaiming(false)}
|
||||
onMouseOver={e => hoverInfo(e, 'vbox')}>
|
||||
<div class="vbox-hdr">
|
||||
<h3 onTouchStart={e => e.target.scrollIntoView(true)}>VBOX</h3>
|
||||
<div class="bits" onMouseOver={e => hoverInfo(e, 'bits')} >{vbox.bits}b</div>
|
||||
</div>
|
||||
<div style="text-align: center"> Colours </div>
|
||||
<table class="vbox-table">
|
||||
<tbody>
|
||||
{freeRows.slice(0, 2)}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align: center"> Skills </div>
|
||||
<table class="vbox-table">
|
||||
<tbody>
|
||||
{freeRows[2]}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align: center"> Specs </div>
|
||||
<table class="vbox-table">
|
||||
<tbody>
|
||||
{freeRows[3]}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="vbox-colours">
|
||||
{range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))}
|
||||
</div>
|
||||
<div class="vbox-items">
|
||||
{range(0, 3).map(i => availableBtn(vbox.free[1][i], 1, i))}
|
||||
{range(0, 3).map(i => availableBtn(vbox.free[2][i], 2, i))}
|
||||
</div>
|
||||
<button
|
||||
class='vbox-btn'
|
||||
onMouseOver={e => hoverInfo(e, 'reroll')}
|
||||
onClick={() => sendVboxDiscard()}>
|
||||
Reroll
|
||||
refill - 5b
|
||||
</button>
|
||||
</div>
|
||||
<div class="vbox-arrow">⮞</div>
|
||||
<div class="vbox-arrow-mobile">⮟</div>
|
||||
<div class='vbox-inventory'
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// INVENTORY
|
||||
//
|
||||
|
||||
// const boundTds = range(0, 9).map(i => {
|
||||
// const value = vbox.bound[i];
|
||||
// if (combiner.indexOf(i) > -1) {
|
||||
// return (
|
||||
// <td
|
||||
// key={i}>
|
||||
//
|
||||
// </td>
|
||||
// );
|
||||
// }
|
||||
|
||||
// const highlighted = value && vboxHighlight.includes(value);
|
||||
|
||||
// return (
|
||||
// <td
|
||||
// key={i}
|
||||
// class={`${highlighted ? 'highlight' : ''}`}
|
||||
// onMouseOver={(e) => vboxHover(e, value)}
|
||||
// onClick={e => boundClick(e, i, highlighted) }>
|
||||
// {convertItem(value)}
|
||||
// </td>
|
||||
// );
|
||||
// });
|
||||
|
||||
|
||||
function reclaimClick(e) {
|
||||
e.stopPropagation();
|
||||
return setReclaiming(!reclaiming);
|
||||
}
|
||||
|
||||
const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`;
|
||||
|
||||
function inventoryBtn(v, i) {
|
||||
if (!v && v !== 0) return <button disabled class='empty' > </button>;
|
||||
|
||||
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 (
|
||||
<button
|
||||
class={classes}
|
||||
onMouseOver={e => vboxHover(e, v)}
|
||||
onClick={onClick}>
|
||||
{shapes.vboxColour(v.toLowerCase())}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
class={classes}
|
||||
onClick={onClick}
|
||||
onMouseOver={e => vboxHover(e, v)}>
|
||||
{v}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function combinerBtn() {
|
||||
let text = '';
|
||||
|
||||
if (combiner.length < 3) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (combiner.length > i) {
|
||||
text += '■ ';
|
||||
} else {
|
||||
text += '▫ ';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text = 'combine';
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
class='vbox-btn'
|
||||
disabled={combiner.length !== 3}
|
||||
onMouseOver={e => hoverInfo(e, 'refine')}
|
||||
onClick={() => sendVboxCombine()}>
|
||||
{text}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function inventoryElement() {
|
||||
return (
|
||||
<div class='vbox-section'
|
||||
onClick={() => setReclaiming(false)}
|
||||
onMouseOver={e => hoverInfo(e, 'inventory')}>
|
||||
<div class="vbox-hdr">
|
||||
@@ -338,21 +332,30 @@ function Vbox(args) {
|
||||
reclaim
|
||||
</button>
|
||||
</div>
|
||||
<table class="vbox-table">
|
||||
<tbody>
|
||||
{boundRows}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="vbox-combiner-arrow" onTouchStart={e => e.target.scrollIntoView(true)}>⮟⮝</div>
|
||||
<div class="vbox-combiner" onMouseOver={e => hoverInfo(e, 'combiner')} >
|
||||
{combinerElement}
|
||||
<button
|
||||
onMouseOver={e => hoverInfo(e, 'refine')}
|
||||
onClick={() => sendVboxCombine()}>
|
||||
combine
|
||||
</button>
|
||||
<div class='vbox-items'>
|
||||
{range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))}
|
||||
</div>
|
||||
{combinerBtn()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// EVERYTHING
|
||||
//
|
||||
|
||||
|
||||
function hoverInfo(e, info) {
|
||||
e.stopPropagation();
|
||||
return setInfo(info);
|
||||
}
|
||||
|
||||
const classes = 'vbox';
|
||||
return (
|
||||
<div class={classes}>
|
||||
{vboxElement()}
|
||||
<div class="vbox-arrow">⮞</div>
|
||||
{inventoryElement()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user