const preact = require('preact'); const get = require('lodash/get'); const toast = require('izitoast'); const shapes = require('./components/shapes'); function match(value, patterns) { for (let i = 0; i < patterns.length; i++) { if (value === patterns[i][0]) { return patterns[i][1](); } } console.warn('default match - return null', value, patterns); return null; } const stringSort = (k, desc) => { if (desc) { return (a, b) => { if (!get(a, k)) return 1; if (!get(b, k)) return -1; return get(b, k).localeCompare(get(a, k)); }; } return (a, b) => { if (!get(a, k)) return 1; if (!get(b, k)) return -1; return get(a, k).localeCompare(get(b, k)); }; }; const numSort = (k, desc) => { if (desc) { return (a, b) => { if (!get(a, k)) return 1; if (!get(b, k)) return -1; return get(b, k) - get(a, k); }; } return (a, b) => { if (!get(a, k)) return 1; if (!get(b, k)) return -1; return get(a, k) - get(b, k); }; }; const NULL_UUID = '00000000-0000-0000-0000-000000000000'; const STATS = { RedPower: { stat: 'red_power', colour: 'red', svg: shapes.circle, }, GreenPower: { stat: 'green_power', colour: 'green', svg: shapes.circle, }, BluePower: { stat: 'blue_power', colour: 'blue', svg: shapes.circle, }, SpeedStat: { stat: 'speed', colour: 'white', svg: shapes.triangle, }, RedLife: { stat: 'red_life', colour: 'red', svg: shapes.square, }, GreenLife: { stat: 'green_life', colour: 'green', svg: shapes.square, }, BlueLife: { stat: 'blue_life', colour: 'blue', svg: shapes.square, }, }; const COLOURS = [ '#a52a2a', '#1FF01F', '#3050f8', ]; const TARGET_COLOURS = { BLUE: '#004bfe', CYAN: '#27e7c0', PURPLE: '#61008c', YELLOW: '#fdfe02', ORANGE: '#ff9215', PINK: '#e766b6', GRAY: '#9d9ea0', LBLUE: '#87c6f2', GREEN: '#166c4f', BROWN: '#583108', }; function randomPoints(numPoints, radius, dimensions) { const { x, y, width, height, } = dimensions; const points = []; let infCheck = 0; while (points.length < numPoints) { const c = [ Math.floor(Math.random() * (x + width - 2 * radius) + x + radius), Math.floor(Math.random() * (y + height - 2 * radius) + y + radius), ]; let overlapping = false; for (let j = 0; j < points.length; j += 1) { const o = points[j]; const dx = c[0] - o[0]; const dy = c[1] - o[1]; const d = Math.floor(Math.sqrt(dx * dx + dy * dy)); if (d < radius) { overlapping = true; } } if (!overlapping) { points.push(c); infCheck = 0; } else { infCheck += 1; if (infCheck > 100) { break; } } } return points; } const removeTier = skill => { if (skill.includes('SiphonTick')) return 'SiphonTick'; if (skill.includes('TriageTick')) return 'TriageTick'; if (skill.includes('DecayTick')) return 'DecayTick'; if (skill.includes('ElectrocuteTick')) return 'ElectrocuteTick'; if (skill.includes('Strike')) return 'Strike'; if (skill.includes('Heal')) return 'Heal'; if (skill.includes('Blast')) return 'Blast'; if (skill.includes('Chaos')) return 'Chaos'; if (skill.includes('Slay')) return 'Slay'; if (skill.includes('Siphon')) return 'Siphon'; if (skill.includes('Restrict')) return 'Restrict'; if (skill.includes('Purge')) return 'Purge'; if (skill.includes('Silence')) return 'Silence'; if (skill.includes('Curse')) return 'Curse'; if (skill.includes('Decay')) return 'Decay'; if (skill.includes('Invert')) return 'Invert'; if (skill.includes('Intercept')) return 'Intercept'; if (skill.includes('Triage')) return 'Triage'; if (skill.includes('Link')) return 'Link'; if (skill.includes('Haste')) return 'Haste'; if (skill.includes('Hybrid')) return 'Hybrid'; if (skill.includes('Amplify')) return 'Amplify'; if (skill.includes('Counter')) return 'Counter'; if (skill.includes('Purify')) return 'Purify'; if (skill.includes('Electrify')) return 'Electrify'; if (skill.includes('Electrocute')) return 'Electrocute'; if (skill.includes('Sustain')) return 'Sustain'; if (skill.includes('Reflect')) return 'Reflect'; if (skill.includes('Recharge')) return 'Recharge'; if (skill.includes('Bash')) return 'Bash'; if (skill.includes('Sleep')) return 'Sleep'; if (skill.includes('Ruin')) return 'Ruin'; if (skill.includes('Break')) return 'Break'; if (skill.includes('Hex')) return 'Hex'; if (skill.includes('Absorb')) return 'Absorb'; if (skill.includes('Banish')) return 'Banish'; return skill; }; function postData(url = '/', data = {}) { // Default options are marked with * return fetch(`/api${url}`, { method: 'POST', // *GET, POST, PUT, DELETE, etc. // mode: 'no-cors', // no-cors, cors, *same-origin cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached credentials: 'include', // include, same-origin, *omit headers: { Accept: 'application/json', 'content-type': 'application/json', }, redirect: 'error', // manual, *follow, error // referrer: ', // no-referrer, *client body: JSON.stringify(data), // body data type must match "Content-Type" header }); } function errorToast(message) { toast.error({ position: 'topRight', drag: false, close: false, message, }); } function infoToast(message) { toast.info({ position: 'topRight', drag: false, close: false, message, }); } function convertItem(v) { if (['Red', 'Green', 'Blue'].includes(v)) { return ( shapes.vboxColour(v.toLowerCase()) ); } if (shapes[v]) return shapes[v](); return v ||  ; // uncomment for double borders in vbox; // if (v) { // return
{v}
; // } // return; } 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 === '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 === 'TriageTick') return 75; if (s === 'TriageTick+') return 110; if (s === 'TriageTick++') return 140; if (s === 'Electrocute' || s === 'ElectrocuteTick') return 80; if (s === 'Electrocute+' || s === 'ElectrocuteTick+') return 100; if (s === 'Electrocute++' || s === 'ElectrocuteTick++') return 130; return 0; } 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 '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.`; case 'Hybrid': return `Construct has ${i.meta[1] - 100}% increased GreenPower. Blue attack skills will trigger a HybridBlast dealing 25% GreenPower as red damage.`; case 'Invert': return 'Reverses damage and healing. Healing will damage this construct and damage will heal.'; case 'Counter': return `Red damage taken by this construct will trigger a CounterAttack. CounterAttack deals ${multiplier(i.meta[1])}% RedPower as red damage.`; case 'Purge': return 'Disable construct from casting any green skills'; case 'Reflect': return 'Reflect blue skills back to caster'; case 'Slow': return `Reduces construct SpeedStat by ${100 - i.meta[1]}%`; case 'Restrict': return 'Disable construct from casting any red skills'; case 'Stun': return 'Stunned construct cannot use skills'; case 'Intercept': return 'Redirect any skills on team to this target construct'; case 'Vulnerable': return `Construct will take ${i.meta[1] - 100}% increased red damage`; case 'Silence': return 'Disable construct from casting any blue skills'; case 'Wither': return `Construct will take ${100 - i.meta[1]}% reduced healing`; // case 'Decay': return `Construct will take ${multiplier(i.tick.skill)}% of caster's BluePower as blue damage each turn.`; // case 'Electric': return `Attacks against this construct will apply Electrocute dealing ${multiplier(i.meta[1])}% of construct BluePower as blue damage each turn.`; case 'Electrocute': return `Construct will take ${multiplier(i.tick.skill)}% of caster's BluePower as blue damage each turn.`; case 'Absorb': return 'If construct takes damage, Absorption will be applied increasing RedPower and BluePower based on damage taken.'; case 'Absorption': return `Increasing construct RedPower and BluePower by ${i.meta[1]}`; case 'Triage': return `Construct will be healed for ${multiplier(i.tick.skill)}% of caster's GreenPower each turn.`; case 'Siphon': return `Construct will take ${multiplier(i.tick.skill)}% of caster's BluePower + GreenPower as blue damage each turn, healing the caster.`; default: return 'Missing Effect Text'; } } module.exports = { stringSort, numSort, postData, convertItem, errorToast, infoToast, NULL_UUID, STATS, COLOURS, TARGET_COLOURS, randomPoints, removeTier, match, effectInfo, };