From bb94e43ca17a11794739883ca6e69f1e4fa7bf43 Mon Sep 17 00:00:00 2001 From: Mashy Date: Sun, 27 Oct 2019 19:05:55 +1000 Subject: [PATCH 01/53] tutorial init --- client/src/actions.jsx | 2 + client/src/components/info.component.jsx | 11 +- client/src/components/info.container.jsx | 11 + client/src/components/instance.constructs.jsx | 64 ++++-- client/src/components/vbox.component.jsx | 32 +-- client/src/events.jsx | 15 +- client/src/reducers.jsx | 2 + client/src/tutorial.utils.jsx | 198 ++++++++++++++++++ 8 files changed, 284 insertions(+), 51 deletions(-) create mode 100644 client/src/tutorial.utils.jsx diff --git a/client/src/actions.jsx b/client/src/actions.jsx index 8c58ed0d..f9fb6cd5 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -50,6 +50,8 @@ export const setTeam = value => ({ type: 'SET_TEAM', value: Array.from(value) }) export const setTeamPage = value => ({ type: 'SET_TEAM_PAGE', value }); export const setTeamSelect = value => ({ type: 'SET_TEAM_SELECT', value: Array.from(value) }); +export const setTutorial = value => ({ type: 'SET_TUTORIAL', value }); + export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value }); export const setVboxSelected = value => ({ type: 'SET_VBOX_SELECTED', value }); diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 3aebbc14..bf1c8cd6 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -4,19 +4,23 @@ const reactStringReplace = require('react-string-replace'); const { INFO } = require('./../constants'); const { convertItem, removeTier } = require('../utils'); +const { tutorialStage } = require('../tutorial.utils'); const shapes = require('./shapes'); function InfoComponent(args) { const { + ws, itemInfo, player, + instance, info, + tutorial, + clearTutorial, } = args; - // args.info = 'Life'; - // const { info } = args; - function Info() { + if (tutorial) return tutorialStage(tutorial, ws, clearTutorial, instance); + if (!info) { return (
@@ -178,6 +182,7 @@ function InfoComponent(args) { function Combos() { if (!player) return false; if (!info) return false; + if (tutorial) return false; const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info)); if (vboxCombos.length > 6) return false; diff --git a/client/src/components/info.container.jsx b/client/src/components/info.container.jsx index 5f8639b8..b19fff8e 100644 --- a/client/src/components/info.container.jsx +++ b/client/src/components/info.container.jsx @@ -13,6 +13,7 @@ const addState = connect( instance, player, account, + tutorial, } = state; return { @@ -23,8 +24,18 @@ const addState = connect( instance, player, account, + tutorial, }; }, + + function receiveDispatch(dispatch) { + function clearTutorial() { + dispatch(actions.setTutorial(null)); + } + return { clearTutorial }; + } + + ); module.exports = addState(Info); diff --git a/client/src/components/instance.constructs.jsx b/client/src/components/instance.constructs.jsx index bc7e005f..5d3ec130 100644 --- a/client/src/components/instance.constructs.jsx +++ b/client/src/components/instance.constructs.jsx @@ -20,6 +20,7 @@ const addState = connect( itemEquip, activeConstruct, navInstance, + tutorial, } = state; function sendVboxApply(constructId, i) { @@ -40,6 +41,7 @@ const addState = connect( navInstance, activeConstruct, sendUnequip, + tutorial, }; }, @@ -75,6 +77,7 @@ const addState = connect( function Construct(props) { const { + iter, itemEquip, construct, player, @@ -86,11 +89,22 @@ function Construct(props) { setInfo, sendUnequip, mobileVisible, + tutorial, } = props; + const { vbox } = player; + + const duplicateSkill = construct.skills.length !== 0 && construct.skills.every(sk => { + if (!itemEquip && itemEquip !== 0) return false; + if (!sk) return false; + return sk.skill === vbox.bound[itemEquip]; + }); + const tutorialDisableEquip = tutorial && tutorial === 6 && iter === 0 && construct.skills.length !== 0; + function onClick(e) { e.stopPropagation(); e.preventDefault(); + if (duplicateSkill || tutorialDisableEquip) return true; if (itemEquip !== null) sendVboxApply(construct.id, itemEquip); setItemEquip(null); return setActiveConstruct(construct); @@ -102,7 +116,6 @@ function Construct(props) { return setInfo(info); } - const { vbox } = player; const skillList = itemInfo.items.filter(v => v.skill).map(v => v.item); const specList = itemInfo.items.filter(v => v.spec).map(v => v.item); @@ -129,9 +142,9 @@ function Construct(props) { e.preventDefault(); return true; } - + // const action = skill ? '' : 'action'; - const equipping = skillList.includes(vbox.bound[itemEquip]) && !skill; + const equipping = skillList.includes(vbox.bound[itemEquip]) && !skill && !tutorialDisableEquip && !duplicateSkill; const border = () => { if (!skill) return ''; const borderFn = buttons[removeTier(skill.skill)]; @@ -246,30 +259,41 @@ function InstanceConstructs(props) { setItemEquip, sendUnequip, navInstance, + tutorial, } = props; if (!player) return false; if (instance.phase === 'Lobby') return false; - const constructs = player.constructs.map((c, i) => Construct({ - construct: c, - activeConstruct, - itemEquip, - setItemUnequip, - setItemEquip, - player, - sendVboxApply, - setInfo, - setActiveConstruct, - itemInfo, - setVboxHighlight, - sendUnequip, - mobileVisible: navInstance === i + 1, - })); + const constructs = range(0, 3).map(i => { + if (tutorial && tutorial < 6) { + if (tutorial <= 2 || (tutorial > 2 && i > 0)) { + const mobileVisible = navInstance === i + 1; + const classes = `instance-construct ${mobileVisible ? 'visible' : ''}`; + return (
); + } + } + return Construct({ + iter: i, + construct: player.constructs[i], + activeConstruct, + itemEquip, + setItemUnequip, + setItemEquip, + player, + sendVboxApply, + setInfo, + setActiveConstruct, + itemInfo, + setVboxHighlight, + sendUnequip, + tutorial, + mobileVisible: navInstance === i + 1, + }); + }); - const classes = `construct-list`; return ( -
setActiveConstruct(null)}> +
setActiveConstruct(null)}> {constructs}
); diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 266ae0b2..ce9da0c3 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -21,6 +21,7 @@ const addState = connect( itemUnequip, navInstance, info, + tutorial, } = state; function sendVboxDiscard() { @@ -57,6 +58,7 @@ const addState = connect( itemUnequip, sendItemUnequip, navInstance, + tutorial, info, }; }, @@ -113,6 +115,7 @@ function Vbox(args) { setVboxSelected, setItemEquip, + tutorial, itemUnequip, sendItemUnequip, @@ -161,16 +164,7 @@ function Vbox(args) { function availableBtn(v, group, index) { if (!v) return ; - const tutorial = instance.time_control === 'Practice' - && instance.rounds.length === 1 - && group === 0 - && combiner.length === 0 - && vboxSelected.length === 0 - && vbox.bits > 10 - && vbox.free[0].filter(c => c).length > 4 - ? 'combo-border' : null; - - const selected = vboxSelected[0] === group && vboxSelected[1] === index; + const selected = vboxSelected[0] === group && vboxSelected[1] === index; // state not yet set in double click handler function onDblClick(e) { @@ -203,7 +197,7 @@ function Vbox(args) { } return false; }) ? 'combo-border' : ''; - const classes = `${v.toLowerCase()} ${selected ? 'highlight' : ''} ${comboHighlight} ${tutorial}`; + const classes = `${v.toLowerCase()} ${selected ? 'highlight' : ''} ${comboHighlight}`; if (shapes[v]) { return ( @@ -251,6 +245,7 @@ function Vbox(args) { ; } - const tutorial = instance.time_control === 'Practice' - && instance.rounds.length === 1 - && i === 0 - && combiner.length === 0 - && vboxSelected.length === 0 - && vbox.bits === 16 - && vbox.bound.length === 5 - && vbox.free[0].filter(c => c).length === 4 - ? 'combo-border' : null; - const combinerItems = combiner.map(j => vbox.bound[j]); const combinerCount = countBy(combinerItems, co => co); @@ -325,7 +310,7 @@ function Vbox(args) { const highlighted = combiner.indexOf(i) > -1; const border = buttons[removeTier(v)] ? buttons[removeTier(v)]() : ''; - const classes = `${highlighted ? 'highlight' : border} ${comboHighlight} ${tutorial}`; + const classes = `${highlighted ? 'highlight' : border} ${comboHighlight}`; if (shapes[v]) { return ( ; + + return ( +
+ {tutorialText()} + {exitTutorial} +
); +} + +module.exports = { + tutorialVbox, + tutorialStage, +}; From 29c4bfe891c56c960784a23dcc18051cfa9afccc Mon Sep 17 00:00:00 2001 From: Mashy Date: Sun, 27 Oct 2019 20:10:47 +1000 Subject: [PATCH 02/53] clean up abandon and reset tutorial if in progress --- client/src/components/game.ctrl.btns.top.jsx | 12 +++++++----- client/src/components/instance.ctrl.top.btns.jsx | 7 +++++-- client/src/components/vbox.component.jsx | 2 +- client/src/events.jsx | 1 - client/src/tutorial.utils.jsx | 1 - 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/client/src/components/game.ctrl.btns.top.jsx b/client/src/components/game.ctrl.btns.top.jsx index 4ab0d543..2e54b54b 100644 --- a/client/src/components/game.ctrl.btns.top.jsx +++ b/client/src/components/game.ctrl.btns.top.jsx @@ -8,6 +8,7 @@ const addState = connect( const { ws, game, + animating, } = state; function sendAbandon() { @@ -16,30 +17,31 @@ const addState = connect( return { game, - sendAbandon, + animating, }; }, + function receiveDispatch(dispatch) { function leave() { dispatch(actions.setNav('play')); dispatch(actions.setGame(null)); - dispatch(actions.setInstance(null)); } return { leave }; } + ); function GameCtrlTopBtns(args) { const { game, - leave, sendAbandon, + animating, } = args; - const finished = game && game.phase === 'Finished'; + const finished = game && game.phase === 'Finish'; const { abandonState } = this.state; const abandonStateTrue = e => { @@ -52,7 +54,7 @@ function GameCtrlTopBtns(args) { const abandonText = abandonState ? 'Confirm' : 'Abandon'; const abandonAction = abandonState ? sendAbandon : abandonStateTrue; - const abandonBtn = ; + const abandonBtn = ; const leaveBtn = ; return ( diff --git a/client/src/components/instance.ctrl.top.btns.jsx b/client/src/components/instance.ctrl.top.btns.jsx index 528e5d0e..3f01aea8 100644 --- a/client/src/components/instance.ctrl.top.btns.jsx +++ b/client/src/components/instance.ctrl.top.btns.jsx @@ -8,6 +8,7 @@ const addState = connect( const { ws, instance, + tutorial, } = state; function sendAbandon() { @@ -21,10 +22,11 @@ const addState = connect( }; }, function receiveDispatch(dispatch) { - function leave() { + function leave(tutorial) { dispatch(actions.setNav('play')); dispatch(actions.setGame(null)); dispatch(actions.setInstance(null)); + if (tutorial && tutorial < 7) dispatch(actions.setTutorial(1)); } return { leave }; @@ -37,6 +39,7 @@ function InstanceTopBtns(args) { leave, sendAbandon, + tutorial, } = args; const finished = instance && instance.phase === 'Finished'; @@ -53,7 +56,7 @@ function InstanceTopBtns(args) { const abandonAction = abandonState ? sendAbandon : abandonStateTrue; const abandonBtn = ; - const leaveBtn = ; + const leaveBtn = ; return (
diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index ce9da0c3..1206f621 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -164,7 +164,7 @@ function Vbox(args) { function availableBtn(v, group, index) { if (!v) return ; - const selected = vboxSelected[0] === group && vboxSelected[1] === index; + const selected = vboxSelected[0] === group && vboxSelected[1] === index; // state not yet set in double click handler function onDblClick(e) { diff --git a/client/src/events.jsx b/client/src/events.jsx index 6cc4cd5d..f088d4e7 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -210,7 +210,6 @@ function registerEvents(store) { } if (v.phase === 'Finished') { - setGame(null); ws.sendAccountInstances(); } if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) { diff --git a/client/src/tutorial.utils.jsx b/client/src/tutorial.utils.jsx index a1fcc669..e425c2ac 100644 --- a/client/src/tutorial.utils.jsx +++ b/client/src/tutorial.utils.jsx @@ -78,7 +78,6 @@ function tutorialVbox(player, store, tutorial) { vbox.free[2] = []; } } - console.log(stage); store.dispatch(actions.setTutorial(stage)); } From 52e67e49d0d5e6ea9882986bde761f35a167bdcd Mon Sep 17 00:00:00 2001 From: Mashy Date: Sun, 27 Oct 2019 20:18:49 +1000 Subject: [PATCH 03/53] actually reset tutorial (if in prog) --- client/src/components/instance.ctrl.top.btns.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/instance.ctrl.top.btns.jsx b/client/src/components/instance.ctrl.top.btns.jsx index 3f01aea8..efb1a75b 100644 --- a/client/src/components/instance.ctrl.top.btns.jsx +++ b/client/src/components/instance.ctrl.top.btns.jsx @@ -17,7 +17,7 @@ const addState = connect( return { instance, - + tutorial, sendAbandon, }; }, From 0dfe181d52da41c080696b2a29cce9941d01553d Mon Sep 17 00:00:00 2001 From: Mashy Date: Sun, 27 Oct 2019 20:22:41 +1000 Subject: [PATCH 04/53] remove tutorial stage check for reset --- client/src/components/instance.ctrl.top.btns.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/instance.ctrl.top.btns.jsx b/client/src/components/instance.ctrl.top.btns.jsx index efb1a75b..108485f7 100644 --- a/client/src/components/instance.ctrl.top.btns.jsx +++ b/client/src/components/instance.ctrl.top.btns.jsx @@ -26,7 +26,7 @@ const addState = connect( dispatch(actions.setNav('play')); dispatch(actions.setGame(null)); dispatch(actions.setInstance(null)); - if (tutorial && tutorial < 7) dispatch(actions.setTutorial(1)); + if (tutorial) dispatch(actions.setTutorial(1)); } return { leave }; From 200482dd79d2f36145dee25247af083f4955783b Mon Sep 17 00:00:00 2001 From: Mashy Date: Sun, 27 Oct 2019 22:13:23 +1000 Subject: [PATCH 05/53] button css, only update info component when info or tutorial changes --- client/assets/styles/instance.less | 11 + client/src/components/anims/wiggle.jsx | 2 +- client/src/components/info.component.jsx | 379 ++++++++++++----------- client/src/components/play.jsx | 70 +++-- client/src/components/vbox.component.jsx | 1 - client/src/tutorial.utils.jsx | 16 +- 6 files changed, 255 insertions(+), 224 deletions(-) diff --git a/client/assets/styles/instance.less b/client/assets/styles/instance.less index 461f8eb0..0f05fc8b 100644 --- a/client/assets/styles/instance.less +++ b/client/assets/styles/instance.less @@ -446,6 +446,17 @@ } } +.tutorial { + button { + width: 100%; + } + + button.focus { + animation: co 0.75s cubic-bezier(0, 0, 1, 1) 0s infinite alternate; + } + +} + @keyframes faceoff { from { color: @black; diff --git a/client/src/components/anims/wiggle.jsx b/client/src/components/anims/wiggle.jsx index 5886a47d..8a54b096 100644 --- a/client/src/components/anims/wiggle.jsx +++ b/client/src/components/anims/wiggle.jsx @@ -6,7 +6,7 @@ function wiggle(id, idle) { const target = document.getElementById(id); const x = window.innerWidth * 0.01 * (Math.round(Math.random()) ? Math.random() : -Math.random()); const y = window.innerHeight * 0.01 * (Math.round(Math.random()) ? Math.random() : -Math.random()); - + const originalX = parseFloat(idle.animations[0].currentValue); const originalY = parseFloat(idle.animations[1].currentValue); // console.log(x, y); diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index bf1c8cd6..f4aafd3e 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -2,211 +2,222 @@ const preact = require('preact'); const range = require('lodash/range'); const reactStringReplace = require('react-string-replace'); +const { Component } = require('preact'); const { INFO } = require('./../constants'); const { convertItem, removeTier } = require('../utils'); const { tutorialStage } = require('../tutorial.utils'); const shapes = require('./shapes'); -function InfoComponent(args) { - const { - ws, - itemInfo, - player, - instance, - info, - tutorial, - clearTutorial, - } = args; - function Info() { - if (tutorial) return tutorialStage(tutorial, ws, clearTutorial, instance); +class InfoComponent extends Component { + shouldComponentUpdate(newProps) { + if (newProps.tutorial !== this.props.tutorial) return true; + if (newProps.tutorial) return false; // We don't care about info during tutorial + if (newProps.info !== this.props.info) return true; + return false; + } - if (!info) { - return ( -
-

VBOX phase

-

Strengthen and specialise your constructs by equipping items to them.

-

Double click to purchase items in the VBOX and move them to your INVENTORY.

-

- Combine a SKILL or SPEC with 2 COLOURS to create an item.
- Combine 3 of the same item to upgrade it.
- Click an item and then click a construct to equip that item to it.
-

-

Click the READY button for the GAME PHASE.

-
- ); - } - const fullInfo = itemInfo.items.find(i => i.item === info) || INFO[info]; - if (!fullInfo) return false; - const isSkill = fullInfo.skill; - const isSpec = fullInfo.spec; + render(args) { + const { + ws, + itemInfo, + player, + instance, + info, + tutorial, + clearTutorial, + } = args; - if (isSkill) { - const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; - const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); - const itemSource = itemInfo.combos.filter(c => c.item === removeTier(info)); - const itemSourceInfo = itemSource.length - ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` - : false; - const itemRegEx = /(Red|Blue|Green)/; - const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]()); - const speed =
Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}%
; - const cooldown = fullInfo.cooldown ? `${fullInfo.cooldown} Turn delay` : null; - return ( -
-

{fullInfo.item} - {fullInfo.cost}b

-

SKILL

- {itemSourceDescription} -
{cooldown}
-
{infoDescription}
- {speed} -
- ); - } + function Info() { + if (tutorial) return tutorialStage(tutorial, ws, clearTutorial, instance); - if (isSpec) { - let red = 0; - let blue = 0; - let green = 0; - player.constructs.forEach(construct => { - red += construct.colours.red; - blue += construct.colours.blue; - green += construct.colours.green; - }); - const teamColours = { red, blue, green }; - - const colourReqs = fullInfo.values.bonuses || []; - - const thresholds = colourReqs.map((bonus, i) => { - const colours = ['red', 'green', 'blue']; - const colourGoals = { - red: [], - green: [], - blue: [], - }; - const overFlow = []; - - colours.forEach(c => { - const colourReq = bonus.req[c]; - if (colourReqs === 0) return false; - - const start = i === 0 - ? 0 - : colourReqs[i - 1].req[c]; - - const dots = range(start, colourReq).map(j => { - const unmet = teamColours[c] < j + 1; - - - const reqClass = unmet - ? 'unmet' - : ''; - - if (j - start > 4) { - overFlow.push( -
- {shapes.vboxColour(c)} -
- ); - } else { - colourGoals[c].push( -
- {shapes.vboxColour(c)} -
- ); - } - - return true; - }); - - return dots; - }); - - const reqsMet = colours.every(c => teamColours[c] >= bonus.req[c]); - - const reqClass = reqsMet - ? '' - : 'unmet'; - - const goals = colours.map((c, j) => { - if (colourGoals[c].length) { - return ( -
{colourGoals[c]}
- ); - } - return false; - }); - const bonusObj = info.includes('Life') - ?
+ {bonus.bonus}
- :
+ {bonus.bonus}%
; - const overFlowObj = overFlow.length ?
{overFlow}
: null; + if (!info) { return ( -
- {goals} - {overFlowObj} - {bonusObj} +
+

VBOX phase

+

Strengthen and specialise your constructs by equipping items to them.

+

Double click to purchase items in the VBOX and move them to your INVENTORY.

+

+ Combine a SKILL or SPEC with 2 COLOURS to create an item.
+ Combine 3 of the same item to upgrade it.
+ Click an item and then click a construct to equip that item to it.
+

+

Click the READY button for the GAME PHASE.

); - }); - const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; - const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); - const itemSource = itemInfo.combos.filter(c => c.item === info); - const itemSourceInfo = itemSource.length - ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` - : false; - const itemRegEx = /(Red|Blue|Green)/; - const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]()); - const infoText = info.replace('Plus', '+'); + } + const fullInfo = itemInfo.items.find(i => i.item === info) || INFO[info]; + if (!fullInfo) return false; + const isSkill = fullInfo.skill; + const isSpec = fullInfo.spec; - return ( -
-

{infoText} - {fullInfo.cost}b

-

SPEC

- {itemSourceDescription} -
{infoDescription}
-
- {thresholds} + if (isSkill) { + const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; + const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); + const itemSource = itemInfo.combos.filter(c => c.item === removeTier(info)); + const itemSourceInfo = itemSource.length + ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` + : false; + const itemRegEx = /(Red|Blue|Green)/; + const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]()); + const speed =
Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}%
; + const cooldown = fullInfo.cooldown ? `${fullInfo.cooldown} Turn delay` : null; + return ( +
+

{fullInfo.item} - {fullInfo.cost}b

+

SKILL

+ {itemSourceDescription} +
{cooldown}
+
{infoDescription}
+ {speed}
+ ); + } + + if (isSpec) { + let red = 0; + let blue = 0; + let green = 0; + player.constructs.forEach(construct => { + red += construct.colours.red; + blue += construct.colours.blue; + green += construct.colours.green; + }); + const teamColours = { red, blue, green }; + + const colourReqs = fullInfo.values.bonuses || []; + + const thresholds = colourReqs.map((bonus, i) => { + const colours = ['red', 'green', 'blue']; + const colourGoals = { + red: [], + green: [], + blue: [], + }; + const overFlow = []; + + colours.forEach(c => { + const colourReq = bonus.req[c]; + if (colourReqs === 0) return false; + + const start = i === 0 + ? 0 + : colourReqs[i - 1].req[c]; + + const dots = range(start, colourReq).map(j => { + const unmet = teamColours[c] < j + 1; + + + const reqClass = unmet + ? 'unmet' + : ''; + + if (j - start > 4) { + overFlow.push( +
+ {shapes.vboxColour(c)} +
+ ); + } else { + colourGoals[c].push( +
+ {shapes.vboxColour(c)} +
+ ); + } + + return true; + }); + + return dots; + }); + + const reqsMet = colours.every(c => teamColours[c] >= bonus.req[c]); + + const reqClass = reqsMet + ? '' + : 'unmet'; + + const goals = colours.map((c, j) => { + if (colourGoals[c].length) { + return ( +
{colourGoals[c]}
+ ); + } + return false; + }); + const bonusObj = info.includes('Life') + ?
+ {bonus.bonus}
+ :
+ {bonus.bonus}%
; + const overFlowObj = overFlow.length ?
{overFlow}
: null; + return ( +
+ {goals} + {overFlowObj} + {bonusObj} +
+ ); + }); + const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; + const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); + const itemSource = itemInfo.combos.filter(c => c.item === info); + const itemSourceInfo = itemSource.length + ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` + : false; + const itemRegEx = /(Red|Blue|Green)/; + const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]()); + const infoText = info.replace('Plus', '+'); + + return ( +
+

{infoText} - {fullInfo.cost}b

+

SPEC

+ {itemSourceDescription} +
{infoDescription}
+
+ {thresholds} +
+
+ ); + } + const cost = fullInfo.cost ? `- ${fullInfo.cost}b` : false; + return ( +
+

{fullInfo.item} {cost}

+
{fullInfo.description}
); } - const cost = fullInfo.cost ? `- ${fullInfo.cost}b` : false; + + function Combos() { + if (!player) return false; + if (!info) return false; + if (tutorial) return false; + + const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info)); + if (vboxCombos.length > 6) return false; + + return ( + + + {vboxCombos.map((c, i) => + + + {c.components.map((u, j) => )} + + )} + +
{convertItem(c.item)}{convertItem(u)}
+ ); + } + return ( -
-

{fullInfo.item} {cost}

-
{fullInfo.description}
+
+ +
); } - - function Combos() { - if (!player) return false; - if (!info) return false; - if (tutorial) return false; - - const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info)); - if (vboxCombos.length > 6) return false; - - return ( - - - {vboxCombos.map((c, i) => - - - {c.components.map((u, j) => )} - - )} - -
{convertItem(c.item)}{convertItem(u)}
- ); - } - - return ( -
- - -
- ); } module.exports = InfoComponent; diff --git a/client/src/components/play.jsx b/client/src/components/play.jsx index 40f5b657..2059f774 100644 --- a/client/src/components/play.jsx +++ b/client/src/components/play.jsx @@ -139,39 +139,41 @@ function Play(args) { ; const list = () => { - if (!instances.length) return ( -
-
- -
Matchmaking
-
- {inviteBtn()} -
- -
Practice MNML
-
-
- -
Join the Community
-
-
- ); + if (!instances.length) { + return ( +
+
+ +
Matchmaking
+
+ {inviteBtn()} +
+ +
Practice MNML
+
+
+ +
Join the Community
+
+
+ ); + } return (
-
+
); - } + }; return (
@@ -201,9 +203,9 @@ function Play(args) {
- Join our Discord server to find opponents and talk to the devs.
- Message @ntr or @mashy for some credits to get started.
- Tutorial Playthrough on YouTube + Join our Discord server to find opponents and talk to the devs.
+ Message @ntr or @mashy for some credits to get started.
+ Tutorial Playthrough on YouTube

diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 1206f621..ca0f3ad4 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -99,7 +99,6 @@ function Vbox(args) { const { combiner, navInstance, - instance, itemInfo, player, reclaiming, diff --git a/client/src/tutorial.utils.jsx b/client/src/tutorial.utils.jsx index e425c2ac..605c4812 100644 --- a/client/src/tutorial.utils.jsx +++ b/client/src/tutorial.utils.jsx @@ -162,7 +162,9 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {

Each round you start with a vbox full of different skills, specs and colours.

Bits are your currency for buying skills, specs and colours from the vbox.
Colours cost 1b, Skills cost 2b and specs cost 3b.
- You can refill the vbox by pressing the refill button for 2b.

+ You can refill the vbox by pressing the refill button for 2b.
+ After each combat round you get more bits to further upgrade your team. +

Press the REFILL button to get a new vbox and continue.

); @@ -182,12 +184,18 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) { return false; }; - const exitTutorial = ; + const classes = tutorial === 8 ? 'focus' : ''; + const exitTutorial = ; return ( -
+
{tutorialText()} - {exitTutorial} +
+ {exitTutorial} +
); } From c534f973a10905795d7f0aa4a0608ead349d6ba2 Mon Sep 17 00:00:00 2001 From: Mashy Date: Sun, 27 Oct 2019 22:59:59 +1000 Subject: [PATCH 06/53] add shouldComponentUpdate to vbox components --- client/src/components/info.component.jsx | 3 +- client/src/components/instance.constructs.jsx | 120 ++-- client/src/components/vbox.component.jsx | 636 +++++++++--------- 3 files changed, 394 insertions(+), 365 deletions(-) diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index f4aafd3e..5d34368b 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -2,14 +2,13 @@ const preact = require('preact'); const range = require('lodash/range'); const reactStringReplace = require('react-string-replace'); -const { Component } = require('preact'); const { INFO } = require('./../constants'); const { convertItem, removeTier } = require('../utils'); const { tutorialStage } = require('../tutorial.utils'); const shapes = require('./shapes'); -class InfoComponent extends Component { +class InfoComponent extends preact.Component { shouldComponentUpdate(newProps) { if (newProps.tutorial !== this.props.tutorial) return true; if (newProps.tutorial) return false; // We don't care about info during tutorial diff --git a/client/src/components/instance.constructs.jsx b/client/src/components/instance.constructs.jsx index 5d3ec130..fb246a57 100644 --- a/client/src/components/instance.constructs.jsx +++ b/client/src/components/instance.constructs.jsx @@ -18,7 +18,6 @@ const addState = connect( account, itemInfo, itemEquip, - activeConstruct, navInstance, tutorial, } = state; @@ -39,7 +38,6 @@ const addState = connect( itemInfo, itemEquip, navInstance, - activeConstruct, sendUnequip, tutorial, }; @@ -77,19 +75,21 @@ const addState = connect( function Construct(props) { const { + // Changing state variables + construct, iter, itemEquip, - construct, + itemInfo, + mobileVisible, player, + tutorial, + // Function Calls sendVboxApply, + sendUnequip, setActiveConstruct, setItemUnequip, setItemEquip, - itemInfo, setInfo, - sendUnequip, - mobileVisible, - tutorial, } = props; const { vbox } = player; @@ -242,61 +242,73 @@ function Construct(props) { ); } -function InstanceConstructs(props) { - const { - activeConstruct, - itemEquip, - player, - instance, - // clearInfo, - setInfo, - setActiveConstruct, +class InstanceConstructs extends preact.Component { + shouldComponentUpdate(newProps) { + if (newProps.itemEquip !== this.props.itemEquip) return true; + if (newProps.instance.phase !== this.props.instance.phase) return true; + if (newProps.tutorial !== this.props.tutorial) return true; + if (newProps.navInstance !== this.props.navInstance) return true; + // JSON or Array objects + if (JSON.stringify(newProps.player) !== JSON.stringify(this.props.player)) return true; + return false; + } - sendVboxApply, - itemInfo, - setVboxHighlight, - setItemUnequip, - setItemEquip, - sendUnequip, - navInstance, - tutorial, - } = props; - - if (!player) return false; - if (instance.phase === 'Lobby') return false; - - const constructs = range(0, 3).map(i => { - if (tutorial && tutorial < 6) { - if (tutorial <= 2 || (tutorial > 2 && i > 0)) { - const mobileVisible = navInstance === i + 1; - const classes = `instance-construct ${mobileVisible ? 'visible' : ''}`; - return (
); - } - } - return Construct({ - iter: i, - construct: player.constructs[i], - activeConstruct, + render(props) { + const { + // Changing state variables itemEquip, - setItemUnequip, - setItemEquip, + instance, // we only change phase + navInstance, player, - sendVboxApply, + tutorial, + // Static data + itemInfo, + // Function calls setInfo, setActiveConstruct, - itemInfo, + sendVboxApply, setVboxHighlight, + setItemUnequip, + setItemEquip, sendUnequip, - tutorial, - mobileVisible: navInstance === i + 1, - }); - }); + } = props; + console.log('grep constructs'); - return ( -
setActiveConstruct(null)}> - {constructs} -
- ); + if (!player) return false; + if (instance.phase === 'Lobby') return false; + + const constructs = range(0, 3).map(i => { + if (tutorial && tutorial < 6) { + if (tutorial <= 2 || (tutorial > 2 && i > 0)) { + const mobileVisible = navInstance === i + 1; + const classes = `instance-construct ${mobileVisible ? 'visible' : ''}`; + return (
); + } + } + return Construct({ + iter: i, + construct: player.constructs[i], + itemEquip, + setItemUnequip, + setItemEquip, + player, + sendVboxApply, + setInfo, + setActiveConstruct, + itemInfo, + setVboxHighlight, + sendUnequip, + tutorial, + mobileVisible: navInstance === i + 1, + }); + }); + + return ( +
setActiveConstruct(null)}> + {constructs} +
+ ); + } } module.exports = addState(InstanceConstructs); diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index ca0f3ad4..f13f3c8f 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -1,8 +1,9 @@ const preact = require('preact'); +const { connect } = require('preact-redux'); const range = require('lodash/range'); const countBy = require('lodash/countBy'); const without = require('lodash/without'); -const { connect } = require('preact-redux'); + const { removeTier } = require('../utils'); const shapes = require('./shapes'); const actions = require('../actions'); @@ -95,333 +96,350 @@ const addState = connect( ); -function Vbox(args) { - const { - combiner, - navInstance, - itemInfo, - player, - reclaiming, - sendVboxAccept, - sendVboxCombine, - sendVboxDiscard, - sendVboxReclaim, - - setCombiner, - setInfo, - - vboxSelected, - setVboxSelected, - - setItemEquip, - tutorial, - itemUnequip, - sendItemUnequip, - - setReclaiming, - info, - } = args; - - if (!player) return false; - const { vbox } = player; - const vboxSelecting = vboxSelected.length; - - function combinerChange(newCombiner) { - setCombiner(newCombiner); - - if (newCombiner.length === 1) { - setItemEquip(newCombiner[0]); - } else { - setItemEquip(null); - } - - return true; +class Vbox extends preact.Component { + shouldComponentUpdate(newProps) { + // Single variable props + if (newProps.combiner !== this.props.combiner) return true; + if (newProps.itemUnequip !== this.props.itemUnequip) return true; + if (newProps.reclaiming !== this.props.reclaiming) return true; + if (newProps.navInstance !== this.props.navInstance) return true; + if (newProps.tutorial !== this.props.tutorial) return true; + // Don't bother if info changes during tutorial + if (!newProps.tutorial && newProps.info !== this.props.info) return true; + // JSON or Array objects + if (JSON.stringify(newProps.vboxSelected) !== JSON.stringify(this.props.vboxSelected)) return true; + if (JSON.stringify(newProps.player) !== JSON.stringify(this.props.player)) return true; + return false; } - // - // VBOX - // - function vboxHover(e, v) { - if (v) { - if (info !== v) setInfo(v); - e.stopPropagation(); - } - return true; - } + render(args) { + const { + // Changing state variables + combiner, + itemUnequip, + player, + reclaiming, + tutorial, + navInstance, + info, + vboxSelected, - function clearVboxSelected() { - setVboxSelected([]); - } + // Static + itemInfo, + // Function Calls + sendItemUnequip, + sendVboxAccept, + sendVboxCombine, + sendVboxDiscard, + sendVboxReclaim, + setVboxSelected, + setItemEquip, + setInfo, + setCombiner, + setReclaiming, + } = args; - function vboxBuySelected() { - if (!vboxSelecting) return false; - document.activeElement.blur(); - clearVboxSelected(); - sendVboxAccept(vboxSelected[0], vboxSelected[1]); - return true; - } + if (!player) return false; + const { vbox } = player; + const vboxSelecting = vboxSelected.length; - function availableBtn(v, group, index) { - if (!v) return ; - const selected = vboxSelected[0] === group && vboxSelected[1] === index; + function combinerChange(newCombiner) { + setCombiner(newCombiner); - // state not yet set in double click handler - function onDblClick(e) { - clearVboxSelected(); - sendVboxAccept(group, index); - e.stopPropagation(); - } - - function onClick(e) { - e.stopPropagation(); - setItemEquip(null); - setCombiner([]); - - if (selected) return clearVboxSelected(); - return setVboxSelected([group, index]); - } - - const combinerItems = combiner.map(j => vbox.bound[j]); - const combinerCount = countBy(combinerItems, co => co); - - const comboHighlight = combinerItems.length > 0 && itemInfo.combos.some(combo => { - if (combo.components.includes(v)) { - return combinerItems.every(c => { - if (!combo.components.includes(c)) return false; - const comboCount = countBy(combo.components, co => co); - if (combinerCount[c] > comboCount[c]) return false; - if (c === v && combinerCount[c] + 1 > comboCount[c]) return false; - return true; - }); - } return false; - }) ? 'combo-border' : ''; - - const classes = `${v.toLowerCase()} ${selected ? 'highlight' : ''} ${comboHighlight}`; - - if (shapes[v]) { - return ( - - ); - } - - return ( - - ); - } - - - function vboxElement() { - return ( -
setReclaiming(false)} - onClick={e => e.stopPropagation()} - onMouseOver={e => hoverInfo(e, 'vbox')}> -
-

e.target.scrollIntoView(true)}>VBOX

-
hoverInfo(e, 'bits')} >{vbox.bits}b
-
-
- {range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))} -
-
- {range(0, 3).map(i => availableBtn(vbox.free[1][i], 1, i))} - {range(0, 3).map(i => availableBtn(vbox.free[2][i], 2, i))} -
- -
- ); - } - - // - // INVENTORY - // - function reclaimClick(e) { - e.stopPropagation(); - return setReclaiming(!reclaiming); - } - - const inventoryClass = `vbox-section ${reclaiming ? 'reclaiming' : ''}`; - - function inventoryBtn(v, i) { - const inventoryHighlight = vboxSelecting || itemUnequip.length; - - if (!v && v !== 0) { - return ; - } - - const combinerItems = combiner.map(j => vbox.bound[j]); - const combinerCount = countBy(combinerItems, co => co); - - const comboHighlight = combinerItems.length > 0 && itemInfo.combos.some(combo => { - if (combo.components.includes(v)) { - return combinerItems.every(c => { - if (!combo.components.includes(c)) return false; - const comboCount = countBy(combo.components, co => co); - if (combinerCount[c] > comboCount[c]) return false; - if (c === v && combinerCount[c] + 1 > comboCount[c]) return false; - return true; - }); - } return false; - }) ? 'combo-border' : ''; - - function onClick(e) { - if (vboxSelecting) clearVboxSelected(); - if (reclaiming) return sendVboxReclaim(i); - - // 4 things selected - if (combiner.length > 2) return combinerChange([i]); - - // removing - const combinerIndex = combiner.indexOf(i); - if (combinerIndex > -1) { - return combinerChange(without(combiner, i)); + if (newCombiner.length === 1) { + setItemEquip(newCombiner[0]); + } else { + setItemEquip(null); } - combiner.push(i); - - if (!comboHighlight) { - return combinerChange([i]); - } - - return combinerChange(combiner); - } - - const highlighted = combiner.indexOf(i) > -1; - const border = buttons[removeTier(v)] ? buttons[removeTier(v)]() : ''; - const classes = `${highlighted ? 'highlight' : border} ${comboHighlight}`; - if (shapes[v]) { - return ( - - ); - } - - return ( - - ); - } - - function combinerBtn() { - let text = ''; - let comboItem = ''; - if (combiner.length < 3) { - for (let i = 0; i < 3; i++) { - if (combiner.length > i) { - text += 'â–  '; - } else { - text += 'â–« '; - } - } - } else { - // Since theres 3 items in combiner and you can't have invalid combos we can preview it - const combinerItems = combiner.map(j => vbox.bound[j]); - const combinerCount = countBy(combinerItems, co => co); - const comboItemObj = itemInfo.combos.find(combo => combinerItems.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; - })); - comboItem = comboItemObj ? comboItemObj.item : 'refine'; - comboItem = comboItem.replace('Plus', '+'); - text = `Combine - ${comboItem}`; - } - - return ( - - ); - } - - function inventoryElement() { - function inventoryClick(e) { - e.stopPropagation(); - setReclaiming(false); - if (vboxSelecting) return vboxBuySelected(); - if (itemUnequip.length) return sendItemUnequip(itemUnequip); return true; } - return ( -
e.stopPropagation()} - style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null} - onMouseOver={e => hoverInfo(e, 'inventory')}> -
-

e.target.scrollIntoView(true)}>INVENTORY

+ // + // VBOX + // + function vboxHover(e, v) { + if (v) { + if (info !== v) setInfo(v); + e.stopPropagation(); + } + return true; + } + + function clearVboxSelected() { + setVboxSelected([]); + } + + function vboxBuySelected() { + if (!vboxSelecting) return false; + document.activeElement.blur(); + clearVboxSelected(); + sendVboxAccept(vboxSelected[0], vboxSelected[1]); + return true; + } + + function availableBtn(v, group, index) { + if (!v) return ; + const selected = vboxSelected[0] === group && vboxSelected[1] === index; + + // state not yet set in double click handler + function onDblClick(e) { + clearVboxSelected(); + sendVboxAccept(group, index); + e.stopPropagation(); + } + + function onClick(e) { + e.stopPropagation(); + setItemEquip(null); + setCombiner([]); + + if (selected) return clearVboxSelected(); + return setVboxSelected([group, index]); + } + + const combinerItems = combiner.map(j => vbox.bound[j]); + const combinerCount = countBy(combinerItems, co => co); + + const comboHighlight = combinerItems.length > 0 && itemInfo.combos.some(combo => { + if (combo.components.includes(v)) { + return combinerItems.every(c => { + if (!combo.components.includes(c)) return false; + const comboCount = countBy(combo.components, co => co); + if (combinerCount[c] > comboCount[c]) return false; + if (c === v && combinerCount[c] + 1 > comboCount[c]) return false; + return true; + }); + } return false; + }) ? 'combo-border' : ''; + + const classes = `${v.toLowerCase()} ${selected ? 'highlight' : ''} ${comboHighlight}`; + + if (shapes[v]) { + return ( + ); + } + + return ( + + ); + } + + + function vboxElement() { + return ( +
setReclaiming(false)} + onClick={e => e.stopPropagation()} + onMouseOver={e => hoverInfo(e, 'vbox')}> +
+

e.target.scrollIntoView(true)}>VBOX

+
hoverInfo(e, 'bits')} >{vbox.bits}b
+
+
+ {range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))} +
+
+ {range(0, 3).map(i => availableBtn(vbox.free[1][i], 1, i))} + {range(0, 3).map(i => availableBtn(vbox.free[2][i], 2, i))} +
+
-
- {range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))} + ); + } + + // + // INVENTORY + // + function reclaimClick(e) { + e.stopPropagation(); + return setReclaiming(!reclaiming); + } + + const inventoryClass = `vbox-section ${reclaiming ? 'reclaiming' : ''}`; + + function inventoryBtn(v, i) { + const inventoryHighlight = vboxSelecting || itemUnequip.length; + + if (!v && v !== 0) { + return ; + } + + const combinerItems = combiner.map(j => vbox.bound[j]); + const combinerCount = countBy(combinerItems, co => co); + + const comboHighlight = combinerItems.length > 0 && itemInfo.combos.some(combo => { + if (combo.components.includes(v)) { + return combinerItems.every(c => { + if (!combo.components.includes(c)) return false; + const comboCount = countBy(combo.components, co => co); + if (combinerCount[c] > comboCount[c]) return false; + if (c === v && combinerCount[c] + 1 > comboCount[c]) return false; + return true; + }); + } return false; + }) ? 'combo-border' : ''; + + function onClick(e) { + if (vboxSelecting) clearVboxSelected(); + if (reclaiming) return sendVboxReclaim(i); + + // 4 things selected + if (combiner.length > 2) return combinerChange([i]); + + // removing + const combinerIndex = combiner.indexOf(i); + if (combinerIndex > -1) { + return combinerChange(without(combiner, i)); + } + + combiner.push(i); + + if (!comboHighlight) { + return combinerChange([i]); + } + + return combinerChange(combiner); + } + + const highlighted = combiner.indexOf(i) > -1; + const border = buttons[removeTier(v)] ? buttons[removeTier(v)]() : ''; + const classes = `${highlighted ? 'highlight' : border} ${comboHighlight}`; + if (shapes[v]) { + return ( + + ); + } + + return ( + + ); + } + + function combinerBtn() { + let text = ''; + let comboItem = ''; + if (combiner.length < 3) { + for (let i = 0; i < 3; i++) { + if (combiner.length > i) { + text += 'â–  '; + } else { + text += 'â–« '; + } + } + } else { + // Since theres 3 items in combiner and you can't have invalid combos we can preview it + const combinerItems = combiner.map(j => vbox.bound[j]); + const combinerCount = countBy(combinerItems, co => co); + const comboItemObj = itemInfo.combos.find(combo => combinerItems.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; + })); + comboItem = comboItemObj ? comboItemObj.item : 'refine'; + comboItem = comboItem.replace('Plus', '+'); + text = `Combine - ${comboItem}`; + } + + return ( + + ); + } + + function inventoryElement() { + function inventoryClick(e) { + e.stopPropagation(); + setReclaiming(false); + if (vboxSelecting) return vboxBuySelected(); + if (itemUnequip.length) return sendItemUnequip(itemUnequip); + return true; + } + + return ( +
e.stopPropagation()} + style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null} + onMouseOver={e => hoverInfo(e, 'inventory')}> +
+

e.target.scrollIntoView(true)}>INVENTORY

+ +
+
+ {range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))} +
+ {combinerBtn()}
- {combinerBtn()} + ); + } + + // + // EVERYTHING + // + function hoverInfo(e, newInfo) { + e.stopPropagation(); + if (info === newInfo) return true; + return setInfo(newInfo); + } + + const classes = `vbox ${navInstance === 0 ? 'visible' : ''}`; + return ( +
+ {vboxElement()} +
⮞
+ {inventoryElement()}
); } - - // - // EVERYTHING - // - function hoverInfo(e, newInfo) { - e.stopPropagation(); - if (info === newInfo) return true; - return setInfo(newInfo); - } - - const classes = `vbox ${navInstance === 0 ? 'visible' : ''}`; - return ( -
- {vboxElement()} -
⮞
- {inventoryElement()} -
- ); } module.exports = addState(Vbox); From 69a361a23b49abacb95f5f4556021dbe431c86e1 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 00:33:52 +1000 Subject: [PATCH 07/53] remove null info, don't set info to null. click into combos for preview. preview base when combining --- client/src/components/info.component.jsx | 50 ++++++++----------- client/src/components/info.container.jsx | 8 ++- client/src/components/instance.component.jsx | 3 +- client/src/components/instance.constructs.jsx | 7 +-- client/src/components/vbox.component.jsx | 28 ++++++++--- 5 files changed, 50 insertions(+), 46 deletions(-) diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index f4aafd3e..664a1c80 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -2,14 +2,13 @@ const preact = require('preact'); const range = require('lodash/range'); const reactStringReplace = require('react-string-replace'); -const { Component } = require('preact'); const { INFO } = require('./../constants'); const { convertItem, removeTier } = require('../utils'); const { tutorialStage } = require('../tutorial.utils'); const shapes = require('./shapes'); -class InfoComponent extends Component { +class InfoComponent extends preact.Component { shouldComponentUpdate(newProps) { if (newProps.tutorial !== this.props.tutorial) return true; if (newProps.tutorial) return false; // We don't care about info during tutorial @@ -19,33 +18,24 @@ class InfoComponent extends Component { render(args) { const { - ws, - itemInfo, - player, - instance, + // Variables that will change info, tutorial, - clearTutorial, + + // Static + player, // Only used for colour calcs which will be update if info changes + ws, + itemInfo, + instance, // Only used for instance id + // functions + setInfo, + setTutorialNull, } = args; function Info() { - if (tutorial) return tutorialStage(tutorial, ws, clearTutorial, instance); + if (tutorial) return tutorialStage(tutorial, ws, setTutorialNull, instance); + if (!info) return false; - if (!info) { - return ( -
-

VBOX phase

-

Strengthen and specialise your constructs by equipping items to them.

-

Double click to purchase items in the VBOX and move them to your INVENTORY.

-

- Combine a SKILL or SPEC with 2 COLOURS to create an item.
- Combine 3 of the same item to upgrade it.
- Click an item and then click a construct to equip that item to it.
-

-

Click the READY button for the GAME PHASE.

-
- ); - } const fullInfo = itemInfo.items.find(i => i.item === info) || INFO[info]; if (!fullInfo) return false; const isSkill = fullInfo.skill; @@ -64,7 +54,7 @@ class InfoComponent extends Component { const cooldown = fullInfo.cooldown ? `${fullInfo.cooldown} Turn delay` : null; return (
-

{fullInfo.item} - {fullInfo.cost}b

+

{fullInfo.item} {fullInfo.cost}b

SKILL

{itemSourceDescription}
{cooldown}
@@ -161,16 +151,20 @@ class InfoComponent extends Component { const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); const itemSource = itemInfo.combos.filter(c => c.item === info); - const itemSourceInfo = itemSource.length + let itemSourceInfo = itemSource.length ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` : false; const itemRegEx = /(Red|Blue|Green)/; + if (itemSourceInfo) { + while (itemSourceInfo.includes('Plus')) itemSourceInfo = itemSourceInfo.replace('Plus', '+'); + } const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]()); - const infoText = info.replace('Plus', '+'); + let infoText = info; + while (infoText.includes('Plus')) infoText = infoText.replace('Plus', '+'); return (
-

{infoText} - {fullInfo.cost}b

+

{infoText} {fullInfo.cost}b

SPEC

{itemSourceDescription}
{infoDescription}
@@ -202,7 +196,7 @@ class InfoComponent extends Component { {vboxCombos.map((c, i) => - {convertItem(c.item)} + setInfo(c.item)} >{convertItem(c.item)} {c.components.map((u, j) => {convertItem(u)})} )} diff --git a/client/src/components/info.container.jsx b/client/src/components/info.container.jsx index b19fff8e..aec4b282 100644 --- a/client/src/components/info.container.jsx +++ b/client/src/components/info.container.jsx @@ -29,10 +29,14 @@ const addState = connect( }, function receiveDispatch(dispatch) { - function clearTutorial() { + function setTutorialNull() { dispatch(actions.setTutorial(null)); } - return { clearTutorial }; + + function setInfo(info) { + dispatch(actions.setInfo(info)); + } + return { setTutorialNull, setInfo }; } diff --git a/client/src/components/instance.component.jsx b/client/src/components/instance.component.jsx index abd2e9da..76291079 100644 --- a/client/src/components/instance.component.jsx +++ b/client/src/components/instance.component.jsx @@ -56,7 +56,6 @@ class Instance extends Component { render(args) { const { instance, - setInfo, clearItems, } = args; @@ -76,7 +75,7 @@ class Instance extends Component { } return ( -
setInfo(null)}> +
diff --git a/client/src/components/instance.constructs.jsx b/client/src/components/instance.constructs.jsx index 5d3ec130..c8afc6e3 100644 --- a/client/src/components/instance.constructs.jsx +++ b/client/src/components/instance.constructs.jsx @@ -58,10 +58,6 @@ const addState = connect( dispatch(actions.setActiveConstruct(value)); } - function clearInfo() { - return dispatch(actions.setInfo(null)); - } - function setItemEquip(v) { return dispatch(actions.setItemEquip(v)); } @@ -70,7 +66,7 @@ const addState = connect( return dispatch(actions.setItemUnequip(v)); } - return { quit, clearInfo, setInfo, setActiveConstruct, setItemUnequip, setItemEquip }; + return { quit, setInfo, setActiveConstruct, setItemUnequip, setItemEquip }; } ); @@ -248,7 +244,6 @@ function InstanceConstructs(props) { itemEquip, player, instance, - // clearInfo, setInfo, setActiveConstruct, diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index ca0f3ad4..82885c81 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -143,8 +143,12 @@ function Vbox(args) { // function vboxHover(e, v) { if (v) { - if (info !== v) setInfo(v); e.stopPropagation(); + if (combiner.length !== 0) { + const base = combiner.find(c => !['Red', 'Blue', 'Green'].includes(vbox.bound[c])); + if (base) return setInfo(vbox.bound[base]); + } + if (info !== v) setInfo(v); } return true; } @@ -228,10 +232,12 @@ function Vbox(args) { return (
setReclaiming(false)} - onClick={e => e.stopPropagation()} - onMouseOver={e => hoverInfo(e, 'vbox')}> + onClick={e => e.stopPropagation()}>
-

e.target.scrollIntoView(true)}>VBOX

+

e.target.scrollIntoView(true)} + onMouseOver={e => hoverInfo(e, 'vbox')}> VBOX +

hoverInfo(e, 'bits')} >{vbox.bits}b
@@ -290,7 +296,10 @@ function Vbox(args) { if (reclaiming) return sendVboxReclaim(i); // 4 things selected - if (combiner.length > 2) return combinerChange([i]); + if (combiner.length > 2) { + setInfo(vbox.bound[i]); + return combinerChange([i]); + } // removing const combinerIndex = combiner.indexOf(i); @@ -301,6 +310,7 @@ function Vbox(args) { combiner.push(i); if (!comboHighlight) { + setInfo(vbox.bound[i]); return combinerChange([i]); } @@ -384,10 +394,12 @@ function Vbox(args) {
e.stopPropagation()} - style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null} - onMouseOver={e => hoverInfo(e, 'inventory')}> + style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null}>
-

e.target.scrollIntoView(true)}>INVENTORY

+

e.target.scrollIntoView(true)} + onMouseOver={e => hoverInfo(e, 'inventory')}> INVENTORY +

-
+
setReclaiming(false)} + onClick={e => e.stopPropagation()}> +
+

e.target.scrollIntoView(true)} + onMouseOver={e => hoverInfo(e, 'vbox')}> VBOX +

+
hoverInfo(e, 'bits')} >{vbox.bits}b
+
+
+ {range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))} +
+
+ {range(0, 3).map(i => availableBtn(vbox.free[1][i], 1, i))} + {range(0, 3).map(i => availableBtn(vbox.free[2][i], 2, i))} +
+ +
); } @@ -313,10 +313,10 @@ class Vbox extends preact.Component { if (reclaiming) return sendVboxReclaim(i); // 4 things selected - if (combiner.length > 2) { - setInfo(vbox.bound[i]); - return combinerChange([i]); - } + if (combiner.length > 2) { + setInfo(vbox.bound[i]); + return combinerChange([i]); + } // removing const combinerIndex = combiner.indexOf(i); if (combinerIndex > -1) { @@ -325,10 +325,10 @@ class Vbox extends preact.Component { combiner.push(i); - if (!comboHighlight) { - setInfo(vbox.bound[i]); - return combinerChange([i]); - } + if (!comboHighlight) { + setInfo(vbox.bound[i]); + return combinerChange([i]); + } return combinerChange(combiner); } @@ -407,29 +407,29 @@ class Vbox extends preact.Component { } return ( -
e.stopPropagation()} - style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null}> -
-

e.target.scrollIntoView(true)} - onMouseOver={e => hoverInfo(e, 'inventory')}> INVENTORY -

- -
-
- {range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))} -
- {combinerBtn()} -
+
e.stopPropagation()} + style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null}> +
+

e.target.scrollIntoView(true)} + onMouseOver={e => hoverInfo(e, 'inventory')}> INVENTORY +

+ +
+
+ {range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))} +
+ {combinerBtn()} +
); } From 5e137af159494b031905f4bc42798972f015d026 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 12:53:36 +1000 Subject: [PATCH 14/53] default general notes for vbox --- client/src/components/info.component.jsx | 18 ++++++++++++++---- client/src/components/vbox.component.jsx | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 86b193e4..cdabfca8 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -189,12 +189,22 @@ class InfoComponent extends preact.Component { } function Combos() { - if (!player) return false; - if (!info) return false; - if (tutorial) return false; + if (tutorial && instance.time_control === 'Practice' && instance.rounds.length === 1) return false; + const generalNotes = ( +
+

General

+

+ Create combos by clicking a white item together with two colours in the inventory.
+ Reclaim can be used to sell items in the inventory.
+ Click the READY button to start the GAME PHASE. +

+
+ ); + if (!player) return generalNotes; + if (!info) return generalNotes; const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info)); - if (vboxCombos.length > 6) return false; + if (vboxCombos.length > 6 || vboxCombos.length === 0) return generalNotes; return ( diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 54427f92..44d193e7 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -163,7 +163,7 @@ class Vbox extends preact.Component { e.stopPropagation(); if (combiner.length !== 0) { const base = combiner.find(c => !['Red', 'Blue', 'Green'].includes(vbox.bound[c])); - if (base) return setInfo(vbox.bound[base]); + if (base || base === 0) return setInfo(vbox.bound[base]); } if (info !== v) setInfo(v); } From 5e41d92e15af980ebe6e198c5d674a2744062f45 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 13:06:09 +1000 Subject: [PATCH 15/53] keep info as vbox selected if base item --- client/src/components/vbox.component.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 44d193e7..022826ff 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -161,9 +161,10 @@ class Vbox extends preact.Component { function vboxHover(e, v) { if (v) { e.stopPropagation(); + if (vboxSelected[0]) return true; // There is a base skill or spec selected in the vbox if (combiner.length !== 0) { const base = combiner.find(c => !['Red', 'Blue', 'Green'].includes(vbox.bound[c])); - if (base || base === 0) return setInfo(vbox.bound[base]); + if (base || base === 0) return true; } if (info !== v) setInfo(v); } @@ -199,6 +200,7 @@ class Vbox extends preact.Component { setCombiner([]); if (selected) return clearVboxSelected(); + setInfo(vbox.free[group][index]); return setVboxSelected([group, index]); } From 5c808902970cb96d314bd4c444244a3da0c79b38 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 13:25:28 +1000 Subject: [PATCH 16/53] vbox info text --- client/src/components/info.component.jsx | 2 +- client/src/constants.jsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index cdabfca8..2574e50a 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -194,7 +194,7 @@ class InfoComponent extends preact.Component {

General

- Create combos by clicking a white item together with two colours in the inventory.
+ You can preview combos by clicking them when they appear in this section.
Reclaim can be used to sell items in the inventory.
Click the READY button to start the GAME PHASE.

diff --git a/client/src/constants.jsx b/client/src/constants.jsx index 97199bb5..3462373d 100644 --- a/client/src/constants.jsx +++ b/client/src/constants.jsx @@ -34,7 +34,7 @@ module.exports = { }, bits: { item: 'BITS', - description: 'The VBOX currency.\nColours: 1b\nSkills: 2b\nSpecs: 3b\nAt the beginning of a round you receive 12 + 6 * round_number bits.', + description: 'The VBOX currency.\nColours - 1b\nSkills - 2b\nSpecs - 3b.\nAt the beginning of each round you receive 18 bits. This amount increases by 6 bits per round.', }, ready: { item: 'READY', @@ -70,7 +70,7 @@ module.exports = { }, constructSpecs: { item: 'SPECS', - description: 'SPECS increase the STATS of a CONSTRUCT.\nSPECS have increased effect once they reach a THRESHOLD across your whole team.\nClick a SPEC above and select a CONSTRUCT to equip.\nDouble-click to unequip.', + description: 'Specialisations increase the stats of a construct. This includes the damage, healing and speed of your skills and life.\n Increased effect when your team meets the colour threshold.\n Double-click to unequip.', }, powerStat: { item: 'POWER', From 58678e958e4dbc86b2cbcd44c961a7300c7a2a8d Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 13:30:14 +1000 Subject: [PATCH 17/53] updated phase tag from merge --- client/src/components/targeting.arrows.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/targeting.arrows.jsx b/client/src/components/targeting.arrows.jsx index 4a7398e9..48dcaf3c 100644 --- a/client/src/components/targeting.arrows.jsx +++ b/client/src/components/targeting.arrows.jsx @@ -31,7 +31,7 @@ class TargetSvg extends Component { const { game, account, animating, animSkill, itemInfo, gameEffectInfo, tutorialGame } = props; const { width, height } = state; if (!game) return false; // game will be null when battle ends - if (game.phase === 'Finish') return false; // Clear everything if its over (in case of abandon) + if (game.phase === 'Finished') return false; // Clear everything if its over (in case of abandon) // First time joining game phase if (tutorialGame) { From 6da01f879dd7621b634c970081786cf46ed6c8f1 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 13:50:05 +1000 Subject: [PATCH 18/53] disable offer during animation, don't set instance to null --- client/src/components/game.ctrl.btns.jsx | 1 - client/src/components/game.ctrl.btns.top.jsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/components/game.ctrl.btns.jsx b/client/src/components/game.ctrl.btns.jsx index 3918b5ca..557e0915 100644 --- a/client/src/components/game.ctrl.btns.jsx +++ b/client/src/components/game.ctrl.btns.jsx @@ -46,7 +46,6 @@ const addState = connect( function quit() { dispatch(actions.setNav('transition')); dispatch(actions.setGame(null)); - dispatch(actions.setInstance(null)); } function setChatShow(v) { diff --git a/client/src/components/game.ctrl.btns.top.jsx b/client/src/components/game.ctrl.btns.top.jsx index 270721c9..55c4caa0 100644 --- a/client/src/components/game.ctrl.btns.top.jsx +++ b/client/src/components/game.ctrl.btns.top.jsx @@ -81,7 +81,7 @@ function GameCtrlTopBtns(args) { ? 'Offered' : drawState ? 'Draw' : 'Offer'; const drawAction = drawState ? sendDraw : drawStateTrue; - const drawBtn = ; + const drawBtn = ; return (
From 50f1c6fa1b700bedd0f0c684a3f7d61b03121f1f Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 14:23:56 +1000 Subject: [PATCH 19/53] construct name and avatar and $$$ jebaited --- client/src/components/construct.jsx | 3 ++- client/src/components/info.component.jsx | 22 +++++++++++++++++++ client/src/components/instance.constructs.jsx | 8 +++---- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 334ba19e..3c2df336 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -29,12 +29,13 @@ class ConstructAvatar extends Component { } render() { - const { construct } = this.props; + const { construct, mouseOver } = this.props; return (
diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 2574e50a..1d78d2ed 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -40,7 +40,29 @@ class InfoComponent extends preact.Component { 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 = itemInfo.items.find(i => i.item === info) || INFO[info]; if (!fullInfo) return false; const isSkill = fullInfo.skill; diff --git a/client/src/components/instance.constructs.jsx b/client/src/components/instance.constructs.jsx index f3367a2a..1e010061 100644 --- a/client/src/components/instance.constructs.jsx +++ b/client/src/components/instance.constructs.jsx @@ -221,11 +221,11 @@ function Construct(props) { }); const classes = `instance-construct ${mobileVisible ? 'visible' : ''}`; - + const avatarMouseOver = e => hoverInfo(e, `constructAvatar ${construct.name}`); return ( -
- -

{construct.name}

+
+ +

hoverInfo(e, `constructName ${construct.name}`)}>{construct.name}

hoverInfo(e, 'constructSkills')} > {skills}
From 2f391fc85bac25087fab72c6b504efaa7a56f94c Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 14:50:25 +1000 Subject: [PATCH 20/53] reclaim text --- client/src/constants.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/constants.jsx b/client/src/constants.jsx index 3462373d..79723abf 100644 --- a/client/src/constants.jsx +++ b/client/src/constants.jsx @@ -46,7 +46,7 @@ module.exports = { }, reclaim: { item: 'RECLAIM', - description: 'Reclaim ITEMS for half the purchase cost of their combined ITEMS.\nClick to enable and click ITEM to reclaim.', + description: 'Reclaim items refunding the listed cost of the item.\nClick to enable and then click the item to reclaim.', }, refine: { item: 'COMBINE', From 85591ec8573458ded55bde6744408b503dccdcdb Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 14:58:33 +1000 Subject: [PATCH 21/53] shouldCompUpdate game construct, disable ko event --- client/src/components/game.construct.jsx | 31 ++++++++++++++++++------ server/src/skill.rs | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/client/src/components/game.construct.jsx b/client/src/components/game.construct.jsx index 79f2a8bc..75a1677d 100644 --- a/client/src/components/game.construct.jsx +++ b/client/src/components/game.construct.jsx @@ -85,21 +85,36 @@ class GameConstruct extends Component { this.resolvedLength = 0; } + shouldComponentUpdate(newProps) { + if (newProps.activeSkill !== this.props.activeSkill) return true; + if (newProps.animFocus !== this.props.animFocus) 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.player !== this.props.player) return true; + if (newProps.tutorialGame !== this.props.tutorialGame) return true; + if (newProps.gameSkillInfo !== this.props.gameSkillInfo) return true; + return false; + } + render() { const { - i, + // Changing state variables + activeSkill, + animFocus, + animText, animating, construct, player, - activeSkill, - selectSkillTarget, - animFocus, - animText, tutorialGame, + gameSkillInfo, + // Constants + i, + itemInfo, + // Functions + selectSkillTarget, setTutorialGameClear, setGameEffectInfo, - gameSkillInfo, - itemInfo, } = this.props; const ko = construct.green_life.value === 0 ? 'ko' : ''; @@ -145,7 +160,7 @@ class GameConstruct extends Component { > {c.effect} - {c.duration}T
) : null; return (
{effects}
); - } + }; return (
}; if target.is_ko() { - resolutions.push(Resolution::new(&source, &target).event(Event::Ko()).stages(EventStages::PostOnly)); + // resolutions.push(Resolution::new(&source, &target).event(Event::Ko()).stages(EventStages::PostOnly)); target.effects.clear(); } From 7355f0668f929b13f3a49117a2231c81db053f9a Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 15:05:30 +1000 Subject: [PATCH 22/53] targetting arrows shouldUpdate --- client/src/components/targeting.arrows.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/src/components/targeting.arrows.jsx b/client/src/components/targeting.arrows.jsx index 48dcaf3c..a79de304 100644 --- a/client/src/components/targeting.arrows.jsx +++ b/client/src/components/targeting.arrows.jsx @@ -27,6 +27,16 @@ class TargetSvg extends Component { }, 500); } + shouldComponentUpdate(newProps) { + if (newProps.game !== this.props.game) return true; + if (newProps.account !== this.props.account) return true; + if (newProps.animating !== this.props.animating) return true; + if (newProps.animSkill !== this.props.animSkill) return true; + if (newProps.gameEffectInfo !== this.props.gameEffectInfo) return true; + if (newProps.tutorialGame !== this.props.tutorialGame) return true; + return false; + } + render(props, state) { const { game, account, animating, animSkill, itemInfo, gameEffectInfo, tutorialGame } = props; const { width, height } = state; From 6a4eb1837d668b311f2b90ffdb3e45cde088dcc4 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 15:08:22 +1000 Subject: [PATCH 23/53] misc --- client/src/components/targeting.arrows.jsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/client/src/components/targeting.arrows.jsx b/client/src/components/targeting.arrows.jsx index a79de304..7bd82010 100644 --- a/client/src/components/targeting.arrows.jsx +++ b/client/src/components/targeting.arrows.jsx @@ -38,7 +38,17 @@ class TargetSvg extends Component { } render(props, state) { - const { game, account, animating, animSkill, itemInfo, gameEffectInfo, tutorialGame } = props; + const { + // Changing State Variables + account, + animating, + animSkill, + game, + gameEffectInfo, + tutorialGame, + // Static + itemInfo, + } = props; const { width, height } = state; if (!game) return false; // game will be null when battle ends if (game.phase === 'Finished') return false; // Clear everything if its over (in case of abandon) From 84acb58573aece47e68c5b0b6e0560e72d8be650 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 19:01:22 +1000 Subject: [PATCH 24/53] move construct calls into componentDidUpdate, change shouldCompUpdate --- client/src/components/construct.jsx | 40 ++++++++++++----------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/client/src/components/construct.jsx b/client/src/components/construct.jsx index 3c2df336..19e9fd20 100644 --- a/client/src/components/construct.jsx +++ b/client/src/components/construct.jsx @@ -61,42 +61,36 @@ class ConstructAvatar extends Component { this.resetAnimations(); } - shouldComponentUpdate(newProps) { - const { animSource, animTarget, animText, construct } = newProps; - - if (construct !== this.props.construct) { - return true; - } - - if (animText && animText !== this.props.animText && animText.constructId === construct.id) { + componentDidUpdate(prevProps) { + const { animSource, animTarget, animText, construct } = this.props; + // a different text object and text construct + if (animText && animText !== prevProps.animText && animText.constructId === construct.id) { return wiggle(construct.id, this.idle); } - 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') + // different source object and source construct + if (animSource && animSource !== prevProps.animSource && animSource.constructId === construct.id) { return sourceCast(animSource.constructId, animSource.direction, this.idle); } - - // this is the target - if (animTarget && animTarget.constructId.includes(construct.id)) { - // console.warn(construct.name, 'should update') + // different target object and target construct + if (animTarget && animTarget !== prevProps.animTarget && animTarget.constructId.includes(construct.id)) { switch (animTarget.skill) { case 'Banish': return banish(construct.id, this.idle); case 'Invert': return invert(construct.id, this.idle); default: return null; } } + return true; + } + + shouldComponentUpdate(newProps) { + const { animSource, animTarget, animText, construct } = newProps; + if (animSource !== this.props.animSource) return true; + if (animTarget !== this.props.animTarget) return true; + if (animText !== this.props.animText) return true; + if (construct !== this.props.construct) return true; return false; } } From cfc1c1ea81f495fb186d8092fb4f507e63d82e3f Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 19:08:01 +1000 Subject: [PATCH 25/53] cleanup old files --- client/src/components/instance.component.jsx | 6 +- client/src/components/instance.equip.jsx | 144 ------------------- client/src/components/particles.config.js | 41 ------ 3 files changed, 5 insertions(+), 186 deletions(-) delete mode 100644 client/src/components/instance.equip.jsx delete mode 100644 client/src/components/particles.config.js diff --git a/client/src/components/instance.component.jsx b/client/src/components/instance.component.jsx index 76291079..d4953550 100644 --- a/client/src/components/instance.component.jsx +++ b/client/src/components/instance.component.jsx @@ -7,7 +7,6 @@ const Hammer = require('hammerjs'); const Vbox = require('./vbox.component'); const InfoContainer = require('./info.container'); const InstanceConstructsContainer = require('./instance.constructs'); -// const EquipmentContainer = require('./instance.equip'); const Faceoff = require('./faceoff'); const actions = require('../actions'); @@ -53,6 +52,11 @@ const addState = connect( ); class Instance extends Component { + componentShouldUpdate(newProps) { + if (newProps.instance !== this.props.instance) return true; + return false; + } + render(args) { const { instance, diff --git a/client/src/components/instance.equip.jsx b/client/src/components/instance.equip.jsx deleted file mode 100644 index ef4ac2e3..00000000 --- a/client/src/components/instance.equip.jsx +++ /dev/null @@ -1,144 +0,0 @@ -const { connect } = require('preact-redux'); -const preact = require('preact'); -const range = require('lodash/range'); - -const actions = require('../actions'); -const shapes = require('./shapes'); -const { convertItem } = require('./../utils'); - -const addState = connect( - function receiveState(state) { - const { account, activeConstruct, itemInfo, info, ws, instance, player, itemUnequip } = state; - - function sendUnequip(constructId, item) { - return ws.sendVboxUnequip(instance.id, constructId, item); - } - - return { player, itemInfo, instance, info, sendUnequip, activeConstruct, itemUnequip }; - }, - - function receiveDispatch(dispatch) { - function setInfo(item) { - dispatch(actions.setInfo(item)); - } - - function clearInfo() { - return dispatch(actions.setInfo(null)); - } - - function setItemEquip(v) { - return dispatch(actions.setItemEquip(v)); - } - - function setItemUnequip(v) { - return dispatch(actions.setItemUnequip(v)); - } - - return { setInfo, setItemEquip, setItemUnequip, clearInfo }; - } - -); - -function Equipment(props) { - const { - player, - instance, - - itemUnequip, - setItemEquip, - setItemUnequip, - activeConstruct, - - itemInfo, - sendUnequip, - - setInfo, - } = props; - - if (instance.phase === 'Lobby') return false; - - const { vbox } = player; - - const fullInfo = itemInfo.items.find(i => i.item === itemUnequip); - const isSkill = fullInfo && fullInfo.skill; - const isSpec = fullInfo && fullInfo.spec; - - function skillClick(e, i) { - if (itemUnequip && activeConstruct) return false; - // const value = vbox.bound[i]; - setItemEquip(i); - return false; - } - - function unequipClick(e) { - e.stopPropagation(); - if (!itemUnequip) return false; - if (!activeConstruct) return false; - setItemUnequip([]); - return sendUnequip(activeConstruct.id, itemUnequip); - } - - function hoverInfo(e, info) { - e.stopPropagation(); - return setInfo(info); - } - - const skillClass = isSkill ? 'skills highlight' : 'skills'; - const specClass = isSpec ? 'specs highlight' : 'specs'; - - const skills = range(0, 9).map(i => { - const item = convertItem(vbox.bound[i]); - const skillInfo = itemInfo.items.find(i => i.item === item); - if (skillInfo && skillInfo.skill) { - return ( - - ); - } - return false; - }); - - const specs = range(0, 9).map(i => { - const item = convertItem(vbox.bound[i]); - const specInfo = itemInfo.items.find(i => i.item === item); - if (specInfo && specInfo.spec) { - return ( -
skillClick(e, i)} onMouseOver={e => hoverInfo(e, item)} > - {shapes[item]()} -
{item ? item : '-'}
-
- ); - } - return false; - }); - - if (skills.every(s => !s)) skills.push(); - if (specs.every(s => !s)) { - specs.push( -
- {shapes.diamond('gray')} -
 
-
- ); - } - - return ( -
-
unequipClick(e)} onMouseOver={e => hoverInfo(e, 'equipSkills')} > -

Skills

-
- {skills} -
-
-
unequipClick(e)} onMouseOver={e => hoverInfo(e, 'equipSpecs')} > -

Specs

-
- {specs} -
-
-
- ); -} - -module.exports = addState(Equipment); diff --git a/client/src/components/particles.config.js b/client/src/components/particles.config.js deleted file mode 100644 index 651cae39..00000000 --- a/client/src/components/particles.config.js +++ /dev/null @@ -1,41 +0,0 @@ -const config = { - particles: { - number: { value: 300, density: { enable: true, value_area: 800 } }, - color: { value: '#ffffff' }, - shape: { - type: 'circle', - stroke: { width: 0, color: '#000000' }, - polygon: { nb_sides: 5 }, - image: { src: 'img/github.svg', width: 100, height: 100 } - }, - opacity: { - value: 0.5, - random: false, - anim: { enable: false, speed: 1, opacity_min: 0.1, sync: false }, - }, - size: { - value: 3, - random: true, - anim: { enable: false, speed: 40, size_min: 0.1, sync: false }, - }, - line_linked: { - enable: true, - distance: 150, - color: '#ffffff', - opacity: 0.4, - width: 1, - }, - move: { - enable: true, - speed: 6, - direction: 'none', - random: false, - straight: false, - out_mode: 'out', - bounce: false, - attract: { enable: false, rotateX: 600, rotateY: 1200 }, - }, - }, -}; - -module.exports = config; From a6cd2a3e0a9262b115b0c1cd6cb67d2bf112db5e Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 20:58:44 +1000 Subject: [PATCH 26/53] tutorial disable check, info formatting --- client/src/components/vbox.component.jsx | 10 +++--- client/src/constants.jsx | 41 ++++++++++++------------ 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 022826ff..d97e3f31 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -104,11 +104,10 @@ class Vbox extends preact.Component { if (newProps.reclaiming !== this.props.reclaiming) return true; if (newProps.navInstance !== this.props.navInstance) return true; if (newProps.tutorial !== this.props.tutorial) return true; - // Don't bother if info changes during tutorial - if (!newProps.tutorial && newProps.info !== this.props.info) return true; - // JSON or Array objects + if (newProps.info !== this.props.info) return true; if (newProps.vboxSelected !== this.props.vboxSelected) return true; if (newProps.player !== this.props.player) return true; + if (newProps.instance !== this.props.instance) return true; return false; } @@ -123,6 +122,7 @@ class Vbox extends preact.Component { navInstance, info, vboxSelected, + instance, // Static itemInfo, @@ -269,7 +269,7 @@ class Vbox extends preact.Component {
); @@ -58,9 +58,9 @@ class InfoComponent extends preact.Component {

{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. + You can change your construct avatar in the RESHAPE tab outside of games.

-
+
); } const fullInfo = itemInfo.items.find(i => i.item === info) || INFO[info]; @@ -216,8 +216,7 @@ class InfoComponent extends preact.Component {

General

- You can preview combos by clicking them when they appear in this section.
- Reclaim can be used to sell items in the inventory.
+ You can preview combos by clicking the combined item when it appears in this section.
Click the READY button to start the GAME PHASE.

diff --git a/client/src/constants.jsx b/client/src/constants.jsx index 32c093ec..afc53c74 100644 --- a/client/src/constants.jsx +++ b/client/src/constants.jsx @@ -38,7 +38,7 @@ module.exports = { description:

The VBOX currency.
Colours - 1b
Skills - 2b
- Specs - 3b.
+ Specs - 3b
At the beginning of each round you receive 18 bits increasing by 6 bits per round.

, }, ready: { From 52f6e528e44b45986ef3eff5e5f5e4e9345f66d6 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 21:52:37 +1000 Subject: [PATCH 29/53] targetting arrows update arrow svg state --- client/src/components/targeting.arrows.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/components/targeting.arrows.jsx b/client/src/components/targeting.arrows.jsx index 7bd82010..b615517b 100644 --- a/client/src/components/targeting.arrows.jsx +++ b/client/src/components/targeting.arrows.jsx @@ -27,13 +27,15 @@ class TargetSvg extends Component { }, 500); } - shouldComponentUpdate(newProps) { + shouldComponentUpdate(newProps, newState) { if (newProps.game !== this.props.game) return true; if (newProps.account !== this.props.account) return true; if (newProps.animating !== this.props.animating) return true; if (newProps.animSkill !== this.props.animSkill) return true; if (newProps.gameEffectInfo !== this.props.gameEffectInfo) return true; if (newProps.tutorialGame !== this.props.tutorialGame) return true; + if (newState.width !== this.state.width) return true; + if (newState.height !== this.state.height) return true; return false; } From 861cc63682084f9c35f10dc6c539a82c196b9630 Mon Sep 17 00:00:00 2001 From: Mashy Date: Mon, 28 Oct 2019 22:36:00 +1000 Subject: [PATCH 30/53] tidy up descriptions --- client/src/components/info.component.jsx | 9 ++- server/src/item.rs | 86 +++++++++++++++--------- 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 8d49b1ac..6a1689dd 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -70,7 +70,8 @@ class InfoComponent extends preact.Component { if (isSkill) { const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; - const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); + let infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); + infoDescription = reactStringReplace(infoDescription, '\n', () =>
); const itemSource = itemInfo.combos.filter(c => c.item === removeTier(info)); const itemSourceInfo = itemSource.length ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` @@ -176,7 +177,8 @@ class InfoComponent extends preact.Component { ); }); const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; - const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); + let infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); + infoDescription = reactStringReplace(infoDescription, '\n', () =>
); const itemSource = itemInfo.combos.filter(c => c.item === info); let itemSourceInfo = itemSource.length ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` @@ -202,10 +204,11 @@ class InfoComponent extends preact.Component { ); } const cost = fullInfo.cost ? `- ${fullInfo.cost}b` : false; + const infoDescription = reactStringReplace(fullInfo.description, '\n', () =>
); return (

{fullInfo.item} {cost}

-
{fullInfo.description}
+
{infoDescription}
); } diff --git a/server/src/item.rs b/server/src/item.rs index 763e17c2..2cae5571 100644 --- a/server/src/item.rs +++ b/server/src/item.rs @@ -584,9 +584,9 @@ impl Item { pub fn into_description(&self) -> String { match self { // colours - Item::Blue => format!("Combine with skills and specs to create upgraded items. \n Deterrents and destruction."), - Item::Green => format!("Combine with skills and specs to create upgraded items.\n Protection and trickery."), - Item::Red => format!("Combine with skills and specs to create upgraded items. \n Speed and chaos."), + Item::Blue => format!("Combine two colours with a white base item to create a new combo. \n Slow speed, magical type. Deterrents and destruction."), + Item::Green => format!("Combine two colours with a white base item to create a new combo.\n Normal speed, healing type. Protection and trickery."), + Item::Red => format!("Combine two colours with a white base item to create a new combo. \n Fast speed, physical type. Chaos and momentum."), // base skills Item::Attack => format!("Deal {:?}% RedPower as red damage.", @@ -603,7 +603,8 @@ impl Item { 100 - self.into_skill().unwrap().effect()[0].get_multiplier()), // specs // Base - Item::Power => format!("Increases all power stats by {:?}%. Power determines the base damage and healing of your construct skills.", + Item::Power => format!("Increases all power stats by {:?}%. + Power determines the base damage and healing of your construct skills.", self.into_spec().unwrap().values().base()), Item::Life => format!("Increases construct GreenLife by {:?}. When your construct reaches 0 GreenLife it is knocked out and cannot cast skills.", @@ -713,7 +714,8 @@ impl Item { Item::Banish| Item::BanishPlus | - Item::BanishPlusPlus => format!("Banish target for {:?}T. Deal blue damage and red damage equal to {:?}% target red and blue life. + Item::BanishPlusPlus => format!("Banish target for {:?}T. + Deal blue damage and red damage equal to {:?}% target red and blue life. Banished constructs are immune to all skills and effects.", self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().multiplier()), @@ -725,20 +727,24 @@ impl Item { Item::Chaos| Item::ChaosPlus | Item::ChaosPlusPlus => format!( - "Hits twice for red and blue damage. Damage {:?}% RedPower and BluePower. Randomly deals 0 to 30% more damage.", + "Hits twice for red and blue damage. Damage {:?}% RedPower and BluePower. + Randomly deals 0 to 30% more damage.", self.into_skill().unwrap().multiplier()), Item::Sustain| Item::SustainPlus | - Item::SustainPlusPlus => format!("Construct cannot be KO'd while active. Additionally provides immunity to disables. \ - Lasts {:?}T", - self.into_skill().unwrap().effect()[0].get_duration()), + Item::SustainPlusPlus => format!( + "Construct cannot be KO'd while active and provides immunity to disables. Lasts {:?}T. + Recharges target RedLife based on {:?}% RedPower.", + self.into_skill().unwrap().effect()[0].get_duration(), + self.into_skill().unwrap().multiplier()), Item::Electrify| Item::ElectrifyPlus | Item::ElectrifyPlusPlus => format!( - "Applies electrify for {:?}T. If a construct with electrify takes damage they will apply an electrocute debuff to the caster dealing {:?}% \ - BluePower as BlueDamage per turn for {:?}T.", + "Applies electrify for {:?}T. + If a construct with electrify takes direct damage they will apply an electrocute debuff to the caster. + Electrocute deals {:?}% BluePower as BlueDamage per turn for {:?}T.", self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().effect()[0].get_skill().unwrap().effect()[0].get_skill().unwrap().multiplier(), self.into_skill().unwrap().effect()[0].get_skill().unwrap().effect()[0].get_duration()), @@ -753,7 +759,8 @@ impl Item { Item::Decay| Item::DecayPlus | Item::DecayPlusPlus => format!( - "Reduces healing taken by {:?}% for {:?}T. Deals blue damage {:?}% BluePower each turn for {:?}T.", + "Reduces healing taken by {:?}% for {:?}T. + Deals blue damage {:?}% BluePower each turn for {:?}T.", 100 - self.into_skill().unwrap().effect()[0].get_multiplier(), self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().effect()[1].get_skill().unwrap().multiplier(), @@ -762,17 +769,20 @@ impl Item { Item::Absorb| Item::AbsorbPlus | Item::AbsorbPlusPlus => format!( - "Gain Absorb for {:?}T. {} Absorption lasts {:?}T.", + "Gain Absorb for {:?}T. When attacked with Absorb you gain Absorption. + Absorption increases RedPower and BluePower based on Damage taken. + Absorption lasts {:?}T.", self.into_skill().unwrap().effect()[0].get_duration(), - "When attacked with Absorb you gain Absorption which increases RedPower and BluePower based on Damage taken.", self.into_skill().unwrap().effect()[0].get_skill().unwrap().effect()[0].get_duration()), Item::Haste| Item::HastePlus | Item::HastePlusPlus => format!( - "Haste increases SpeedStat by {:?}%, Red Attack based skills will strike again dealing {:?}% SpeedStat as red damage. Lasts {:?}T", + "Haste increases SpeedStat by {:?}%. + Red Attack based skills will strike again dealing {:?}% SpeedStat as red damage. + Lasts {:?}T", self.into_skill().unwrap().effect()[0].get_multiplier() - 100, - Skill::HasteStrike.multiplier(), + Skill::HasteStrike.multiplier(), self.into_skill().unwrap().effect()[0].get_duration()), Item::Heal| @@ -782,7 +792,9 @@ impl Item { Item::Hybrid| Item::HybridPlus | Item::HybridPlusPlus => format!( - "Hybrid increases GreenPower by {:?}%, Blue based Attack skills will blast again dealing {:?}% GreenPower as blue damage. Lasts {:?}T.", + "Hybrid increases GreenPower by {:?}%. + Blue based Attack skills will blast again dealing {:?}% GreenPower as blue damage. + Lasts {:?}T.", self.into_skill().unwrap().effect()[0].get_multiplier() - 100, Skill::HybridBlast.multiplier(), self.into_skill().unwrap().effect()[0].get_duration()), @@ -790,20 +802,26 @@ impl Item { Item::Invert| Item::InvertPlus | Item::InvertPlusPlus => format!( - "Reverse healing into damage and damage into healing. Any excess red or blue damage is converted into shield recharge. Lasts {:?}T.", + "Reverse healing into damage and damage into healing. + Any excess red or blue damage is converted into shield recharge. + Lasts {:?}T.", self.into_skill().unwrap().effect()[0].get_duration()), Item::Counter| Item::CounterPlus | - Item::CounterPlusPlus => format!("Applies counter and block {:?}T. Block reduces incoming red damage by {:?}%. - Red damage taken during counter will trigger a counter attack dealing {:?}% RedPower as red damage.", + Item::CounterPlusPlus => format!( + "Applies counter and block {:?}T. Block reduces incoming red damage by {:?}%. + Red damage taken during counter will trigger a counter attack. + Counter attack deals {:?}% RedPower as red damage.", self.into_skill().unwrap().effect()[0].get_duration(), 100 - self.into_skill().unwrap().effect()[1].get_multiplier(), self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier()), Item::Purge| Item::PurgePlus | - Item::PurgePlusPlus => format!("Remove buffs from target construct. Applies purge disabling target green skills for {:?}T.", + Item::PurgePlusPlus => format!( + "Remove buffs from target construct. + Applies purge disabling target green skills for {:?}T.", self.into_skill().unwrap().effect()[0].get_duration()), Item::Purify| @@ -815,8 +833,10 @@ impl Item { Item::Reflect| Item::ReflectPlus | Item::ReflectPlusPlus => format!( - "Reflect incoming blue skills to source. Lasts {:?}T.", - self.into_skill().unwrap().effect()[0].get_duration()), + "Reflect incoming blue skills to source. Lasts {:?}T. + Recharges target BlueLife based on {:?}% BluePower.", + self.into_skill().unwrap().effect()[0].get_duration(), + self.into_skill().unwrap().multiplier()), Item::Recharge| Item::RechargePlus | @@ -833,8 +853,8 @@ impl Item { Item::Link| Item::LinkPlus | Item::LinkPlusPlus => format!( - "Form a link with target swapping relative life values. - If the target construct has more green life than caster, {:?}% of green life difference as blue damage to the target and heal to the caster. + "Swap {:?}% of green life difference as blue damage to the target and healing to the caster. + The swap only occurs if the target construct has more green life than caster. Stuns caster for {:?}T in the process.", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().effect()[0].get_duration()), @@ -850,7 +870,8 @@ impl Item { Item::Slay| Item::SlayPlus | Item::SlayPlusPlus => format!( - "Deals {:?}% RedPower + {:?}% GreenPower as red damage and provides self healing based on damage dealt.", + "Deals {:?}% RedPower + {:?}% GreenPower as red damage. + Provides self healing based on damage dealt.", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().multiplier()), @@ -864,7 +885,8 @@ impl Item { Item::Restrict| Item::RestrictPlus | Item::RestrictPlusPlus => format!( - "Block the target from using red skills for {:?}T and deals {:?}% RedPower as red damage. Deals 35% more damage per red skill on target.", + "Block the target from using red skills for {:?}T and deals {:?}% RedPower as red damage. + Deals 35% more damage per red skill on target.", self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().multiplier()), @@ -872,7 +894,8 @@ impl Item { Item::BashPlus | Item::BashPlusPlus => format!( "Bash the target increasing the cooldowns of target skills by 1T. - Deals {:?}% RedPower as red damage and 45% more damage per cooldown increased. Stuns for {:?}T.", + Deals {:?}% RedPower as red damage and 45% more damage per cooldown increased. + Stuns for {:?}T.", self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier(), self.into_skill().unwrap().effect()[0].get_duration()), @@ -885,14 +908,17 @@ impl Item { Item::Siphon| Item::SiphonPlus | Item::SiphonPlusPlus => format!( - "Deals {:?}% BluePower + {:?}% GreenPower as blue damage each turn and heals caster based on damage dealt. Lasts {:?}T.", + "Deals {:?}% BluePower + {:?}% GreenPower as blue damage each turn. + Heals caster based on damage dealt. + Lasts {:?}T.", self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier(), self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier(), self.into_skill().unwrap().effect()[0].get_duration()), Item::Intercept| Item::InterceptPlus | - Item::InterceptPlusPlus => format!("Intercept redirects skills against the team to target, lasts {:?}T.\ + Item::InterceptPlusPlus => format!( + "Intercept redirects skills against the team to target, lasts {:?}T. Recharges RedLife for {:?} RedPower.", self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().multiplier()), From b30c4463facfb6148079ae44170ab32af4d7a149 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 11:31:07 +1000 Subject: [PATCH 31/53] skill rebalance --- CHANGELOG.md | 55 ++++++++++++++++++++++++++++++++++++++++ server/src/effect.rs | 6 ++--- server/src/item.rs | 27 +++++++++++--------- server/src/skill.rs | 60 ++++++++++++++++++-------------------------- 4 files changed, 98 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a6107c0..d4283869 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,61 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [1.6.7] - 2019-10-27 +# Added +- Step by step tutorial + - Will activate during the learn game for the first round + - There is a button which will exit tutorial so you can continune the normal practice mode +- Skill combo previews + - You can now preview what item combos will create! + - Click into the item in the info section table (top right) and it will be replaced with the new item + +# Changed +- Vbox phase + - Made general performance improvements + - Removed the default info state (should be smoother to navigate now) + - When combining or selecting base items (skills/specs) the base item info won't be replaced with other vbox items + - Added info text for construct names and avatars + - Changed a number of info descriptions for clarity + +- Game phase + - Made general performance improvements + - Now has default tutorial text for the first round + - Will tell the player to select skills and then the targets + +# Skill Balance Updates +- Buff + - Previously increased red power and speed stat by 25% + - Now increases red power, blue power and speed stat by 30% + +- Block + - Previously reduced red damage taken by 50% + - Now reduces red damage and blue damage taken by 65% + +- Counter + - No longer applies block effect + - CounterAttack multiplier increased from 70/95/120 -> 120/160/230 +- Haste + - Cooldown reduced to 1T (was 2T) +- Sleep + - Cooldown reduced to 2T (was 3T) + - Skill multiplier reduced from 240/300/400 -> 200/290/400 +- Hybrid + - Cooldown reduced to 1T (was 3T) +- Silence + - Cooldown reduced to 2T (was 3T) +- Banish + - Cooldown reduced to 2T (was 3T) +- Siphon + - Skill multiplier increased from 20/25/30 -> 25/30/40 +- Bash + - Skill multiplier reduced from 65/95/140 -> 45/65/100 +- Curse + - Now created by combining Debuff + RB was Debuff + RG + - Fixed issue where curse was only increasing blue damage taken instead of red and blue +- Invert + - Now created by combining Debuff + RG was debuff + RB + ## [1.6.6] - 2019-10-27 # Added - Offering of draws diff --git a/server/src/effect.rs b/server/src/effect.rs index 1e959e50..c2c77392 100644 --- a/server/src/effect.rs +++ b/server/src/effect.rs @@ -100,13 +100,13 @@ impl Effect { pub fn modifications(&self) -> Vec { match self { Effect::Vulnerable => vec![Stat::RedDamageTaken], - Effect::Block => vec![Stat::RedDamageTaken], - Effect::Buff => vec![Stat::RedPower, Stat::Speed], + Effect::Block => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken], + Effect::Buff => vec![Stat::BluePower, Stat::RedPower, Stat::Speed], Effect::Absorption => vec![Stat::RedPower, Stat::BluePower], Effect::Amplify => vec![Stat::RedPower, Stat::BluePower], - Effect::Curse => vec![Stat::BlueDamageTaken], + Effect::Curse => vec![Stat::RedDamageTaken, Stat::BlueDamageTaken], Effect::Hybrid => vec![Stat::GreenPower], Effect::Wither => vec![Stat::GreenDamageTaken], diff --git a/server/src/item.rs b/server/src/item.rs index 2cae5571..b697828a 100644 --- a/server/src/item.rs +++ b/server/src/item.rs @@ -591,16 +591,20 @@ impl Item { // base skills Item::Attack => format!("Deal {:?}% RedPower as red damage.", self.into_skill().unwrap().multiplier()), - Item::Block => format!("Reduce red damage taken by {:?}%.", - 100 - self.into_skill().unwrap().effect()[0].get_multiplier()), + Item::Block => format!("Reduce red damage and blue damage taken by {:?}%. Block lasts {:?}T", + 100 - self.into_skill().unwrap().effect()[0].get_multiplier(), + self.into_skill().unwrap().effect()[0].get_duration()), Item::Stun => format!("Stun target construct for {:?}T.", self.into_skill().unwrap().effect()[0].get_duration()), - Item::Buff => format!("Increase target construct RedPower and SpeedStat by {:?}%.", - self.into_skill().unwrap().effect()[0].get_multiplier() - 100), - Item::Debuff => format!("Slows the target reducing SpeedStat by {:?}%.", - 100 - self.into_skill().unwrap().effect()[0].get_multiplier()), + Item::Buff => format!("Increase target construct RedPower BluePower SpeedStat by {:?}%. Buff lasts {:?}T", + self.into_skill().unwrap().effect()[0].get_multiplier() - 100, + self.into_skill().unwrap().effect()[0].get_duration()), + + Item::Debuff => format!("Slows the target reducing SpeedStat by {:?}%. Debuff lasts {:?}T", + 100 - self.into_skill().unwrap().effect()[0].get_multiplier(), + self.into_skill().unwrap().effect()[0].get_duration()), // specs // Base Item::Power => format!("Increases all power stats by {:?}%. @@ -810,11 +814,10 @@ impl Item { Item::Counter| Item::CounterPlus | Item::CounterPlusPlus => format!( - "Applies counter and block {:?}T. Block reduces incoming red damage by {:?}%. + "Applies counter for {:?}T. Red damage taken during counter will trigger a counter attack. Counter attack deals {:?}% RedPower as red damage.", self.into_skill().unwrap().effect()[0].get_duration(), - 100 - self.into_skill().unwrap().effect()[1].get_multiplier(), self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier()), Item::Purge| @@ -862,7 +865,7 @@ impl Item { Item::Silence| Item::SilencePlus | Item::SilencePlusPlus => format!( - "Block the target from using blue skills for {:?}T and deals {:?}% BluePower as blue damage. + "Disable the target from using blue skills for {:?}T and deals {:?}% BluePower as blue damage. Deals 45% more Damage per blue skill on target.", self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().multiplier()), @@ -885,7 +888,7 @@ impl Item { Item::Restrict| Item::RestrictPlus | Item::RestrictPlusPlus => format!( - "Block the target from using red skills for {:?}T and deals {:?}% RedPower as red damage. + "Disable the target from using red skills for {:?}T and deals {:?}% RedPower as red damage. Deals 35% more damage per red skill on target.", self.into_skill().unwrap().effect()[0].get_duration(), self.into_skill().unwrap().multiplier()), @@ -962,10 +965,10 @@ impl Item { Item::AmplifyPlusPlus => vec![Item::AmplifyPlus, Item::AmplifyPlus, Item::AmplifyPlus], Item::Purge => vec![Item::Debuff, Item::Green, Item::Green], // Needs flavour - Item::Invert => vec![Item::Debuff, Item::Red, Item::Blue], + Item::Invert => vec![Item::Debuff, Item::Red, Item::Green], Item::Restrict => vec![Item::Debuff, Item::Red, Item::Red], Item::Silence => vec![Item::Debuff, Item::Blue, Item::Blue], - Item::Curse => vec![Item::Debuff, Item::Red, Item::Green], + Item::Curse => vec![Item::Debuff, Item::Red, Item::Blue], Item::Decay => vec![Item::Debuff, Item::Green, Item::Blue], Item::RestrictPlus => vec![Item::Restrict, Item::Restrict, Item::Restrict], Item::RestrictPlusPlus => vec![Item::RestrictPlus, Item::RestrictPlus, Item::RestrictPlus], diff --git a/server/src/skill.rs b/server/src/skill.rs index 26a7525b..3659a19d 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -765,9 +765,9 @@ impl Skill { Skill::HealPlus => 185, //GG Skill::HealPlusPlus => 270, //GG - Skill::SiphonTick=> 20, // GB - Skill::SiphonTickPlus => 25, - Skill::SiphonTickPlusPlus => 30, + Skill::SiphonTick=> 25, // GB + Skill::SiphonTickPlus => 30, + Skill::SiphonTickPlusPlus => 40, Skill::Slay=> 40, // RG Skill::SlayPlus => 60, @@ -782,9 +782,9 @@ impl Skill { Skill::ElectrocuteTickPlus => 100, Skill::ElectrocuteTickPlusPlus => 130, - Skill::CounterAttack=> 70, - Skill::CounterAttackPlus => 95, - Skill::CounterAttackPlusPlus => 120, + Skill::CounterAttack=> 120, + Skill::CounterAttackPlus => 160, + Skill::CounterAttackPlusPlus => 230, Skill::Purify=> 45, //Green dmg (heal) Skill::PurifyPlus => 70, @@ -803,17 +803,17 @@ impl Skill { Skill::SustainPlusPlus => 230, // Stun Base - Skill::Sleep=> 240, //Green dmg (heal) - Skill::SleepPlus => 300, + Skill::Sleep=> 200, //Green dmg (heal) + Skill::SleepPlus => 290, Skill::SleepPlusPlus => 400, Skill::Banish=> 40, //Green dmg (heal) Skill::BanishPlus => 75, Skill::BanishPlusPlus => 125, - Skill::Bash=> 65, - Skill::BashPlus => 95, - Skill::BashPlusPlus => 140, + Skill::Bash=> 45, + Skill::BashPlus => 65, + Skill::BashPlusPlus => 100, // Debuff Base Skill::DecayTick=> 33, @@ -857,9 +857,9 @@ impl Skill { Skill::BanishPlus => vec![ConstructEffect {effect: Effect::Banish, duration: 2, meta: None, tick: None}], Skill::BanishPlusPlus => vec![ConstructEffect {effect: Effect::Banish, duration: 2, meta: None, tick: None}], Skill::Block => vec![ConstructEffect {effect: Effect::Block, duration: 1, - meta: Some(EffectMeta::Multiplier(50)), tick: None}], + meta: Some(EffectMeta::Multiplier(35)), tick: None}], Skill::Buff => vec![ConstructEffect {effect: Effect::Buff, duration: 2, - meta: Some(EffectMeta::Multiplier(125)), tick: None }], + meta: Some(EffectMeta::Multiplier(130)), tick: None }], Skill::Electrify => vec![ConstructEffect {effect: Effect::Electric, duration: 1, meta: Some(EffectMeta::Skill(Skill::Electrocute)), tick: None}], @@ -931,17 +931,11 @@ impl Skill { Skill::InvertPlusPlus => vec![ConstructEffect {effect: Effect::Invert, duration: 4, meta: None, tick: None}], Skill::Counter => vec![ConstructEffect {effect: Effect::Counter, duration: 1, - meta: Some(EffectMeta::Skill(Skill::CounterAttack)), tick: None}, - ConstructEffect {effect: Effect::Block, duration: 1, - meta: Some(EffectMeta::Multiplier(60)), tick: None}], + meta: Some(EffectMeta::Skill(Skill::CounterAttack)), tick: None}], Skill::CounterPlus => vec![ConstructEffect {effect: Effect::Counter, duration: 1, - meta: Some(EffectMeta::Skill(Skill::CounterAttackPlus)), tick: None}, - ConstructEffect {effect: Effect::Block, duration: 1, - meta: Some(EffectMeta::Multiplier(40)), tick: None}], + meta: Some(EffectMeta::Skill(Skill::CounterAttackPlus)), tick: None}], Skill::CounterPlusPlus => vec![ConstructEffect {effect: Effect::Counter, duration: 1, - meta: Some(EffectMeta::Skill(Skill::CounterAttackPlusPlus)), tick: None}, - ConstructEffect {effect: Effect::Block, duration: 1, - meta: Some(EffectMeta::Multiplier(20)), tick: None}], + meta: Some(EffectMeta::Skill(Skill::CounterAttackPlusPlus)), tick: None}], Skill::Reflect => vec![ConstructEffect {effect: Effect::Reflect, duration: 1, meta: None, tick: None }], Skill::ReflectPlus => vec![ConstructEffect {effect: Effect::Reflect, duration: 1, meta: None, tick: None }], @@ -1060,7 +1054,7 @@ impl Skill { Skill::AmplifyPlusPlus => Some(1), Skill::Hybrid| Skill::HybridPlus | - Skill::HybridPlusPlus => Some(3), + Skill::HybridPlusPlus => Some(1), Skill::Invert=> Some(2), Skill::InvertPlus => Some(2), @@ -1080,7 +1074,7 @@ impl Skill { Skill::LinkPlus => Some(2), Skill::LinkPlusPlus => Some(2), - Skill::Silence=> Some(3), + Skill::Silence=> Some(2), Skill::SilencePlus => Some(2), Skill::SilencePlusPlus => Some(2), @@ -1094,11 +1088,11 @@ impl Skill { Skill::Banish | Skill::BanishPlus | - Skill::BanishPlusPlus => Some(3), + Skill::BanishPlusPlus => Some(2), - Skill::Haste=> Some(2), - Skill::HastePlus => Some(2), - Skill::HastePlusPlus => Some(2), + Skill::Haste=> Some(1), + Skill::HastePlus => Some(1), + Skill::HastePlusPlus => Some(1), Skill::Reflect | Skill::ReflectPlus | @@ -1116,9 +1110,9 @@ impl Skill { Skill::SlayPlus => None, Skill::SlayPlusPlus => None, - Skill::Sleep=> Some(3), - Skill::SleepPlus => Some(3), - Skill::SleepPlusPlus => Some(3), + Skill::Sleep=> Some(2), + Skill::SleepPlus => Some(2), + Skill::SleepPlusPlus => Some(2), Skill::Sustain | Skill::SustainPlus | @@ -1445,10 +1439,6 @@ fn counter(source: &mut Construct, target: &mut Construct, mut results: Resoluti results.push(Resolution::new(source, target) .event(target.add_effect(skill, skill.effect()[0]))); - results.push(Resolution::new(source, target) - .event(target.add_effect(skill, skill.effect()[1])) - .stages(EventStages::PostOnly)); - return results; } From 2617183b33141e7b51d0cf282ad7ed9634a5832e Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 11:36:56 +1000 Subject: [PATCH 32/53] fix curse animation (wouldn't go off if already cast once) --- client/src/components/anims/curse.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/anims/curse.jsx b/client/src/components/anims/curse.jsx index 0747b1c8..f6305e4a 100644 --- a/client/src/components/anims/curse.jsx +++ b/client/src/components/anims/curse.jsx @@ -21,9 +21,9 @@ class Curse extends Component { render() { return ( @@ -64,7 +64,7 @@ class Curse extends Component { targets: ['#curse circle'], r: 0, easing: 'easeInOutSine', - delay: TIMES.TARGET_DURATION_MS / 2, + delay: TIMES.TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS, direction: 'reverse', })); From a254c1d0a71a1cd86c9aa727e02750ee4e47f675 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 11:49:41 +1000 Subject: [PATCH 33/53] client side descriptions, add counterattack anim --- client/src/utils.jsx | 17 +++++++++-------- server/src/skill.rs | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/client/src/utils.jsx b/client/src/utils.jsx index 88719c34..42761a0a 100644 --- a/client/src/utils.jsx +++ b/client/src/utils.jsx @@ -143,6 +143,7 @@ function randomPoints(numPoints, radius, dimensions) { const removeTier = skill => { if (!skill) return skill; + if (skill.includes('CounterAttack')) return 'CounterAttack'; if (skill.includes('SiphonTick')) return 'SiphonTick'; if (skill.includes('TriageTick')) return 'TriageTick'; if (skill.includes('DecayTick')) return 'DecayTick'; @@ -242,17 +243,17 @@ function effectInfo(i) { console.log(i); function multiplier(s) { // Update later to use server info in future - if (s === 'CounterAttack') return 70; - if (s === 'CounterAttack+') return 95; - if (s === 'CounterAttack++') return 120; + if (s === 'CounterAttack') return 120; + if (s === 'CounterAttack+') return 160; + if (s === 'CounterAttack++') return 230; if (s === 'DecayTick') return 33; if (s === 'DecayTick+') return 45; if (s === 'DecayTick++') return 70; - if (s === 'SiphonTick') return 20; - if (s === 'SiphonTick+') return 25; - if (s === 'SiphonTick++') return 30; + if (s === 'SiphonTick') return 25; + if (s === 'SiphonTick+') return 30; + if (s === 'SiphonTick++') return 40; if (s === 'TriageTick') return 75; if (s === 'TriageTick+') return 110; @@ -267,8 +268,8 @@ function effectInfo(i) { switch (i.effect) { case 'Amplify': return `Increases construct RedPower and BluePower by ${i.meta[1] - 100}%`; case 'Banish': return 'Banished construct cannot cast or take damage'; - case 'Block': return `Reduces construct red damage taken by ${100 - i.meta[1]}%`; - case 'Buff': return `Increases construct RedPower and SpeedStat by ${i.meta[1] - 100}%`; + case 'Block': return `Reduces construct red damage and blue damage taken by ${100 - i.meta[1]}%`; + case 'Buff': return `Increases construct RedPower BluePower SpeedStat by ${i.meta[1] - 100}%`; case 'Sustain': return 'Construct cannot be KO while active. Additionally provides immunity to disables'; case 'Curse': return `Construct will take ${i.meta[1] - 100}% increased red and blue damage`; case 'Haste': return `Construct has ${i.meta[1] - 100}% increased SpeedStat. Red attack skills will trigger a HasteStrike dealing 30% SpeedStat as red damage.`; diff --git a/server/src/skill.rs b/server/src/skill.rs index 3659a19d..6cbb383e 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -1446,7 +1446,7 @@ fn counter_attack(source: &mut Construct, target: &mut Construct, mut results: R let amount = source.red_power().pct(skill.multiplier()); target.deal_red_damage(skill, amount) .into_iter() - .for_each(|e| results.push(Resolution::new(source, target).event(e).stages(EventStages::StartPost))); + .for_each(|e| results.push(Resolution::new(source, target).event(e))); return results; } From 663faa2b2484752a65df4ba8aa375193cd94d75b Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 12:14:20 +1000 Subject: [PATCH 34/53] replace single quotes with double quotes (was causing curse to bug out) --- client/src/components/anims/blast.jsx | 2 +- client/src/components/anims/buff.jsx | 2 +- client/src/components/anims/chaos.jsx | 2 +- client/src/components/anims/counter.jsx | 4 ++-- client/src/components/anims/debuff.jsx | 2 +- client/src/components/anims/decay.jsx | 2 +- client/src/components/anims/electrify.jsx | 2 +- client/src/components/anims/electrocute.jsx | 2 +- client/src/components/anims/haste.jsx | 2 +- client/src/components/anims/heal.jsx | 4 ++-- client/src/components/anims/hex.jsx | 2 +- client/src/components/anims/hybrid.jsx | 4 ++-- client/src/components/anims/intercept.jsx | 2 +- client/src/components/anims/link.jsx | 2 +- client/src/components/anims/purge.jsx | 2 +- client/src/components/anims/purify.jsx | 2 +- client/src/components/anims/recharge.jsx | 2 +- client/src/components/anims/red.block.jsx | 2 +- client/src/components/anims/red.circles.jsx | 2 +- client/src/components/anims/reflect.jsx | 2 +- client/src/components/anims/restrict.jsx | 2 +- client/src/components/anims/ruin.jsx | 2 +- client/src/components/anims/silence.jsx | 2 +- client/src/components/anims/sleep.jsx | 2 +- client/src/components/anims/strike.jsx | 2 +- client/src/components/anims/stun.jsx | 2 +- client/src/components/anims/sustain.jsx | 2 +- client/src/components/anims/triage.jsx | 4 ++-- client/src/components/anims/triage.tick.jsx | 4 ++-- 29 files changed, 34 insertions(+), 34 deletions(-) diff --git a/client/src/components/anims/blast.jsx b/client/src/components/anims/blast.jsx index 21d985fa..c11bdc95 100644 --- a/client/src/components/anims/blast.jsx +++ b/client/src/components/anims/blast.jsx @@ -36,7 +36,7 @@ class Blast extends Component { render() { return ( - + diff --git a/client/src/components/anims/counter.jsx b/client/src/components/anims/counter.jsx index 0ae9d709..e19d3518 100644 --- a/client/src/components/anims/counter.jsx +++ b/client/src/components/anims/counter.jsx @@ -21,13 +21,13 @@ class Counter extends Component { render({ team }) { return ( - + diff --git a/client/src/components/anims/debuff.jsx b/client/src/components/anims/debuff.jsx index 0f68d33d..14bbab7a 100644 --- a/client/src/components/anims/debuff.jsx +++ b/client/src/components/anims/debuff.jsx @@ -21,7 +21,7 @@ class Debuff extends Component { render() { return ( diff --git a/client/src/components/anims/hex.jsx b/client/src/components/anims/hex.jsx index c279225d..fb31b373 100644 --- a/client/src/components/anims/hex.jsx +++ b/client/src/components/anims/hex.jsx @@ -23,7 +23,7 @@ class Hex extends Component { render() { return ( diff --git a/client/src/components/anims/intercept.jsx b/client/src/components/anims/intercept.jsx index 1edb45a1..5049febf 100644 --- a/client/src/components/anims/intercept.jsx +++ b/client/src/components/anims/intercept.jsx @@ -25,7 +25,7 @@ class Intercept extends Component { render() { return ( diff --git a/client/src/components/anims/triage.tick.jsx b/client/src/components/anims/triage.tick.jsx index afeb6034..ecda83f1 100644 --- a/client/src/components/anims/triage.tick.jsx +++ b/client/src/components/anims/triage.tick.jsx @@ -37,8 +37,8 @@ class TriageTick extends Component { render() { return ( From d665eec8a74d2d800f7f62ff86caccde7de7ae86 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 12:28:36 +1000 Subject: [PATCH 35/53] changelog --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4283869..59f027bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,10 +21,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Game phase - Made general performance improvements - - Now has default tutorial text for the first round - - Will tell the player to select skills and then the targets + - Now has default tutorial text for the first round (tells the player to select skills and then the targets) -# Skill Balance Updates - Buff - Previously increased red power and speed stat by 25% - Now increases red power, blue power and speed stat by 30% @@ -36,6 +34,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Counter - No longer applies block effect - CounterAttack multiplier increased from 70/95/120 -> 120/160/230 + - Will now animate an attack animation on counter attack + - Haste - Cooldown reduced to 1T (was 2T) - Sleep @@ -54,6 +54,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Curse - Now created by combining Debuff + RB was Debuff + RG - Fixed issue where curse was only increasing blue damage taken instead of red and blue + - Fixed an issue where the animation would not display if it occured already - Invert - Now created by combining Debuff + RG was debuff + RB From 75f4c6236a8ac7f1f0f577217b6baefbad607519 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 13:05:19 +1000 Subject: [PATCH 36/53] separate out demo tab --- CHANGELOG.md | 8 +++++ client/src/components/anims/counter.jsx | 2 +- client/src/components/demo.jsx | 18 +++++----- client/src/components/welcome.jsx | 47 ++++++++++++++----------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f027bf..e86d66ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,23 +38,31 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Haste - Cooldown reduced to 1T (was 2T) + - Sleep - Cooldown reduced to 2T (was 3T) - Skill multiplier reduced from 240/300/400 -> 200/290/400 + - Hybrid - Cooldown reduced to 1T (was 3T) + - Silence - Cooldown reduced to 2T (was 3T) + - Banish - Cooldown reduced to 2T (was 3T) + - Siphon - Skill multiplier increased from 20/25/30 -> 25/30/40 + - Bash - Skill multiplier reduced from 65/95/140 -> 45/65/100 + - Curse - Now created by combining Debuff + RB was Debuff + RG - Fixed issue where curse was only increasing blue damage taken instead of red and blue - Fixed an issue where the animation would not display if it occured already + - Invert - Now created by combining Debuff + RG was debuff + RB diff --git a/client/src/components/anims/counter.jsx b/client/src/components/anims/counter.jsx index e19d3518..ec7a0399 100644 --- a/client/src/components/anims/counter.jsx +++ b/client/src/components/anims/counter.jsx @@ -60,7 +60,7 @@ class Counter extends Component { this.animations.push(anime({ targets: ['#counter'], rotateX: 180, - delay: TIMES.TARGET_DELAY_MS * 2, + delay: TIMES.TARGET_DELAY_MS + TIMES.TARGET_DURATION_MS / 3, duration: TIMES.TARGET_DURATION_MS / 2, easing: 'easeOutSine', })); diff --git a/client/src/components/demo.jsx b/client/src/components/demo.jsx index 57c814ee..6735998e 100644 --- a/client/src/components/demo.jsx +++ b/client/src/components/demo.jsx @@ -1,11 +1,11 @@ const { connect } = require('preact-redux'); const preact = require('preact'); -const actions = require('../actions'); +// const actions = require('../actions'); const shapes = require('./shapes'); const { ConstructAvatar } = require('./construct'); -const { ConstructAnimation } = require('./animations'); +// const { ConstructAnimation } = require('./animations'); const addState = connect( function receiveState(state) { @@ -20,15 +20,15 @@ const addState = connect( itemInfo, demo, }; - }, + } - function receiveDispatch(dispatch) { +/* function receiveDispatch(dispatch) { function setAnimTarget(anim) { dispatch(actions.setAnimTarget(anim)); } return { setAnimTarget }; - } + } */ ); @@ -38,7 +38,7 @@ function Demo(args) { itemInfo, account, - setAnimTarget, + // setAnimTarget, } = args; if (!demo || !itemInfo.items.length || account) return false; @@ -90,7 +90,7 @@ function Demo(args) { VBOX PHASE {shapes.Red()} {shapes.Green()} {shapes.Blue()}

- Combine the colour base items with an array of skills and specialisations to build powerful variants. + Combine the colour base items with skills and specialisations to build an array of powerful variants.

 
@@ -179,10 +179,10 @@ function Demo(args) { }; return ( -
+
+ {gameDemo()} {vboxDemo()} {vboxConstructs()} - {gameDemo()}
); } diff --git a/client/src/components/welcome.jsx b/client/src/components/welcome.jsx index 558e5719..2a1bfa67 100644 --- a/client/src/components/welcome.jsx +++ b/client/src/components/welcome.jsx @@ -10,7 +10,6 @@ const Demo = require('./demo'); function Welcome() { const page = this.state.page || 'register'; - const navRegister = () => this.setState({ page: 'register' }); const pageEl = () => { if (page === 'login') return ; if (page === 'register') return ; @@ -18,6 +17,26 @@ function Welcome() { return false; }; + const news = ( +
+

Welcome to mnml.

+ +

MNML is a turn-based 1v1 strategy game in an abstract setting.

+

+ Build a unique team of 3 constructs from a range of skills and specialisations.
+ Outplay your opponent in multiple rounds by adapting to an always shifting meta.
+ Simple rules, complex interactions and unique mechanics.
+

+

Free to play, no pay to win. Register to start playing.

+ + Tutorial Playthrough on YouTube +
+ ); + + const main = (['login', 'register', 'help'].includes(page)) + ?
{news}{pageEl()}
+ : ; + return (
@@ -39,6 +58,12 @@ function Welcome() { onClick={() => this.setState({ page: 'register' })}> Register +
-
-
-

- Welcome to mnml. -

-

MNML is a turn-based 1v1 strategy game in an abstract setting.

-

- Build a unique team of 3 constructs from a range of skills and specialisations.
- Outplay your opponent in multiple rounds by adapting to an always shifting meta.
- Simple rules, complex interactions and unique mechanics.
-

-

- Free to play, no pay to win. Register to start playing.
-

- Tutorial Playthrough on YouTube -
- {pageEl()} -
+ {main}
-
); } From 0c3cd46ce2c4084cecb96383be9b95d5c6b35c17 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 13:33:24 +1000 Subject: [PATCH 37/53] speed up the demo --- client/src/events.jsx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/src/events.jsx b/client/src/events.jsx index f088d4e7..5c10e2e3 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -247,13 +247,13 @@ function registerEvents(store) { if (account) return false; store.dispatch(actions.setDemo(initial)); store.dispatch(actions.setAnimTarget(null)); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0] }))), 2000); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1] }))), 4000); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1, 2] }))), 6000); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['Strike', '', ''] }))), 8000); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0], items: ['Strike', '', ''], equipping: true }))), 10000); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['', '', ''], equipped: true, equipping: false }))), 12000); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { items: ['', '', ''], equipped: true, equipping: false }))), 12000); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0] }))), 500); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1] }))), 1000); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1, 2] }))), 1500); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['Strike', '', ''] }))), 2500); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0], items: ['Strike', '', ''], equipping: true }))), 3500); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['', '', ''], equipped: true, equipping: false }))), 4250); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { items: ['', '', ''], equipped: true, equipping: false }))), 4250); setTimeout(() => { const { itemInfo } = store.getState(); @@ -263,7 +263,7 @@ function registerEvents(store) { player: false, direction: 0, })); - }, 14000); + }, 1000); setTimeout(() => { const { itemInfo } = store.getState(); @@ -273,9 +273,9 @@ function registerEvents(store) { player: true, direction: 0, })); - }, 16000); + }, 3000); - setTimeout(startDemo, 20000); + setTimeout(startDemo, 6000); }; startDemo(); From 188ae0de6a5220ba39751eba9034dc245b2f21a3 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 16:11:00 +1000 Subject: [PATCH 38/53] vbox demo generate random skill combos, disable part of broken curse anim --- client/src/components/demo.jsx | 6 +++--- client/src/events.jsx | 33 ++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/client/src/components/demo.jsx b/client/src/components/demo.jsx index 6735998e..45dcf71d 100644 --- a/client/src/components/demo.jsx +++ b/client/src/components/demo.jsx @@ -43,7 +43,7 @@ function Demo(args) { if (!demo || !itemInfo.items.length || account) return false; - const { combiner, items, equipping, equipped, players } = demo; + const { combiner, items, equipping, equipped, players, combo } = demo; const vboxDemo = () => { function inventoryBtn(i, j) { @@ -90,7 +90,7 @@ function Demo(args) { VBOX PHASE {shapes.Red()} {shapes.Green()} {shapes.Blue()}

- Combine the colour base items with skills and specialisations to build an array of powerful variants. + Combine colours with base skills and specialisations to build an array of powerful variants.

 
@@ -122,7 +122,7 @@ function Demo(args) {
{equipped - ? + ? : } diff --git a/client/src/events.jsx b/client/src/events.jsx index 5c10e2e3..a957b380 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -234,39 +234,42 @@ function registerEvents(store) { function setDemo(d) { - const initial = { + const vboxDemo = { players: d, combiner: [], - items: ['Red', 'Red', 'Attack'], equipped: false, equipping: false, }; const startDemo = () => { - const { account } = store.getState(); + const { account, itemInfo } = store.getState(); if (account) return false; - store.dispatch(actions.setDemo(initial)); + if (!itemInfo || itemInfo.items.length === 0) return setTimeout(startDemo, 500); store.dispatch(actions.setAnimTarget(null)); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0] }))), 500); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1] }))), 1000); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0, 1, 2] }))), 1500); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['Strike', '', ''] }))), 2500); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [0], items: ['Strike', '', ''], equipping: true }))), 3500); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { combiner: [], items: ['', '', ''], equipped: true, equipping: false }))), 4250); - setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, initial, { items: ['', '', ''], equipped: true, equipping: false }))), 4250); + const bases = ['Attack', 'Stun', 'Buff', 'Debuff', 'Block']; + const combo = sample(itemInfo.combos.filter(i => bases.some(b => i.components.includes(b)))); + vboxDemo.combo = combo.item; + vboxDemo.items = combo.components; + store.dispatch(actions.setDemo(vboxDemo)); + + + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0] }))), 500); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0, 1] }))), 1000); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0, 1, 2] }))), 1500); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [], items: [vboxDemo.combo, '', ''] }))), 2500); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [0], items: [vboxDemo.combo, '', ''], equipping: true }))), 3000); + setTimeout(() => store.dispatch(actions.setDemo(Object.assign({}, vboxDemo, { combiner: [], items: ['', '', ''], equipped: true, equipping: false }))), 4000); setTimeout(() => { - const { itemInfo } = store.getState(); return store.dispatch(actions.setAnimTarget({ skill: sample(itemInfo.items.filter(i => i.skill)).item, constructId: d[1].constructs[0].id, player: false, direction: 0, })); - }, 1000); + }, 500); setTimeout(() => { - const { itemInfo } = store.getState(); return store.dispatch(actions.setAnimTarget({ skill: sample(itemInfo.items.filter(i => i.skill)).item, constructId: d[1].constructs[1].id, @@ -275,7 +278,7 @@ function registerEvents(store) { })); }, 3000); - setTimeout(startDemo, 6000); + return setTimeout(startDemo, 5000); }; startDemo(); From 8ce7edd8415d20a80a1bdb6b65e3e4706b8a215d Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 17:32:22 +1000 Subject: [PATCH 39/53] actually fix curse (anime doesn't seem to reset 'reverse') --- client/src/components/anims/curse.jsx | 35 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/client/src/components/anims/curse.jsx b/client/src/components/anims/curse.jsx index f6305e4a..d186a4d3 100644 --- a/client/src/components/anims/curse.jsx +++ b/client/src/components/anims/curse.jsx @@ -36,15 +36,15 @@ class Curse extends Component { - - - + + + - - - + + + ); @@ -61,12 +61,27 @@ class Curse extends Component { })); this.animations.push(anime({ - targets: ['#curse circle'], - r: 0, + targets: ['#curseCircleOne', '#curseFilterOne'], + r: 30, easing: 'easeInOutSine', - delay: TIMES.TIMES.TARGET_DELAY_MS, + delay: TIMES.TARGET_DELAY_MS, + duration: TIMES.TARGET_DURATION_MS, + })); + + this.animations.push(anime({ + targets: ['#curseCircleTwo', '#curseFilterTwo'], + r: 60, + easing: 'easeInOutSine', + delay: TIMES.TARGET_DELAY_MS, + duration: TIMES.TARGET_DURATION_MS, + })); + + this.animations.push(anime({ + targets: ['#curseCircleThree', '#curseFilterThree'], + r: 90, + easing: 'easeInOutSine', + delay: TIMES.TARGET_DELAY_MS, duration: TIMES.TARGET_DURATION_MS, - direction: 'reverse', })); } From 83a87a64e3dbac1561c5031cdd88093e454b05c1 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 17:49:32 +1000 Subject: [PATCH 40/53] add inventory info hover if you have 1 or less items in inventory --- CHANGELOG.md | 3 +++ client/src/components/vbox.component.jsx | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e86d66ca..b638b666 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Step by step tutorial - Will activate during the learn game for the first round - There is a button which will exit tutorial so you can continune the normal practice mode + - Skill combo previews - You can now preview what item combos will create! - Click into the item in the info section table (top right) and it will be replaced with the new item @@ -23,6 +24,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Made general performance improvements - Now has default tutorial text for the first round (tells the player to select skills and then the targets) +- Moved the login page demo to a new info tab, increased the speed of demo and it now creates random combos + - Buff - Previously increased red power and speed stat by 25% - Now increases red power, blue power and speed stat by 30% diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index c2c1a51a..81155b66 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -404,9 +404,12 @@ class Vbox extends preact.Component { return true; } + const inventoryHover = vbox.bound.length > 1 ? false : e => hoverInfo(e, 'inventory'); + return (
e.stopPropagation()} style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null}>
From 39be7b952f48943002edb478027766cf32365c73 Mon Sep 17 00:00:00 2001 From: Mashy Date: Tue, 29 Oct 2019 18:36:15 +1000 Subject: [PATCH 41/53] don't sort vbox after combine --- server/src/vbox.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/vbox.rs b/server/src/vbox.rs index c8df2087..162f48de 100644 --- a/server/src/vbox.rs +++ b/server/src/vbox.rs @@ -169,7 +169,7 @@ impl Vbox { let combo = combos.iter().find(|c| c.components == input).ok_or(err_msg("not a combo"))?; self.bound.push(combo.item); - self.bound.sort_unstable(); + // self.bound.sort_unstable(); Ok(self) } From 0009e1fb5bfea7e9b2a5065749f6e873b2d4d08d Mon Sep 17 00:00:00 2001 From: Mashy Date: Wed, 30 Oct 2019 13:17:06 +1000 Subject: [PATCH 42/53] tutorial text, vbox hover inventory --- client/src/components/vbox.component.jsx | 2 +- client/src/tutorial.utils.jsx | 48 ++++++++++++++---------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 81155b66..1727850d 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -404,7 +404,7 @@ class Vbox extends preact.Component { return true; } - const inventoryHover = vbox.bound.length > 1 ? false : e => hoverInfo(e, 'inventory'); + const inventoryHover = vbox.bound.length > 1 || vboxSelected[0] ? false : e => hoverInfo(e, 'inventory'); return (

Tutorial

-

This is the vbox phase tutorial.

-

The game revolves around combining colours with items to create skills and specs.

-

Buy two colours from the vbox by double clicking or click the colour once and then the inventory.

+

Welcome to the vbox phase tutorial.

+

Colours are used to create powerful combinations.

+

Buy two colours from the vbox by double clicking.
+ You can also click the colour once and then click the inventory.

); } @@ -120,19 +121,24 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) { return (

Tutorial

-

In a normal game you start with 3 Attack Skill items.

-

These can be combined with colours to create powerful combinations.

-

Select the Attack item along with two colours and press combine.

+

In a normal game you start with three base Attack skill items.

+

The Attack item can be combined with colours to create a new skill.

+

Select the Attack item along with two colours.
+ When all three items are selected you can then press combine. +

); } if (tutorial === 3) { + const constructOne = instance.players[0].constructs[0].name; return (

Tutorial

-

Skill items can be equipped to your constructs to give them that ability for the combat phase.

-

Click the newly combined skill item in the inventory and then the construct at the bottom to equip the skill.

+

The first construct on your team is {constructOne}.

+

Skill items can be equipped to your constructs to be used in the combat phase.

+

Click the newly combined skill item in the top right of the inventory.
+ Once selected click the construct SKILL slot to equip the skill.

); } @@ -141,8 +147,10 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) { return (

Tutorial

-

You can also buy spec items to increase the stats of your constructs.

-

Buy the spec item by double clicking or click the spec once and then the inventory.

+

You can also buy specialisation items for your constructs.
+ Specialisation items increase stats including power, speed and life.

+

Buy the specialisation item from the vbox by double clicking.
+ You can also click the specialisation once and then click the inventory.

); } @@ -151,9 +159,10 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) { return (

Tutorial

-

Equipping spec items will increase the stats of your constructs.

-

These can also be combined with colours for more specialisation.

-

Click the spec item in the inventory followed by an empty inventory spec slot to equip the spec.

+

Equipping specialisation items will increase the stats of your constructs.

+

These can also be combined with colours for further specialisation.

+

Click the specialisation item in the top right of the inventory.
+ Once selected click the construct SPEC slot to equip the specialisation.

); } @@ -165,10 +174,9 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {

Tutorial

You have now created a construct with an upgraded skill and base spec.

-

You can unequip skills and specs back into the inventory by double clicking or clicking once and then the inventory.

The goal is to create three powerful constructs for combat.

-

Equip {constructTwo} and {constructThree} with the Attack skill.
- Ensure each construct has a single skill to continue

+

Equip your other constructs {constructTwo} and {constructThree} with the Attack skill.
+ Ensure each construct has a single skill to continue.

); } @@ -192,10 +200,10 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) { return (

Tutorial

-

You can now freely create different skill and spec combos.

-

Reclaim is used only if needed to refund items in your inventory.
- If you click the exit tutorial button this section will be replaced with more information on selected items.

-

When ready, you can go into the combat phase by hitting ready in the bottom right.

+

You've completed the tutorial! Try to create more skill and spec combinations.

+

You can unequip skills and specs back into the inventory by double clicking.
+ Reclaim can be used to refund the cost of items in your inventory.

+

Click the EXIT TUTORIAL button to replace this section with more information.

); } From 2c77d035bd6afe52244572be78dad01f02be31e0 Mon Sep 17 00:00:00 2001 From: Mashy Date: Wed, 30 Oct 2019 14:14:57 +1000 Subject: [PATCH 43/53] moar haste / hybrid buffs --- CHANGELOG.md | 2 ++ server/src/skill.rs | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b638b666..d8a3d7a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Haste - Cooldown reduced to 1T (was 2T) + - Duration increased from 2/3/4T -> 3/4/5T - Sleep - Cooldown reduced to 2T (was 3T) @@ -48,6 +49,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Hybrid - Cooldown reduced to 1T (was 3T) + - Duration increased from 2/3/4T -> 3/4/5T - Silence - Cooldown reduced to 2T (was 3T) diff --git a/server/src/skill.rs b/server/src/skill.rs index 6cbb383e..340b7185 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -815,6 +815,9 @@ impl Skill { Skill::BashPlus => 65, Skill::BashPlusPlus => 100, + Skill::Link=> 75, + Skill::LinkPlus => 100, + Skill::LinkPlusPlus => 150, // Debuff Base Skill::DecayTick=> 33, Skill::DecayTickPlus => 45, @@ -828,13 +831,13 @@ impl Skill { // Buff base Skill::HybridBlast => 25, + Skill::HasteStrike => 30, - Skill::Link=> 75, - Skill::LinkPlus => 100, - Skill::LinkPlusPlus => 150, + Skill::Intercept=> 80, Skill::InterceptPlus => 110, Skill::InterceptPlusPlus => 150, + Skill::TriageTick=> 75, Skill::TriageTickPlus => 110, Skill::TriageTickPlusPlus => 140, @@ -901,11 +904,11 @@ impl Skill { ConstructEffect {effect: Effect::Decay, duration: 4, meta: Some(EffectMeta::Skill(Skill::DecayTickPlusPlus)), tick: None}], - Skill::Haste => vec![ConstructEffect {effect: Effect::Haste, duration: 2, + Skill::Haste => vec![ConstructEffect {effect: Effect::Haste, duration: 3, meta: Some(EffectMeta::Multiplier(150)), tick: None }], - Skill::HastePlus => vec![ConstructEffect {effect: Effect::Haste, duration: 3, + Skill::HastePlus => vec![ConstructEffect {effect: Effect::Haste, duration: 4, meta: Some(EffectMeta::Multiplier(175)), tick: None }], - Skill::HastePlusPlus => vec![ConstructEffect {effect: Effect::Haste, duration: 4, + Skill::HastePlusPlus => vec![ConstructEffect {effect: Effect::Haste, duration: 5, meta: Some(EffectMeta::Multiplier(225)), tick: None }], Skill::Absorb => vec![ConstructEffect {effect: Effect::Absorb, duration: 2, @@ -919,11 +922,11 @@ impl Skill { Skill::AbsorptionPlus => vec![ConstructEffect {effect: Effect::Absorption, duration: 5, meta: None, tick: None}], Skill::AbsorptionPlusPlus => vec![ConstructEffect {effect: Effect::Absorption, duration: 7, meta: None, tick: None}], - Skill::Hybrid => vec![ConstructEffect {effect: Effect::Hybrid, duration: 2, + Skill::Hybrid => vec![ConstructEffect {effect: Effect::Hybrid, duration: 3, meta: Some(EffectMeta::Multiplier(150)), tick: None }], - Skill::HybridPlus => vec![ConstructEffect {effect: Effect::Hybrid, duration: 3, + Skill::HybridPlus => vec![ConstructEffect {effect: Effect::Hybrid, duration: 4, meta: Some(EffectMeta::Multiplier(175)), tick: None }], - Skill::HybridPlusPlus => vec![ConstructEffect {effect: Effect::Hybrid, duration: 4, + Skill::HybridPlusPlus => vec![ConstructEffect {effect: Effect::Hybrid, duration: 5, meta: Some(EffectMeta::Multiplier(225)), tick: None }], Skill::Invert => vec![ConstructEffect {effect: Effect::Invert, duration: 2, meta: None, tick: None}], From 31bfffab26c280526b5b901a953b42241dedc662 Mon Sep 17 00:00:00 2001 From: Mashy Date: Wed, 30 Oct 2019 15:34:58 +1000 Subject: [PATCH 44/53] remove inventory hover text again, buff hybridblast / hastestrike dmg --- CHANGELOG.md | 2 ++ client/src/components/vbox.component.jsx | 3 --- server/src/skill.rs | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8a3d7a5..afef43f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Haste - Cooldown reduced to 1T (was 2T) - Duration increased from 2/3/4T -> 3/4/5T + - HasteStrike damage multiplier changed from 30% -> 60% - Sleep - Cooldown reduced to 2T (was 3T) @@ -50,6 +51,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Hybrid - Cooldown reduced to 1T (was 3T) - Duration increased from 2/3/4T -> 3/4/5T + - HybridBlast damage multiplier changed from 25% -> 50% - Silence - Cooldown reduced to 2T (was 3T) diff --git a/client/src/components/vbox.component.jsx b/client/src/components/vbox.component.jsx index 1727850d..c2c1a51a 100644 --- a/client/src/components/vbox.component.jsx +++ b/client/src/components/vbox.component.jsx @@ -404,12 +404,9 @@ class Vbox extends preact.Component { return true; } - const inventoryHover = vbox.bound.length > 1 || vboxSelected[0] ? false : e => hoverInfo(e, 'inventory'); - return (
e.stopPropagation()} style={vboxSelecting || (itemUnequip.length) ? { cursor: 'pointer' } : null}>
diff --git a/server/src/skill.rs b/server/src/skill.rs index 340b7185..0b37d3e2 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -830,9 +830,9 @@ impl Skill { Skill::RestrictPlusPlus => 100, // Buff base - Skill::HybridBlast => 25, + Skill::HybridBlast => 50, - Skill::HasteStrike => 30, + Skill::HasteStrike => 60, Skill::Intercept=> 80, Skill::InterceptPlus => 110, From ea6936940aeb8d10a5ab662734d54b34b5047e0a Mon Sep 17 00:00:00 2001 From: Mashy Date: Wed, 30 Oct 2019 15:45:59 +1000 Subject: [PATCH 45/53] 50% slay self heal increase dmg, minor blast nerf --- CHANGELOG.md | 21 ++++++++++++++------- server/src/item.rs | 4 ++-- server/src/skill.rs | 14 +++++++------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afef43f6..df885c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,14 +26,17 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Moved the login page demo to a new info tab, increased the speed of demo and it now creates random combos -- Buff - - Previously increased red power and speed stat by 25% - - Now increases red power, blue power and speed stat by 30% +- Blast + - Damage multiplier reduced 110/145/210 -> 105/140/200 - Block - Previously reduced red damage taken by 50% - Now reduces red damage and blue damage taken by 65% +- Buff + - Previously increased red power and speed stat by 25% + - Now increases red power, blue power and speed stat by 30% + - Counter - No longer applies block effect - CounterAttack multiplier increased from 70/95/120 -> 120/160/230 @@ -44,10 +47,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Duration increased from 2/3/4T -> 3/4/5T - HasteStrike damage multiplier changed from 30% -> 60% -- Sleep - - Cooldown reduced to 2T (was 3T) - - Skill multiplier reduced from 240/300/400 -> 200/290/400 - - Hybrid - Cooldown reduced to 1T (was 3T) - Duration increased from 2/3/4T -> 3/4/5T @@ -56,6 +55,14 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Silence - Cooldown reduced to 2T (was 3T) +- Slay + - Self healing is now 50% of damage dealt to green life (was 100%) + - Damage multiplier increased from (40/60/90)% -> (45/65/100%)% + +- Sleep + - Cooldown reduced to 2T (was 3T) + - Skill multiplier reduced from 240/300/400 -> 200/290/400 + - Banish - Cooldown reduced to 2T (was 3T) diff --git a/server/src/item.rs b/server/src/item.rs index b697828a..52b3bb8b 100644 --- a/server/src/item.rs +++ b/server/src/item.rs @@ -874,7 +874,7 @@ impl Item { Item::SlayPlus | Item::SlayPlusPlus => format!( "Deals {:?}% RedPower + {:?}% GreenPower as red damage. - Provides self healing based on damage dealt.", + Construct heals self for 50% of damage dealt to target construct GreenLife.", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().multiplier()), @@ -912,7 +912,7 @@ impl Item { Item::SiphonPlus | Item::SiphonPlusPlus => format!( "Deals {:?}% BluePower + {:?}% GreenPower as blue damage each turn. - Heals caster based on damage dealt. + Construct heals self for 100% of damage dealt to target construct GreenLife. Lasts {:?}T.", self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier(), self.into_skill().unwrap().effect()[0].get_skill().unwrap().multiplier(), diff --git a/server/src/skill.rs b/server/src/skill.rs index 0b37d3e2..9c02408f 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -753,9 +753,9 @@ impl Skill { // Attack Base Skill::Attack => 80, // Base - Skill::Blast=> 110, // BB - Skill::BlastPlus => 145, // BB - Skill::BlastPlusPlus => 210, // BB + Skill::Blast=> 105, // BB + Skill::BlastPlus => 140, // BB + Skill::BlastPlusPlus => 200, // BB Skill::Chaos=> 40, // BR Skill::ChaosPlus => 65, // BR @@ -769,9 +769,9 @@ impl Skill { Skill::SiphonTickPlus => 30, Skill::SiphonTickPlusPlus => 40, - Skill::Slay=> 40, // RG - Skill::SlayPlus => 60, - Skill::SlayPlusPlus => 90, + Skill::Slay=> 45, // RG + Skill::SlayPlus => 65, + Skill::SlayPlusPlus => 100, Skill::Strike=> 90, //RR Skill::StrikePlus => 140, @@ -1482,7 +1482,7 @@ fn slay(source: &mut Construct, target: &mut Construct, mut results: Resolutions match e { Event::Damage { amount, mitigation: _, colour: _, skill: _ } => { results.push(Resolution::new(source, target).event(e)); - let heal = source.deal_green_damage(skill, amount); + let heal = source.deal_green_damage(skill, amount.pct(50)); for h in heal { results.push(Resolution::new(source, source).event(h).stages(EventStages::PostOnly)); }; From e4f091b2b8184e14c2fe6ad8aa4f20dbcd648705 Mon Sep 17 00:00:00 2001 From: Mashy Date: Wed, 30 Oct 2019 18:02:50 +1000 Subject: [PATCH 46/53] more description improvements --- CHANGELOG.md | 36 +++++++++++++----------- client/src/components/info.component.jsx | 5 +++- client/src/components/shapes.jsx | 4 ++- client/src/constants.jsx | 17 ++++------- client/src/tutorial.utils.jsx | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df885c50..8960d207 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Moved the login page demo to a new info tab, increased the speed of demo and it now creates random combos +- Banish + - Cooldown reduced to 2T (was 3T) + +- Bash + - Skill multiplier reduced from 65/95/140 -> 45/65/100 + - Blast - Damage multiplier reduced 110/145/210 -> 105/140/200 @@ -42,6 +48,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). - CounterAttack multiplier increased from 70/95/120 -> 120/160/230 - Will now animate an attack animation on counter attack +- Curse + - Now created by combining Debuff + RB was Debuff + RG + - Fixed issue where curse was only increasing blue damage taken instead of red and blue + - Fixed an issue where the animation would not display if it occured already + - Haste - Cooldown reduced to 1T (was 2T) - Duration increased from 2/3/4T -> 3/4/5T @@ -52,33 +63,24 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Duration increased from 2/3/4T -> 3/4/5T - HybridBlast damage multiplier changed from 25% -> 50% +- Invert + - Now created by combining Debuff + RG was debuff + RB + - Silence - Cooldown reduced to 2T (was 3T) +- Siphon + - Skill multiplier increased from 20/25/30 -> 25/30/40 + - Reworded part of description "Construct heals self for 100% of damage dealt to target construct GreenLife." + - Slay - Self healing is now 50% of damage dealt to green life (was 100%) - - Damage multiplier increased from (40/60/90)% -> (45/65/100%)% + - Damage multiplier increased from (40/60/90)% -> (45/65/100)% - Sleep - Cooldown reduced to 2T (was 3T) - Skill multiplier reduced from 240/300/400 -> 200/290/400 -- Banish - - Cooldown reduced to 2T (was 3T) - -- Siphon - - Skill multiplier increased from 20/25/30 -> 25/30/40 - -- Bash - - Skill multiplier reduced from 65/95/140 -> 45/65/100 - -- Curse - - Now created by combining Debuff + RB was Debuff + RG - - Fixed issue where curse was only increasing blue damage taken instead of red and blue - - Fixed an issue where the animation would not display if it occured already - -- Invert - - Now created by combining Debuff + RG was debuff + RB ## [1.6.6] - 2019-10-27 # Added diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 6a1689dd..8bb4b5db 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -204,7 +204,10 @@ class InfoComponent extends preact.Component { ); } const cost = fullInfo.cost ? `- ${fullInfo.cost}b` : false; - const infoDescription = reactStringReplace(fullInfo.description, '\n', () =>
); + + const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat|POWER|SPEED|LIFE)/; + let infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); + infoDescription = reactStringReplace(infoDescription, '\n', () =>
); return (

{fullInfo.item} {cost}

diff --git a/client/src/components/shapes.jsx b/client/src/components/shapes.jsx index a8a20ed8..454e51fe 100644 --- a/client/src/components/shapes.jsx +++ b/client/src/components/shapes.jsx @@ -35,7 +35,9 @@ module.exports = { BluePower: () => circle(['blue']), SpeedStat: () => triangle(['white']), - + POWER: () => circle(['white']), + LIFE: () => square(['white']), + SPEED: () => triangle(['white']), // specs // Base diff --git a/client/src/constants.jsx b/client/src/constants.jsx index afc53c74..bf370e14 100644 --- a/client/src/constants.jsx +++ b/client/src/constants.jsx @@ -60,30 +60,23 @@ module.exports = { }, constructSkills: { item: 'SKILLS', - description:

Skills are used by constructs in the game phase.
- Base skills can be bought from the VBOX.
- Equip skills from the inventory. Double-click to unequip.

, + description: 'Skills are used by constructs in the game phase.\nBase skills can be bought from the VBOX.\nEquip skills from the inventory. Double-click to unequip.', }, constructSpecs: { item: 'SPECS', - description:

Specialisations increase the stats of a construct.
- Increased effect when your team meets the colour threshold.
Double-click to unequip.

, + description: 'Specialisations increase the stats of a construct.\nIncreased effect when your team meets the colour threshold.\nDouble-click to unequip.', }, powerStat: { item: 'POWER', - description:

Power determines the base damage and healing of your construct skills.
- Combine POWER specs to increase construct power.

, + description: 'Power determines the damage and healing of your construct skills.\nRed power RedPower is used by red skills.\nGreen power GreenPower is used by green skills.\nBlue power BluePower is used by blue skills.\nCombine coloured POWER specs to increase specific construct power.', }, lifeStat: { item: 'LIFE', - description:

The life of your construct.
- When your construct reaches 0 green life it is knocked out and cannot cast skills.
- Red life mitigates red damage and blue life mitigates blue damage.
- Combine LIFE specs to increase life totals.

, + description: 'The life of your construct.\nWhen your construct reaches 0 GreenLife it is knocked out.\nRed life RedLife mitigates red damage.\nBlue life BlueLife mitigates blue damage.\nCombine coloured LIFE specs to increase specific construct life.', }, speedStat: { item: 'SPEED', - description:

Speed determines the order in which skills resolve.
Combine SPEED specs to increase speed.

, + description: 'Speed determines the order in which skills resolve.\nCombine SPEED specs to increase speed.', }, }, }; diff --git a/client/src/tutorial.utils.jsx b/client/src/tutorial.utils.jsx index a8c45b94..7f6bb854 100644 --- a/client/src/tutorial.utils.jsx +++ b/client/src/tutorial.utils.jsx @@ -124,7 +124,7 @@ function tutorialStage(tutorial, ws, clearTutorial, instance) {

In a normal game you start with three base Attack skill items.

The Attack item can be combined with colours to create a new skill.

Select the Attack item along with two colours.
- When all three items are selected you can then press combine. + Once selected press COMBINE to create a new combo.

); From d52efc6c0199224cb1c59f3eed135fd4654ce368 Mon Sep 17 00:00:00 2001 From: Mashy Date: Thu, 31 Oct 2019 10:49:43 +1000 Subject: [PATCH 47/53] refactor info.comp --- client/src/components/info.component.jsx | 168 +++++----------------- client/src/components/info.thresholds.jsx | 96 +++++++++++++ client/src/utils.jsx | 2 - 3 files changed, 132 insertions(+), 134 deletions(-) create mode 100644 client/src/components/info.thresholds.jsx diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 8bb4b5db..87c96eeb 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -1,9 +1,9 @@ const preact = require('preact'); -const range = require('lodash/range'); const reactStringReplace = require('react-string-replace'); +const specThresholds = require('./info.thresholds'); const { INFO } = require('./../constants'); -const { convertItem, removeTier } = require('../utils'); +const { convertItem, removeTier, formatInfo } = require('../utils'); const { tutorialStage } = require('../tutorial.utils'); const shapes = require('./shapes'); @@ -68,150 +68,54 @@ class InfoComponent extends preact.Component { const isSkill = fullInfo.skill; const isSpec = fullInfo.spec; - if (isSkill) { + const itemDescription = () => { const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; - let infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); - infoDescription = reactStringReplace(infoDescription, '\n', () =>
); - const itemSource = itemInfo.combos.filter(c => c.item === removeTier(info)); - const itemSourceInfo = itemSource.length - ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` - : false; - const itemRegEx = /(Red|Blue|Green)/; - const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]()); - const speed =
Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}%
; - const cooldown = fullInfo.cooldown ? `${fullInfo.cooldown} Turn delay` : null; - return ( -
-

{fullInfo.item} {fullInfo.cost}b

-

SKILL

- {itemSourceDescription} -
{cooldown}
-
{infoDescription}
- {speed} -
- ); - } + const infoDescription = reactStringReplace(fullInfo.description, regEx, m => shapes[m]()); + return
{reactStringReplace(infoDescription, '\n', () =>
)}
; + }; - if (isSpec) { - let red = 0; - let blue = 0; - let green = 0; - player.constructs.forEach(construct => { - red += construct.colours.red; - blue += construct.colours.blue; - green += construct.colours.green; - }); - const teamColours = { red, blue, green }; - - const colourReqs = fullInfo.values.bonuses || []; - - const thresholds = colourReqs.map((bonus, i) => { - const colours = ['red', 'green', 'blue']; - const colourGoals = { - red: [], - green: [], - blue: [], - }; - const overFlow = []; - - colours.forEach(c => { - const colourReq = bonus.req[c]; - if (colourReqs === 0) return false; - - const start = i === 0 - ? 0 - : colourReqs[i - 1].req[c]; - - const dots = range(start, colourReq).map(j => { - const unmet = teamColours[c] < j + 1; - - - const reqClass = unmet - ? 'unmet' - : ''; - - if (j - start > 4) { - overFlow.push( -
- {shapes.vboxColour(c)} -
- ); - } else { - colourGoals[c].push( -
- {shapes.vboxColour(c)} -
- ); - } - - return true; - }); - - return dots; - }); - - const reqsMet = colours.every(c => teamColours[c] >= bonus.req[c]); - - const reqClass = reqsMet - ? '' - : 'unmet'; - - const goals = colours.map((c, j) => { - if (colourGoals[c].length) { - return ( -
{colourGoals[c]}
- ); - } - return false; - }); - const bonusObj = info.includes('Life') - ?
+ {bonus.bonus}
- :
+ {bonus.bonus}%
; - const overFlowObj = overFlow.length ?
{overFlow}
: null; - return ( -
- {goals} - {overFlowObj} - {bonusObj} -
- ); - }); - const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; - let infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); - infoDescription = reactStringReplace(infoDescription, '\n', () =>
); - const itemSource = itemInfo.combos.filter(c => c.item === info); - let itemSourceInfo = itemSource.length - ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` - : false; - const itemRegEx = /(Red|Blue|Green)/; - if (itemSourceInfo) { - while (itemSourceInfo.includes('Plus')) itemSourceInfo = itemSourceInfo.replace('Plus', '+'); - } - const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]()); + if (isSkill || isSpec) { let infoText = info; while (infoText.includes('Plus')) infoText = infoText.replace('Plus', '+'); + const header = isSkill ?

SKILL

:

SPEC

; + + const itemSource = itemInfo.combos.filter(c => c.item === removeTier(info)); + let itemSourceInfo = itemSource.length + ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}` + : false; + + 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 ( -
+

{infoText} {fullInfo.cost}b

-

SPEC

- {itemSourceDescription} -
{infoDescription}
-
- {thresholds} -
+ {header} + {itemSourceInfo} + {cooldown} + {itemDescription()} + {speed} + {thresholds}
); } const cost = fullInfo.cost ? `- ${fullInfo.cost}b` : false; - - const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat|POWER|SPEED|LIFE)/; - let infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]()); - infoDescription = reactStringReplace(infoDescription, '\n', () =>
); return (

{fullInfo.item} {cost}

-
{infoDescription}
+ {itemDescription()}
); } diff --git a/client/src/components/info.thresholds.jsx b/client/src/components/info.thresholds.jsx new file mode 100644 index 00000000..7136a855 --- /dev/null +++ b/client/src/components/info.thresholds.jsx @@ -0,0 +1,96 @@ +const preact = require('preact'); +const range = require('lodash/range'); +const shapes = require('./shapes'); + +function specThresholds(player, fullInfo, info) { + let red = 0; + let blue = 0; + let green = 0; + player.constructs.forEach(construct => { + red += construct.colours.red; + blue += construct.colours.blue; + green += construct.colours.green; + }); + const teamColours = { red, blue, green }; + + const colourReqs = fullInfo.values.bonuses || []; + + const thresholds = colourReqs.map((bonus, i) => { + const colours = ['red', 'green', 'blue']; + const colourGoals = { + red: [], + green: [], + blue: [], + }; + const overFlow = []; + + colours.forEach(c => { + const colourReq = bonus.req[c]; + if (colourReqs === 0) return false; + + const start = i === 0 + ? 0 + : colourReqs[i - 1].req[c]; + + const dots = range(start, colourReq).map(j => { + const unmet = teamColours[c] < j + 1; + + + const reqClass = unmet + ? 'unmet' + : ''; + + if (j - start > 4) { + overFlow.push( +
+ {shapes.vboxColour(c)} +
+ ); + } else { + colourGoals[c].push( +
+ {shapes.vboxColour(c)} +
+ ); + } + + return true; + }); + + return dots; + }); + + const reqsMet = colours.every(c => teamColours[c] >= bonus.req[c]); + + const reqClass = reqsMet + ? '' + : 'unmet'; + + const goals = colours.map((c, j) => { + if (colourGoals[c].length) { + return ( +
{colourGoals[c]}
+ ); + } + return false; + }); + const bonusObj = info.includes('Life') + ?
+ {bonus.bonus}
+ :
+ {bonus.bonus}%
; + const overFlowObj = overFlow.length ?
{overFlow}
: null; + return ( +
+ {goals} + {overFlowObj} + {bonusObj} +
+ ); + }); + return ( +
+ {thresholds} +
+ ); +} + +module.exports = specThresholds; diff --git a/client/src/utils.jsx b/client/src/utils.jsx index 42761a0a..ec49e659 100644 --- a/client/src/utils.jsx +++ b/client/src/utils.jsx @@ -240,8 +240,6 @@ function convertItem(v) { } function effectInfo(i) { - console.log(i); - function multiplier(s) { // Update later to use server info in future if (s === 'CounterAttack') return 120; if (s === 'CounterAttack+') return 160; From b554464802b1c554002f767f7183d79beaf9a88d Mon Sep 17 00:00:00 2001 From: Mashy Date: Thu, 31 Oct 2019 11:50:27 +1000 Subject: [PATCH 48/53] should comp updates --- client/src/components/faceoff.jsx | 156 +++++++++---------- client/src/components/info.component.jsx | 8 +- client/src/components/instance.component.jsx | 8 +- client/src/components/main.jsx | 62 ++++---- client/src/components/mnml.jsx | 22 ++- 5 files changed, 138 insertions(+), 118 deletions(-) diff --git a/client/src/components/faceoff.jsx b/client/src/components/faceoff.jsx index 251f10e6..ea3858cd 100644 --- a/client/src/components/faceoff.jsx +++ b/client/src/components/faceoff.jsx @@ -1,34 +1,25 @@ const preact = require('preact'); const { connect } = require('preact-redux'); -const actions = require('../actions'); - const { ConstructAvatar } = require('./construct'); -const Controls = require('./controls'); const addState = connect( function receiveState(state) { const { - ws, instance, account, } = state; - function sendInstanceReady() { - return ws.sendInstanceReady(instance.id); - } - return { instance, account, - sendInstanceReady, }; - }, + } ); function FaceoffConstruct(args) { const { - construct + construct, } = args; return ( @@ -39,75 +30,82 @@ function FaceoffConstruct(args) {
- ) -} - -function Faceoff(props) { - const { - instance, - account, - sendInstanceReady, - } = props; - - if (!instance) return
...
; - - const otherTeam = instance.players.find(t => t.id !== account.id); - const playerTeam = instance.players.find(t => t.id === account.id); - - function PlayerTeam(team) { - const constructs = team.constructs.map((c, i) => - ); - - const winner = instance.winner === team.id; - const classes = `team player ${winner ? 'winner' : team.ready ? 'ready' : ''}` - return ( -
- {constructs} -
- ); - } - - - function OpponentTeam(team) { - const constructs = team.constructs.map((c, i) => - ); - - const winner = instance.winner === team.id; - const classes = `team opponent ${winner ? 'winner' : team.ready ? 'ready' : ''}` - - return ( -
- {constructs} -
- ); - } - function faceoffText() { - if (!instance.winner) { - return ( -
-
{otherTeam.name}
-
vs
-
{playerTeam.name}
-
- ); - } - const winner = instance.winner === playerTeam.id ? playerTeam : otherTeam; - return ( -
-
{winner.name}
-
wins
-
- ) - - } - - return ( -
- {OpponentTeam(otherTeam)} - {faceoffText()} - {PlayerTeam(playerTeam)} -
); } +class Faceoff extends preact.Component { + shouldComponentUpdate(newProps) { + if (newProps.instance !== this.props.instance) return true; + if (newProps.account !== this.props.account) return true; + return false; + } + + render(props) { + const { + instance, + account, + } = props; + + if (!instance) return
...
; + + const otherTeam = instance.players.find(t => t.id !== account.id); + const playerTeam = instance.players.find(t => t.id === account.id); + + function PlayerTeam(team) { + const constructs = team.constructs.map((c, i) => + ); + + const winner = instance.winner === team.id; + const classes = `team player ${winner ? 'winner' : team.ready ? 'ready' : ''}`; + return ( +
+ {constructs} +
+ ); + } + + + function OpponentTeam(team) { + const constructs = team.constructs.map((c, i) => + ); + + const winner = instance.winner === team.id; + const classes = `team opponent ${winner ? 'winner' : team.ready ? 'ready' : ''}`; + + return ( +
+ {constructs} +
+ ); + } + function faceoffText() { + if (!instance.winner) { + return ( +
+
{otherTeam.name}
+
vs
+
{playerTeam.name}
+
+ ); + } + const winner = instance.winner === playerTeam.id ? playerTeam : otherTeam; + return ( +
+
{winner.name}
+
wins
+
+ ) + + } + + return ( +
+ {OpponentTeam(otherTeam)} + {faceoffText()} + {PlayerTeam(playerTeam)} +
+ ); + } +} + module.exports = addState(Faceoff); diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 87c96eeb..1c7010fc 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -3,7 +3,7 @@ const reactStringReplace = require('react-string-replace'); const specThresholds = require('./info.thresholds'); const { INFO } = require('./../constants'); -const { convertItem, removeTier, formatInfo } = require('../utils'); +const { convertItem, removeTier } = require('../utils'); const { tutorialStage } = require('../tutorial.utils'); const shapes = require('./shapes'); @@ -75,8 +75,8 @@ class InfoComponent extends preact.Component { }; if (isSkill || isSpec) { - let infoText = info; - while (infoText.includes('Plus')) infoText = infoText.replace('Plus', '+'); + let infoName = info; + while (infoName.includes('Plus')) infoName = infoName.replace('Plus', '+'); const header = isSkill ?

SKILL

:

SPEC

; @@ -101,7 +101,7 @@ class InfoComponent extends preact.Component { return (
-

{infoText} {fullInfo.cost}b

+

{infoName} {fullInfo.cost}b

{header} {itemSourceInfo} {cooldown} diff --git a/client/src/components/instance.component.jsx b/client/src/components/instance.component.jsx index d4953550..b5e98674 100644 --- a/client/src/components/instance.component.jsx +++ b/client/src/components/instance.component.jsx @@ -13,11 +13,13 @@ const actions = require('../actions'); const addState = connect( function receiveState(state) { - const { instance, + const { + instance, nav, navInstance, } = state; - return { instance, + return { + instance, nav, navInstance, }; @@ -52,7 +54,7 @@ const addState = connect( ); class Instance extends Component { - componentShouldUpdate(newProps) { + shouldComponentUpdate(newProps) { if (newProps.instance !== this.props.instance) return true; return false; } diff --git a/client/src/components/main.jsx b/client/src/components/main.jsx index ab923182..b03e0069 100644 --- a/client/src/components/main.jsx +++ b/client/src/components/main.jsx @@ -16,35 +16,45 @@ const addState = connect( } ); -function Main(props) { - const { - game, - instance, - account, - nav, - } = props; - - if (!account) { - return ; +class Main extends preact.Component { + shouldComponentUpdate(newProps) { + if (newProps.game !== this.props.game) return true; + if (newProps.instance !== this.props.instance) return true; + if (newProps.account !== this.props.account) return true; + if (newProps.nav !== this.props.nav) return true; + return false; } - if (game) { - return ; + render(props) { + const { + game, + instance, + account, + nav, + } = props; + + if (!account) { + return ; + } + + if (game) { + return ; + } + + if (instance) { + return ; + } + + if (nav === 'transition') return false; + + return ( +
+
+ + +
+ ); } - - if (instance) { - return ; - } - - if (nav === 'transition') return false; - - return ( -
-
- - -
- ); } module.exports = addState(Main); diff --git a/client/src/components/mnml.jsx b/client/src/components/mnml.jsx index 5c4ae51b..60dad587 100644 --- a/client/src/components/mnml.jsx +++ b/client/src/components/mnml.jsx @@ -10,11 +10,21 @@ const addState = connect( state => ({ showNav: state.showNav }) ); -const Mnml = ({ showNav }) => -
-
- -
-
; +class Mnml extends preact.Component { + shouldComponentUpdate(newProps) { + if (newProps.showNav !== this.props.showNav) return true; + return false; + } + + render(args) { + return ( +
+
+ +
+
+ ); + } +} module.exports = addState(Mnml); From 1be37161ef3e2ff98ad52453d9f4af29cad20f9a Mon Sep 17 00:00:00 2001 From: Mashy Date: Thu, 31 Oct 2019 15:34:05 +1000 Subject: [PATCH 49/53] info description fix --- client/src/components/info.component.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/info.component.jsx b/client/src/components/info.component.jsx index 1c7010fc..0666010a 100644 --- a/client/src/components/info.component.jsx +++ b/client/src/components/info.component.jsx @@ -69,7 +69,7 @@ class InfoComponent extends preact.Component { const isSpec = fullInfo.spec; const itemDescription = () => { - const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/; + 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', () =>
)}
; }; From 0ce19240f70527bff55eb57fa96e485900f89587 Mon Sep 17 00:00:00 2001 From: Mashy Date: Thu, 31 Oct 2019 15:41:20 +1000 Subject: [PATCH 50/53] increase buff duration 2T->3T --- CHANGELOG.md | 1 + server/src/skill.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8960d207..904fc8d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Buff - Previously increased red power and speed stat by 25% - Now increases red power, blue power and speed stat by 30% + - Increased duration from 2T -> 3T - Counter - No longer applies block effect diff --git a/server/src/skill.rs b/server/src/skill.rs index 9c02408f..1f655e6d 100644 --- a/server/src/skill.rs +++ b/server/src/skill.rs @@ -861,7 +861,7 @@ impl Skill { Skill::BanishPlusPlus => vec![ConstructEffect {effect: Effect::Banish, duration: 2, meta: None, tick: None}], Skill::Block => vec![ConstructEffect {effect: Effect::Block, duration: 1, meta: Some(EffectMeta::Multiplier(35)), tick: None}], - Skill::Buff => vec![ConstructEffect {effect: Effect::Buff, duration: 2, + Skill::Buff => vec![ConstructEffect {effect: Effect::Buff, duration: 3, meta: Some(EffectMeta::Multiplier(130)), tick: None }], Skill::Electrify => vec![ConstructEffect {effect: Effect::Electric, duration: 1, From 38177f84e9670f50929b1136c0f2f8f882c3f481 Mon Sep 17 00:00:00 2001 From: ntr Date: Thu, 31 Oct 2019 16:59:26 +1100 Subject: [PATCH 51/53] disable tutorial via localstorage" --- client/src/tutorial.utils.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/tutorial.utils.jsx b/client/src/tutorial.utils.jsx index 7f6bb854..3732d11a 100644 --- a/client/src/tutorial.utils.jsx +++ b/client/src/tutorial.utils.jsx @@ -2,6 +2,7 @@ const preact = require('preact'); const actions = require('./actions'); function tutorialConstructDisplay(player, instance, tutorial, navInstance, i) { + if (localStorage.getItem('tutorial-complete')) return false; if (instance.time_control === 'Practice' && instance.rounds.length === 1 && tutorial && tutorial < 6) { if (tutorial <= 2 || (tutorial > 2 && i > 0)) { const mobileVisible = navInstance === i + 1; @@ -13,12 +14,14 @@ function tutorialConstructDisplay(player, instance, tutorial, navInstance, i) { } function tutorialShouldDisableEquip(tutorial, iter, instance, construct) { + if (localStorage.getItem('tutorial-complete')) return false; return tutorial && tutorial === 6 && iter === 0 && construct.skills.length !== 0 && instance.time_control === 'Practice' && instance.rounds.length === 1; } function tutorialVbox(player, store, tutorial) { + if (localStorage.getItem('tutorial-complete')) return false; let stage = tutorial; const { vbox } = player; if (stage === 1) { @@ -99,11 +102,15 @@ function tutorialVbox(player, store, tutorial) { } function tutorialStage(tutorial, ws, clearTutorial, instance) { + if (localStorage.getItem('tutorial-complete')) return false; if (!(instance.time_control === 'Practice' && instance.rounds.length === 1)) return false; + const exit = () => { clearTutorial(); + localStorage.setItem('tutorial-complete', true); ws.sendInstanceState(instance.id); }; + const tutorialText = () => { if (tutorial === 1) { return ( From 88194975ac848a8f9bdf0d735c6f77a4d37d6758 Mon Sep 17 00:00:00 2001 From: Mashy Date: Thu, 31 Oct 2019 16:07:45 +1000 Subject: [PATCH 52/53] setTutorial false --- client/src/events.jsx | 5 ++++- client/src/tutorial.utils.jsx | 4 ---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/client/src/events.jsx b/client/src/events.jsx index a957b380..22be4613 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -212,7 +212,10 @@ function registerEvents(store) { if (v.phase === 'Finished') { ws.sendAccountInstances(); } - if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) { + if (localStorage.getItem('tutorial-complete')){ + store.dispatch(actions.setTutorial(null)); + + } else if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) { tutorialVbox(player, store, tutorial); } } diff --git a/client/src/tutorial.utils.jsx b/client/src/tutorial.utils.jsx index 3732d11a..1cdf0dfb 100644 --- a/client/src/tutorial.utils.jsx +++ b/client/src/tutorial.utils.jsx @@ -2,7 +2,6 @@ const preact = require('preact'); const actions = require('./actions'); function tutorialConstructDisplay(player, instance, tutorial, navInstance, i) { - if (localStorage.getItem('tutorial-complete')) return false; if (instance.time_control === 'Practice' && instance.rounds.length === 1 && tutorial && tutorial < 6) { if (tutorial <= 2 || (tutorial > 2 && i > 0)) { const mobileVisible = navInstance === i + 1; @@ -14,14 +13,12 @@ function tutorialConstructDisplay(player, instance, tutorial, navInstance, i) { } function tutorialShouldDisableEquip(tutorial, iter, instance, construct) { - if (localStorage.getItem('tutorial-complete')) return false; return tutorial && tutorial === 6 && iter === 0 && construct.skills.length !== 0 && instance.time_control === 'Practice' && instance.rounds.length === 1; } function tutorialVbox(player, store, tutorial) { - if (localStorage.getItem('tutorial-complete')) return false; let stage = tutorial; const { vbox } = player; if (stage === 1) { @@ -102,7 +99,6 @@ function tutorialVbox(player, store, tutorial) { } function tutorialStage(tutorial, ws, clearTutorial, instance) { - if (localStorage.getItem('tutorial-complete')) return false; if (!(instance.time_control === 'Practice' && instance.rounds.length === 1)) return false; const exit = () => { From 5f2e73e3739c6ed0715742a4db7d3c4d28d8d40a Mon Sep 17 00:00:00 2001 From: Mashy Date: Thu, 31 Oct 2019 16:08:29 +1000 Subject: [PATCH 53/53] formatting --- client/src/events.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/events.jsx b/client/src/events.jsx index 22be4613..0cc1e4a0 100644 --- a/client/src/events.jsx +++ b/client/src/events.jsx @@ -212,9 +212,8 @@ function registerEvents(store) { if (v.phase === 'Finished') { ws.sendAccountInstances(); } - if (localStorage.getItem('tutorial-complete')){ + if (localStorage.getItem('tutorial-complete')) { store.dispatch(actions.setTutorial(null)); - } else if (v.time_control === 'Practice' && v.rounds.length === 1 && tutorial) { tutorialVbox(player, store, tutorial); }