Aww, that\'s too bad. :( I hope playing on Pokémon Showdown today can help cheer you up!
';
} else if (answer === 'Y') {
buf += 'Cool! I just added some pretty cool teambuilder features, so I\'m pretty happy, too. Did you know you can drag and drop teams to different format-folders? You can also drag and drop them to and from your computer (works best in Chrome).
';
buf += 'Oh, I\'m Zarel! I made a Credits button for this...
';
buf += '';
buf += 'Isn\'t it pretty? Matches your background and everything. It used to be in the Main Menu but we had to get rid of it to save space.
';
buf += 'No, they were free. That just makes it easier to get my money\'s worth. Let\'s play rock paper scissors!
';
buf += 'I play laser, I win.
';
buf += 'Okay, sure. I warn you, I\'m using the same RNG that makes Stone Edge miss for you.
';
buf += 'And ' + rpsChart[my] + ' ' + rpsWinChart[my + your] + ' ' + rpsChart[your] + ', so I win!
';
} else if ((your + my) in rpsWinChart) {
buf += 'But ' + rpsChart[your] + ' ' + rpsWinChart[your + my] + ' ' + rpsChart[my] + ', so you win...
';
} else {
buf += 'We played the same thing, so it\'s a tie.
';
}
if (!this.rpsScores || !this.rpsScores.length) {
this.rpsScores = ['pi', '$3.50', '9.80665 m/s List ';
buf += '
';
buf += '
Import/Export ';
buf += '
';
buf += '
';
buf += '' + this.clipboardHTML() + ' ';
var i = 0;
if (this.curSetList.length && !this.curSetList[this.curSetList.length - 1].species) {
this.curSetList.splice(this.curSetList.length - 1, 1);
}
var isGenericFormat = function (formatName) {
if (!formatName) return true;
if (/^gen\d+$/.test(formatName)) return true;
return false;
};
if (exports.BattleFormats) {
buf += '';
buf += 'Format: ' + (isGenericFormat(this.curTeam.format) ? 'Select a format ' : BattleLog.escapeFormat(this.curTeam.format)) + ' ';
var btnClass = 'button' + (!this.curSetList.length ? ' disabled' : '');
buf += ' Validate ';
}
if (!this.curSetList.length) {
buf += 'you have no pokemon lol ';
}
for (i = 0; i < this.curSetList.length; i++) {
if (this.curSetList.length < 6 && this.deletedSet && i === this.deletedSetLoc) {
buf += ' Undo Delete ';
}
buf += this.renderSet(this.curSetList[i], i);
}
if (this.deletedSet && i === this.deletedSetLoc) {
buf += ' Undo Delete ';
}
if (i === 0) {
buf += ' Import from text or URL ';
}
if (i < 6) {
buf += ' Add Pokémon ';
}
buf += ' ';
buf += '
';
buf += '
';
}
this.$el.html('
' + buf + '
');
this.$(".teamedit textarea").focus().select();
if ($(window).width() < 640) this.show();
},
renderSet: function (set, i) {
var species = Dex.getSpecies(set.species);
var isLetsGo = this.curTeam.format.includes('letsgo');
var isNatDex = this.curTeam.format.includes('nationaldex');
var buf = '
';
if (!set.species) {
if (this.deletedSet) {
buf += '';
}
buf += '';
buf += '';
buf += ' ';
return buf;
}
buf += '';
buf += '
';
buf += 'Nickname ';
buf += '
';
buf += '
';
// icon
buf += '
';
if (species.cosmeticFormes) {
buf += '
';
} else {
buf += '
';
}
buf += '
Pokémon
';
// details
buf += '
';
buf += '
Details ';
var GenderChart = {
'M': 'Male',
'F': 'Female',
'N': '—'
};
buf += 'Level ' + (set.level || 100) + ' ';
if (this.curTeam.gen > 1) {
buf += 'Gender ' + GenderChart[set.gender || species.gender || 'N'] + ' ';
if (isLetsGo) {
buf += 'Happiness ' + (typeof set.happiness === 'number' ? set.happiness : 70) + ' ';
} else if (this.curTeam.gen < 8 || isNatDex) {
buf += 'Happiness ' + (typeof set.happiness === 'number' ? set.happiness : 255) + ' ';
}
buf += 'Shiny ' + (set.shiny ? 'Yes' : 'No') + ' ';
if (!isLetsGo) {
if (this.curTeam.gen === 8 && !isNatDex) {
// Hidden Power isn't in normal Gen 8
} else {
buf += 'HP Type ' + (set.hpType || 'Dark') + ' ';
}
}
}
buf += '
';
// item/type icons
buf += '
';
buf += '
';
var itemicon = ' ';
if (set.item) {
var item = Dex.getItem(set.item);
itemicon = ' ';
}
buf += itemicon;
buf += '
';
buf += '
';
var types = species.types;
var table = (this.curTeam.gen < 7 ? BattleTeambuilderTable['gen' + this.curTeam.gen] : null);
if (table && species.id in table.overrideType) types = table.overrideType[species.id].split('/');
if (types) {
for (var i = 0; i < types.length; i++) buf += Dex.getTypeIcon(types[i]);
}
buf += '
';
buf += '
';
// moves
if (!set.moves) set.moves = [];
buf += '
';
// stats
buf += '
Stats ';
buf += ' ' + (!isLetsGo ? 'EV' : 'AV') + ' ';
var stats = {};
var defaultEV = (this.curTeam.gen > 2 ? 0 : 252);
for (var j in BattleStatNames) {
if (j === 'spd' && this.curTeam.gen === 1) continue;
stats[j] = this.getStat(j, set);
var ev = (set.evs[j] === undefined ? defaultEV : set.evs[j]);
var evBuf = '' + (ev === defaultEV ? '' : ev) + ' ';
if (BattleNatures[set.nature] && BattleNatures[set.nature].plus === j) {
evBuf += '+ ';
} else if (BattleNatures[set.nature] && BattleNatures[set.nature].minus === j) {
evBuf += '− ';
}
var width = stats[j] * 75 / 504;
if (j == 'hp') width = stats[j] * 75 / 704;
if (width > 75) width = 75;
var color = Math.floor(stats[j] * 180 / 714);
if (color > 360) color = 360;
var statName = this.curTeam.gen === 1 && j === 'spa' ? 'Spc' : BattleStatNames[j];
buf += '' + statName + ' ' + evBuf + ' ';
}
buf += '
';
buf += '
';
return buf;
},
saveImport: function () {
var text = this.$('.teamedit textarea').val();
var url = this.importableUrl(text);
if (url) {
this.$('.teamedit textarea, .teamedit .savebutton').attr('disabled', true);
var self = this;
$.ajax({
type: 'GET',
url: url,
success: function (data) {
Storage.activeSetList = self.curSetList = Storage.importTeam(data);
self.$('.teamedit textarea, .teamedit .savebutton').attr('disabled', null);
self.back();
},
error: function () {
app.addPopupMessage("Could not fetch a team from this URL. Make sure you copied the full link, or paste the team in by hand.");
self.$('.teamedit textarea, .teamedit .savebutton').attr('disabled', null);
}
});
} else {
Storage.activeSetList = this.curSetList = Storage.importTeam(text);
this.back();
}
},
importableUrl: function (value) {
var match = value.match(/^https?:\/\/(pokepast\.es|gist\.github(?:usercontent)?\.com)\/(.*)\s*$/);
if (!match) return;
var host = match[1];
var path = match[2];
switch (host) {
case 'pokepast.es':
return 'https://pokepast.es/' + path.replace(/\/.*/, '') + '/raw';
default: // gist
var split = path.split('/');
return split.length < 2 ? undefined : 'https://gist.githubusercontent.com/' + split[0] + '/' + split[1] + '/raw';
}
},
addPokemon: function () {
if (!this.curTeam) return;
var team = this.curSetList;
if (!team.length || team[team.length - 1].species) {
var newPokemon = {
name: '',
species: '',
item: '',
nature: '',
evs: {},
ivs: {},
moves: []
};
team.push(newPokemon);
}
this.curSet = team[team.length - 1];
this.curSetLoc = team.length - 1;
this.curChartName = '';
this.update();
this.$('input[name=pokemon]').select();
},
pastePokemon: function (i, btn) {
if (!this.curTeam) return;
var team = this.curSetList;
if (team.length >= 6) return;
if (!this.clipboardCount()) return;
if (team.push($.extend(true, {}, this.clipboard[0])) >= 6) {
$(btn).css('display', 'none');
}
this.update();
this.save();
},
saveFlag: false,
save: function () {
this.saveFlag = true;
if (this.curTeam) {
Storage.saveTeam(this.curTeam);
} else {
Storage.saveTeams();
}
},
validate: function () {
var format = this.curTeam.format || 'gen7anythinggoes';
if (!this.curSetList.length) {
app.addPopupMessage("You need at least one Pokémon to validate.");
return;
}
if (window.BattleFormats && BattleFormats[format] && BattleFormats[format].battleFormat) {
format = BattleFormats[format].battleFormat;
}
app.sendTeam(this.curTeam);
app.send('/vtm ' + format);
},
teamNameChange: function (e) {
var name = ($.trim(e.currentTarget.value) || 'Untitled ' + (this.curTeamLoc + 1));
if (name.indexOf('/') >= 0 || name.indexOf('\\') >= 0) {
app.addPopupMessage("Names can't contain slashes, since they're used as a folder separator.");
name = name.replace(/[\\\/]/g, '');
}
if (name.indexOf('|') >= 0) {
app.addPopupMessage("Names can't contain the character |, since they're used for storing teams.");
name = name.replace(/\|/g, '');
}
this.curTeam.name = name;
e.currentTarget.value = name;
this.save();
},
format: function (format, button) {
if (!window.BattleFormats) {
return;
}
var self = this;
app.addPopup(FormatPopup, {format: format, sourceEl: button, selectType: 'teambuilder', onselect: function (newFormat) {
self.changeFormat(newFormat);
}});
},
changeFormat: function (format) {
this.curTeam.format = format;
this.curTeam.gen = this.getGen(this.curTeam.format);
this.save();
if (this.curTeam.gen === 5 && !Dex.loadedSpriteData['bw']) Dex.loadSpriteData('bw');
this.update();
},
nicknameChange: function (e) {
var i = +$(e.currentTarget).closest('li').attr('value');
var set = this.curSetList[i];
var name = $.trim(e.currentTarget.value).replace(/\|/g, '');
e.currentTarget.value = set.name = name;
this.save();
},
// clipboard
clipboard: [],
clipboardCount: function () {
return this.clipboard.length;
},
clipboardVisible: function () {
return !!this.clipboardCount();
},
clipboardHTML: function () {
var buf = '';
buf += '
';
buf += '
Clipboard:
';
buf += '
' + this.clipboardInnerHTML() + '
';
buf += '
';
if (this.curTeam && this.curSetList.length < 6) {
buf += ' Paste! ';
}
buf += ' Clear clipboard ';
buf += '
';
buf += '
';
return buf;
},
clipboardInnerHTMLCache: '',
clipboardInnerHTML: function () {
if (this.clipboardInnerHTMLCache) {
return this.clipboardInnerHTMLCache;
}
var buf = '';
for (var i = 0; i < this.clipboardCount(); i++) {
var res = this.clipboard[i];
var species = Dex.getSpecies(res.species);
buf += '
';
buf += '
';
buf += '' + (species.name === species.baseSpecies ? BattleLog.escapeHTML(species.name) : (BattleLog.escapeHTML(species.baseSpecies) + '-' + BattleLog.escapeHTML(species.name.substr(species.baseSpecies.length + 1)) + ' ')) + '
';
buf += '
' + (BattleLog.escapeHTML(res.ability) || 'No ability ') + ' ' + (BattleLog.escapeHTML(res.item) || 'No item ') + '
';
buf += '
';
for (var j = 0; j < 4; j++) {
if (!(j & 1)) {
buf += '';
}
buf += (BattleLog.escapeHTML(res.moves[j]) || 'No move ') + (!(j & 1) ? ' ' : '');
if (j & 1) {
buf += ' ';
}
}
buf += '
';
buf += '
';
}
this.clipboardInnerHTMLCache = buf;
return buf;
},
clipboardUpdate: function () {
this.clipboardInnerHTMLCache = '';
$('.teambuilder-clipboard-data').html(this.clipboardInnerHTML());
},
clipboardExpanded: false,
clipboardExpand: function () {
var $clipboard = $('.teambuilder-clipboard-data');
$clipboard.animate({height: this.clipboardCount() * 34}, 500, function () {
setTimeout(function () { $clipboard.focus(); }, 100);
});
setTimeout(function () {
this.clipboardExpanded = true;
}.bind(this), 10);
},
clipboardShrink: function () {
var $clipboard = $('.teambuilder-clipboard-data');
$clipboard.animate({height: 32}, 500);
setTimeout(function () {
this.clipboardExpanded = false;
}.bind(this), 10);
},
clipboardResultSelect: function (e) {
if (!this.clipboardExpanded) return;
e.preventDefault();
e.stopPropagation();
var target = +($(e.target).closest('.result').data('id'));
if (target === -1) {
this.clipboardShrink();
this.clipboardRemoveAll();
return;
}
this.clipboard.unshift(this.clipboard.splice(target, 1)[0]);
this.clipboardUpdate();
this.clipboardShrink();
},
clipboardAdd: function (set) {
if (this.clipboard.unshift(set) > 6) {
// we don't want the clipboard so big that it lags the teambuilder
this.clipboard.pop();
}
this.clipboardUpdate();
if (this.clipboardCount() === 1) {
var $clipboard = $('.teambuilder-clipboard-container').css('opacity', 0);
$clipboard.slideDown(250, function () {
$clipboard.animate({opacity: 1}, 250);
});
}
},
clipboardRemoveAll: function () {
this.clipboard = [];
var self = this;
var $clipboard = $('.teambuilder-clipboard-container');
$clipboard.animate({opacity: 0}, 250, function () {
$clipboard.slideUp(250, function () {
self.clipboardUpdate();
});
});
},
// copy/import/export/move/delete
copySet: function (i, button) {
i = +($(button).closest('li').attr('value'));
this.clipboardAdd($.extend(true, {}, this.curSetList[i]));
button.blur();
},
wasViewingPokemon: false,
importSet: function (i, button) {
i = +($(button).closest('li').attr('value'));
this.wasViewingPokemon = true;
if (!this.curSet) {
this.wasViewingPokemon = false;
this.selectPokemon(i);
}
this.$('li').find('input, button').prop('disabled', true);
this.$chart.hide();
this.$('.teambuilder-pokemon-import')
.show()
.find('textarea')
.val(Storage.exportTeam([this.curSet]).trim())
.focus()
.select();
this.getSmogonSets();
},
getSmogonSets: function () {
this.$('.teambuilder-pokemon-import .teambuilder-import-smogon-sets').empty();
var format = this.curTeam.format;
// If we don't have a specific format, don't try and guess which sets to use.
if (format.match(/gen\d$/)) return;
var self = this;
this.smogonSets = this.smogonSets || {};
if (this.smogonSets[format] !== undefined) {
this.importSetButtons();
return;
}
// We fetch this as 'text' and JSON.parse it ourserves in order to have consistent behavior
// between the localdev CORS helper and the real jQuery.get function, which would already parse
// this into an object based on the content-type header.
$.get('https://' + Config.routes.client + '/data/sets/' + format + '.json', {}, function (data) {
try {
self.smogonSets[format] = JSON.parse(data);
} catch (e) {
// An error occured. Mark this as false, so that we don't try to reimport sets for this format
// in the future.
self.smogonSets[format] = false;
}
self.importSetButtons();
}, 'text');
},
importSetButtons: function () {
var formatSets = this.smogonSets[this.curTeam.format];
var species = this.curSet.species;
var $setDiv = this.$('.teambuilder-pokemon-import .teambuilder-import-smogon-sets');
$setDiv.empty();
if (!formatSets) return;
var sets = $.extend({}, formatSets['dex'][species], formatSets['stats'][species]);
$setDiv.text('Sample sets: ');
for (var set in sets) {
$setDiv.append('
' + BattleLog.escapeHTML(set) + ' ');
}
$setDiv.append('
(Smogon analysis ) ');
},
importSmogonSet: function (i, button) {
var formatSets = this.smogonSets[this.curTeam.format];
var species = this.curSet.species;
var setName = this.$(button).text();
var smogonSet = formatSets['dex'][species][setName] || formatSets['stats'][species][setName];
var curSet = $.extend({}, this.curSet, smogonSet);
var text = Storage.exportTeam([curSet]);
this.$('.teambuilder-pokemon-import .pokemonedit').val(text);
},
closePokemonImport: function (force) {
if (!this.wasViewingPokemon) return this.back();
var $li = this.$('li');
var i = +($li.attr('value'));
this.$('.teambuilder-pokemon-import').hide();
this.$chart.show();
if (force === true) return this.selectPokemon(i);
$li.find('input, button').prop('disabled', false);
},
savePokemonImport: function (i) {
i = +(this.$('li').attr('value'));
var curSet = Storage.importTeam(this.$('.pokemonedit').val())[0];
if (curSet) {
this.curSet = curSet;
this.curSetList[i] = curSet;
}
this.closePokemonImport(true);
},
moveSet: function (i, button) {
i = +($(button).closest('li').attr('value'));
app.addPopup(MoveSetPopup, {
i: i,
team: this.curSetList
});
},
deleteSet: function (i, button) {
i = +($(button).closest('li').attr('value'));
this.deletedSetLoc = i;
this.deletedSet = this.curSetList.splice(i, 1)[0];
if (this.curSet) {
this.addPokemon();
} else {
this.update();
}
this.save();
},
undeleteSet: function () {
if (this.deletedSet) {
var loc = this.deletedSetLoc;
this.curSetList.splice(loc, 0, this.deletedSet);
this.deletedSet = null;
this.deletedSetLoc = -1;
this.save();
if (this.curSet) {
this.curSetLoc = loc;
this.curSet = this.curSetList[loc];
this.curChartName = '';
this.update();
this.updateChart();
} else {
this.update();
}
}
},
/*********************************************************
* Set view
*********************************************************/
updateSetView: function () {
// pokemon
var buf = '
';
buf += ' Team
';
buf += '
';
buf += this.renderTeambar();
buf += '
';
// pokemon
buf += '
';
buf += '
';
buf += this.renderSet(this.curSet, this.curSetLoc);
buf += ' ';
buf += '
';
// results
this.chartPrevSearch = '[init]';
buf += '
';
// import/export
buf += '
';
buf += '
Back Save
';
buf += '
';
buf += '
';
buf += '
';
this.$el.html('
' + buf + '
');
if ($(window).width() < 640) this.show();
this.$chart = this.$('.teambuilder-results');
this.search = new BattleSearch(this.$chart, this.$chart);
var self = this;
// fun fact: Backbone DOM events don't support scroll...
// I guess scroll doesn't bubble like other events
this.$chart.on('scroll', function () {
if (self.curChartType in self.searchChartTypes) {
self.search.updateScroll();
}
});
},
updateSetTop: function () {
this.$('.teambar').html(this.renderTeambar());
this.$('.teamchart').first().html(this.renderSet(this.curSet, this.curSetLoc));
},
renderTeambar: function () {
var buf = '';
var isAdd = false;
if (this.curSetList.length && !this.curSetList[this.curSetList.length - 1].species && this.curSetLoc !== this.curSetList.length - 1) {
this.curSetList.splice(this.curSetList.length - 1, 1);
}
for (var i = 0; i < this.curSetList.length; i++) {
var set = this.curSetList[i];
var pokemonicon = '
';
if (!set.species) {
buf += '
';
isAdd = true;
} else if (i == this.curSetLoc) {
buf += '
' + pokemonicon + BattleLog.escapeHTML(set.name || Dex.getSpecies(set.species).baseSpecies || ' ') + ' ';
} else {
buf += '
' + pokemonicon + BattleLog.escapeHTML(set.name || Dex.getSpecies(set.species).baseSpecies) + ' ';
}
}
if (this.curSetList.length < 6 && !isAdd) {
buf += '
';
}
return buf;
},
updatePokemonSprite: function () {
var set = this.curSet;
if (!set) return;
this.$('.setchart').attr('style', Dex.getTeambuilderSprite(set, this.curTeam.gen));
this.$('.pokemonicon-' + this.curSetLoc).css('background', Dex.getPokemonIcon(set).substr(11));
var item = Dex.getItem(set.item);
if (item.id) {
this.$('.setcol-details .itemicon').css('background', Dex.getItemIcon(item).substr(11));
} else {
this.$('.setcol-details .itemicon').css('background', 'none');
}
this.updateStatGraph();
},
updateStatGraph: function () {
var set = this.curSet;
if (!set) return;
var stats = {hp:'', atk:'', def:'', spa:'', spd:'', spe:''};
var supportsEVs = !this.curTeam.format.includes('letsgo');
// stat cell
var buf = '
' + (supportsEVs ? 'EV' : 'AV') + ' ';
var defaultEV = (this.curTeam.gen > 2 ? 0 : 252);
for (var stat in stats) {
if (stat === 'spd' && this.curTeam.gen === 1) continue;
stats[stat] = this.getStat(stat, set);
var ev = (set.evs[stat] === undefined ? defaultEV : set.evs[stat]);
var evBuf = '
' + (ev === defaultEV ? '' : ev) + ' ';
if (BattleNatures[set.nature] && BattleNatures[set.nature].plus === stat) {
evBuf += '
+ ';
} else if (BattleNatures[set.nature] && BattleNatures[set.nature].minus === stat) {
evBuf += '
− ';
}
var width = stats[stat] * 75 / 504;
if (stat == 'hp') width = stats[stat] * 75 / 704;
if (width > 75) width = 75;
var color = Math.floor(stats[stat] * 180 / 714);
if (color > 360) color = 360;
buf += '
' + BattleStatNames[stat] + ' ' + evBuf + '';
}
this.$('button[name=stats]').html(buf);
if (this.curChartType !== 'stats') return;
buf = '
';
for (var stat in stats) {
if (stat === 'spd' && this.curTeam.gen === 1) continue;
buf += '
' + stats[stat] + '
';
}
this.$chart.find('.statscol').html(buf);
buf = '
';
var totalev = 0;
for (var stat in stats) {
if (stat === 'spd' && this.curTeam.gen === 1) continue;
var width = stats[stat] * 180 / 504;
if (stat == 'hp') width = stats[stat] * 180 / 704;
if (width > 179) width = 179;
var color = Math.floor(stats[stat] * 180 / 714);
if (color > 360) color = 360;
buf += '
';
totalev += (set.evs[stat] || 0);
}
if (this.curTeam.gen > 2 && supportsEVs) buf += '
Remaining:
';
this.$chart.find('.graphcol').html(buf);
if (this.curTeam.gen <= 2) return;
if (supportsEVs) {
var maxEv = 510;
if (totalev <= maxEv) {
this.$chart.find('.totalev').html('
' + (totalev > (maxEv - 2) ? 0 : (maxEv - 2) - totalev) + ' ');
} else {
this.$chart.find('.totalev').html('
' + (maxEv - totalev) + ' ');
}
}
this.$chart.find('select[name=nature]').val(set.nature || 'Serious');
},
curChartType: '',
curChartName: '',
searchChartTypes: {
pokemon: 'pokemon',
ability: 'abilities',
move: 'moves',
item: 'items'
},
updateChart: function (pokemonChanged, wasIncomplete) {
var type = this.curChartType;
if (type === 'stats') {
this.search.qType = null;
this.search.qName = null;
this.updateStatForm();
return;
}
if (type === 'details') {
this.search.qType = null;
this.search.qName = null;
this.updateDetailsForm();
return;
}
var $inputEl = this.$('input[name=' + this.curChartName + ']');
var q = $inputEl.val();
if (pokemonChanged || this.search.qName !== this.curChartName) {
var cur = {};
cur[toID(q)] = 1; // make sure selected one is first
if (type === 'move') {
cur[toID(this.$('input[name=move1]').val())] = 1;
cur[toID(this.$('input[name=move2]').val())] = 1;
cur[toID(this.$('input[name=move3]').val())] = 1;
cur[toID(this.$('input[name=move4]').val())] = 1;
}
if (type !== this.search.qType) {
this.$chart.scrollTop(0);
}
this.search.$inputEl = $inputEl;
this.search.setType(type, this.curTeam.format || 'gen8', this.curSet, cur);
this.qInitial = q;
this.search.qName = this.curChartName;
if (wasIncomplete) {
if (this.search.find(q)) {
if (this.search.q) this.$chart.find('a').first().addClass('hover');
}
}
} else if (q !== this.qInitial) {
this.qInitial = undefined;
if (this.search.find(q)) {
if (this.search.q) this.$chart.find('a').first().addClass('hover');
}
}
},
selectPokemon: function (i) {
i = +i;
var set = this.curSetList[i];
if (set) {
this.curSet = set;
this.curSetLoc = i;
if (!this.curChartName) {
this.curChartName = 'details';
this.curChartType = 'details';
}
if (this.curChartType in this.searchChartTypes) {
this.update();
this.updateChart(true);
this.$('input[name=' + this.curChartName + ']').select();
} else {
this.update();
this.updateChart(true);
}
}
},
stats: function (i, button) {
if (!this.curSet) this.selectPokemon($(button).closest('li').val());
this.curChartName = 'stats';
this.curChartType = 'stats';
this.updateChart();
},
details: function (i, button) {
if (!this.curSet) this.selectPokemon($(button).closest('li').val());
this.curChartName = 'details';
this.curChartType = 'details';
this.updateChart();
},
/*********************************************************
* Set stat form
*********************************************************/
plus: '',
minus: '',
smogdexLink: function (s) {
var species = Dex.getSpecies(s);
var format = this.curTeam && this.curTeam.format;
var smogdexid = toID(species.baseSpecies);
if (species.id === 'meowstic') {
smogdexid = 'meowstic-m';
} else if (species.forme) {
switch (species.baseSpecies) {
case 'Alcremie':
case 'Basculin':
case 'Burmy':
case 'Castform':
case 'Cherrim':
case 'Deerling':
case 'Flabebe':
case 'Floette':
case 'Florges':
case 'Furfrou':
case 'Gastrodon':
case 'Genesect':
case 'Keldeo':
case 'Mimikyu':
case 'Minior':
case 'Pikachu':
case 'Polteageist':
case 'Sawsbuck':
case 'Shellos':
case 'Sinistea':
case 'Vivillon':
break;
default:
smogdexid += '-' + toID(species.forme);
break;
}
}
var generationNumber = 8;
if (format.substr(0, 3) === 'gen') {
var number = format.charAt(3);
if ('1' <= number && number <= '6') {
generationNumber = +number;
format = format.substr(4);
}
}
var generation = ['rb', 'gs', 'rs', 'dp', 'bw', 'xy', 'sm', 'ss'][generationNumber - 1];
if (format === 'battlespotdoubles') {
smogdexid += '/vgc15';
} else if (format === 'doublesou' || format === 'doublesuu') {
smogdexid += '/doubles';
} else if (format === 'ou' || format === 'uu' || format === 'ru' || format === 'nu' || format === 'pu' || format === 'lc' || format === 'monotype' || format === 'mixandmega' || format === 'nfe' || format === 'nationaldex' || format === 'stabmons' || format === '1v1' || format === 'almostanyability') {
smogdexid += '/' + format;
} else if (format === 'balancedhackmons') {
smogdexid += 'bh';
} else if (format === 'nationaldexag' || format === 'anythinggoes') {
smogdexid += 'ag';
}
return 'http://smogon.com/dex/' + generation + '/pokemon/' + smogdexid + '/';
},
updateStatForm: function (setGuessed) {
var buf = '';
var set = this.curSet;
var species = Dex.forGen(this.curTeam.gen).getSpecies(this.curSet.species);
var baseStats = species.baseStats;
buf += '';
buf += '
';
buf += '
Base
';
for (var i in stats) {
buf += '
' + baseStats[i] + '
';
}
buf += '
';
buf += '
';
for (var i in stats) {
stats[i] = this.getStat(i);
var width = stats[i] * 180 / 504;
if (i == 'hp') width = Math.floor(stats[i] * 180 / 704);
if (width > 179) width = 179;
var color = Math.floor(stats[i] * 180 / 714);
if (color > 360) color = 360;
buf += '
';
}
if (this.curTeam.gen > 2 && supportsEVs) buf += '
Remaining:
';
buf += '
';
buf += '
' + (supportsEVs ? 'EVs' : 'AVs') + '
';
var totalev = 0;
this.plus = '';
this.minus = '';
for (var i in stats) {
var val;
val = '' + ((set.evs[i] === undefined ? defaultEV : set.evs[i]) || '');
if (nature.plus === i) {
val += '+';
this.plus = i;
}
if (nature.minus === i) {
val += '-';
this.minus = i;
}
buf += '
';
totalev += (set.evs[i] || 0);
}
if (this.curTeam.gen > 2 && supportsEVs) {
var maxTotalEVs = 510;
if (totalev <= maxTotalEVs) {
buf += '
' + (totalev > (maxTotalEVs - 2) ? 0 : (maxTotalEVs - 2) - totalev) + '
';
} else {
buf += '
' + (maxTotalEVs - totalev) + '
';
}
}
buf += '
';
buf += '
';
for (var i in stats) {
if (i === 'spd' && this.curTeam.gen === 1) continue;
buf += '
';
}
buf += '
';
if (this.curTeam.gen > 2) {
buf += '
IVs
';
if (!set.ivs) set.ivs = {};
for (var i in stats) {
if (set.ivs[i] === undefined || isNaN(set.ivs[i])) set.ivs[i] = 31;
var val = '' + (set.ivs[i]);
buf += '
';
}
var hpType = '';
if (set.moves) {
for (var i = 0; i < set.moves.length; i++) {
var moveid = toID(set.moves[i]);
if (moveid.slice(0, 11) === 'hiddenpower') {
hpType = moveid.slice(11);
}
}
}
if (hpType && !this.canHyperTrain(set)) {
var hpIVs;
switch (hpType) {
case 'dark':
hpIVs = ['111111']; break;
case 'dragon':
hpIVs = ['011111', '101111', '110111']; break;
case 'ice':
hpIVs = ['010111', '100111', '111110']; break;
case 'psychic':
hpIVs = ['011110', '101110', '110110']; break;
case 'electric':
hpIVs = ['010110', '100110', '111011']; break;
case 'grass':
hpIVs = ['011011', '101011', '110011']; break;
case 'water':
hpIVs = ['100011', '111010']; break;
case 'fire':
hpIVs = ['101010', '110010']; break;
case 'steel':
hpIVs = ['100010', '111101']; break;
case 'ghost':
hpIVs = ['101101', '110101']; break;
case 'bug':
hpIVs = ['100101', '111100', '101100']; break;
case 'rock':
hpIVs = ['001100', '110100', '100100']; break;
case 'ground':
hpIVs = ['000100', '111001', '101001']; break;
case 'poison':
hpIVs = ['001001', '110001', '100001']; break;
case 'flying':
hpIVs = ['000001', '111000', '101000']; break;
case 'fighting':
hpIVs = ['001000', '110000', '100000']; break;
}
buf += '
';
buf += 'HP ' + hpType.charAt(0).toUpperCase() + hpType.slice(1) + ' IVs ';
var minStat = this.curTeam.gen >= 6 ? 0 : 2;
buf += '';
for (var i = 0; i < hpIVs.length; i++) {
var spread = '';
for (var j = 0; j < 6; j++) {
if (j) spread += '/';
spread += (j === 1 ? minStat : 30) + parseInt(hpIVs[i].charAt(j), 10);
}
buf += '' + spread + ' ';
}
buf += ' ';
buf += '';
for (var i = 0; i < hpIVs.length; i++) {
var spread = '';
for (var j = 0; j < 6; j++) {
if (j) spread += '/';
spread += (j === 5 || j === 1 ? minStat : 30) + parseInt(hpIVs[i].charAt(j), 10);
}
buf += '' + spread + ' ';
}
buf += ' ';
buf += '';
for (var i = 0; i < hpIVs.length; i++) {
var spread = '';
for (var j = 0; j < 6; j++) {
if (j) spread += '/';
spread += 30 + parseInt(hpIVs[i].charAt(j), 10);
}
buf += '' + spread + ' ';
}
buf += ' ';
buf += '';
for (var i = 0; i < hpIVs.length; i++) {
var spread = '';
for (var j = 0; j < 6; j++) {
if (j) spread += '/';
spread += (j === 5 ? minStat : 30) + parseInt(hpIVs[i].charAt(j), 10);
}
buf += '' + spread + ' ';
}
buf += ' ';
buf += '
';
} else {
buf += '
';
buf += 'IV spreads ';
buf += '';
buf += '31/0/31/31/31/31 ';
buf += ' ';
buf += '';
buf += '31/0/31/31/31/0 ';
buf += ' ';
buf += '';
buf += '31/31/31/31/31/31 ';
buf += ' ';
buf += '';
buf += '31/31/31/31/31/0 ';
buf += ' ';
buf += '
';
}
buf += '
';
} else {
buf += '
DVs
';
if (!set.ivs) set.ivs = {};
for (var i in stats) {
if (set.ivs[i] === undefined || isNaN(set.ivs[i])) set.ivs[i] = 31;
var val = '' + Math.floor(set.ivs[i] / 2);
buf += '
';
}
buf += '
';
}
buf += '
';
for (var i in stats) {
buf += '
' + stats[i] + '
';
}
buf += '
';
if (this.curTeam.gen > 2) {
buf += '
Nature: ';
for (var i in BattleNatures) {
var curNature = BattleNatures[i];
buf += '' + i;
if (curNature.plus) {
buf += ' (+' + BattleStatNames[curNature.plus] + ', -' + BattleStatNames[curNature.minus] + ')';
}
buf += ' ';
}
buf += '
';
buf += '
Protip: You can also set natures by typing "+" and "-" next to a stat.
';
}
buf += '
';
this.$chart.html(buf);
},
setStatFormGuesses: function () {
this.updateStatForm(true);
},
setSlider: function (stat, val) {
this.$chart.find('input[name=evslider-' + stat + ']').val(val || 0);
},
updateNature: function () {
var set = this.curSet;
if (!set) return;
if (this.plus === '' || this.minus === '') {
set.nature = 'Serious';
} else {
for (var i in BattleNatures) {
if (BattleNatures[i].plus === this.plus && BattleNatures[i].minus === this.minus) {
set.nature = i;
break;
}
}
}
},
statChange: function (e) {
var inputName = '';
inputName = e.currentTarget.name;
var val = Math.abs(parseInt(e.currentTarget.value, 10));
var supportsEVs = !this.curTeam.format.includes('letsgo');
var supportsAVs = !supportsEVs && this.curTeam.format.endsWith('norestrictions');
var set = this.curSet;
if (!set) return;
if (inputName.substr(0, 5) === 'stat-') {
// EV
// Handle + and -
var stat = inputName.substr(5);
var lastchar = e.currentTarget.value.charAt(e.target.value.length - 1);
var firstchar = e.currentTarget.value.charAt(0);
var natureChange = true;
if ((lastchar === '+' || firstchar === '+') && stat !== 'hp') {
if (this.plus && this.plus !== stat) this.$chart.find('input[name=stat-' + this.plus + ']').val(set.evs[this.plus] || '');
this.plus = stat;
} else if ((lastchar === '-' || lastchar === "\u2212" || firstchar === '-' || firstchar === "\u2212") && stat !== 'hp') {
if (this.minus && this.minus !== stat) this.$chart.find('input[name=stat-' + this.minus + ']').val(set.evs[this.minus] || '');
this.minus = stat;
} else if (this.plus === stat) {
this.plus = '';
} else if (this.minus === stat) {
this.minus = '';
} else {
natureChange = false;
}
if (natureChange) {
this.updateNature();
}
// cap
if (val > 252) val = 252;
if (val < 0 || isNaN(val)) val = 0;
if (set.evs[stat] !== val || natureChange) {
set.evs[stat] = val;
if (this.ignoreEVLimits) {
var evNum = supportsEVs ? 252 : supportsAVs ? 200 : 0;
if (set.evs['hp'] === undefined) set.evs['hp'] = evNum;
if (set.evs['atk'] === undefined) set.evs['atk'] = evNum;
if (set.evs['def'] === undefined) set.evs['def'] = evNum;
if (set.evs['spa'] === undefined) set.evs['spa'] = evNum;
if (set.evs['spd'] === undefined) set.evs['spd'] = evNum;
if (set.evs['spe'] === undefined) set.evs['spe'] = evNum;
}
this.setSlider(stat, val);
this.updateStatGraph();
}
} else {
// IV
var stat = inputName.substr(3);
if (this.curTeam.gen <= 2) {
val *= 2;
if (val === 30) val = 31;
}
if (val > 31 || isNaN(val)) val = 31;
if (val < 0) val = 0;
if (!set.ivs) set.ivs = {};
if (set.ivs[stat] !== val) {
set.ivs[stat] = val;
this.updateIVs();
this.updateStatGraph();
}
}
this.save();
},
updateIVs: function () {
var set = this.curSet;
if (!set.moves || this.canHyperTrain(set)) return;
var hasHiddenPower = false;
for (var i = 0; i < set.moves.length; i++) {
if (toID(set.moves[i]).slice(0, 11) === 'hiddenpower') {
hasHiddenPower = true;
break;
}
}
if (!hasHiddenPower) return;
var hpTypes = ['Fighting', 'Flying', 'Poison', 'Ground', 'Rock', 'Bug', 'Ghost', 'Steel', 'Fire', 'Water', 'Grass', 'Electric', 'Psychic', 'Ice', 'Dragon', 'Dark'];
var hpType;
if (this.curTeam.gen <= 2) {
var hpDV = Math.floor(set.ivs.hp / 2);
var atkDV = Math.floor(set.ivs.atk / 2);
var defDV = Math.floor(set.ivs.def / 2);
var speDV = Math.floor(set.ivs.spe / 2);
var spcDV = Math.floor(set.ivs.spa / 2);
hpType = hpTypes[4 * (atkDV % 4) + (defDV % 4)];
var expectedHpDV = (atkDV % 2) * 8 + (defDV % 2) * 4 + (speDV % 2) * 2 + (spcDV % 2);
if (expectedHpDV !== hpDV) {
set.ivs.hp = expectedHpDV * 2;
if (set.ivs.hp === 30) set.ivs.hp = 31;
this.$chart.find('input[name=iv-hp]').val(expectedHpDV);
}
} else {
var hpTypeX = 0;
var i = 1;
var stats = {hp: 31, atk: 31, def: 31, spe: 31, spa: 31, spd: 31};
for (var s in stats) {
if (set.ivs[s] === undefined) set.ivs[s] = 31;
hpTypeX += i * (set.ivs[s] % 2);
i *= 2;
}
hpType = hpTypes[Math.floor(hpTypeX * 15 / 63)];
}
for (var i = 0; i < set.moves.length; i++) {
if (toID(set.moves[i]).slice(0, 11) === 'hiddenpower') {
set.moves[i] = "Hidden Power " + hpType;
if (i < 4) this.$('input[name=move' + (i + 1) + ']').val("Hidden Power " + hpType);
}
}
},
statSlide: function (e) {
var slider = e.currentTarget;
var stat = slider.name.substr(9);
var set = this.curSet;
if (!set) return;
var val = +slider.value;
var originalVal = val;
var result = this.getStat(stat, set, val);
var supportsEVs = !this.curTeam.format.includes('letsgo');
var supportsAVs = !supportsEVs && this.curTeam.format.endsWith('norestrictions');
if (supportsEVs) {
while (val > 0 && this.getStat(stat, set, val - 4) == result) val -= 4;
}
if (supportsEVs && !this.ignoreEVLimits && set.evs) {
var total = 0;
for (var i in set.evs) {
total += (i === stat ? val : set.evs[i]);
}
var totalLimit = 508;
var limit = 252;
if (total > totalLimit && val - total + totalLimit >= 0) {
// don't allow dragging beyond 508 EVs
val = val - total + totalLimit;
// make sure val is a legal value
val = +val;
if (!val || val <= 0) val = 0;
if (val > limit) val = limit;
}
}
// Don't try this at home.
// I am a trained professional.
if (val !== originalVal) slider.value = val;
if (!set.evs) set.evs = {};
if (this.ignoreEVLimits) {
var evNum = supportsEVs ? 252 : supportsAVs ? 200 : 0;
if (set.evs['hp'] === undefined) set.evs['hp'] = evNum;
if (set.evs['atk'] === undefined) set.evs['atk'] = evNum;
if (set.evs['def'] === undefined) set.evs['def'] = evNum;
if (set.evs['spa'] === undefined) set.evs['spa'] = evNum;
if (set.evs['spd'] === undefined) set.evs['spd'] = evNum;
if (set.evs['spe'] === undefined) set.evs['spe'] = evNum;
}
set.evs[stat] = val;
val = '' + (val || '') + (this.plus === stat ? '+' : '') + (this.minus === stat ? '-' : '');
this.$('input[name=stat-' + stat + ']').val(val);
this.updateStatGraph();
},
statSlided: function (e) {
this.statSlide(e);
this.save();
},
natureChange: function (e) {
var set = this.curSet;
if (!set) return;
if (e) {
set.nature = e.currentTarget.value;
}
this.plus = '';
this.minus = '';
var nature = BattleNatures[set.nature || 'Serious'];
for (var i in BattleStatNames) {
var val = '' + (set.evs[i] || '');
if (nature.plus === i) {
this.plus = i;
val += '+';
}
if (nature.minus === i) {
this.minus = i;
val += '-';
}
this.$chart.find('input[name=stat-' + i + ']').val(val);
if (!e) this.setSlider(i, set.evs[i]);
}
this.save();
this.updateStatGraph();
},
ivSpreadChange: function (e) {
var set = this.curSet;
if (!set) return;
var spread = e.currentTarget.value.split('/');
if (!set.ivs) set.ivs = {};
if (spread.length !== 6) return;
var stats = ['hp', 'atk', 'def', 'spa', 'spd', 'spe'];
for (var i = 0; i < 6; i++) {
this.$chart.find('input[name=iv-' + stats[i] + ']').val(spread[i]);
set.ivs[stats[i]] = parseInt(spread[i], 10);
}
$(e.currentTarget).val('');
this.save();
this.updateStatGraph();
},
/*********************************************************
* Set details form
*********************************************************/
updateDetailsForm: function () {
var buf = '';
var set = this.curSet;
var isLetsGo = this.curTeam.format.includes('letsgo');
var isNatDex = this.curTeam.gen === 8 && this.curTeam.format.includes('nationaldex');
var species = Dex.getSpecies(set.species);
if (!set) return;
buf += '';
buf += '';
var formCount = forms.length;
for (var i = 0; i < formCount; i++) {
var formid = forms[i].substring(baseid.length);
var form = (formid ? formid[0].toUpperCase() + formid.slice(1) : '');
var offset = '-' + (((i - 1) % 7) * spriteSize) + 'px -' + (Math.floor((i - 1) / 7) * spriteSize) + 'px';
buf += ' ';
}
buf += '
';
var height = Math.ceil(formCount / 7);
var width = Math.ceil(formCount / height);
this.$el.html(buf).css({'max-width': (4 + spriteSize) * width, 'height': 42 + (4 + spriteSize) * height});
},
setForm: function (form) {
var species = Dex.getSpecies(this.curSet.species);
if (form && form !== species.form) {
this.curSet.species = Dex.getSpecies(species.baseSpecies + form).name;
} else if (!form) {
this.curSet.species = species.baseSpecies;
}
this.close();
if (this.room.curSet) {
this.room.updatePokemonSprite();
} else {
this.room.update();
}
this.room.$('input[name=pokemon]').eq(this.chartIndex).val(this.curSet.species);
this.room.curTeam.team = Storage.packTeam(this.room.curSetList);
Storage.saveTeam(this.room.curTeam);
}
});
})(window, jQuery);