Merge branch 'master' of https://github.com/smogon/pokemon-showdown-client into champions-tera-button-beta-client

This commit is contained in:
ry 2026-04-19 23:14:04 -05:00
commit bd27d43889
5 changed files with 86 additions and 99 deletions

View File

@ -314,8 +314,6 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
const overrideTier = {};
const metagameBans = {};
const nonstandardMoves = [];
const gen5zuBans = {};
const gen4puBans = {};
for (const id of pokemon) {
const species = Dex.mod(gen).species.get(id);
const baseSpecies = Dex.mod(gen).species.get(species.baseSpecies);
@ -382,7 +380,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
if (species.tier === 'LC') return 'LC';
return 'Regular';
}
if (isRS || isFRLG) {
if (isRS) {
if (species.isNonstandard) {
if (species.isNonstandard === 'Unobtainable') return 'Unreleased';
return 'Illegal';
@ -483,20 +481,6 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
metagameBans['nationaldex35pokes'][species.id] = 1;
}
}
if (genNum >= 5) {
if (genNum === 5) {
const gen5zu = Dex.formats.get(gen + 'zu');
if (gen5zu.exists && Dex.formats.getRuleTable(gen5zu).isBannedSpecies(species)) {
gen5zuBans[species.id] = 1;
}
}
}
if (genNum === 4) {
const gen4pu = Dex.formats.get(gen + 'pu');
if (gen4pu.exists && Dex.formats.getRuleTable(gen4pu).isBannedSpecies(species)) {
gen4puBans[species.id] = 1;
}
}
}
nonstandardMoves.push(...Object.keys(Dex.data.Moves).filter(id => {
@ -599,12 +583,6 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
BattleTeambuilderTable[gen].learnsets = {};
} else {
BattleTeambuilderTable[gen] = {};
if (genNum === 5) {
BattleTeambuilderTable[gen].gen5zuBans = gen5zuBans;
}
if (genNum === 4) {
BattleTeambuilderTable[gen].gen4puBans = gen4puBans;
}
BattleTeambuilderTable[gen].overrideTier = overrideTier;
BattleTeambuilderTable[gen].tiers = tiers;
BattleTeambuilderTable[gen].items = items;
@ -622,15 +600,12 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
if (isVGC || isGen9BH) {
return ["Mythical", "Restricted", "Regular", "NFE", "LC"];
}
if (isRS || isFRLG) {
if (isRS) {
return ["Regular", "NFE", "LC", "Uber"];
}
if (isDoubles && genNum > 4) {
return ["DUber", "(DUber)", "DOU", "DBL", "(DOU)", "DUU", "(DUU)", "New", "NFE", "LC"];
}
if (gen === 'gen4') {
return ["CAP", "CAP NFE", "CAP LC", "AG", "Uber", "OU", "(OU)", "UUBL", "UU", "NUBL", "NU", "NFE", "LC"];
}
return [
"CAP", "CAP NFE", "CAP LC", "AG", "Uber", "(Uber)", "OU", "(OU)", "UUBL", "UU", "RUBL", "RU", "NUBL", "NU", "PUBL", "PU", "ZUBL", "ZU", "New", "NFE", "LC", "Unreleased",
];
@ -990,6 +965,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
const G2Learnsets = Dex.mod('gen2').data.Learnsets;
for (const id in G2Learnsets) {
const learnset = G2Learnsets[id].learnset;
if (!learnset) continue;
for (const moveid in learnset) {
const gens = learnset[moveid].map(x => Number(x[0]));
const minGen = Math.min(...gens);
@ -1006,6 +982,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
const species = Dex.mod('gen3rs').species.get(id);
if (species.isNonstandard && !['Unobtainable', 'CAP'].includes(species.isNonstandard)) continue;
const learnset = G3RSLearnsets[id].learnset;
if (!learnset) continue;
BattleTeambuilderTable['gen3rs'].learnsets[id] = {};
for (const moveid in learnset) {
BattleTeambuilderTable['gen3rs'].learnsets[id][moveid] = '3';
@ -1016,6 +993,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
const species = Dex.mod('gen3frlg').species.get(id);
if (species.isNonstandard && !['Unobtainable', 'CAP'].includes(species.isNonstandard)) continue;
const learnset = G3FRLGLearnsets[id].learnset;
if (!learnset) continue;
BattleTeambuilderTable['gen3frlg'].learnsets[id] = {};
for (const moveid in learnset) {
BattleTeambuilderTable['gen3frlg'].learnsets[id][moveid] = '3';
@ -1026,6 +1004,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
const species = Dex.mod('gen5bw1').species.get(id);
if (species.isNonstandard && !['Unobtainable', 'CAP'].includes(species.isNonstandard)) continue;
const learnset = G5BW1Learnsets[id].learnset;
if (!learnset) continue;
BattleTeambuilderTable['gen5bw1'].learnsets[id] = {};
for (const moveid in learnset) {
BattleTeambuilderTable['gen5bw1'].learnsets[id][moveid] = '5';
@ -1039,6 +1018,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
if (!validNum) continue;
if (species.forme && !['Alola', 'Mega', 'Mega-X', 'Mega-Y', 'Starter'].includes(species.forme)) continue;
const learnset = LGLearnsets[id].learnset;
if (!learnset) continue;
BattleTeambuilderTable['gen7letsgo'].learnsets[id] = {};
for (const moveid in learnset) {
BattleTeambuilderTable['gen7letsgo'].learnsets[id][moveid] = '7';
@ -1049,6 +1029,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
const species = Dex.mod('gen8bdsp').species.get(id);
if (species.isNonstandard && !['Unobtainable', 'CAP'].includes(species.isNonstandard)) continue;
const learnset = BDSPLearnsets[id].learnset;
if (!learnset) continue;
BattleTeambuilderTable['gen8bdsp'].learnsets[id] = {};
for (const moveid in learnset) {
BattleTeambuilderTable['gen8bdsp'].learnsets[id][moveid] = '8g';
@ -1059,6 +1040,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... ");
const species = Dex.mod('champions').species.get(id);
if (species.isNonstandard) continue;
const learnset = ChampionsLearnsets[id].learnset;
if (!learnset) continue;
BattleTeambuilderTable['champions'].learnsets[id] = {};
for (const moveid in learnset) {
BattleTeambuilderTable['champions'].learnsets[id][moveid] = '9a';

View File

@ -1291,11 +1291,16 @@
if ($(window).width() < 640) this.show();
},
renderSet: function (set, i) {
var baseFormat = this.curTeam.format;
if (baseFormat.substr(-5) === 'draft') baseFormat = baseFormat.substr(0, baseFormat.length - 5);
var species = this.curTeam.dex.species.get(set.species);
var isChampions = this.curTeam.format.includes('champions');
var isLetsGo = this.curTeam.format.includes('letsgo');
var isBDSP = this.curTeam.format.includes('bdsp');
var isNatDex = this.curTeam.format.includes('nationaldex') || this.curTeam.format.includes('natdex');
var isChampions = baseFormat.includes('champions');
var isLetsGo = baseFormat.includes('letsgo');
var isBDSP = baseFormat.includes('bdsp');
var isNatDex = baseFormat.includes('nationaldex') || baseFormat.includes('natdex');
var isVGC = baseFormat.includes('battlespot') || baseFormat.includes('bss') ||
baseFormat.includes('vgc') || baseFormat.includes('battlefestival');
var isLC = baseFormat.startsWith('lc') || baseFormat.endsWith('lc');
var buf = '<li value="' + i + '">';
if (!set.species) {
if (this.deletedSet) {
@ -1409,16 +1414,16 @@
} else if (BattleNatures[set.nature] && BattleNatures[set.nature].minus === j) {
evBuf += '<small>&minus;</small>';
}
var highestStat = 504;
if (j === 'hp') highestStat = 704;
if (isChampions) {
if (j === 'hp') highestStat = 267;
else highestStat = 310;
var highestStat = j === 'hp' ? 714 : 499;
if (isChampions || isVGC) {
highestStat = j === 'hp' ? 362 : 252;
}
if (isLC) {
highestStat = j === 'hp' ? 45 : 29;
}
var width = stats[j] * 75 / highestStat;
if (j === 'hp') width = stats[j] * 75 / highestStat;
if (width > 75) width = 75;
var color = Math.floor(stats[j] * 180 / (isChampions ? 310 : 714));
var color = Math.floor(stats[j] * 180 / highestStat);
if (color > 360) color = 360;
var statName = this.curTeam.gen === 1 && j === 'spa' ? 'Spc' : BattleStatNames[j];
buf += '<span class="statrow"><label>' + statName + '</label> <span class="statgraph"><span style="width:' + width + 'px;background:hsl(' + color + ',40%,75%);"></span></span> ' + evBuf + '</span>';
@ -2074,8 +2079,13 @@
var stats = { hp: '', atk: '', def: '', spa: '', spd: '', spe: '' };
var usesStatPoints = this.curTeam.format.includes('champions');
var supportsEVs = !this.curTeam.format.includes('letsgo');
var baseFormat = this.curTeam.format;
if (baseFormat.substr(-5) === 'draft') baseFormat = baseFormat.substr(0, baseFormat.length - 5);
var usesStatPoints = baseFormat.includes('champions');
var supportsEVs = !baseFormat.includes('letsgo');
var isVGC = baseFormat.includes('battlespot') || baseFormat.includes('bss') ||
baseFormat.includes('vgc') || baseFormat.includes('battlefestival');
var isLC = baseFormat.startsWith('lc') || baseFormat.endsWith('lc');
// stat cell
var buf = '<span class="statrow statrow-head"><label></label> <span class="statgraph"></span> <em>' + (usesStatPoints ? 'Points' : supportsEVs ? 'EV' : 'AV') + '</em></span>';
@ -2090,16 +2100,16 @@
} else if (BattleNatures[set.nature] && BattleNatures[set.nature].minus === stat) {
evBuf += '<small>&minus;</small>';
}
var highestStat = 504;
if (stat === 'hp') highestStat = 704;
if (usesStatPoints) {
if (stat === 'hp') highestStat = 267;
else highestStat = 310;
var highestStat = stat === 'hp' ? 714 : 499;
if (usesStatPoints || isVGC) {
highestStat = stat === 'hp' ? 362 : 252;
}
if (isLC) {
highestStat = stat === 'hp' ? 45 : 29;
}
var width = stats[stat] * 75 / highestStat;
if (stat === 'hp') width = stats[stat] * 75 / highestStat;
if (width > 75) width = 75;
var color = Math.floor(stats[stat] * 180 / (usesStatPoints ? 310 : 714));
var color = Math.floor(stats[stat] * 180 / highestStat);
if (color > 360) color = 360;
var statName = this.curTeam.gen === 1 && stat === 'spa' ? 'Spc' : BattleStatNames[stat];
buf += '<span class="statrow"><label>' + statName + '</label> <span class="statgraph"><span style="width:' + width + 'px;background:hsl(' + color + ',40%,75%);"></span></span> ' + evBuf + '</span>';
@ -2119,16 +2129,16 @@
var totalev = 0;
for (var stat in stats) {
if (stat === 'spd' && this.curTeam.gen === 1) continue;
var highestStat = 504;
if (stat === 'hp') highestStat = 704;
if (usesStatPoints) {
if (stat === 'hp') highestStat = 267;
else highestStat = 310;
var highestStat = stat === 'hp' ? 714 : 499;
if (usesStatPoints || isVGC) {
highestStat = stat === 'hp' ? 362 : 252;
}
if (isLC) {
highestStat = stat === 'hp' ? 45 : 29;
}
var width = stats[stat] * 180 / highestStat;
if (stat === 'hp') width = stats[stat] * 180 / highestStat;
if (width > 179) width = 179;
var color = Math.floor(stats[stat] * 180 / (usesStatPoints ? 310 : 714));
var color = Math.floor(stats[stat] * 180 / highestStat);
if (color > 360) color = 360;
buf += '<div><em><span style="width:' + Math.floor(width) + 'px;background:hsl(' + color + ',85%,45%);border-color:hsl(' + color + ',85%,35%)"></span></em></div>';
totalev += (set.evs[stat] || 0);
@ -2355,12 +2365,17 @@
var nature = BattleNatures[set.nature || 'Serious'];
if (!nature) nature = {};
var usesStatPoints = this.curTeam.format.includes('champions');
var supportsEVs = !this.curTeam.format.includes('letsgo') && !usesStatPoints;
// var supportsAVs = !supportsEVs && this.curTeam.format.endsWith('norestrictions');
var baseFormat = this.curTeam.format;
if (baseFormat.substr(-5) === 'draft') baseFormat = baseFormat.substr(0, baseFormat.length - 5);
var usesStatPoints = baseFormat.includes('champions');
var supportsEVs = !baseFormat.includes('letsgo') && !usesStatPoints;
// var supportsAVs = !supportsEVs && baseFormat.endsWith('norestrictions');
var defaultEV = this.curTeam.gen <= 2 ? 252 : 0;
var maxEV = usesStatPoints ? 32 : supportsEVs ? 252 : 200;
var stepEV = supportsEVs ? 4 : 1;
var isVGC = baseFormat.includes('battlespot') || baseFormat.includes('bss') ||
baseFormat.includes('vgc') || baseFormat.includes('battlefestival');
var isLC = baseFormat.startsWith('lc') || baseFormat.endsWith('lc');
// label column
buf += '<div class="col labelcol"><div></div>';
@ -2382,16 +2397,16 @@
buf += '<div class="col graphcol"><div></div>';
for (var i in stats) {
stats[i] = this.getStat(i);
var highestStat = 504;
if (i === 'hp') highestStat = 704;
if (usesStatPoints) {
if (i === 'hp') highestStat = 267;
else highestStat = 310;
var highestStat = i === 'hp' ? 714 : 499;
if (usesStatPoints || isVGC) {
highestStat = i === 'hp' ? 362 : 252;
}
if (isLC) {
highestStat = i === 'hp' ? 45 : 29;
}
var width = stats[i] * 180 / highestStat;
if (i === 'hp') width = Math.floor(stats[i] * 180 / highestStat);
if (width > 179) width = 179;
var color = Math.floor(stats[i] * 180 / (usesStatPoints ? 310 : 714));
var color = Math.floor(stats[i] * 180 / highestStat);
if (color > 360) color = 360;
buf += '<div><em><span style="width:' + Math.floor(width) + 'px;background:hsl(' + color + ',85%,45%);border-color:hsl(' + color + ',85%,35%)"></span></em></div>';
}

View File

@ -653,7 +653,8 @@ abstract class BattleTypedSearch<T extends SearchType> {
if (format.includes('champions')) {
this.formatType = 'champions';
this.dex = Dex.mod('champions' as ID);
format = 'ou' as ID;
format = format.slice(9) as ID;
if (format !== 'ou') format = 'ubers' as ID;
}
if (format.startsWith('vgc')) {
this.formatType = 'doubles';
@ -686,6 +687,7 @@ abstract class BattleTypedSearch<T extends SearchType> {
if (format.includes('frlg')) {
this.formatType = 'frlg';
this.dex = Dex.mod('gen3frlg' as ID);
format = format.slice(4) as ID;
}
if (format === 'partnersincrime') this.formatType = 'doubles';
if (format.startsWith('ffa') || format === 'freeforall') this.formatType = 'doubles';
@ -1036,7 +1038,7 @@ class BattlePokemonSearch extends BattleTypedSearch<'pokemon'> {
table = table[`gen${dex.gen}`];
} else if (this.formatType === 'champions') {
table = table[`champions`];
} else if (isVGCOrBS && !this.formatType) {
} else if (isVGCOrBS) {
table = table[`gen${dex.gen}vgc`];
} else if (dex.gen === 9 && isHackmons && !this.formatType) {
table = table['bh'];
@ -1143,10 +1145,9 @@ class BattlePokemonSearch extends BattleTypedSearch<'pokemon'> {
else if (format === 'uubl') tierSet = tierSet.slice(slices.UUBL);
else if (format === 'uu') tierSet = tierSet.slice(slices.UU);
else if (format === 'ru') tierSet = tierSet.slice(slices.RU || slices.UU);
else if (format === 'nu') tierSet = tierSet.slice(slices.NU || slices.RU || slices.UU);
else if (format === 'pu') tierSet = tierSet.slice(slices.PU || slices.NU);
else if (format === 'zu' && dex.gen === 5) tierSet = tierSet.slice(slices.PU || slices.NU);
else if (format === 'zu') tierSet = tierSet.slice(slices.ZU || slices.PU || slices.NU);
else if (format === 'nu') tierSet = tierSet.slice(slices.NU);
else if (format === 'pu') tierSet = tierSet.slice(slices.PU);
else if (format === 'zu') tierSet = tierSet.slice(slices.ZU);
else if (
format === 'lc' || format === 'lcuu' || format.startsWith('lc') || (format !== 'caplc' && format.endsWith('lc'))
) tierSet = tierSet.slice(slices.LC);
@ -1236,18 +1237,6 @@ class BattlePokemonSearch extends BattleTypedSearch<'pokemon'> {
});
}
}
if (format === 'zu' && dex.gen === 5 && table.gen5zuBans) {
tierSet = tierSet.filter(([type, id]) => {
if (id in table.gen5zuBans) return false;
return true;
});
}
if (format === 'pu' && dex.gen === 4 && table.gen4puBans) {
tierSet = tierSet.filter(([type, id]) => {
if (id in table.gen4puBans) return false;
return true;
});
}
// Filter out Gmax Pokemon from standard tier selection
if (!(/^(battlestadium|vgc|doublesubers)/g.test(format) || (format === 'doubles' && this.formatType === 'natdex'))) {

View File

@ -118,7 +118,8 @@ export class TeamEditorState extends PSModel {
this.defaultLevel = 100;
if (
formatid.includes('vgc') || formatid.includes('bss') || formatid.includes('ultrasinnohclassic') ||
formatid.includes('battlespot') || formatid.includes('battlestadium') || formatid.includes('battlefestival')
formatid.includes('battlespot') || formatid.includes('battlestadium') || formatid.includes('battlefestival') ||
formatid.includes('letsgo') || formatid.includes('champions')
) {
this.defaultLevel = 50;
}
@ -2451,11 +2452,11 @@ class StatForm extends preact.Component<{
const stat = editor.getStat(statID, set, ivs[statID]);
let ev: number | string = set.evs ? (set.evs[statID] || 0) : defaultEV;
let width = stat * 75 / 504;
if (statID === 'hp') width = stat * 75 / 704;
if (width > 75) width = 75;
let hue = Math.floor(stat * 180 / 714);
if (hue > 360) hue = 360;
const maxStat = statID === 'hp' ?
Math.floor(176 * editor.defaultLevel / 25) + 10 :
Math.floor(247 * editor.defaultLevel / 50) + 5;
const width = Math.min(stat * 75 / maxStat, 75);
const hue = Math.min(Math.floor(stat * 180 / maxStat), 360);
const statName = editor.gen === 1 && statID === 'spa' ? 'Spc' : BattleStatNames[statID];
if (evs && !ev && !set.evs && statID === 'hp') ev = 'EVs';
return <span class="statrow">
@ -2715,11 +2716,12 @@ class StatForm extends preact.Component<{
plus: Dex.StatNameExceptHP | null = null;
minus: Dex.StatNameExceptHP | null = null;
renderStatbar(stat: number, statID: StatName) {
let width = stat * 180 / 504;
if (statID === 'hp') width = Math.floor(stat * 180 / 704);
if (width > 179) width = 179;
let hue = Math.floor(stat * 180 / 714);
if (hue > 360) hue = 360;
const { editor } = this.props;
const maxStat = statID === 'hp' ?
Math.floor(176 * editor.defaultLevel / 25) + 10 :
Math.floor(247 * editor.defaultLevel / 50) + 5;
const width = Math.min(stat * 180 / maxStat, 180);
const hue = Math.min(Math.floor(stat * 180 / maxStat), 360);
return <span
style={`width:${Math.floor(width)}px;background:hsl(${hue},85%,45%);border-color:hsl(${hue},85%,35%)`}
></span>;

View File

@ -1636,7 +1636,9 @@ export class BattleTooltips {
}
// Weather and pseudo-weather type changes.
if (move.id === 'weatherball') {
if (value.weatherModify(0)) {
if (value.abilityModify(0, 'Mega Sol')) {
moveType = 'Fire';
} else if (value.weatherModify(0)) {
switch (this.battle.weather) {
case 'sunnyday':
case 'desolateland':
@ -1656,8 +1658,6 @@ export class BattleTooltips {
moveType = 'Ice';
break;
}
} else if (value.abilityModify(0, 'Mega Sol')) {
moveType = 'Fire';
}
}
if (move.id === 'terrainpulse' && pokemon.isGrounded(serverPokemon)) {
@ -2143,7 +2143,7 @@ export class BattleTooltips {
value.set(move.accuracy as number);
if (move.id === 'hurricane' || move.id === 'thunder') {
if (value.tryAbility('Mega Sol')) value.set(50, 'Mega Sol');
if (value.tryAbility('Mega Sol')) value.set(50, 'Mega Sol'); // TODO check implementation
if (value.tryWeather('Sunny Day')) value.set(50, 'Sunny Day');
if (value.tryWeather('Desolate Land')) value.set(50, 'Desolate Land');
}
@ -2276,8 +2276,7 @@ export class BattleTooltips {
}
}
if (move.id === 'weatherball') {
value.abilityModify(2, "Mega Sol");
if (this.battle.weather !== 'deltastream') {
if (!value.abilityModify(2, "Mega Sol") && this.battle.weather !== 'deltastream') {
value.weatherModify(2);
}
}