Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Copyright (c) 2011-2014 Guangcong Luo and other contributors
- * http://pokemonshowdown.com/
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **/
- /* config/formats.js */
- {
- name: "TYPEmons",
- ruleset: ['Pokemon', 'Species Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Team Preview', 'Swagger Clause', 'Baton Pass Clause', 'Sleep Clause Mod'],
- banlist: ['Unreleased', 'Uber', 'Soul Dew', 'Gengarite', 'Kangaskhanite', 'Lucarionite', 'Mawilite', 'Salamencite',
- 'Gengar-Mega', 'Kangaskhan-Mega', 'Mewtwo', 'Lugia', 'Ho-Oh', 'Blaziken', 'Mawile-Mega', 'Salamence-Mega',
- 'Kyogre', 'Groudon', 'Rayquaza', 'Deoxys', 'Deoxys-Attack', 'Deoxys-Defense', 'Deoxys-Speed', 'Lucario-Mega',
- 'Dialga', 'Palkia', 'Giratina', 'Giratina-Origin', 'Darkrai', 'Shaymin-Sky', 'Arceus', 'Reshiram', 'Zekrom',
- 'Kyurem-White', 'Genesect', 'Greninja', 'Aegislash', 'Xerneas', 'Yveltal'
- ],
- validateTeam: function (team, format) {
- for (var type in this.data.TypeChart) {
- var problems = [];
- var teamHas = {formatType: type};
- for (var i = 0; i < team.length; i++) {
- var setProblems = format.customValidateSet.call(this, team[i], teamHas);
- if (setProblems) {
- problems = problems.concat(setProblems);
- }
- }
- for (var i = 0; i < format.teamBanTable.length; i++) {
- var bannedCombo = true;
- for (var j = 0; j < format.teamBanTable[i].length; j++) {
- if (!teamHas[format.teamBanTable[i][j]]) {
- bannedCombo = false;
- break;
- }
- }
- if (bannedCombo) {
- var clause = format.name ? " by " + format.name : '';
- problems.push("Your team has the combination of " + format.teamBanTable[i].join(' + ') + ", which is banned" + clause + ".");
- }
- }
- if (format.ruleset) {
- for (var i = 0; i < format.ruleset.length; i++) {
- var subformat = this.getFormat(format.ruleset[i]);
- if (subformat.validateTeam) {
- problems = problems.concat(subformat.validateTeam.call(this, team, format, teamHas) || []);
- }
- }
- }
- if (!problems.length) return false;
- }
- return problems;
- },
- customValidateSet: function (set, teamHas) {
- var format = this.getFormat('typemons');
- var problems = [];
- var isHidden = false;
- var lsetData = {set:set, format:format};
- var name = set.name || set.species;
- var setHas = {};
- if (format.ruleset) {
- for (var i = 0; i < format.ruleset.length; i++) {
- var subformat = this.getFormat(format.ruleset[i]);
- if (subformat.validateSet) {
- problems = problems.concat(subformat.validateSet.call(this, set, format) || []);
- }
- }
- }
- template = this.getTemplate(set.species);
- item = this.getItem(set.item);
- ability = this.getAbility(set.ability);
- var banlistTable = this.getBanlistTable(format);
- var check = template.id;
- var clause = '';
- setHas[check] = true;
- if (banlistTable[check]) {
- clause = typeof banlistTable[check] === 'string' ? " by " + banlistTable[check] : '';
- problems.push(set.species + ' is banned' + clause + '.');
- } else if (!this.data.FormatsData[check] || !this.data.FormatsData[check].tier) {
- check = toId(template.baseSpecies);
- if (banlistTable[check]) {
- clause = typeof banlistTable[check] === 'string' ? " by " + banlistTable[check] : '';
- problems.push(template.baseSpecies + ' is banned' + clause + '.');
- }
- }
- check = toId(set.ability);
- setHas[check] = true;
- if (banlistTable[check]) {
- clause = typeof banlistTable[check] === 'string' ? " by " + banlistTable[check] : '';
- problems.push(name + "'s ability " + set.ability + " is banned" + clause + ".");
- }
- check = toId(set.item);
- setHas[check] = true;
- if (banlistTable[check]) {
- clause = typeof banlistTable[check] === 'string' ? " by " + banlistTable[check] : '';
- problems.push(name + "'s item " + set.item + " is banned" + clause + ".");
- }
- if (banlistTable['Unreleased'] && item.isUnreleased) {
- problems.push(name + "'s item " + set.item + " is unreleased.");
- }
- if (banlistTable['Unreleased'] && template.isUnreleased) {
- if (!format.requirePentagon || (template.eggGroups[0] === 'Undiscovered' && !template.evos)) {
- problems.push(name + " (" + template.species + ") is unreleased.");
- }
- }
- setHas[toId(set.ability)] = true;
- // Don't check abilities for metagames with All Abilities
- if (this.gen <= 2) {
- set.ability = 'None';
- } else if (!banlistTable['ignoreillegalabilities']) {
- if (!ability.name) {
- problems.push(name + " needs to have an ability.");
- } else if (ability.name !== template.abilities['0'] &&
- ability.name !== template.abilities['1'] &&
- ability.name !== template.abilities['H']) {
- problems.push(name + " can't have " + set.ability + ".");
- }
- if (ability.name === template.abilities['H']) {
- isHidden = true;
- if (template.unreleasedHidden && banlistTable['illegal']) {
- problems.push(name + "'s hidden ability is unreleased.");
- } else if (this.gen === 5 && set.level < 10 && (template.maleOnlyHidden || template.gender === 'N')) {
- problems.push(name + " must be at least level 10 with its hidden ability.");
- }
- if (template.maleOnlyHidden) {
- set.gender = 'M';
- lsetData.sources = ['5D'];
- }
- }
- }
- for (var i = 0; i < set.moves.length; i++) {
- var move = this.getMove(string(set.moves[i]));
- set.moves[i] = move.name;
- check = move.id;
- setHas[check] = true;
- if (banlistTable[check]) {
- clause = typeof banlistTable[check] === 'string' ? " by " + banlistTable[check] : '';
- problems.push(name + "'s move " + set.moves[i] + " is banned" + clause + ".");
- }
- if (banlistTable['Unreleased']) {
- if (move.isUnreleased) problems.push(name + "'s move " + set.moves[i] + " is unreleased.");
- }
- lsetData['ignoreMoveType'] = teamHas['formatType'];
- var problem = format.checkLearnset.call(this, move, template, lsetData);
- if (problem) {
- var problemString = name + " can't learn " + move.name;
- if (problem.type === 'incompatible') {
- if (isHidden) {
- problemString = problemString.concat(" because it's incompatible with its ability or another move.");
- } else {
- problemString = problemString.concat(" because it's incompatible with another move.");
- }
- } else if (problem.type === 'oversketched') {
- problemString = problemString.concat(" because it can only sketch " + problem.maxSketches + " move" + (problem.maxSketches > 1 ? "s" : "") + ".");
- } else if (problem.type === 'pokebank') {
- problemString = problemString.concat(" because it's only obtainable from a previous generation.");
- } else {
- problemString = problemString.concat(".");
- }
- problems.push(problemString);
- }
- }
- if (lsetData.sources && lsetData.sources.length === 1 && !lsetData.sourcesBefore) {
- // we're restricted to a single source
- var source = lsetData.sources[0];
- if (source.substr(1, 1) === 'S') {
- // it's an event
- var eventData = null;
- var splitSource = source.substr(2).split(' ');
- var eventTemplate = this.getTemplate(splitSource[1]);
- if (eventTemplate.eventPokemon) eventData = eventTemplate.eventPokemon[parseInt(splitSource[0], 10)];
- if (eventData) {
- if (eventData.nature && eventData.nature !== set.nature) {
- problems.push(name + " must have a " + eventData.nature + " nature because it has a move only available from a specific event.");
- }
- if (eventData.shiny) {
- set.shiny = true;
- }
- if (eventData.generation < 5) eventData.isHidden = false;
- if (eventData.isHidden !== undefined && eventData.isHidden !== isHidden) {
- problems.push(name + (isHidden ? " can't have" : " must have") + " its hidden ability because it has a move only available from a specific event.");
- }
- if (this.gen <= 5 && eventData.abilities && eventData.abilities.indexOf(ability.id) < 0) {
- problems.push(name + " must have " + eventData.abilities.join(" or ") + " because it has a move only available from a specific event.");
- }
- if (eventData.gender) {
- set.gender = eventData.gender;
- }
- if (eventData.level && set.level < eventData.level) {
- problems.push(name + " must be at least level " + eventData.level + " because it has a move only available from a specific event.");
- }
- }
- isHidden = false;
- }
- }
- if (isHidden && lsetData.sourcesBefore) {
- if (!lsetData.sources && lsetData.sourcesBefore < 5) {
- problems.push(name + " has a hidden ability - it can't have moves only learned before gen 5.");
- } else if (lsetData.sources && template.gender && template.gender !== 'F' && !{'Nidoran-M':1, 'Nidorino':1, 'Nidoking':1, 'Volbeat':1}[template.species]) {
- var compatibleSource = false;
- for (var i = 0, len = lsetData.sources.length; i < len; i++) {
- if (lsetData.sources[i].charAt(1) === 'E' || (lsetData.sources[i].substr(0, 2) === '5D' && set.level >= 10)) {
- compatibleSource = true;
- break;
- }
- }
- if (!compatibleSource) {
- problems.push(name + " has moves incompatible with its hidden ability.");
- }
- }
- }
- if (set.level < template.evoLevel) {
- // FIXME: Event pokemon given at a level under what it normally can be attained at gives a false positive
- problems.push(name + " must be at least level " + template.evoLevel + " to be evolved.");
- }
- if (!lsetData.sources && lsetData.sourcesBefore <= 3 && this.getAbility(set.ability).gen === 4 && !template.prevo && this.gen <= 5) {
- problems.push(name + " has a gen 4 ability and isn't evolved - it can't use anything from gen 3.");
- }
- if (!lsetData.sources && lsetData.sourcesBefore >= 3 && (isHidden || this.gen <= 5) && template.gen <= lsetData.sourcesBefore) {
- var oldAbilities = this.mod('gen' + lsetData.sourcesBefore).getTemplate(set.species).abilities;
- if (ability.name !== oldAbilities['0'] && ability.name !== oldAbilities['1'] && !oldAbilities['H']) {
- problems.push(name + " has moves incompatible with its ability.");
- }
- }
- setHas[toId(template.tier)] = true;
- if (banlistTable[template.tier]) {
- problems.push(name + " is in " + template.tier + ", which is banned.");
- }
- if (teamHas) {
- for (var i in setHas) {
- teamHas[i] = true;
- }
- }
- for (var i = 0; i < format.setBanTable.length; i++) {
- var bannedCombo = true;
- for (var j = 0; j < format.setBanTable[i].length; j++) {
- if (!setHas[format.setBanTable[i][j]]) {
- bannedCombo = false;
- break;
- }
- }
- if (bannedCombo) {
- clause = format.name ? " by " + format.name : '';
- problems.push(name + " has the combination of " + format.setBanTable[i].join(' + ') + ", which is banned" + clause + ".");
- }
- }
- if (!problems.length) {
- if (set.forcedLevel) set.level = set.forcedLevel;
- return false;
- }
- return problems;
- },
- checkLearnset: function (move, template, lsetData) {
- move = toId(move);
- template = this.getTemplate(template);
- lsetData = lsetData || {};
- var set = (lsetData.set || (lsetData.set = {}));
- var format = (lsetData.format || (lsetData.format = {}));
- var alreadyChecked = {};
- var level = set.level || 100;
- var isHidden = false;
- if (set.ability && this.getAbility(set.ability).name === template.abilities['H']) isHidden = true;
- var incompatibleHidden = false;
- var limit1 = true;
- var sketch = false;
- var sometimesPossible = false; // is this move in the learnset at all?
- // This is a pretty complicated algorithm
- // Abstractly, what it does is construct the union of sets of all
- // possible ways this pokemon could be obtained, and then intersect
- // it with a the pokemon's existing set of all possible ways it could
- // be obtained. If this intersection is non-empty, the move is legal.
- // We apply several optimizations to this algorithm. The most
- // important is that with, for instance, a TM move, that Pokemon
- // could have been obtained from any gen at or before that TM's gen.
- // Instead of adding every possible source before or during that gen,
- // we keep track of a maximum gen variable, intended to mean "any
- // source at or before this gen is possible."
- // set of possible sources of a pokemon with this move, represented as an array
- var sources = [];
- // the equivalent of adding "every source at or before this gen" to sources
- var sourcesBefore = 0;
- var noPastGen = !!format.requirePentagon;
- // since Gen 3, Pokemon cannot be traded to past generations
- var noFutureGen = this.gen >= 3 ? true : !!(format.banlistTable && format.banlistTable['tradeback']);
- do {
- alreadyChecked[template.speciesid] = true;
- if (lsetData.ignoreMoveType && this.getMove(move).type === lsetData.ignoreMoveType) return false;
- if (template.learnset) {
- if (template.learnset[move] || template.learnset['sketch']) {
- sometimesPossible = true;
- var lset = template.learnset[move];
- if (!lset || template.speciesid === 'smeargle') {
- lset = template.learnset['sketch'];
- sketch = true;
- // Chatter, Struggle and Magikarp's Revenge cannot be sketched
- if (move in {'chatter':1, 'struggle':1, 'magikarpsrevenge':1}) return true;
- }
- if (typeof lset === 'string') lset = [lset];
- for (var i = 0, len = lset.length; i < len; i++) {
- var learned = lset[i];
- if (noPastGen && learned.charAt(0) !== '6') continue;
- if (noFutureGen && parseInt(learned.charAt(0), 10) > this.gen) continue;
- if (learned.charAt(0) !== '6' && isHidden && !this.mod('gen' + learned.charAt(0)).getTemplate(template.species).abilities['H']) {
- // check if the Pokemon's hidden ability was available
- incompatibleHidden = true;
- continue;
- }
- if (!template.isNonstandard) {
- // HMs can't be transferred
- if (this.gen >= 4 && learned.charAt(0) <= 3 && move in {'cut':1, 'fly':1, 'surf':1, 'strength':1, 'flash':1, 'rocksmash':1, 'waterfall':1, 'dive':1}) continue;
- if (this.gen >= 5 && learned.charAt(0) <= 4 && move in {'cut':1, 'fly':1, 'surf':1, 'strength':1, 'rocksmash':1, 'waterfall':1, 'rockclimb':1}) continue;
- }
- if (learned.substr(0, 2) in {'4L':1, '5L':1, '6L':1}) {
- // gen 4-6 level-up moves
- if (level >= parseInt(learned.substr(2), 10)) {
- // we're past the required level to learn it
- return false;
- }
- if (!template.gender || template.gender === 'F') {
- // available as egg move
- learned = learned.charAt(0) + 'Eany';
- } else {
- // this move is unavailable, skip it
- continue;
- }
- }
- if (learned.charAt(1) in {L:1, M:1, T:1}) {
- if (learned.charAt(0) === '6') {
- // current-gen TM or tutor moves:
- // always available
- return false;
- }
- // past-gen level-up, TM, or tutor moves:
- // available as long as the source gen was or was before this gen
- limit1 = false;
- sourcesBefore = Math.max(sourcesBefore, parseInt(learned.charAt(0), 10));
- } else if (learned.charAt(1) in {E:1, S:1, D:1}) {
- // egg, event, or DW moves:
- // only if that was the source
- if (learned.charAt(1) === 'E') {
- // it's an egg move, so we add each pokemon that can be bred with to its sources
- if (learned.charAt(0) === '6') {
- // gen 6 doesn't have egg move incompatibilities except for certain cases with baby Pokemon
- learned = '6E' + (template.prevo ? template.id : '');
- sources.push(learned);
- continue;
- }
- var eggGroups = template.eggGroups;
- if (!eggGroups) continue;
- if (eggGroups[0] === 'Undiscovered') eggGroups = this.getTemplate(template.evos[0]).eggGroups;
- var atLeastOne = false;
- var fromSelf = (learned.substr(1) === 'Eany');
- learned = learned.substr(0, 2);
- for (var templateid in this.data.Pokedex) {
- var dexEntry = this.getTemplate(templateid);
- if (
- // CAP pokemon can't breed
- !dexEntry.isNonstandard &&
- // can't breed mons from future gens
- dexEntry.gen <= parseInt(learned.charAt(0), 10) &&
- // genderless pokemon can't pass egg moves
- (dexEntry.gender !== 'N' || this.gen <= 1 && dexEntry.gen <= 1)) {
- if (
- // chainbreeding
- fromSelf ||
- // otherwise parent must be able to learn the move
- !alreadyChecked[dexEntry.speciesid] && dexEntry.learnset && (dexEntry.learnset[move] || dexEntry.learnset['sketch'])) {
- if (dexEntry.eggGroups.intersect(eggGroups).length) {
- // we can breed with it
- atLeastOne = true;
- sources.push(learned + dexEntry.id);
- }
- }
- }
- }
- // chainbreeding with itself from earlier gen
- if (!atLeastOne) sources.push(learned + template.id);
- // Egg move tradeback for gens 1 and 2.
- if (!noFutureGen) sourcesBefore = Math.max(sourcesBefore, parseInt(learned.charAt(0), 10));
- } else if (learned.charAt(1) === 'S') {
- // Event Pokémon:
- // Available as long as the past gen can get the Pokémon and then trade it back.
- sources.push(learned + ' ' + template.id);
- if (!noFutureGen) sourcesBefore = Math.max(sourcesBefore, parseInt(learned.charAt(0), 10));
- } else {
- // DW Pokemon are at level 10 or at the evolution level
- var minLevel = (template.evoLevel && template.evoLevel > 10) ? template.evoLevel : 10;
- if (set.level < minLevel) continue;
- sources.push(learned);
- }
- }
- }
- }
- if (format.mimicGlitch && template.gen < 5) {
- // include the Mimic Glitch when checking this mon's learnset
- var glitchMoves = {metronome:1, copycat:1, transform:1, mimic:1, assist:1};
- var getGlitch = false;
- for (var i in glitchMoves) {
- if (template.learnset[i]) {
- if (!(i === 'mimic' && this.getAbility(set.ability).gen === 4 && !template.prevo)) {
- getGlitch = true;
- break;
- }
- }
- }
- if (getGlitch) {
- sourcesBefore = Math.max(sourcesBefore, 4);
- if (this.getMove(move).gen < 5) {
- limit1 = false;
- }
- }
- }
- }
- // also check to see if the mon's prevo or freely switchable formes can learn this move
- if (!template.learnset && template.baseSpecies !== template.species) {
- // forme takes precedence over prevo only if forme has no learnset
- template = this.getTemplate(template.baseSpecies);
- } else if (template.prevo) {
- template = this.getTemplate(template.prevo);
- if (template.gen > Math.max(2, this.gen)) template = null;
- } else if (template.baseSpecies !== template.species && template.baseSpecies !== 'Kyurem' && template.baseSpecies !== 'Pikachu') {
- template = this.getTemplate(template.baseSpecies);
- } else {
- template = null;
- }
- } while (template && template.species && !alreadyChecked[template.speciesid]);
- if (limit1 && sketch) {
- // limit 1 sketch move
- if (lsetData.sketchMove) {
- return {type:'oversketched', maxSketches: 1};
- }
- lsetData.sketchMove = move;
- }
- // Now that we have our list of possible sources, intersect it with the current list
- if (!sourcesBefore && !sources.length) {
- if (noPastGen && sometimesPossible) return {type:'pokebank'};
- if (incompatibleHidden) return {type:'incompatible'};
- return true;
- }
- if (!sources.length) sources = null;
- if (sourcesBefore || lsetData.sourcesBefore) {
- // having sourcesBefore is the equivalent of having everything before that gen
- // in sources, so we fill the other array in preparation for intersection
- var learned;
- if (sourcesBefore && lsetData.sources) {
- if (!sources) sources = [];
- for (var i = 0, len = lsetData.sources.length; i < len; i++) {
- learned = lsetData.sources[i];
- if (parseInt(learned.substr(0, 1), 10) <= sourcesBefore) {
- sources.push(learned);
- }
- }
- if (!lsetData.sourcesBefore) sourcesBefore = 0;
- }
- if (lsetData.sourcesBefore && sources) {
- if (!lsetData.sources) lsetData.sources = [];
- for (var i = 0, len = sources.length; i < len; i++) {
- learned = sources[i];
- if (parseInt(learned.substr(0, 1), 10) <= lsetData.sourcesBefore) {
- lsetData.sources.push(learned);
- }
- }
- if (!sourcesBefore) delete lsetData.sourcesBefore;
- }
- }
- if (sources) {
- if (lsetData.sources) {
- var intersectSources = lsetData.sources.intersect(sources);
- if (!intersectSources.length && !(sourcesBefore && lsetData.sourcesBefore)) {
- return {type:'incompatible'};
- }
- lsetData.sources = intersectSources;
- } else {
- lsetData.sources = sources.unique();
- }
- }
- if (sourcesBefore) {
- lsetData.sourcesBefore = Math.min(sourcesBefore, lsetData.sourcesBefore || 6);
- }
- return false;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement