diff --git a/client/assets/styles/vbox.less b/client/assets/styles/vbox.less index 2e3bbde8..b6bff59f 100644 --- a/client/assets/styles/vbox.less +++ b/client/assets/styles/vbox.less @@ -3,7 +3,7 @@ grid-area: vbox; display: grid; grid-template-rows: 3fr minmax(min-content, 2fr); - grid-template-columns: 1fr 4fr 6fr 17em; // =\ + grid-template-columns: 1fr 4fr 6fr min-content; grid-template-areas: "store-hdr store info combos" "stash-hdr stash combiner combos"; @@ -217,7 +217,9 @@ display: grid; grid-area: combos; margin-left: 0.5em; + margin-right: 0.5em; grid-template-rows: min-content min-content; + width: 15.5em; grid-template-areas: "comboHeader" "comboList"; diff --git a/client/src/actions.jsx b/client/src/actions.jsx index 0c1456af..ab644966 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -48,5 +48,8 @@ export const setTutorial = value => ({ type: 'SET_TUTORIAL', value }); export const setTutorialGame = value => ({ type: 'SET_TUTORIAL_GAME', value }); export const setVboxSelected = value => ({ type: 'SET_VBOX_SELECTED', value }); +export const setVboxCombiner = value => ({ type: 'SET_VBOX_COMBINER', value }); +export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value }); +export const setVboxInfo = value => ({ type: 'SET_VBOX_INFO', value }); export const setWs = value => ({ type: 'SET_WS', value }); diff --git a/client/src/app.jsx b/client/src/app.jsx index 0d668980..1599c1ab 100644 --- a/client/src/app.jsx +++ b/client/src/app.jsx @@ -8,7 +8,6 @@ const { createStore, combineReducers } = require('redux'); const { StripeProvider } = require('react-stripe-elements'); const reducers = require('./reducers'); -const actions = require('./actions'); const setupKeys = require('./keyboard'); const createSocket = require('./socket'); const registerEvents = require('./events'); diff --git a/client/src/components/vbox.combiner.jsx b/client/src/components/vbox.combiner.jsx index 93051a33..9fef580e 100644 --- a/client/src/components/vbox.combiner.jsx +++ b/client/src/components/vbox.combiner.jsx @@ -1,104 +1,44 @@ const preact = require('preact'); -const { connect } = require('preact-redux'); -const countBy = require('lodash/countBy'); - -const addState = connect( - function receiveState(state) { - const { - ws, - itemInfo, - instance, - player, - vboxSelected, - } = state; - - function sendVboxAccept(group, index) { - document.activeElement.blur(); - return ws.sendVboxAccept(instance.id, group, index); - } - - function sendVboxCombine() { - return ws.sendVboxCombine(instance.id, vboxSelected.stashSelect, vboxSelected.storeSelect); - } - - return { - itemInfo, - player, - vboxSelected, - sendVboxAccept, - sendVboxCombine, - }; - } -); function Combiner(args) { const { - // Variables that will change - vboxHighlight, + vbox, + vboxCombiner, vboxSelected, - // Static - player, - itemInfo, - // functions - sendVboxAccept, + vboxBuySelected, sendVboxCombine, } = args; - 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(); - - function vboxBuySelected() { - if (!(storeSelect.length === 1 && stashSelect.length === 0)) return false; - document.activeElement.blur(); - sendVboxAccept(storeSelect[0][0], storeSelect[0][1]); - return true; - } - let text = ''; - let mouseEvent = false; - if (combinerCombo) { - const combinerComboText = combinerCombo.replace('Plus', '+'); + if (vboxCombiner) { + const combinerComboText = vboxCombiner.replace('Plus', '+'); let bits = 0; storeSelect.forEach(item => bits += item[0] + 1); - text = bits - ? `Buy ${combinerComboText} ${bits}b` - : `Combine ${combinerComboText}`; - if (vbox.bits >= bits) mouseEvent = sendVboxCombine; - } else if (stashSelect.length === 0 && storeSelect.length === 1) { - const item = storeSelect[0]; - text = `Buy ${vbox.free[item[0]][item[1]]} ${item[0] + 1}b`; - mouseEvent = vboxBuySelected; - } else { - return false; + return ( + + ); } - return ( - - ); + if (stashSelect.length === 0 && storeSelect.length === 1) { + const item = storeSelect[0]; + return ( + + ); + } + + return false; } -module.exports = addState(Combiner); +module.exports = Combiner; diff --git a/client/src/components/vbox.combos.jsx b/client/src/components/vbox.combos.jsx index 410252d0..f988064c 100644 --- a/client/src/components/vbox.combos.jsx +++ b/client/src/components/vbox.combos.jsx @@ -1,112 +1,27 @@ const preact = require('preact'); const { connect } = require('preact-redux'); -const reactStringReplace = require('react-string-replace'); -const countBy = require('lodash/countBy'); -const { convertItem, removeTier } = require('../utils'); -const shapes = require('./shapes'); +const { convertItem } = require('../utils'); -const actions = require('../actions'); - -const addState = connect( - function receiveState(state) { - const { - ws, - info, - itemInfo, - itemUnequip, - instance, - player, - account, - tutorial, - vboxSelected, - } = state; - - function sendVboxAccept(group, index) { - document.activeElement.blur(); - return ws.sendVboxAccept(instance.id, group, index); - } - - function sendVboxCombine() { - return ws.sendVboxCombine(instance.id, vboxSelected.stashSelect, vboxSelected.storeSelect); - } - - return { - ws, - info, - itemInfo, - itemUnequip, - instance, - player, - account, - tutorial, - vboxSelected, - sendVboxAccept, - sendVboxCombine, - }; - } -); +const addState = connect(({ info, itemInfo, instance, tutorial, vboxInfo }) => + ({ info, itemInfo, instance, tutorial, vboxInfo })); function Combos(args) { const { // Variables that will change info, - itemUnequip, tutorial, - vboxHighlight, - vboxSelected, + vboxInfo, // Static - player, // Only used for colour calcs which will be update if info changes - ws, itemInfo, - instance, // Only used for instance id + instance, // Only used for tutorial check // functions - sendVboxAccept, - sendVboxCombine, - 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; - }; - let vboxInfo = false; - if (itemUnequip.length) [, vboxInfo] = itemUnequip; - else if (stashSelect.length > 0 || storeSelect.length > 0) vboxInfo = checkVboxInfo(); 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 vboxCombos = itemInfo.combos.filter(c => c.components.includes(vboxInfo || info)); + if (vboxCombos.length > 6 || vboxCombos.length === 0) return
; const comboTable = vboxCombos.map((c, i) => { const mouseOver = e => { @@ -126,14 +41,15 @@ function Combos(args) { ); }); - const comboList = comboTable.length > 0 ?
{comboTable}
: false; return (

COMBOS

Combine colours and items.
- {comboList} +
+ {comboTable} +
); } diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 2f808f08..e0eb4307 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -1,7 +1,5 @@ const preact = require('preact'); const { connect } = require('preact-redux'); -const countBy = require('lodash/countBy'); -const forEach = require('lodash/forEach'); const actions = require('../actions'); @@ -11,17 +9,23 @@ const StoreElement = require('./vbox.store'); const Combiner = require('./vbox.combiner'); const Combos = require('./vbox.combos'); +const { setVboxState } = require('./vbox.utils'); + const addState = connect( function receiveState(state) { const { ws, instance, player, - vboxSelected, info, itemInfo, itemUnequip, tutorial, + + vboxCombiner, + vboxHighlight, + vboxInfo, + vboxSelected, } = state; function sendVboxDiscard() { @@ -29,10 +33,15 @@ const addState = connect( } function sendVboxAccept(group, index) { + if (!(vboxSelected.storeSelect.length === 1 && vboxSelected.stashSelect.length === 0)) return false; document.activeElement.blur(); return ws.sendVboxAccept(instance.id, group, index); } + function sendVboxCombine() { + return ws.sendVboxCombine(instance.id, vboxSelected.stashSelect, vboxSelected.storeSelect); + } + function sendVboxReclaim(i) { return ws.sendVboxReclaim(instance.id, i); } @@ -42,17 +51,23 @@ const addState = connect( } return { + player, instance, info, - player, - sendVboxAccept, - sendVboxDiscard, - sendVboxReclaim, - vboxSelected, itemInfo, itemUnequip, sendItemUnequip, tutorial, + + vboxCombiner, + vboxHighlight, + vboxInfo, + vboxSelected, + + sendVboxAccept, + sendVboxCombine, + sendVboxDiscard, + sendVboxReclaim, }; }, @@ -61,55 +76,26 @@ const addState = connect( return dispatch(actions.setInfo(item)); } - function setVboxSelected(v) { + function dispatchVboxSelect(v, state) { + setVboxState(dispatch, v, state); dispatch(actions.setItemUnequip([])); - dispatch(actions.setVboxSelected(v)); return dispatch(actions.setVboxSelected(v)); } return { + dispatchVboxSelect, setInfo, - setVboxSelected, }; } ); -function validVboxSelect(vbox, itemInfo, storeSelect, stashSelect) { - if (storeSelect.length === 0 && stashSelect.length === 0) return false; - - const validSelects = []; - - 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 itemCount = countBy(selectedItems, co => co); - - itemInfo.combos.forEach(combo => { - const comboCount = countBy(combo.components, co => co); - const buyCount = countBy(combo.components, co => co); - const valid = selectedItems.every(c => { - if (!combo.components.includes(c)) return false; - if (itemCount[c] > comboCount[c]) return false; - buyCount[c] -= 1; - return true; - }); - if (valid) { - forEach(buyCount, (value, key) => { - if (value > 0 && !validSelects.includes(key)) validSelects.push(key); - }); - } - }); - - return validSelects; -} - class Vbox extends preact.Component { shouldComponentUpdate(newProps) { // Single variable props if (newProps.itemUnequip !== this.props.itemUnequip) return true; if (newProps.tutorial !== this.props.tutorial) return true; if (newProps.vboxSelected !== this.props.vboxSelected) return true; + if (newProps.vboxHighlight !== this.props.vboxHighlight) return true; if (newProps.player !== this.props.player) return true; if (newProps.instance !== this.props.instance) return true; return false; @@ -121,33 +107,33 @@ class Vbox extends preact.Component { itemUnequip, player, tutorial, - vboxSelected, instance, + vboxCombiner, + vboxHighlight, + vboxInfo, + vboxSelected, + // Static itemInfo, // Function Calls + dispatchVboxSelect, sendItemUnequip, sendVboxAccept, + sendVboxCombine, sendVboxDiscard, sendVboxReclaim, - setVboxSelected, setInfo, } = args; if (!player) return false; const { vbox } = player; const { storeSelect, stashSelect } = vboxSelected; - const vboxSelecting = storeSelect.length === 1 && stashSelect.length === 0; - function combinerChange(newStashSelect) { - return setVboxSelected({ storeSelect, stashSelect: newStashSelect }); - } + const setVboxSelected = v => dispatchVboxSelect(v, { itemInfo, itemUnequip, vbox }); + const clearVboxSelected = () => setVboxSelected({ storeSelect: [], stashSelect: [] }); + const vboxBuySelected = () => sendVboxAccept(storeSelect[0][0], storeSelect[0][1]); - const vboxHighlight = validVboxSelect(vbox, itemInfo, storeSelect, stashSelect); - // - // VBOX - // function vboxHover(e, v) { if (v) { e.stopPropagation(); @@ -157,17 +143,6 @@ class Vbox extends preact.Component { return true; } - function clearVboxSelected() { - setVboxSelected({ storeSelect: [], stashSelect: [] }); - } - - function vboxBuySelected() { - if (!vboxSelecting) return false; - document.activeElement.blur(); - sendVboxAccept(storeSelect[0][0], storeSelect[0][1]); - return true; - } - function storeHdr() { return (
@@ -233,37 +208,33 @@ class Vbox extends preact.Component { clearVboxSelected = {clearVboxSelected} setInfo = {setInfo} setVboxSelected = {setVboxSelected} - storeSelect = {storeSelect} stashSelect = {stashSelect} + storeSelect = {storeSelect} vbox = {vbox} vboxHighlight = {vboxHighlight} vboxHover = {vboxHover} /> - - + +
); } diff --git a/client/src/components/vbox.info.jsx b/client/src/components/vbox.info.jsx index 452f268d..80f32528 100644 --- a/client/src/components/vbox.info.jsx +++ b/client/src/components/vbox.info.jsx @@ -1,169 +1,33 @@ 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 { genItemInfo } = require('./vbox.utils'); -const actions = require('../actions'); - -const addState = connect( - function receiveState(state) { - const { - ws, - info, - itemInfo, - itemUnequip, - instance, - player, - account, - tutorial, - vboxSelected, - } = state; - - return { - ws, - info, - itemInfo, - itemUnequip, - instance, - player, - account, - tutorial, - vboxSelected, - }; - }, - - function receiveDispatch(dispatch) { - function setTutorialNull() { - dispatch(actions.setTutorial(null)); - } - - function setInfo(info) { - dispatch(actions.setInfo(info)); - } - return { setTutorialNull, setInfo }; - } -); +const addState = connect(({ info, player, tutorial, vboxInfo, ws, itemInfo, instance }) => + ({ info, player, tutorial, vboxInfo, ws, itemInfo, instance })); function Info(args) { const { // Variables that will change info, - itemUnequip, + player, tutorial, - vboxHighlight, - vboxSelected, + vboxInfo, // Static - player, // Only used for colour calcs which will be update if info changes ws, itemInfo, - instance, // Only used for instance id - // functions - setTutorialNull, + instance, } = 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; - }; - let vboxInfo = false; - if (itemUnequip.length) [, vboxInfo] = itemUnequip; - else if (stashSelect.length > 0 || storeSelect.length > 0) vboxInfo = checkVboxInfo(); if (tutorial) { - const tutorialStageInfo = tutorialStage(tutorial, ws, setTutorialNull, instance); + const tutorialStageInfo = tutorialStage(tutorial, ws, 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', '+'); + // Prioritise the vbox info + if (vboxInfo) return genItemInfo(vboxInfo, itemInfo, player, info); - 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 stateFullInfo = comboItem || vboxInfo; - if (stateFullInfo) return genItemInfo(stateFullInfo); + // check normal info state if (!info) return false; if (info.includes('constructName')) { return ( @@ -189,7 +53,7 @@ function Info(args) { ); } - return genItemInfo(info); + return genItemInfo(info, itemInfo, player, info); } module.exports = addState(Info); diff --git a/client/src/components/vbox.stash.jsx b/client/src/components/vbox.stash.jsx index 18dd6b78..264a9f60 100644 --- a/client/src/components/vbox.stash.jsx +++ b/client/src/components/vbox.stash.jsx @@ -8,20 +8,20 @@ const { removeTier } = require('../utils'); function stashElement(props) { const { - combinerChange, itemUnequip, + sendItemUnequip, + setInfo, + setVboxSelected, + stashSelect, + storeSelect, vbox, vboxBuySelected, vboxHighlight, vboxHover, - vboxSelecting, - stashSelect, - - sendItemUnequip, - setInfo, - setVboxSelected, - } = props; + + const vboxSelecting = storeSelect.length === 1 && stashSelect.length === 0; + function stashClick(e) { e.stopPropagation(); if (itemUnequip.length) return sendItemUnequip(itemUnequip); @@ -46,12 +46,13 @@ function stashElement(props) { const notValidCombo = vboxHighlight && !vboxHighlight.includes(v); - function onClick(type) { + function onClick(type, e) { + e.stopPropagation(); const combinerContainsIndex = stashSelect.indexOf(i) > -1; // removing if (combinerContainsIndex) { if (type === 'click') { - return combinerChange(without(stashSelect, i)); + return setVboxSelected({ storeSelect, stashSelect: without(stashSelect, i) }); } return true; } @@ -61,9 +62,7 @@ function stashElement(props) { return setVboxSelected({ storeSelect: [], stashSelect: [i] }); } - stashSelect.push(i); - // if (stashSelect.length === 3) setInfo(comboItem.item); - return combinerChange(stashSelect); + return setVboxSelected({ storeSelect, stashSelect: [...stashSelect, i] }); } const highlighted = stashSelect.indexOf(i) > -1; @@ -79,14 +78,14 @@ function stashElement(props) { key={i} draggable='true' onDragStart={ev => { - onClick('drag'); + onClick('drag', ev); ev.dataTransfer.setData('text', ''); }}> diff --git a/client/src/components/vbox.utils.jsx b/client/src/components/vbox.utils.jsx new file mode 100644 index 00000000..6d934263 --- /dev/null +++ b/client/src/components/vbox.utils.jsx @@ -0,0 +1,128 @@ +const preact = require('preact'); +const countBy = require('lodash/countBy'); +const forEach = require('lodash/forEach'); +const reactStringReplace = require('react-string-replace'); + +const actions = require('../actions'); +const specThresholds = require('./vbox.info.thresholds'); +const { INFO } = require('./../constants'); +const { removeTier } = require('../utils'); +const shapes = require('./shapes'); + +function setVboxState(dispatch, vboxSelected, state) { + const { + itemInfo, + itemUnequip, + vbox, + } = state; + const { storeSelect, stashSelect } = vboxSelected; + + // default returns + let vboxCombiner = false; + let vboxHighlight = false; + + if (!(storeSelect.length === 0 && stashSelect.length === 0)) { + vboxHighlight = []; + 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 itemCount = countBy(selectedItems, co => co); + + itemInfo.combos.forEach(combo => { + const comboCount = countBy(combo.components, co => co); + const buyCount = countBy(combo.components, co => co); + const valid = selectedItems.every(c => { + if (!combo.components.includes(c)) return false; + if (itemCount[c] > comboCount[c]) return false; + buyCount[c] -= 1; + return true; + }); + if (valid) { + const fullCombo = combo.components.every(c => itemCount[c] === comboCount[c]); + if (fullCombo) vboxCombiner = combo.item; + + forEach(buyCount, (value, key) => { + if (value > 0 && !vboxHighlight.includes(key)) { + vboxHighlight.push(key); + } + }); + } + }); + } + + + const vboxInfo = () => { + if (vboxCombiner) return vboxCombiner; + if (itemUnequip.length) return itemUnequip[1]; + 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; + }; + + dispatch(actions.setVboxInfo(vboxInfo())); + dispatch(actions.setVboxCombiner(vboxCombiner)); + return dispatch(actions.setVboxHighlight(vboxHighlight)); +} + +function genItemInfo(item, itemInfo, player, info) { + 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()} +
+ ); +} + + +module.exports = { setVboxState, genItemInfo }; diff --git a/client/src/events.jsx b/client/src/events.jsx index f852313c..a4b637a8 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -26,6 +26,12 @@ function registerEvents(store) { return errorToast(msg); } + function clearTutorial() { + store.dispatch(actions.setTutorial(null)); + localStorage.setItem('tutorial-complete', true); + } + + function setPing(ping) { store.dispatch(actions.setPing(ping)); } @@ -182,6 +188,9 @@ function registerEvents(store) { store.dispatch(actions.setActiveSkill(null)); store.dispatch(actions.setInfo(null)); store.dispatch(actions.setItemUnequip([])); + store.dispatch(actions.setItemUnequip([])); + store.dispatch(actions.setVboxCombiner(null)); + store.dispatch(actions.setVboxHighlight(null)); store.dispatch(actions.setVboxSelected({ storeSelect: [], stashSelect: [] })); } @@ -292,6 +301,9 @@ function registerEvents(store) { startDemo(); } + // store.subscribe(setInfo); + // store.on('SET_INFO', setInfo); + // events.on('SET_PLAYER', setInstance); // events.on('SEND_SKILL', function skillActive(gameId, constructId, targetConstructId, skill) { @@ -340,6 +352,7 @@ function registerEvents(store) { clearInfo, clearInstance, clearMtxActive, + clearTutorial, setAccount, setAccountInstances, setActiveItem, diff --git a/client/src/reducers.jsx b/client/src/reducers.jsx index 3dcb0670..0267cf3f 100644 --- a/client/src/reducers.jsx +++ b/client/src/reducers.jsx @@ -57,6 +57,9 @@ module.exports = { tutorialGame: createReducer(1, 'SET_TUTORIAL_GAME'), vboxSelected: createReducer({ storeSelect: [], stashSelect: [] }, 'SET_VBOX_SELECTED'), + vboxCombiner: createReducer(null, 'SET_VBOX_COMBINER'), + vboxHighlight: createReducer(null, 'SET_VBOX_HIGHLIGHT'), + vboxInfo: createReducer(null, 'SET_VBOX_INFO'), ws: createReducer(null, 'SET_WS'), }; diff --git a/client/src/socket.jsx b/client/src/socket.jsx index a9ec07ba..2ca12623 100644 --- a/client/src/socket.jsx +++ b/client/src/socket.jsx @@ -204,6 +204,11 @@ function createSocket(events) { send(['SubscriptionState', {}]); } + function clearTutorial(instanceId) { + events.clearTutorial(); + sendInstanceState(instanceId); + } + // ------------- // Incoming // ------------- @@ -430,6 +435,8 @@ function createSocket(events) { sendMtxBuy, sendMtxConstructSpawn, + clearTutorial, + connect, }; } diff --git a/client/src/tutorial.utils.jsx b/client/src/tutorial.utils.jsx index 8736bd72..2e311ead 100644 --- a/client/src/tutorial.utils.jsx +++ b/client/src/tutorial.utils.jsx @@ -97,14 +97,10 @@ function tutorialVbox(player, store, tutorial) { store.dispatch(actions.setTutorial(stage)); } -function tutorialStage(tutorial, ws, clearTutorial, instance) { +function tutorialStage(tutorial, ws, instance) { if (!(instance.time_control === 'Practice' && instance.rounds.length === 1)) return false; - const exit = () => { - clearTutorial(); - localStorage.setItem('tutorial-complete', true); - ws.sendInstanceState(instance.id); - }; + const exit = () => ws.clearTutorial(instance.id); const tutorialText = () => { if (tutorial === 1) {