diff --git a/.eslintrc.js b/.eslintrc.js index 2f83eb384..9c820e10c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,10 +19,10 @@ module.exports = { "BattleAbilities": false, "BattleAliases": false, "BattleBackdrops": false, "BattleBackdropsFour": false, "BattleBackdropsThree": false, "BattleEffects": false, "BattleFormats": false, "BattleFormatsData": false, "BattleLearnsets": false, "BattleItems": false, "BattleMoveAnims": false, "BattleMovedex": false, "BattleNatures": false, "BattleOtherAnims": false, "BattlePokedex": false,"BattlePokemonSprites": false, "BattlePokemonSpritesBW": false, "BattleSearchCountIndex": false, "BattleSearchIndex": false, - "BattleSearchIndexOffset": false, "BattleSearchIndexType": false, "BattleStatIDs": false, "BattleStatNames": false, "BattleStats": false, "BattleStatusAnims": false, "BattleStatuses": false, + "BattleSearchIndexOffset": false, "BattleSearchIndexType": false, "BattleStatIDs": false, "BattleStatNames": false, "BattleStats": false, "BattleStatusAnims": false, "BattleStatuses": false, "BattleTeambuilderTable": false, // Generic global variables - "Config": false, "Chart": false, "soundManager": false, "Storage": false, "Tools": false, + "Config": false, "BattleSearch": false, "soundManager": false, "Storage": false, "Tools": false, "app": false, "toId": false, "toRoomid": false, "toUserid": false, "toName": false, "hashColor": false, "MD5": false, "ChatHistory": false, "Topbar": false, "UserList": false, diff --git a/githooks/build-indexes b/githooks/build-indexes index c90318ced..1f4bf185c 100755 --- a/githooks/build-indexes +++ b/githooks/build-indexes @@ -103,3 +103,51 @@ const fs = require("fs"); } console.log("DONE"); + +/********************************************************* + * Build teambuilder-tables.js + *********************************************************/ + +process.stdout.write("Building `data/teambuilder-tables.js`... "); + +{ + const BattleTeambuilderTable = {}; + + let buf = '// automatically built with githooks/build-indexes\n\n'; + + const pokemon = Object.keys(Tools.data.Pokedex); + pokemon.sort(); + const tierTable = {}; + for (const id of pokemon) { + const tier = Tools.getTemplate(id).tier; + + if (!tierTable[tier]) tierTable[tier] = []; + tierTable[tier].push(id); + } + + const tiers = BattleTeambuilderTable.tiers = []; + const formatSlices = BattleTeambuilderTable.formatSlices = {}; + + const tierOrder = ["Uber", "OU", "BL", "(OU)", "UU", "BL2", "RU", "BL3", "NU", "BL4", "PU", "NFE", "LC Uber", "LC"]; + + for (const tier of tierOrder) { + if (tier === "OU" || tier === "Uber" || tier === "UU" || tier === "RU" || tier === "NU" || tier === "PU" || tier === "LC") { + formatSlices[tier] = tiers.length; + } + if (!tierTable[tier]) continue; + 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]); + } + + buf += 'exports.BattleTeambuilderTable = ' + JSON.stringify(BattleTeambuilderTable) + ';\n\n'; + + fs.writeFileSync('data/teambuilder-tables.js', buf); +} + +console.log("DONE"); diff --git a/index.template.html b/index.template.html index 5667b9096..da9269fc2 100644 --- a/index.template.html +++ b/index.template.html @@ -164,7 +164,9 @@ ga('send', 'pageview'); - + + + diff --git a/js/battledata.js b/js/battledata.js index 20824a55f..abdb23fe8 100644 --- a/js/battledata.js +++ b/js/battledata.js @@ -409,16 +409,16 @@ var Tools = { return '
'; case 'data-pokemon': if (!window.Chart) return ''; - return ''; + return ''; case 'data-item': if (!window.Chart) return ''; - return ''; + return ''; case 'data-ability': if (!window.Chart) return ''; - return ''; + return ''; case 'data-move': if (!window.Chart) return ''; - return ''; + return ''; case 'text': return 'Filters: '; for (var i = 0; i < this.filters.length; i++) { - if (i) buf += ', '; var text = this.filters[i][1]; - if (this.filters[i][0] === 'moves') text = Tools.getMove(text).name; + if (this.filters[i][0] === 'move') text = Tools.getMove(text).name; if (this.filters[i][0] === 'pokemon') text = Tools.getTemplate(text).name; - buf += '' + text + ''; + buf += ' '; } - if (!q) buf += ' (backspace = delete filter)'; - return buf; + if (!q) buf += '(backspace = delete filter)'; + return buf + '
'; }; Search.prototype.filteredPokemon = function () { var resultSet = [['html', this.getFilterText(), 0]]; resultSet.push(['header', "Filtered results", 0]); + var illegalResultSet = []; var filters = this.filters; for (var id in BattlePokedex) { var template = BattlePokedex[id]; + if (template.exists === false) continue; for (var i = 0; i < filters.length; i++) { - if (filters[i][0] === 'types') { + if (filters[i][0] === 'type') { var type = filters[i][1]; if (template.types[0] !== type && template.types[1] !== type) break; - } else if (filters[i][0] === 'egggroups') { + } else if (filters[i][0] === 'egggroup') { var egggroup = filters[i][1]; if (template.eggGroups[0] !== egggroup && template.eggGroups[1] !== egggroup) break; - } else if (filters[i][0] === 'abilities') { + } else if (filters[i][0] === 'ability') { var ability = filters[i][1]; if (template.abilities['0'] !== ability && template.abilities['1'] !== ability && template.abilities['H'] !== ability) break; - } else if (filters[i][0] === 'moves') { + } else if (filters[i][0] === 'move') { var learned = false; var learnsetid = id; while (true) { @@ -345,9 +375,13 @@ } } if (i < filters.length) continue; - resultSet.push(['pokemon', id, 0]); + if (this.legalityFilter && !(id in this.legalityFilter)) { + illegalResultSet.push(['pokemon', id, -1]); + } else { + resultSet.push(['pokemon', id, 0]); + } } - this.resultSet = resultSet; + this.resultSet = resultSet.concat(illegalResultSet); this.renderedIndex = 0; this.renderingDone = false; this.updateScroll(); @@ -355,13 +389,15 @@ Search.prototype.filteredMoves = function () { var resultSet = [['html', this.getFilterText(), 0]]; resultSet.push(['header', "Filtered results", 0]); + var illegalResultSet = []; var filters = this.filters; for (var id in BattleMovedex) { var move = BattleMovedex[id]; + if (move.exists === false) continue; for (var i = 0; i < filters.length; i++) { - if (filters[i][0] === 'types') { + if (filters[i][0] === 'type') { if (move.type !== filters[i][1]) break; - } else if (filters[i][0] === 'categories') { + } else if (filters[i][0] === 'category') { if (move.category !== filters[i][1]) break; } else if (filters[i][0] === 'pokemon') { var learned = false; @@ -381,9 +417,13 @@ } } if (i < filters.length) continue; - resultSet.push(['move', id, 0]); + if (this.legalityFilter && !(id in this.legalityFilter)) { + illegalResultSet.push(['move', id, -1]); + } else { + resultSet.push(['move', id, 0]); + } } - this.resultSet = resultSet; + this.resultSet = resultSet.concat(illegalResultSet); this.renderedIndex = 0; this.renderingDone = false; this.updateScroll(); @@ -397,29 +437,142 @@ if (forceAdd && finalIndex < i + 20) finalIndex = i + 20; if (finalIndex <= i) return; + var resultSet = this.resultSet || this.defaultResultSet; var buf = ''; while (i < finalIndex) { - if (!this.resultSet[i]) { + if (!resultSet[i]) { this.renderingDone = true; break; } - var row = this.resultSet[i]; + var row = resultSet[i]; - buf += Search.renderRow(row[1], row[0], 0, row[2]); + var errorMessage = ''; + if (row[2] < 0) { + errorMessage = '' + this.legalityLabel + ''; + row[2] = 0; + } + + buf += Search.renderRow(row[1], row[0], 0, row[2], errorMessage, row[1] in this.cur ? ' class="cur"' : ''); i++; } if (!this.renderedIndex) { - this.el.innerHTML = 'Will be ' + Tools.escapeHTML(template.abilities['0']) + ' after Mega Evolving.
']); + template = Tools.getTemplate(template.baseSpecies); + } + abilitySet.push(['ability', toId(template.abilities['0']), 0]); + if (template.abilities['1']) { + abilitySet.push(['ability', toId(template.abilities['1']), 0]); + } + if (template.abilities['H']) { + abilitySet.push(['header', "Hidden Ability", 0]); + abilitySet.push(['ability', toId(template.abilities['H']), 0]); + } + this.defaultResultSet = abilitySet; + break; + + case 'move': + template = Tools.getTemplate(set.species); + var moves = []; + while (true) { + var learnsetTemplate = BattleLearnsets[toId(template.baseSpecies)]; + if (learnsetTemplate) { + for (var l in learnsetTemplate.learnset) { + if (requirePentagon && !learnsetTemplate.learnset[l].length) continue; + if (moves.indexOf(l) >= 0) continue; + moves.push(l); + if (l === 'hiddenpower') { + moves.push('hiddenpowerbug', 'hiddenpowerdark', 'hiddenpowerdragon', 'hiddenpowerelectric', 'hiddenpowerfighting', 'hiddenpowerfire', 'hiddenpowerflying', 'hiddenpowerghost', 'hiddenpowergrass', 'hiddenpowerground', 'hiddenpowerice', 'hiddenpowerpoison', 'hiddenpowerpsychic', 'hiddenpowerrock', 'hiddenpowersteel', 'hiddenpowerwater'); + } + } + } + if (template.baseSpecies && !learnsetTemplate) template = BattlePokedex[toId(template.baseSpecies)]; + else if (template.prevo) template = BattlePokedex[template.prevo]; + else break; + } + moves.sort(); + + var usableMoves = []; + var uselessMoves = []; + for (var i = 0; i < moves.length; i++) { + var id = moves[i]; + if (BattleMovedex[id] && BattleMovedex[id].isViable) { + if (!usableMoves.length) usableMoves.push(['header', "Moves", 0]); + usableMoves.push(['move', id, 0]); + } else { + if (!uselessMoves.length) uselessMoves.push(['header', "Usually useless moves", 0]); + uselessMoves.push(['move', id, 0]); + } + } + this.defaultResultSet = usableMoves.concat(uselessMoves); + break; + } + + if (this.legalityFilter) { + for (var i = 0; i < this.defaultResultSet.length; i++) { + if (this.defaultResultSet[i][0] !== 'header') { + this.legalityFilter[this.defaultResultSet[i][1]] = 1; + } + } + } + + this.renderedIndex = 0; + this.renderingDone = false; + this.find(''); + }; Search.getClosest = function (query) { // binary search through the index! @@ -439,13 +592,13 @@ return left; }; - // - // Rendering functions - // - // These are all static! - // +/********************************************************* + * Rendering functions + *********************************************************/ - Search.renderRow = function (id, type, matchStart, matchLength, errorMessage) { + // These are all static! + + Search.renderRow = function (id, type, matchStart, matchLength, errorMessage, attrs) { // errorMessage = '' + errorMessage + ''; switch (type) { case 'html': @@ -454,16 +607,16 @@ return '