305 lines
10 KiB
JavaScript
305 lines
10 KiB
JavaScript
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) 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';
|
|
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: {
|
|
Buy: '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 || <span> </span>;
|
|
// uncomment for double borders in vbox;
|
|
// if (v) {
|
|
// return <div>{v}</div>;
|
|
// }
|
|
// return;
|
|
}
|
|
|
|
function effectInfo(i) {
|
|
// FIX ME
|
|
const hybridBlast = 25;
|
|
const hasteStrike = 30;
|
|
function multiplier(s) { // Update later to use server info in future
|
|
if (s === 'CounterAttack') return 115;
|
|
if (s === 'CounterAttack+') return 130;
|
|
if (s === 'CounterAttack++') return 160;
|
|
if (s === 'Electrocute') return 80;
|
|
if (s === 'Electrocute+') return 90;
|
|
if (s === 'Electrocute++') return 100;
|
|
return 0;
|
|
}
|
|
|
|
switch (i.effect) {
|
|
case 'Amplify': return `Increases construct RedPower BluePower by ${i.meta[1] - 100}%`;
|
|
case 'Banish': return 'Banished construct cannot cast or take damage';
|
|
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 ${hasteStrike}% SpeedStat as red damage.`;
|
|
case 'Hybrid': return `Construct has ${i.meta[1] - 100}% increased GreenPower. Blue attack skills will trigger a HybridBlast dealing ${hybridBlast}% GreenPower as red damage.`;
|
|
case 'Invert': return 'Reverse healing/recharge into damage and damage into healing/recharge.';
|
|
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 'Pure': return `Construct will take ${i.meta[1] - 100}% increased healing`;
|
|
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 ${i.meta[1].amount} 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 ${i.meta[1].amount} 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 ${i.meta[1].amount} green life each turn.`;
|
|
case 'Siphon': return `Construct will take ${i.meta[1].amount} 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,
|
|
};
|