diff --git a/client/assets/styles/vbox.less b/client/assets/styles/vbox.less
index ec739a11..859919d8 100644
--- a/client/assets/styles/vbox.less
+++ b/client/assets/styles/vbox.less
@@ -218,11 +218,10 @@
margin-top: 1em;
line-height: 1.3;
font-size: 1.25em;
-
-
letter-spacing: 0.1em;
- border: 0;
- transition-property: 0;
+ &:hover {
+ border: 2px solid @gray-hover;
+ }
}
}
diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx
deleted file mode 100644
index 4b59e4d3..00000000
--- a/client/src/components/info.component.jsx
+++ /dev/null
@@ -1,195 +0,0 @@
-const preact = require('preact');
-const reactStringReplace = require('react-string-replace');
-
-const specThresholds = require('./info.thresholds');
-const { INFO } = require('./../constants');
-const { convertItem, removeTier } = require('../utils');
-const { tutorialStage } = require('../tutorial.utils');
-const shapes = require('./shapes');
-
-const Combiner = require('./vbox.combiner');
-
-
-class InfoComponent extends preact.Component {
- shouldComponentUpdate(newProps, newState) {
- if (newProps.vboxHighlight !== this.props.vboxHighlight) return true;
- if (newProps.tutorial !== this.props.tutorial) return true;
- // We don't care about info during tutorial
- if (newProps.tutorial && this.props.instance.time_control === 'Practice'
- && this.props.instance.rounds.length === 1) return false;
- if (newProps.info !== this.props.info) return true;
- if (newState.comboItem !== this.state.comboItem) return true;
-
- return false;
- }
-
- componentDidUpdate(prevProps) {
- // Catch case where mouse events don't properly clear state and info changed
- if (prevProps.info !== this.props.info && this.state.comboItem) this.setState({ comboItem: null });
- }
-
- render(args) {
- const {
- // Variables that will change
- info,
- tutorial,
- vboxHighlight,
-
- // Static
- player, // Only used for colour calcs which will be update if info changes
- ws,
- itemInfo,
- instance, // Only used for instance id
- // functions
- setTutorialNull,
- } = args;
- const { comboItem } = this.state;
- function Info() {
- if (tutorial) {
- const tutorialStageInfo = tutorialStage(tutorial, ws, setTutorialNull, instance);
- if (tutorialStageInfo) return tutorialStageInfo;
- }
- if (!info) return false;
- if (info.includes('constructName')) {
- return (
-
-
{info.replace('constructName ', '')}
-
This is the name of your construct.
- Names are randomly generated and are purely cosmetic.
- You can change change your construct name in the RESHAPE tab outside of games.
-
-
- );
- }
-
- if (info.includes('constructAvatar')) {
- return (
-
-
{info.replace('constructAvatar ', '')}
-
This is your construct avatar.
- Avatars are randomly generated and are purely cosmetic.
- You can change your construct avatar in the RESHAPE tab outside of games.
-
-
- );
- }
- const fullInfo = comboItem
- ? itemInfo.items.find(i => i.item === comboItem) || INFO[comboItem]
- : itemInfo.items.find(i => i.item === info) || INFO[info];
- if (!fullInfo) return false;
- const isSkill = fullInfo.skill;
- const isSpec = fullInfo.spec;
-
- const itemDescription = () => {
- const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat|LIFE|SPEED|POWER)/;
- const infoDescription = reactStringReplace(fullInfo.description, regEx, m => shapes[m]());
- return {reactStringReplace(infoDescription, '\n', () =>
)}
;
- };
-
- if (isSkill || isSpec) {
- let infoName = fullInfo.item;
- while (infoName.includes('Plus')) infoName = infoName.replace('Plus', '+');
-
- const itemSource = itemInfo.combos.filter(c => c.item === removeTier(fullInfo.item));
-
- let itemSourceInfo = itemSource.length && !isSpec
- ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
- : false;
-
- let header = null;
- if (!itemSource.length) header = isSkill ? SKILL
: SPEC
;
- if (itemSourceInfo) {
- while (itemSourceInfo.includes('Plus')) itemSourceInfo = itemSourceInfo.replace('Plus', '+');
- const itemRegEx = /(Red|Blue|Green)/;
- itemSourceInfo = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
- }
-
- const cooldown = isSkill && fullInfo.cooldown ? {fullInfo.cooldown} Turn delay
: null;
-
- const speed = isSkill
- ? Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}%
- : null;
-
- const thresholds = isSpec ? specThresholds(player, fullInfo, info) : null;
-
- return (
-
-
{infoName}
- {header}
- {itemSourceInfo}
- {cooldown}
- {itemDescription()}
- {speed}
- {thresholds}
-
- );
- }
-
- return (
-
-
{fullInfo.item}
- {itemDescription()}
-
- );
- }
-
- const Combos = () => {
- if (tutorial && instance.time_control === 'Practice' && instance.rounds.length === 1) return false;
-/* const generalNotes = (
-
-
General
-
- You can preview combos by clicking the combined item when it appears in this section.
- Click the READY button to start the GAME PHASE.
-
-
- );*/
- if (!player) return false;
- if (!info) return false;
-
- const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info));
- if (vboxCombos.length > 6 || vboxCombos.length === 0) return false;
-
- const comboTable = vboxCombos.map((c, i) => {
- const mouseOver = e => {
- e.stopPropagation();
- this.setState({ comboItem: c.item });
- };
- const componentTable = (c.components.some(ci => ['Red', 'Blue', 'Green'].includes(ci)))
- ? [{convertItem(c.components[0])} {convertItem(c.components[1])}
,
- {convertItem(c.components[2])}
]
- : c.components.map((u, j) => {convertItem(u)}
);
- return (
-
- );
- });
- const comboList = comboTable.length > 0 ? {comboTable}
: false;
- return (
-
-
- {comboList}
-
- );
- };
-
- return (
-
-
this.setState({ comboItem: null })}>
-
-
-
-
-
- );
- }
-}
-
-module.exports = InfoComponent;
diff --git a/client/src/components/info.container.jsx b/client/src/components/info.container.jsx
deleted file mode 100644
index 8a8dbb6f..00000000
--- a/client/src/components/info.container.jsx
+++ /dev/null
@@ -1,43 +0,0 @@
-const { connect } = require('preact-redux');
-
-const actions = require('../actions');
-const Info = require('./info.component');
-
-const addState = connect(
- function receiveState(state) {
- const {
- ws,
- info,
- itemInfo,
- instance,
- player,
- account,
- tutorial,
- } = state;
-
- return {
- ws,
- info,
- itemInfo,
- instance,
- player,
- account,
- tutorial,
- };
- },
-
- function receiveDispatch(dispatch) {
- function setTutorialNull() {
- dispatch(actions.setTutorial(null));
- }
-
- function setInfo(info) {
- dispatch(actions.setInfo(info));
- }
- return { setTutorialNull, setInfo };
- }
-
-
-);
-
-module.exports = addState(Info);
diff --git a/client/src/components/instance.component.jsx b/client/src/components/instance.component.jsx
index d0d34345..c59b5833 100644
--- a/client/src/components/instance.component.jsx
+++ b/client/src/components/instance.component.jsx
@@ -55,10 +55,6 @@ function Instance(args) {
clearItems();
}
- function onTouchMove(e) {
- e.preventDefault();
- }
-
return (
diff --git a/client/src/components/vbox.combiner.jsx b/client/src/components/vbox.combiner.jsx
index 1ffd6797..261fb7a2 100644
--- a/client/src/components/vbox.combiner.jsx
+++ b/client/src/components/vbox.combiner.jsx
@@ -1,6 +1,5 @@
const preact = require('preact');
const { connect } = require('preact-redux');
-const countBy = require('lodash/countBy');
const actions = require('../actions');
@@ -27,19 +26,9 @@ const addState = connect(
return {
vbox,
vboxSelected,
- itemInfo,
sendVboxAccept,
sendVboxCombine,
};
- },
- function receiveDispatch(dispatch) {
- function setInfo(item) {
- return dispatch(actions.setInfo(item));
- }
-
- return {
- setInfo,
- };
}
);
@@ -47,22 +36,18 @@ class CombinerBtn extends preact.Component {
shouldComponentUpdate(newProps) {
// Single variable props
if (newProps.vbox !== this.props.vbox) return true;
- if (newProps.vboxHighlight !== this.props.vboxHighlight) return true;
if (newProps.vboxSelected !== this.props.vboxSelected) return true;
return false;
}
render(props) {
const {
- vboxHighlight,
-
vbox,
vboxSelected,
- itemInfo,
sendVboxAccept,
sendVboxCombine,
+ combinerCombo,
- setInfo,
} = props;
const { stashSelect, storeSelect } = vboxSelected;
@@ -73,31 +58,15 @@ class CombinerBtn extends preact.Component {
sendVboxAccept(storeSelect[0][0], storeSelect[0][1]);
return true;
}
-
let text = '';
let mouseEvent = false;
- const combineLength = stashSelect.length + storeSelect.length;
- if (vboxHighlight && vboxHighlight.length === 0) {
- // The selected items can't be combined with additional items therefore valid combo
- const stashItems = stashSelect.map(j => vbox.bound[j]);
- const shopItems = storeSelect.map(j => vbox.free[j[0]][j[1]]);
- const selectedItems = stashItems.concat(shopItems);
- const combinerCount = countBy(selectedItems, co => co);
-
- const comboItemObj = itemInfo.combos.find(combo => selectedItems.every(c => {
- if (!combo.components.includes(c)) return false;
- const comboCount = countBy(combo.components, co => co);
- if (combinerCount[c] > comboCount[c]) return false;
- return true;
- }));
- let comboItem = comboItemObj ? comboItemObj.item : 'refine';
- setInfo(comboItem);
- comboItem = comboItem.replace('Plus', '+');
+ if (combinerCombo) {
+ const comboItem = combinerCombo.replace('Plus', '+');
let bits = 0;
storeSelect.forEach(item => bits += item[0] + 1);
text = bits
? `Buy ${comboItem} ${bits}b`
- : `Combine${comboItem}`;
+ : `Combine ${comboItem}`;
if (vbox.bits >= bits) mouseEvent = sendVboxCombine;
} else if (stashSelect.length === 0 && storeSelect.length === 1) {
const item = storeSelect[0];
diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx
index 756f17ee..1476ffb7 100644
--- a/client/src/components/vbox.component.jsx
+++ b/client/src/components/vbox.component.jsx
@@ -5,7 +5,7 @@ const forEach = require('lodash/forEach');
const actions = require('../actions');
-const InfoContainer = require('./info.container');
+const InfoContainer = require('./vbox.info');
const StashElement = require('./vbox.stash');
const StoreElement = require('./vbox.store');
@@ -149,11 +149,7 @@ class Vbox extends preact.Component {
function vboxHover(e, v) {
if (v) {
e.stopPropagation();
- if (storeSelect.find(c => c[0])) return true; // There is a base skill or spec selected in the vbox
- if (stashSelect.length !== 0) {
- const base = stashSelect.find(c => !['Red', 'Blue', 'Green'].includes(vbox.bound[c]));
- if (base || base === 0) return true;
- }
+ if (stashSelect.length !== 0 || storeSelect.length !== 0) return true;
setInfo(v);
}
return true;
diff --git a/client/src/components/vbox.info.jsx b/client/src/components/vbox.info.jsx
new file mode 100644
index 00000000..3a553c0d
--- /dev/null
+++ b/client/src/components/vbox.info.jsx
@@ -0,0 +1,261 @@
+const preact = require('preact');
+const { connect } = require('preact-redux');
+const reactStringReplace = require('react-string-replace');
+const countBy = require('lodash/countBy');
+
+const specThresholds = require('./vbox.info.thresholds');
+const { INFO } = require('./../constants');
+const { convertItem, removeTier } = require('../utils');
+const { tutorialStage } = require('../tutorial.utils');
+const shapes = require('./shapes');
+const Combiner = require('./vbox.combiner');
+
+const actions = require('../actions');
+
+const addState = connect(
+ function receiveState(state) {
+ const {
+ ws,
+ info,
+ itemInfo,
+ instance,
+ player,
+ account,
+ tutorial,
+ vboxSelected,
+ } = state;
+
+ return {
+ ws,
+ info,
+ itemInfo,
+ instance,
+ player,
+ account,
+ tutorial,
+ vboxSelected,
+ };
+ },
+
+ function receiveDispatch(dispatch) {
+ function setTutorialNull() {
+ dispatch(actions.setTutorial(null));
+ }
+
+ function setInfo(info) {
+ dispatch(actions.setInfo(info));
+ }
+ return { setTutorialNull, setInfo };
+ }
+);
+
+class InfoComponent extends preact.Component {
+ shouldComponentUpdate(newProps, newState) {
+ if (newProps.vboxSelected !== this.props.vboxSelected) return true;
+ if (newProps.vboxHighlight !== this.props.vboxHighlight) return true;
+ if (newProps.tutorial !== this.props.tutorial) return true;
+ // We don't care about info during tutorial
+ if (newProps.tutorial && this.props.instance.time_control === 'Practice'
+ && this.props.instance.rounds.length === 1) return false;
+ if (newProps.info !== this.props.info) return true;
+ if (newState.comboItem !== this.state.comboItem) return true;
+
+ return false;
+ }
+
+ componentDidUpdate(prevProps) {
+ // Catch case where mouse events don't properly clear state and info changed
+ if (prevProps.info !== this.props.info && this.state.comboItem) this.setState({ comboItem: null });
+ }
+
+ render(args) {
+ const {
+ // Variables that will change
+ info,
+ tutorial,
+ vboxHighlight,
+ vboxSelected,
+ // Static
+ player, // Only used for colour calcs which will be update if info changes
+ ws,
+ itemInfo,
+ instance, // Only used for instance id
+ // functions
+ setTutorialNull,
+ } = args;
+ const { comboItem } = this.state;
+
+ const { vbox } = player;
+ const { stashSelect, storeSelect } = vboxSelected;
+
+ const vboxCombo = () => {
+ if (!(vboxHighlight && vboxHighlight.length === 0)) return false;
+ // The selected items can't be combined with additional items therefore valid combo
+ const stashItems = stashSelect.map(j => vbox.bound[j]);
+ const shopItems = storeSelect.map(j => vbox.free[j[0]][j[1]]);
+ const selectedItems = stashItems.concat(shopItems);
+ const combinerCount = countBy(selectedItems, co => co);
+
+ const comboItemObj = itemInfo.combos.find(combo => selectedItems.every(c => {
+ if (!combo.components.includes(c)) return false;
+ const comboCount = countBy(combo.components, co => co);
+ if (combinerCount[c] > comboCount[c]) return false;
+ return true;
+ }));
+ return comboItemObj.item;
+ };
+
+ const combinerCombo = vboxCombo();
+ const checkVboxInfo = () => {
+ if (combinerCombo) return combinerCombo;
+ const stashBase = stashSelect.find(i => !(['Red', 'Blue', 'Green'].includes(vbox.bound[i])));
+ if (stashBase > -1) return vbox.bound[stashBase];
+ const storeBase = storeSelect.find(j => !(['Red', 'Blue', 'Green'].includes(vbox.free[j[0]][j[1]])));
+ if (storeBase) return vbox.free[storeBase[0]][storeBase[1]];
+ if (stashSelect.length > 0) return vbox.bound[stashSelect[0]];
+ if (storeSelect.length > 0) return vbox.free[storeSelect[0][0]][storeSelect[0][1]];
+ return false;
+ };
+
+ const vboxInfo = (stashSelect.length > 0 || storeSelect.length > 0) ? checkVboxInfo() : false;
+
+ function Info() {
+ if (tutorial) {
+ const tutorialStageInfo = tutorialStage(tutorial, ws, setTutorialNull, instance);
+ if (tutorialStageInfo) return tutorialStageInfo;
+ }
+
+ function genItemInfo(item) {
+ const fullInfo = itemInfo.items.find(i => i.item === item) || INFO[item];
+ const isSkill = fullInfo.skill;
+ const isSpec = fullInfo.spec;
+ const itemDescription = () => {
+ const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat|LIFE|SPEED|POWER)/;
+ const infoDescription = reactStringReplace(fullInfo.description, regEx, m => shapes[m]());
+ return {reactStringReplace(infoDescription, '\n', () =>
)}
;
+ };
+ if (isSkill || isSpec) {
+ let infoName = fullInfo.item;
+ while (infoName.includes('Plus')) infoName = infoName.replace('Plus', '+');
+
+ const itemSource = itemInfo.combos.filter(c => c.item === removeTier(fullInfo.item));
+
+ let itemSourceInfo = itemSource.length && !isSpec
+ ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
+ : false;
+
+ let header = null;
+ if (!itemSource.length) header = isSkill ? SKILL
: SPEC
;
+ if (itemSourceInfo) {
+ while (itemSourceInfo.includes('Plus')) itemSourceInfo = itemSourceInfo.replace('Plus', '+');
+ const itemRegEx = /(Red|Blue|Green)/;
+ itemSourceInfo = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());
+ }
+
+ const cooldown = isSkill && fullInfo.cooldown ? {fullInfo.cooldown} Turn delay
: null;
+
+ const speed = isSkill
+ ? Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}%
+ : null;
+
+ const thresholds = isSpec ? specThresholds(player, fullInfo, info) : null;
+
+ return (
+
+
{infoName}
+ {header}
+ {itemSourceInfo}
+ {cooldown}
+ {itemDescription()}
+ {speed}
+ {thresholds}
+
+ );
+ }
+ return (
+
+
{fullInfo.item}
+ {itemDescription()}
+
+ );
+ }
+ if (vboxInfo) return genItemInfo(vboxInfo);
+ if (!info) return false;
+ if (info.includes('constructName')) {
+ return (
+
+
{info.replace('constructName ', '')}
+
This is the name of your construct.
+ Names are randomly generated and are purely cosmetic.
+ You can change change your construct name in the RESHAPE tab outside of games.
+
+
+ );
+ }
+
+ if (info.includes('constructAvatar')) {
+ return (
+
+
{info.replace('constructAvatar ', '')}
+
This is your construct avatar.
+ Avatars are randomly generated and are purely cosmetic.
+ You can change your construct avatar in the RESHAPE tab outside of games.
+
+
+ );
+ }
+ const stateFullInfo = comboItem || info;
+ if (!stateFullInfo) return false;
+ return genItemInfo(stateFullInfo);
+ }
+
+ const Combos = () => {
+ if (tutorial && instance.time_control === 'Practice' && instance.rounds.length === 1) return false;
+ if (!info && !vboxInfo) return false;
+ const comboInfo = vboxInfo || info;
+ const vboxCombos = itemInfo.combos.filter(c => c.components.includes(comboInfo));
+ if (vboxCombos.length > 6 || vboxCombos.length === 0) return false;
+
+ const comboTable = vboxCombos.map((c, i) => {
+ const mouseOver = e => {
+ e.stopPropagation();
+ this.setState({ comboItem: c.item });
+ };
+ const componentTable = (c.components.some(ci => ['Red', 'Blue', 'Green'].includes(ci)))
+ ? [{convertItem(c.components[0])} {convertItem(c.components[1])}
,
+ {convertItem(c.components[2])}
]
+ : c.components.map((u, j) => {convertItem(u)}
);
+ return (
+
+ );
+ });
+ const comboList = comboTable.length > 0 ? {comboTable}
: false;
+ return (
+
+
+ {comboList}
+
+ );
+ };
+
+ return (
+
+
this.setState({ comboItem: null })}>
+
+
+
+
+
+ );
+ }
+}
+
+module.exports = addState(InfoComponent);
diff --git a/client/src/components/info.thresholds.jsx b/client/src/components/vbox.info.thresholds.jsx
similarity index 100%
rename from client/src/components/info.thresholds.jsx
rename to client/src/components/vbox.info.thresholds.jsx