const preact = require('preact'); const range = require('lodash/range'); const reactStringReplace = require('react-string-replace'); const { INFO } = require('./../constants'); const { convertItem, removeTier } = require('../utils'); const { tutorialStage } = require('../tutorial.utils'); const shapes = require('./shapes'); class InfoComponent extends preact.Component { shouldComponentUpdate(newProps) { if (newProps.tutorial !== this.props.tutorial) return true; // We don't care about info during tutorial if (newProps.tutorial && this.props.instance.time_control === 'Practice' && this.props.instance.rounds.length === 1) return false; if (newProps.info !== this.props.info) return true; return false; } render(args) { const { // Variables that will change info, tutorial, // 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) { const tutorialStageInfo = tutorialStage(tutorial, ws, setTutorialNull, instance); if (tutorialStageInfo) return tutorialStageInfo; } if (!info) return false; if (info.includes('constructName')) { return (

{info.replace('constructName ', '')}

This is the name of your construct.
Names are randomly generated and are purely cosmetic.
You can change change your construct name in the RESHAPE tab outside of games.

); } if (info.includes('constructAvatar')) { return (

{info.replace('constructAvatar ', '')}

This is your construct avatar.
Avatars are randomly generated and are purely cosmetic.
You can change your construct avatar in the RESHAPE tab outside of games.

); } const fullInfo = itemInfo.items.find(i => i.item === info) || INFO[info]; if (!fullInfo) return false; const isSkill = fullInfo.skill; const isSpec = fullInfo.spec; if (isSkill) { 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}
); } 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]()); let infoText = info; while (infoText.includes('Plus')) infoText = infoText.replace('Plus', '+'); return (

{infoText} {fullInfo.cost}b

SPEC

{itemSourceDescription}
{infoDescription}
{thresholds}
); } const cost = fullInfo.cost ? `- ${fullInfo.cost}b` : false; const infoDescription = reactStringReplace(fullInfo.description, '\n', () =>
); return (

{fullInfo.item} {cost}

{infoDescription}
); } function Combos() { if (tutorial && instance.time_control === 'Practice' && instance.rounds.length === 1) return false; const generalNotes = (

General

You can preview combos by clicking the combined item when it appears in this section.
Click the READY button to start the GAME PHASE.

); if (!player) return generalNotes; if (!info) return generalNotes; const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info)); if (vboxCombos.length > 6 || vboxCombos.length === 0) return generalNotes; return ( {vboxCombos.map((c, i) => {c.components.map((u, j) => )} )}
setInfo(c.item)} >{convertItem(c.item)}{convertItem(u)}
); } return (
); } } module.exports = InfoComponent;