mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-04-25 16:14:01 -05:00
1165 lines
40 KiB
JavaScript
Executable File
1165 lines
40 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
'use strict';
|
|
|
|
const fs = require("fs");
|
|
const path = require('path');
|
|
const child_process = require("child_process");
|
|
|
|
const rootDir = path.resolve(__dirname, '..');
|
|
process.chdir(rootDir);
|
|
|
|
if (!fs.existsSync('data/pokemon-showdown')) {
|
|
child_process.execSync('git clone https://github.com/smogon/pokemon-showdown.git', {
|
|
cwd: 'data',
|
|
});
|
|
}
|
|
|
|
process.stdout.write("Syncing data from Git repository... ");
|
|
child_process.execSync('git pull', {cwd: 'data/pokemon-showdown'});
|
|
child_process.execSync('npm run build', {cwd: 'data/pokemon-showdown'});
|
|
console.log("DONE");
|
|
|
|
const Dex = require('../data/pokemon-showdown/.sim-dist/dex').Dex;
|
|
const Tags = require('../data/pokemon-showdown/.data-dist/tags').Tags;
|
|
const toID = Dex.toID;
|
|
process.stdout.write("Loading gen 6 data... ");
|
|
Dex.includeData();
|
|
console.log("DONE");
|
|
|
|
function es3stringify(obj) {
|
|
const buf = JSON.stringify(obj);
|
|
return buf.replace(/\"([A-Za-z][A-Za-z0-9]*)\"\:/g, (fullMatch, key) => (
|
|
['return', 'new', 'delete'].includes(key) ? fullMatch : `${key}:`
|
|
));
|
|
}
|
|
|
|
function requireNoCache(pathSpec) {
|
|
delete require.cache[require.resolve(pathSpec)];
|
|
return require(pathSpec);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build search-index.js
|
|
*********************************************************/
|
|
|
|
{
|
|
process.stdout.write("Building `data/search-index.js`... ");
|
|
|
|
let index = [];
|
|
|
|
index = index.concat(Object.keys(Dex.data.Pokedex).map(x => x + ' pokemon'));
|
|
index = index.concat(Object.keys(Dex.data.Moves).map(x => x + ' move'));
|
|
index = index.concat(Object.keys(Dex.data.Items).map(x => x + ' item'));
|
|
index = index.concat(Object.keys(Dex.data.Abilities).map(x => x + ' ability'));
|
|
index = index.concat(Object.keys(Dex.data.TypeChart).map(x => toID(x) + ' type'));
|
|
index = index.concat(['physical', 'special', 'status'].map(x => toID(x) + ' category'));
|
|
index = index.concat(['monster', 'water1', 'bug', 'flying', 'field', 'fairy', 'grass', 'humanlike', 'water3', 'mineral', 'amorphous', 'water2', 'ditto', 'dragon', 'undiscovered'].map(x => toID(x) + ' egggroup'));
|
|
index = index.concat(['ou', 'uu', 'ru', 'nu', 'pu', 'lc', 'nfe', 'uber', 'uubl', 'rubl', 'nubl', 'publ', 'cap', 'caplc', 'capnfe'].map(x => toID(x) + ' tier'));
|
|
|
|
let BattleArticleTitles = {};
|
|
|
|
try {
|
|
for (const file of fs.readdirSync('../dex.pokemonshowdown.com/articles/')) {
|
|
if (file.endsWith('.md')) {
|
|
const id = file.slice(0, -3);
|
|
const contents = '' + fs.readFileSync('../dex.pokemonshowdown.com/articles/' + file);
|
|
if (contents.startsWith('# ')) {
|
|
const title = contents.slice(2, contents.indexOf('\n'));
|
|
if (title !== id.charAt(0).toUpperCase() + id.slice(1)) {
|
|
BattleArticleTitles[id] = title;
|
|
}
|
|
}
|
|
index.push('' + id + ' article');
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.log('\n(WARNING: NO ARTICLES)');
|
|
}
|
|
index.push('pokemon article');
|
|
index.push('moves article');
|
|
|
|
// generate aliases
|
|
function generateAlias(id, name, type) {
|
|
let i = name.lastIndexOf(' ');
|
|
if (i < 0) i = name.lastIndexOf('-');
|
|
if (name.endsWith('-Mega-X') || name.endsWith('-Mega-Y')) {
|
|
index.push('mega' + toID(name.slice(0, -7) + name.slice(-1)) + ' ' + type + ' ' + id + ' 0');
|
|
index.push('m' + toID(name.slice(0, -7) + name.slice(-1)) + ' ' + type + ' ' + id + ' 0');
|
|
index.push('mega' + toID(name.slice(-1)) + ' ' + type + ' ' + id + ' ' + toID(name.slice(0, -7)).length);
|
|
return;
|
|
}
|
|
if (name.endsWith('-Mega')) {
|
|
index.push('mega' + toID(name.slice(0, -5)) + ' ' + type + ' ' + id + ' 0');
|
|
index.push('m' + toID(name.slice(0, -5)) + ' ' + type + ' ' + id + ' 0');
|
|
return;
|
|
}
|
|
if (name.endsWith('-Alola')) {
|
|
index.push('alolan' + toID(name.slice(0, -6)) + ' ' + type + ' ' + id + ' 0');
|
|
return;
|
|
}
|
|
let oldI = i;
|
|
if (name === 'Alakazam') i = 5;
|
|
if (name === 'Arctovish') i = 5;
|
|
if (name === 'Arctozolt') i = 5;
|
|
if (name === 'Articuno') i = 5;
|
|
if (name === 'Breloom') i = 3;
|
|
if (name === 'Bronzong') i = 4;
|
|
if (name === 'Celebi') i = 4;
|
|
if (name === 'Charizard') i = 5;
|
|
if (name === 'Donphan') i = 3;
|
|
if (name === 'Dracovish') i = 5;
|
|
if (name === 'Dracozolt') i = 5;
|
|
if (name === 'Dragapult') i = 5;
|
|
if (name === 'Dusclops') i = 3;
|
|
if (name === 'Electabuzz') i = 6;
|
|
if (name === 'Exeggutor') i = 2;
|
|
if (name === 'Garchomp') i = 3;
|
|
if (name === 'Hariyama') i = 4;
|
|
if (name === 'Magearna') i = 2;
|
|
if (name === 'Magnezone') i = 5;
|
|
if (name === 'Mamoswine') i = 4;
|
|
if (name === 'Moltres') i = 3;
|
|
if (name === 'Nidoking') i = 4;
|
|
if (name === 'Nidoqueen') i = 4;
|
|
if (name === 'Nidorina') i = 4;
|
|
if (name === 'Nidorino') i = 4;
|
|
if (name === 'Regice') i = 3;
|
|
if (name === 'Regidrago') i = 4;
|
|
if (name === 'Regieleki') i = 4;
|
|
if (name === 'Regigigas') i = 4;
|
|
if (name === 'Regirock') i = 4;
|
|
if (name === 'Registeel') i = 4;
|
|
if (name === 'Slowbro') i = 4;
|
|
if (name === 'Slowking') i = 4;
|
|
if (name === 'Starmie') i = 4;
|
|
if (name === 'Tyranitar') i = 6;
|
|
if (name === 'Zapdos') i = 3;
|
|
|
|
if (name === 'Acupressure') i = 3;
|
|
if (name === 'Aromatherapy') i = 5;
|
|
if (name === 'Boomburst') i = 4;
|
|
if (name === 'Crabhammer') i = 4;
|
|
if (name === 'Discharge') i = 3;
|
|
if (name === 'Earthquake') i = 5;
|
|
if (name === 'Extrasensory') i = 5;
|
|
if (name === 'Flamethrower') i = 5;
|
|
if (name === 'Headbutt') i = 4;
|
|
if (name === 'Moonblast') i = 4;
|
|
if (name === 'Moonlight') i = 4;
|
|
if (name === 'Overheat') i = 4;
|
|
if (name === 'Outrage') i = 3;
|
|
if (name === 'Octazooka') i = 4;
|
|
if (name === 'Payback') i = 3;
|
|
if (name === 'Psyshock') i = 3;
|
|
if (name === 'Psywave') i = 3;
|
|
if (name === 'Rototiller') i = 4;
|
|
if (name === 'Rollout') i = 4;
|
|
if (name === 'Safeguard') i = 4;
|
|
if (name === 'Sandstorm') i = 4;
|
|
if (name === 'Smokescreen') i = 5;
|
|
if (name === 'Stockpile') i = 5;
|
|
if (name === 'Steamroller') i = 5;
|
|
if (name === 'Superpower') i = 5;
|
|
if (name === 'Supersonic') i = 5;
|
|
if (name === 'Synchronoise') i = 7;
|
|
if (name === 'Tailwind') i = 4;
|
|
if (name === 'Telekinesis') i = 4;
|
|
if (name === 'Teleport') i = 4;
|
|
if (name === 'Thunderbolt') i = 7;
|
|
if (name === 'Twineedle') i = 3;
|
|
if (name === 'Uproar') i = 2;
|
|
if (name === 'Venoshock') i = 4;
|
|
if (name === 'Whirlpool') i = 5;
|
|
if (name === 'Whirlwind') i = 5;
|
|
let acronym;
|
|
if (oldI < 0 && i > 0) {
|
|
acronym = toID(name.charAt(0) + name.slice(i));
|
|
}
|
|
if (i < 0) return;
|
|
index.push('' + toID(name.slice(i)) + ' ' + type + ' ' + id + ' ' + toID(name.slice(0, i)).length);
|
|
if (name.startsWith('Hidden Power ')) {
|
|
acronym = 'hp' + toID(name.substr(13));
|
|
index.push('' + acronym + ' ' + type + ' ' + id + ' 0');
|
|
} else if (name === 'Hidden Power') {
|
|
index.push('hp ' + type + ' ' + id + ' 0');
|
|
} else if (name.includes(' ')) {
|
|
acronym = toID(name.split(' ').map((x, i) => i !== 0 ? x : x.charAt(0)).join(''));
|
|
} else if (name.includes('-') && name.charAt(1) !== '-') {
|
|
acronym = toID(name.split('-').map((x, i) => i !== 0 ? x : x.charAt(0)).join(''));
|
|
}
|
|
if (acronym) {
|
|
index.push('' + acronym + ' ' + type + ' ' + id + ' 0');
|
|
}
|
|
if (name === 'High Jump Kick') {
|
|
index.push('hjkick ' + type + ' ' + id + ' 0');
|
|
} else if (name === 'Wake-Up Slap') {
|
|
index.push('wuslap ' + type + ' ' + id + ' 0');
|
|
index.push('wupslap ' + type + ' ' + id + ' 0');
|
|
} else if (name === 'Zen Headbutt') {
|
|
index.push('zhbutt ' + type + ' ' + id + ' 0');
|
|
} else if (name === 'Articuno') {
|
|
index.push('cuno ' + type + ' ' + id + ' 4');
|
|
}
|
|
|
|
let i2 = name.lastIndexOf(' ', i - 1);
|
|
if (i2 < 0) i2 = name.lastIndexOf('-', i - 1);
|
|
if (name === 'Zen Headbutt') i2 = 8;
|
|
if (i2 >= 0) {
|
|
index.push('' + toID(name.slice(i2)) + ' ' + type + ' ' + id + ' ' + toID(name.slice(0, i2)).length);
|
|
}
|
|
}
|
|
for (const id in Dex.data.Pokedex) {
|
|
const name = Dex.data.Pokedex[id].name;
|
|
generateAlias(id, name, 'pokemon');
|
|
}
|
|
for (const id in Dex.data.Moves) {
|
|
const name = Dex.data.Moves[id].name;
|
|
generateAlias(id, name, 'move');
|
|
}
|
|
for (const id in Dex.data.Items) {
|
|
const name = Dex.data.Items[id].name;
|
|
generateAlias(id, name, 'item');
|
|
}
|
|
for (const id in Dex.data.Abilities) {
|
|
const name = Dex.data.Abilities[id].name;
|
|
generateAlias(id, name, 'ability');
|
|
}
|
|
|
|
index.sort();
|
|
|
|
// manually rearrange
|
|
index[index.indexOf('grass type')] = 'grass egggroup';
|
|
index[index.indexOf('grass egggroup')] = 'grass type';
|
|
|
|
index[index.indexOf('fairy type')] = 'fairy egggroup';
|
|
index[index.indexOf('fairy egggroup')] = 'fairy type';
|
|
|
|
index[index.indexOf('flying type')] = 'flying egggroup';
|
|
index[index.indexOf('flying egggroup')] = 'flying type';
|
|
|
|
index[index.indexOf('dragon type')] = 'dragon egggroup';
|
|
index[index.indexOf('dragon egggroup')] = 'dragon type';
|
|
|
|
index[index.indexOf('bug type')] = 'bug egggroup';
|
|
index[index.indexOf('bug egggroup')] = 'bug type';
|
|
|
|
index[index.indexOf('psychic type')] = 'psychic move';
|
|
index[index.indexOf('psychic move')] = 'psychic type';
|
|
|
|
index[index.indexOf('ditto pokemon')] = 'ditto egggroup';
|
|
index[index.indexOf('ditto egggroup')] = 'ditto pokemon';
|
|
|
|
|
|
let BattleSearchIndex = index.map(x => {
|
|
x = x.split(' ');
|
|
if (x.length > 3) {
|
|
x[3] = Number(x[3]);
|
|
x[2] = index.indexOf(x[2] + ' ' + x[1]);
|
|
}
|
|
return x;
|
|
});
|
|
|
|
let BattleSearchIndexOffset = BattleSearchIndex.map((entry, i) => {
|
|
const id = entry[0];
|
|
let name = '';
|
|
switch (entry[1]) {
|
|
case 'pokemon': name = Dex.species.get(id).name; break;
|
|
case 'move': name = Dex.moves.get(id).name; break;
|
|
case 'item': name = Dex.items.get(id).name; break;
|
|
case 'ability': name = Dex.abilities.get(id).name; break;
|
|
case 'article': name = BattleArticleTitles[id] || ''; break;
|
|
}
|
|
let res = '';
|
|
let nonAlnum = 0;
|
|
for (let i = 0, j = 0; i < id.length; i++, j++) {
|
|
while (!/[a-zA-Z0-9]/.test(name[j])) {
|
|
j++;
|
|
nonAlnum++;
|
|
}
|
|
res += nonAlnum;
|
|
}
|
|
if (nonAlnum) return res;
|
|
return '';
|
|
});
|
|
|
|
let BattleSearchCountIndex = {};
|
|
for (const type in Dex.data.TypeChart) {
|
|
BattleSearchCountIndex[type + ' move'] = Object.keys(Dex.data.Moves).filter(id => (Dex.data.Moves[id].type === type)).length;
|
|
}
|
|
|
|
for (const type in Dex.data.TypeChart) {
|
|
BattleSearchCountIndex[type + ' pokemon'] = Object.keys(Dex.data.Pokedex).filter(id => (Dex.data.Pokedex[id].types.indexOf(type) >= 0)).length;
|
|
}
|
|
|
|
let buf = '// DO NOT EDIT - automatically built with build-tools/build-indexes\n\n';
|
|
|
|
buf += 'exports.BattleSearchIndex = ' + JSON.stringify(BattleSearchIndex) + ';\n\n';
|
|
|
|
buf += 'exports.BattleSearchIndexOffset = ' + JSON.stringify(BattleSearchIndexOffset) + ';\n\n';
|
|
|
|
buf += 'exports.BattleSearchCountIndex = ' + JSON.stringify(BattleSearchCountIndex) + ';\n\n';
|
|
|
|
buf += 'exports.BattleArticleTitles = ' + JSON.stringify(BattleArticleTitles) + ';\n\n';
|
|
|
|
fs.writeFileSync('data/search-index.js', buf);
|
|
}
|
|
|
|
console.log("DONE");
|
|
|
|
/*********************************************************
|
|
* Build teambuilder-tables.js
|
|
*********************************************************/
|
|
|
|
const restrictedLegends = ['Mewtwo', 'Lugia', 'Ho-Oh', 'Kyogre', 'Groudon', 'Rayquaza', 'Dialga', 'Palkia', 'Giratina', 'Reshiram', 'Zekrom', 'Kyurem', 'Xerneas', 'Yveltal', 'Zygarde', 'Cosmog', 'Cosmoem', 'Solgaleo', 'Lunala', 'Necrozma'];
|
|
const mythicals = ['Mew', 'Celebi', 'Jirachi', 'Deoxys', 'Phione', 'Manaphy', 'Darkrai', 'Shaymin', 'Arceus', 'Victini', 'Keldeo', 'Meloetta', 'Genesect', 'Diancie', 'Hoopa', 'Volcanion', 'Greninja-Ash', 'Magearna', 'Marshadow', 'Zeraora'];
|
|
|
|
process.stdout.write("Building `data/teambuilder-tables.js`... ");
|
|
|
|
{
|
|
const BattleTeambuilderTable = {};
|
|
|
|
let buf = '// DO NOT EDIT - automatically built with build-tools/build-indexes\n\n';
|
|
const GENS = [8, 7, 6, 5, 4, 3, 2, 1];
|
|
const DOUBLES = GENS.filter(x => x > 2).map(num => -num);
|
|
const NFE = GENS.map(num => num + 0.3);
|
|
const OTHER = [8.4, 8.2, 8.1, -8.4, 7.1, -7.5];
|
|
|
|
// process.stdout.write("\n ");
|
|
for (const genIdent of [...GENS, ...DOUBLES, ...NFE, ...OTHER]) {
|
|
const isLetsGo = (genIdent === 7.1);
|
|
const isMetBattle = (genIdent === 8.2);
|
|
const isNFE = (('' + genIdent).endsWith('.3'));
|
|
const isDLC1 = (genIdent === 8.4 || genIdent === -8.4);
|
|
const isNatDex = (genIdent === 8.1);
|
|
const isDoubles = (genIdent < 0);
|
|
const isVGC = (genIdent === -7.5);
|
|
const genNum = Math.floor(isDoubles ? -genIdent : genIdent);
|
|
const gen = 'gen' + genNum + (isDLC1 ? 'dlc1' : isLetsGo ? 'letsgo' : '');
|
|
// process.stdout.write("" + gen + (isDoubles ? " doubles" : "") + "... ");
|
|
const pokemon = Object.keys(Dex.data.Pokedex);
|
|
pokemon.sort();
|
|
const tierTable = {};
|
|
const overrideTier = {};
|
|
const zuBans = {};
|
|
const nonstandardMoves = [];
|
|
for (const id of pokemon) {
|
|
const species = Dex.mod(gen).species.get(id);
|
|
if (species.gen > genNum) continue;
|
|
const tier = (() => {
|
|
if (isNatDex) {
|
|
const unobtainables = [
|
|
'Eevee-Starter', 'Floette-Eternal', 'Pichu-Spiky-eared', 'Pikachu-Belle', 'Pikachu-Cosplay', 'Pikachu-Libre', 'Pikachu-PhD', 'Pikachu-Pop-Star', 'Pikachu-Rock-Star', 'Pikachu-Starter', 'Eternatus-Eternamax',
|
|
].map(toID);
|
|
if (species.isNonstandard && !['Past', 'Gigantamax'].includes(species.isNonstandard)) return 'Illegal';
|
|
if (unobtainables.includes(species.id)) return 'Illegal';
|
|
const uu = Dex.formats.get('gen8nationaldexuu');
|
|
const ou = Dex.formats.get('gen8nationaldex');
|
|
if (Dex.formats.getRuleTable(ou).isBannedSpecies(species)) return 'Uber';
|
|
if (Dex.formats.getRuleTable(ou).has('dynamaxclause') && species.name.endsWith('Gmax')) return '(Uber)';
|
|
if (Tags.nduubl.speciesFilter(species)) return 'UUBL';
|
|
if (Dex.formats.getRuleTable(uu).isBannedSpecies(species)) return 'OU';
|
|
if (Dex.formats.getRuleTable(uu).isRestrictedSpecies(species)) {
|
|
return 'UU';
|
|
} else {
|
|
if (species.nfe) {
|
|
if (species.prevo) {
|
|
return 'NFE';
|
|
} else {
|
|
return 'LC';
|
|
}
|
|
}
|
|
return '(UU)';
|
|
}
|
|
}
|
|
if (isMetBattle) {
|
|
let tier = species.tier;
|
|
if (species.isNonstandard) {
|
|
if (species.isNonstandard === 'Past') {
|
|
tier = Dex.mod('gen7').species.get(species.name).tier;
|
|
} else {
|
|
tier = 'OU';
|
|
}
|
|
}
|
|
if (species.isNonstandard === 'Gigantamax') tier = '(Uber)';
|
|
if (species.tier === 'CAP LC') tier = 'LC';
|
|
if (species.tier === 'CAP NFE') tier = 'NFE';
|
|
if (species.tier === 'CAP') tier = 'OU';
|
|
const format = Dex.formats.get('gen8metronomebattle');
|
|
let bst = 0;
|
|
for (const stat of Object.values(species.baseStats)) {
|
|
bst += stat;
|
|
}
|
|
if (bst > 625) tier = 'Illegal';
|
|
if (Dex.formats.getRuleTable(format).isBannedSpecies(species)) tier = 'Illegal';
|
|
if (species.types.includes('Steel')) tier = 'Illegal';
|
|
return tier;
|
|
}
|
|
if (isNFE) {
|
|
let tier = species.tier;
|
|
if (!species.nfe) tier = 'Illegal';
|
|
const format = Dex.formats.get(gen + 'nfe');
|
|
const banlist = Dex.formats.getRuleTable(format);
|
|
if (banlist.isBannedSpecies(species)) {
|
|
tier = 'Uber';
|
|
}
|
|
return tier;
|
|
}
|
|
if (isLetsGo) {
|
|
let baseSpecies = Dex.mod(gen).species.get(species.baseSpecies);
|
|
let validNum = (baseSpecies.num <= 151 && species.num >= 1) || [808, 809].includes(baseSpecies.num);
|
|
if (!validNum) return 'Illegal';
|
|
if (species.forme && !['Alola', 'Mega', 'Mega-X', 'Mega-Y', 'Starter'].includes(species.forme)) return 'Illegal';
|
|
return species.tier;
|
|
}
|
|
if (isVGC) {
|
|
if (species.tier === 'NFE') return 'NFE';
|
|
if (species.tier === 'LC') return 'NFE';
|
|
if (species.tier === 'Illegal' || species.tier === 'Unreleased') return 'Illegal';
|
|
if (restrictedLegends.includes(species.name) || restrictedLegends.includes(species.baseSpecies)) {
|
|
return 'Restricted Legendary';
|
|
}
|
|
if (mythicals.includes(species.name) || mythicals.includes(species.baseSpecies)) {
|
|
return 'Mythical';
|
|
}
|
|
return 'Regular';
|
|
}
|
|
if (species.tier === 'CAP' || species.tier === 'CAP NFE' || species.tier === 'CAP LC') {
|
|
return species.tier;
|
|
}
|
|
if (isDoubles && genNum > 4) {
|
|
return species.doublesTier;
|
|
}
|
|
return species.tier;
|
|
})();
|
|
overrideTier[species.id] = tier;
|
|
if (species.forme) {
|
|
if (
|
|
[
|
|
'Aegislash', 'Castform', 'Cherrim', 'Cramorant', 'Eiscue', 'Meloetta', 'Mimikyu', 'Minior', 'Morpeko', 'Wishiwashi',
|
|
].includes(species.baseSpecies) || species.forme.includes('Totem') || species.forme.includes('Zen')
|
|
) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!tierTable[tier]) tierTable[tier] = [];
|
|
tierTable[tier].push(id);
|
|
|
|
if (gen === 'gen7' && id in {ferroseed:1} && tier !== 'LC') {
|
|
if (!tierTable['LC']) tierTable['LC'] = [];
|
|
tierTable['LC'].push(id);
|
|
} else if (gen === 'gen6' && id in {ferroseed:1, pawniard:1, vullaby:1} && tier !== 'LC') {
|
|
if (!tierTable['LC']) tierTable['LC'] = [];
|
|
tierTable['LC'].push(id);
|
|
} else if (gen === 'gen5' && id in {misdreavus:1, ferroseed:1} && tier !== 'LC') {
|
|
if (!tierTable['LC']) tierTable['LC'] = [];
|
|
tierTable['LC'].push(id);
|
|
} else if (gen === 'gen4' && id in {clamperl:1, diglett:1, gligar:1, hippopotas:1, snover:1, wynaut:1} && tier !== 'LC') {
|
|
if (!tierTable['LC']) tierTable['LC'] = [];
|
|
tierTable['LC'].push(id);
|
|
}
|
|
|
|
if (genNum >= 7) {
|
|
const format = Dex.formats.get(gen + 'zu');
|
|
if (Dex.formats.getRuleTable(format).isBannedSpecies(species) && ["(PU)", "NFE", "LC"].includes(species.tier)) {
|
|
zuBans[species.id] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
nonstandardMoves.push(...Object.keys(Dex.data.Moves).filter(id => {
|
|
const move = Dex.mod('gen8dlc1').moves.get(id);
|
|
const bMove = Dex.mod('gen8').moves.get(id);
|
|
return bMove.isNonstandard !== move.isNonstandard;
|
|
}));
|
|
|
|
const tiers = [];
|
|
const items = [];
|
|
const formatSlices = {};
|
|
|
|
if (isNatDex) {
|
|
BattleTeambuilderTable['natdex'] = {};
|
|
BattleTeambuilderTable['natdex'].tiers = tiers;
|
|
BattleTeambuilderTable['natdex'].items = items;
|
|
BattleTeambuilderTable['natdex'].formatSlices = formatSlices;
|
|
} else if (isMetBattle) {
|
|
BattleTeambuilderTable['metronome'] = {};
|
|
BattleTeambuilderTable['metronome'].tiers = tiers;
|
|
BattleTeambuilderTable['metronome'].items = items;
|
|
BattleTeambuilderTable['metronome'].formatSlices = formatSlices;
|
|
} else if (isNFE) {
|
|
BattleTeambuilderTable[gen + 'nfe'] = {};
|
|
BattleTeambuilderTable[gen + 'nfe'].tiers = tiers;
|
|
BattleTeambuilderTable[gen + 'nfe'].overrideTier = overrideTier;
|
|
BattleTeambuilderTable[gen + 'nfe'].formatSlices = formatSlices;
|
|
} else if (isLetsGo) {
|
|
BattleTeambuilderTable['letsgo'] = {};
|
|
BattleTeambuilderTable['letsgo'].learnsets = {};
|
|
BattleTeambuilderTable['letsgo'].tiers = tiers;
|
|
BattleTeambuilderTable['letsgo'].overrideTier = overrideTier;
|
|
BattleTeambuilderTable['letsgo'].formatSlices = formatSlices;
|
|
} else if (isVGC) {
|
|
BattleTeambuilderTable[gen + 'vgc'] = {};
|
|
BattleTeambuilderTable[gen + 'vgc'].tiers = tiers;
|
|
BattleTeambuilderTable[gen + 'vgc'].formatSlices = formatSlices;
|
|
} else if (isDoubles) {
|
|
BattleTeambuilderTable[gen + 'doubles'] = {};
|
|
BattleTeambuilderTable[gen + 'doubles'].tiers = tiers;
|
|
BattleTeambuilderTable[gen + 'doubles'].overrideTier = overrideTier;
|
|
BattleTeambuilderTable[gen + 'doubles'].formatSlices = formatSlices;
|
|
} else if (gen === 'gen8') {
|
|
BattleTeambuilderTable.tiers = tiers;
|
|
BattleTeambuilderTable.items = items;
|
|
BattleTeambuilderTable.overrideTier = overrideTier;
|
|
BattleTeambuilderTable.zuBans = zuBans;
|
|
BattleTeambuilderTable.formatSlices = formatSlices;
|
|
} else {
|
|
BattleTeambuilderTable[gen] = {};
|
|
BattleTeambuilderTable[gen].overrideTier = overrideTier;
|
|
BattleTeambuilderTable[gen].tiers = tiers;
|
|
BattleTeambuilderTable[gen].items = items;
|
|
BattleTeambuilderTable[gen].formatSlices = formatSlices;
|
|
if (genNum >= 7) {
|
|
BattleTeambuilderTable[gen].zuBans = zuBans;
|
|
}
|
|
if (isDLC1) {
|
|
BattleTeambuilderTable[gen].nonstandardMoves = nonstandardMoves;
|
|
BattleTeambuilderTable[gen].learnsets = {};
|
|
}
|
|
}
|
|
|
|
const tierOrder = (() => {
|
|
if (isNatDex) {
|
|
return ["CAP", "CAP NFE", "CAP LC", "AG", "Uber", "OU", "UUBL", "(OU)", "UU", "(UU)", "NFE", "LC"];
|
|
}
|
|
if (isLetsGo) {
|
|
return ["Uber", "OU", "UU", "NFE", "LC"];
|
|
}
|
|
if (isVGC) {
|
|
return ["Mythical", "Restricted Legendary", "Regular", "NFE", "LC"];
|
|
}
|
|
if (isDoubles && genNum > 4) {
|
|
return ["DUber", "(DUber)", "DOU", "DBL", "(DOU)", "DUU", "(DUU)", "New", "NFE", "LC"];
|
|
}
|
|
if (gen === 'gen1' || gen === 'gen2' || gen === 'gen3') {
|
|
return ["Uber", "OU", "(OU)", "UUBL", "UU", "NUBL", "NU", "PUBL", "PU", "NFE", "LC"];
|
|
}
|
|
if (gen === 'gen4') {
|
|
return ["CAP", "CAP NFE", "CAP LC", "AG", "Uber", "OU", "(OU)", "UUBL", "UU", "NUBL", "NU", "NFE", "LC"];
|
|
}
|
|
if (gen === 'gen5') {
|
|
return ["CAP", "CAP NFE", "CAP LC", "Uber", "OU", "(OU)", "UUBL", "UU", "RUBL", "RU", "NUBL", "NU", "(NU)", "NFE", "LC"];
|
|
}
|
|
if (gen === 'gen7') {
|
|
return ["CAP", "CAP NFE", "CAP LC", "AG", "Uber", "OU", "(OU)", "UUBL", "UU", "RUBL", "RU", "NUBL", "NU", "PUBL", "PU", "(PU)", "NFE", "LC", "Unreleased"];
|
|
}
|
|
return ["CAP", "CAP NFE", "CAP LC", "AG", "Uber", "(Uber)", "OU", "(OU)", "UUBL", "UU", "RUBL", "RU", "NUBL", "NU", "PUBL", "PU", "(PU)", "New", "NFE", "LC", "Unreleased"];
|
|
})();
|
|
|
|
for (const tier of tierOrder) {
|
|
if (tier in {OU:1, AG:1, Uber:1, UU:1, "(UU)":1, RU:1, NU:1, "(NU)":1, PU:1, "(PU)":1, NFE:1, LC:1, DOU:1, DUU:1, "(DUU)":1, New:1, Legal:1, Regular:1, "Restricted Legendary":1, "CAP LC":1}) {
|
|
let usedTier = tier;
|
|
if (usedTier === "(UU)") usedTier = "RU";
|
|
if (usedTier === "(NU)") usedTier = "PU";
|
|
if (usedTier === "(PU)") usedTier = "ZU";
|
|
if (usedTier === "(DUU)") usedTier = "DNU";
|
|
formatSlices[usedTier] = tiers.length;
|
|
}
|
|
if (!tierTable[tier]) continue;
|
|
if (tier === "(UU)") {
|
|
tiers.push(['header', "Below UU"]);
|
|
} else if (tier === "(NU)") {
|
|
tiers.push(['header', "Below NU"]);
|
|
} else if (tier === "(PU)") {
|
|
tiers.push(['header', "Below PU"]);
|
|
} else if (tier === "(DUU)") {
|
|
tiers.push(['header', "Below DUU"]);
|
|
} else if (tier.charAt(0) === '(') {
|
|
tiers.push(['header', tier.slice(1, -1) + " by technicality"]);
|
|
} else if (tier === "NFE") {
|
|
tiers.push(['header', "NFEs not in a higher tier"]);
|
|
} else {
|
|
tiers.push(['header', tier]);
|
|
}
|
|
tiers.push(...tierTable[tier]);
|
|
}
|
|
if (!isDoubles) {
|
|
if (!formatSlices['OU']) formatSlices['OU'] = formatSlices['New'];
|
|
if (!formatSlices['UU']) formatSlices['UU'] = formatSlices['New'];
|
|
if (!formatSlices['RU']) formatSlices['RU'] = formatSlices['New'];
|
|
} else {
|
|
if (!formatSlices['DOU']) formatSlices['DOU'] = formatSlices['New'];
|
|
if (!formatSlices['DUU']) formatSlices['DUU'] = formatSlices['New'];
|
|
}
|
|
|
|
const itemList = Object.keys(Dex.data.Items);
|
|
itemList.sort();
|
|
|
|
const greatItems = [['header', "Popular items"]];
|
|
const goodItems = [['header', "Items"]];
|
|
const specificItems = [['header', "Pokémon-specific items"]];
|
|
const poorItems = [['header', "Usually useless items"]];
|
|
const badItems = [['header', "Useless items"]];
|
|
const unreleasedItems = [];
|
|
if (genNum === 6) unreleasedItems.push(['header', "Unreleased"]);
|
|
for (const id of itemList) {
|
|
const item = Dex.mod(gen).items.get(id);
|
|
if (item.gen > genNum) {
|
|
continue;
|
|
}
|
|
if (item.isNonstandard && !isMetBattle) {
|
|
if (isNatDex) {
|
|
if (item.isNonstandard !== "Past") continue;
|
|
if (!item.itemUser && !item.zMove) continue;
|
|
} else if (genNum !== 2) {
|
|
continue;
|
|
}
|
|
}
|
|
if (isMetBattle) {
|
|
const banlist = Dex.formats.getRuleTable(Dex.formats.get('gen8metronomebattle'));
|
|
if (banlist.isBanned('item:' + item.id)) continue;
|
|
}
|
|
switch (id) {
|
|
case 'leftovers':
|
|
case 'lifeorb':
|
|
case 'choiceband':
|
|
case 'choicescarf':
|
|
case 'choicespecs':
|
|
case 'eviolite':
|
|
case 'assaultvest':
|
|
case 'focussash':
|
|
case 'powerherb':
|
|
case 'rockyhelmet':
|
|
case 'heavydutyboots':
|
|
case 'expertbelt':
|
|
case 'salacberry':
|
|
greatItems.push(id);
|
|
break;
|
|
case 'mentalherb':
|
|
if (genNum > 4) greatItems.push(id);
|
|
else poorItems.push(id);
|
|
break;
|
|
case 'lumberry':
|
|
if (genNum === 2 || genNum > 6) goodItems.push(id);
|
|
else greatItems.push(id);
|
|
break;
|
|
case 'sitrusberry':
|
|
if (genNum > 6) goodItems.push(id);
|
|
else if (genNum > 3 && genNum < 7) greatItems.push(id);
|
|
else poorItems.push(id);
|
|
break;
|
|
case 'aguavberry':
|
|
case 'figyberry':
|
|
case 'iapapaberry':
|
|
case 'magoberry':
|
|
case 'wikiberry':
|
|
if (genNum >= 7) greatItems.push(id);
|
|
else poorItems.push(id);
|
|
break;
|
|
case 'berryjuice':
|
|
if (genNum === 2) poorItems.push(id);
|
|
else goodItems.push(id);
|
|
break;
|
|
case 'dragonfang':
|
|
if (genNum === 2) badItems.push(id);
|
|
else goodItems.push(id);
|
|
break;
|
|
case 'mail':
|
|
if (genNum >= 6) unreleasedItems.push(id);
|
|
else goodItems.push(id);
|
|
break;
|
|
// Legendaries
|
|
case 'adamantorb':
|
|
case 'griseousorb':
|
|
case 'lustrousorb':
|
|
case 'blueorb':
|
|
case 'redorb':
|
|
case 'souldew':
|
|
// Other
|
|
// fallsthrough
|
|
case 'stick':
|
|
case 'thickclub':
|
|
case 'lightball':
|
|
case 'luckypunch':
|
|
case 'quickpowder':
|
|
case 'metalpowder':
|
|
case 'deepseascale':
|
|
case 'deepseatooth':
|
|
specificItems.push(id);
|
|
break;
|
|
// Fling-only
|
|
case 'rarebone':
|
|
case 'belueberry':
|
|
case 'blukberry':
|
|
case 'cornnberry':
|
|
case 'durinberry':
|
|
case 'hondewberry':
|
|
case 'magostberry':
|
|
case 'nanabberry':
|
|
case 'nomelberry':
|
|
case 'pamtreberry':
|
|
case 'pinapberry':
|
|
case 'pomegberry':
|
|
case 'qualotberry':
|
|
case 'rabutaberry':
|
|
case 'razzberry':
|
|
case 'spelonberry':
|
|
case 'tamatoberry':
|
|
case 'watmelberry':
|
|
case 'wepearberry':
|
|
case 'energypowder':
|
|
case 'electirizer':
|
|
case 'oldamber':
|
|
case 'dawnstone':
|
|
case 'dragonscale':
|
|
case 'dubiousdisc':
|
|
case 'duskstone':
|
|
case 'firestone':
|
|
case 'icestone':
|
|
case 'leafstone':
|
|
case 'magmarizer':
|
|
case 'moonstone':
|
|
case 'ovalstone':
|
|
case 'prismscale':
|
|
case 'protector':
|
|
case 'reapercloth':
|
|
case 'sachet':
|
|
case 'shinystone':
|
|
case 'sunstone':
|
|
case 'thunderstone':
|
|
case 'upgrade':
|
|
case 'waterstone':
|
|
case 'whippeddream':
|
|
case 'bottlecap':
|
|
case 'goldbottlecap':
|
|
case 'galaricacuff':
|
|
badItems.push(id);
|
|
break;
|
|
// outclassed items
|
|
case 'aspearberry':
|
|
case 'bindingband':
|
|
case 'cheriberry':
|
|
case 'destinyknot':
|
|
case 'enigmaberry':
|
|
case 'floatstone':
|
|
case 'ironball':
|
|
case 'jabocaberry':
|
|
case 'oranberry':
|
|
case 'machobrace':
|
|
case 'pechaberry':
|
|
case 'persimberry':
|
|
case 'poweranklet':
|
|
case 'powerband':
|
|
case 'powerbelt':
|
|
case 'powerbracer':
|
|
case 'powerlens':
|
|
case 'powerweight':
|
|
case 'rawstberry':
|
|
case 'ringtarget':
|
|
case 'rowapberry':
|
|
case 'bigroot':
|
|
case 'focusband':
|
|
// gen 2
|
|
case 'psncureberry':
|
|
case 'przcureberry':
|
|
case 'burntberry':
|
|
case 'bitterberry':
|
|
case 'iceberry':
|
|
case 'berry':
|
|
poorItems.push(id);
|
|
break;
|
|
default:
|
|
if (
|
|
item.name.endsWith(" Ball") || item.name.endsWith(" Fossil") || item.name.startsWith("Fossilized ") ||
|
|
item.name.endsWith(" Sweet") || item.name.endsWith(" Apple")
|
|
) {
|
|
badItems.push(id);
|
|
} else if (item.name.startsWith("TR")) {
|
|
badItems.push(id);
|
|
} else if (item.name.endsWith(" Gem") && item.name !== "Normal Gem") {
|
|
if (genNum >= 6) {
|
|
unreleasedItems.push(id);
|
|
} else if (item.name === "Flying Gem") {
|
|
greatItems.push(id);
|
|
} else {
|
|
goodItems.push(id);
|
|
}
|
|
} else if (item.name.endsWith(" Drive")) {
|
|
specificItems.push(id);
|
|
} else if (item.name.endsWith(" Memory")) {
|
|
specificItems.push(id);
|
|
} else if (item.name.startsWith("Rusted")) {
|
|
specificItems.push(id);
|
|
} else if (item.itemUser) {
|
|
specificItems.push(id);
|
|
} else if (item.megaStone) {
|
|
specificItems.push(id);
|
|
} else {
|
|
goodItems.push(id);
|
|
}
|
|
}
|
|
}
|
|
items.push(...greatItems);
|
|
items.push(...goodItems);
|
|
items.push(...specificItems);
|
|
items.push(...poorItems);
|
|
items.push(...badItems);
|
|
items.push(...unreleasedItems);
|
|
}
|
|
|
|
//
|
|
// Learnset table
|
|
//
|
|
|
|
const gen3HMs = new Set(['cut', 'fly', 'surf', 'strength', 'flash', 'rocksmash', 'waterfall', 'dive']);
|
|
const gen4HMs = new Set(['cut', 'fly', 'surf', 'strength', 'rocksmash', 'waterfall', 'rockclimb']);
|
|
|
|
const learnsets = {};
|
|
BattleTeambuilderTable.learnsets = learnsets;
|
|
for (const id in Dex.data.Learnsets) {
|
|
const learnset = Dex.data.Learnsets[id].learnset;
|
|
if (!learnset) continue;
|
|
learnsets[id] = {};
|
|
for (const moveid in learnset) {
|
|
const gens = learnset[moveid].map(x => Number(x[0]));
|
|
const minGen = Math.min(...gens);
|
|
const vcOnly = (minGen === 7 && learnset[moveid].every(x => x[0] !== '7' || x === '7V') ||
|
|
minGen === 8 && learnset[moveid].every(x => x[0] !== '8' || x === '8V'));
|
|
|
|
if (minGen <= 4 && (gen3HMs.has(moveid) || gen4HMs.has(moveid))) {
|
|
let legalGens = '';
|
|
let available = false;
|
|
|
|
if (minGen === 3) {
|
|
legalGens += '3';
|
|
available = true;
|
|
}
|
|
if (available) available = !gen3HMs.has(moveid);
|
|
|
|
if (available || gens.includes(4)) {
|
|
legalGens += '4';
|
|
available = true;
|
|
}
|
|
if (available) available = !gen4HMs.has(moveid);
|
|
|
|
let minUpperGen = available ? 5 : Math.min(
|
|
...gens.filter(gen => gen > 4)
|
|
);
|
|
legalGens += '012345678'.slice(minUpperGen);
|
|
learnsets[id][moveid] = legalGens;
|
|
} else {
|
|
learnsets[id][moveid] = '012345678'.slice(minGen);
|
|
}
|
|
|
|
if (gens.indexOf(6) >= 0) learnsets[id][moveid] += 'p';
|
|
if (gens.indexOf(7) >= 0 && !vcOnly) learnsets[id][moveid] += 'q';
|
|
if (gens.indexOf(8) >= 0 && !vcOnly) learnsets[id][moveid] += 'g';
|
|
}
|
|
}
|
|
const G2Learnsets = Dex.mod('gen2').data.Learnsets;
|
|
for (const id in G2Learnsets) {
|
|
const learnset = G2Learnsets[id].learnset;
|
|
for (const moveid in learnset) {
|
|
const gens = learnset[moveid].map(x => Number(x[0]));
|
|
const minGen = Math.min(...gens);
|
|
if (!learnsets[id]) {
|
|
throw new Error(`${id} has a Gen 2 learnset but not a modern learnset`);
|
|
}
|
|
if (!learnsets[id][moveid]) learnsets[id][moveid] = '';
|
|
if (minGen === 2) learnsets[id][moveid] = '2' + learnsets[id][moveid];
|
|
if (minGen === 1) learnsets[id][moveid] = '12' + learnsets[id][moveid];
|
|
}
|
|
}
|
|
const LGLearnsets = Dex.mod('gen7letsgo').data.Learnsets;
|
|
for (const id in LGLearnsets) {
|
|
const species = Dex.mod('gen7letsgo').species.get(id);
|
|
const baseSpecies = Dex.mod('gen7letsgo').species.get(species.baseSpecies);
|
|
const validNum = (baseSpecies.num <= 151 && baseSpecies.num >= 1) || [808, 809].includes(baseSpecies.num);
|
|
if (!validNum) continue;
|
|
if (species.forme && !['Alola', 'Mega', 'Mega-X', 'Mega-Y', 'Starter'].includes(species.forme)) continue;
|
|
const learnset = LGLearnsets[id].learnset;
|
|
BattleTeambuilderTable['letsgo'].learnsets[id] = {};
|
|
for (const moveid in learnset) {
|
|
BattleTeambuilderTable['letsgo'].learnsets[id][moveid] = '7';
|
|
}
|
|
}
|
|
const DLC1Learnsets = Dex.mod('gen8dlc1').data.Learnsets;
|
|
for (const id in DLC1Learnsets) {
|
|
const learnset = DLC1Learnsets[id].learnset;
|
|
if (!learnset) continue;
|
|
BattleTeambuilderTable['gen8dlc1'].learnsets[id] = {};
|
|
for (const moveid in learnset) {
|
|
const gens = learnset[moveid].map(x => Number(x[0]));
|
|
const minGen = Math.min(...gens);
|
|
const vcOnly = (minGen === 7 && learnset[moveid].every(x => x[0] !== '7' || x === '7V') ||
|
|
minGen === 8 && learnset[moveid].every(x => x[0] !== '8' || x === '8V'));
|
|
|
|
if (minGen <= 4 && (gen3HMs.has(moveid) || gen4HMs.has(moveid))) {
|
|
let legalGens = '';
|
|
let available = false;
|
|
|
|
if (minGen === 3) {
|
|
legalGens += '3';
|
|
available = true;
|
|
}
|
|
if (available) available = !gen3HMs.has(moveid);
|
|
|
|
if (available || gens.includes(4)) {
|
|
legalGens += '4';
|
|
available = true;
|
|
}
|
|
if (available) available = !gen4HMs.has(moveid);
|
|
|
|
let minUpperGen = available ? 5 : Math.min(
|
|
...gens.filter(gen => gen > 4)
|
|
);
|
|
legalGens += '012345678'.slice(minUpperGen);
|
|
BattleTeambuilderTable['gen8dlc1'].learnsets[id][moveid] = legalGens;
|
|
} else {
|
|
BattleTeambuilderTable['gen8dlc1'].learnsets[id][moveid] = '012345678'.slice(minGen);
|
|
}
|
|
|
|
if (gens.indexOf(6) >= 0) BattleTeambuilderTable['gen8dlc1'].learnsets[id][moveid] += 'p';
|
|
if (gens.indexOf(7) >= 0 && !vcOnly) BattleTeambuilderTable['gen8dlc1'].learnsets[id][moveid] += 'q';
|
|
if (gens.indexOf(8) >= 0 && !vcOnly) BattleTeambuilderTable['gen8dlc1'].learnsets[id][moveid] += 'g';
|
|
}
|
|
}
|
|
|
|
//
|
|
// Past gen table
|
|
//
|
|
|
|
for (const genNum of [7, 6, 5, 4, 3, 2, 1]) {
|
|
const gen = 'gen' + genNum;
|
|
const nextGen = 'gen' + (genNum + 1);
|
|
const genData = Dex.mod(gen).data;
|
|
const nextGenData = Dex.mod(nextGen).data;
|
|
const overrideSpeciesData = {};
|
|
BattleTeambuilderTable[gen].overrideSpeciesData = overrideSpeciesData;
|
|
const overrideSpeciesKeys = ['abilities', 'baseStats', 'requiredItem', 'types'];
|
|
for (const id in genData.Pokedex) {
|
|
const curEntry = genData.Pokedex[id];
|
|
const nextEntry = nextGenData.Pokedex[id];
|
|
for (const key of overrideSpeciesKeys) {
|
|
if (JSON.stringify(curEntry[key]) !== JSON.stringify(nextEntry[key])) {
|
|
if (!overrideSpeciesData[id]) overrideSpeciesData[id] = {};
|
|
overrideSpeciesData[id][key] = curEntry[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
const overrideMoveData = {};
|
|
BattleTeambuilderTable[gen].overrideMoveData = overrideMoveData;
|
|
const overrideMoveKeys = ['accuracy', 'basePower', 'category', 'desc', 'flags', 'pp', 'shortDesc', 'target', 'type'];
|
|
for (const id in genData.Moves) {
|
|
const curEntry = Dex.mod(gen).moves.get(id);
|
|
const nextEntry = Dex.mod(nextGen).moves.get(id);
|
|
for (const key of overrideMoveKeys) {
|
|
if (key === 'category' && genNum <= 3) continue;
|
|
if (JSON.stringify(curEntry[key]) !== JSON.stringify(nextEntry[key])) {
|
|
if (!overrideMoveData[id]) overrideMoveData[id] = {};
|
|
overrideMoveData[id][key] = curEntry[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
const overrideItemDesc = {};
|
|
BattleTeambuilderTable[gen].overrideItemDesc = overrideItemDesc;
|
|
for (const id in genData.Items) {
|
|
const curEntry = Dex.mod(gen).items.get(id);
|
|
const nextEntry = Dex.mod(nextGen).items.get(id);
|
|
if ((curEntry.shortDesc || curEntry.desc) !== (nextEntry.shortDesc || nextEntry.desc)) {
|
|
overrideItemDesc[id] = (curEntry.shortDesc || curEntry.desc);
|
|
}
|
|
}
|
|
|
|
const overrideAbilityDesc = {};
|
|
BattleTeambuilderTable[gen].overrideAbilityDesc = overrideAbilityDesc;
|
|
for (const id in genData.Abilities) {
|
|
const curEntry = Dex.mod(gen).abilities.get(id);
|
|
const nextEntry = Dex.mod(nextGen).abilities.get(id);
|
|
if ((curEntry.shortDesc || curEntry.desc) !== (nextEntry.shortDesc || nextEntry.desc)) {
|
|
overrideAbilityDesc[id] = (curEntry.shortDesc || curEntry.desc);
|
|
}
|
|
}
|
|
|
|
const overrideTypeChart = {};
|
|
BattleTeambuilderTable[gen].overrideTypeChart = overrideTypeChart;
|
|
const removeType = {};
|
|
BattleTeambuilderTable[gen].removeType = removeType;
|
|
for (const id in nextGenData.TypeChart) {
|
|
const curEntry = genData.TypeChart[id];
|
|
const nextEntry = nextGenData.TypeChart[id];
|
|
if (curEntry.isNonstandard) {
|
|
removeType[id] = true;
|
|
continue;
|
|
}
|
|
if (JSON.stringify(nextEntry) !== JSON.stringify(curEntry)) {
|
|
overrideTypeChart[id] = curEntry;
|
|
}
|
|
}
|
|
}
|
|
|
|
buf += `exports.BattleTeambuilderTable = JSON.parse('${JSON.stringify(BattleTeambuilderTable).replace(/['\\]/g, "\\$&")}');\n\n`;
|
|
|
|
fs.writeFileSync('data/teambuilder-tables.js', buf);
|
|
}
|
|
|
|
console.log("DONE");
|
|
|
|
/*********************************************************
|
|
* Build pokedex.js
|
|
*********************************************************/
|
|
|
|
process.stdout.write("Building `data/pokedex.js`... ");
|
|
|
|
{
|
|
const Pokedex = requireNoCache('../data/pokemon-showdown/.data-dist/pokedex.js').Pokedex;
|
|
for (const id in Pokedex) {
|
|
const entry = Pokedex[id];
|
|
if (Dex.data.FormatsData[id]) {
|
|
// console.log('formatsentry:' + id);
|
|
const formatsEntry = Dex.data.FormatsData[id];
|
|
if (formatsEntry.tier) entry.tier = formatsEntry.tier;
|
|
if (formatsEntry.isNonstandard) entry.isNonstandard = formatsEntry.isNonstandard;
|
|
if (formatsEntry.unreleasedHidden) entry.unreleasedHidden = formatsEntry.unreleasedHidden;
|
|
}
|
|
}
|
|
const buf = 'exports.BattlePokedex = ' + es3stringify(Pokedex) + ';';
|
|
fs.writeFileSync('data/pokedex.js', buf);
|
|
fs.writeFileSync('data/pokedex.json', JSON.stringify(Pokedex));
|
|
}
|
|
|
|
console.log("DONE");
|
|
|
|
/*********************************************************
|
|
* Build moves.js
|
|
*********************************************************/
|
|
|
|
process.stdout.write("Building `data/moves,items,abilities,typechart,learnsets.js`...");
|
|
|
|
{
|
|
const Moves = requireNoCache('../data/pokemon-showdown/.data-dist/moves.js').Moves;
|
|
for (const id in Moves) {
|
|
const move = Dex.moves.get(Moves[id].name);
|
|
if (move.desc) Moves[id].desc = move.desc;
|
|
if (move.shortDesc) Moves[id].shortDesc = move.shortDesc;
|
|
}
|
|
const buf = 'exports.BattleMovedex = ' + es3stringify(Moves) + ';';
|
|
fs.writeFileSync('data/moves.js', buf);
|
|
fs.writeFileSync('data/moves.json', JSON.stringify(Moves));
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build items.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const Items = requireNoCache('../data/pokemon-showdown/.data-dist/items.js').Items;
|
|
for (const id in Items) {
|
|
const item = Dex.items.get(Items[id].name);
|
|
if (item.desc) Items[id].desc = item.desc;
|
|
if (item.shortDesc) Items[id].shortDesc = item.shortDesc;
|
|
}
|
|
const buf = 'exports.BattleItems = ' + es3stringify(Items) + ';';
|
|
fs.writeFileSync('data/items.js', buf);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build abilities.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const Abilities = requireNoCache('../data/pokemon-showdown/.data-dist/abilities.js').Abilities;
|
|
for (const id in Abilities) {
|
|
const ability = Dex.abilities.get(Abilities[id].name);
|
|
if (ability.desc) Abilities[id].desc = ability.desc;
|
|
if (ability.shortDesc) Abilities[id].shortDesc = ability.shortDesc;
|
|
}
|
|
const buf = 'exports.BattleAbilities = ' + es3stringify(Abilities) + ';';
|
|
fs.writeFileSync('data/abilities.js', buf);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build typechart.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const TypeChart = requireNoCache('../data/pokemon-showdown/.data-dist/typechart.js').TypeChart;
|
|
const buf = 'exports.BattleTypeChart = ' + es3stringify(TypeChart) + ';';
|
|
fs.writeFileSync('data/typechart.js', buf);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build aliases.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const Aliases = requireNoCache('../data/pokemon-showdown/.data-dist/aliases.js').Aliases;
|
|
const buf = 'exports.BattleAliases = ' + es3stringify(Aliases) + ';';
|
|
fs.writeFileSync('data/aliases.js', buf);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build formats-data.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const FormatsData = requireNoCache('../data/pokemon-showdown/.data-dist/formats-data.js').FormatsData;
|
|
const buf = 'exports.BattleFormatsData = ' + es3stringify(FormatsData) + ';';
|
|
fs.writeFileSync('data/formats-data.js', buf);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build formats.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const Formats = requireNoCache('../data/pokemon-showdown/.config-dist/formats.js').Formats;
|
|
const buf = 'exports.Formats = ' + es3stringify(Formats) + ';';
|
|
fs.writeFileSync('data/formats.js', buf);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build learnsets.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const Learnsets = requireNoCache('../data/pokemon-showdown/.data-dist/learnsets.js').Learnsets;
|
|
const buf = 'exports.BattleLearnsets = ' + es3stringify(Learnsets) + ';';
|
|
fs.writeFileSync('data/learnsets.js', buf);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Build text.js
|
|
*********************************************************/
|
|
|
|
{
|
|
const textData = Dex.loadTextData();
|
|
const Text = textData.Default;
|
|
|
|
function assignData(id, entry) {
|
|
for (const key in entry) {
|
|
if (['name', 'desc', 'shortDesc'].includes(key)) continue;
|
|
const textEntry = Text[id] || (Text[id] = {});
|
|
if (key.startsWith('gen')) {
|
|
for (const modKey in entry[key]) {
|
|
if (['desc', 'shortDesc'].includes(key)) continue;
|
|
textEntry[modKey + 'Gen' + key.charAt(3)] = entry[key][modKey];
|
|
}
|
|
} else {
|
|
textEntry[key] = entry[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const id in textData.Moves) assignData(id, textData.Moves[id]);
|
|
for (const id in textData.Abilities) assignData(id, textData.Abilities[id]);
|
|
for (const id in textData.Items) assignData(id, textData.Items[id]);
|
|
|
|
const buf = 'exports.BattleText = ' + es3stringify(Text) + ';';
|
|
fs.writeFileSync('data/text.js', buf);
|
|
}
|
|
|
|
console.log("DONE");
|