mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-10-02 06:07:10 -05:00
Add December 2025 rotational ladders
This commit is contained in:
@@ -506,202 +506,32 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
column: 2,
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Fortemons",
|
||||
desc: `Put an attacking move in the item slot to have all of a Pokémon's attacks inherit its properties.`,
|
||||
name: "[Gen 9] Convergence",
|
||||
desc: `Allows all Pokémon that have identical types to share moves and abilities.`,
|
||||
mod: 'gen9',
|
||||
// searchShow: false,
|
||||
ruleset: ['Standard OMs', 'Sleep Moves Clause', 'Terastal Clause'],
|
||||
ruleset: ['Standard OMs', 'Sleep Clause Mod', 'Convergence Legality', 'Terastal Clause', '!Obtainable Abilities'],
|
||||
banlist: [
|
||||
'Annihilape', 'Arceus', 'Archaludon', 'Azumarill', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chi-Yu', 'Chien-Pao', 'Cloyster', 'Comfey', 'Deoxys-Normal', 'Deoxys-Attack',
|
||||
'Dialga-Base', 'Espathra', 'Eternatus', 'Flutter Mane', 'Giratina-Altered', 'Great Tusk', 'Groudon', 'Ho-Oh', 'Iron Bundle', 'Iron Treads', 'Koraidon', 'Kyogre',
|
||||
'Kyurem-Black', 'Kyurem-White', 'Landorus-Incarnate', 'Lugia', 'Lunala', 'Magearna', 'Meowscarada', 'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
|
||||
'Palafin', 'Palkia', 'Palkia-Origin', 'Quaquaval', 'Raging Bolt', 'Rayquaza', 'Reshiram', 'Samurott-Hisui', 'Shaymin-Sky', 'Skeledirge', 'Smeargle', 'Solgaleo',
|
||||
'Spectrier', 'Sneasler', 'Terapagos', 'Urshifu', 'Urshifu-Rapid-Strike', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Arena Trap',
|
||||
'Moody', 'Serene Grace', 'Shadow Tag', 'Damp Rock', 'Heat Rock', 'Light Clay', 'Baton Pass', 'Beat Up', 'Fake Out', 'Last Respects', 'move:Metronome', 'Shed Tail',
|
||||
'Arceus', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chi-Yu', 'Chien-Pao', 'Darkrai', 'Deoxys-Normal', 'Deoxys-Attack', 'Deoxys-Speed', 'Dialga', 'Dialga-Origin',
|
||||
'Dondozo', 'Eternatus', 'Flutter Mane', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-oh', 'Inteleon', 'Iron Bundle', 'Iron Hands', 'Koraidon', 'Kyogre',
|
||||
'Kyurem-Black', 'Kyurem-White', 'Landorus-Incarnate', 'Lilligant-Hisui', 'Lugia', 'Lunala', 'Magearna', 'Manaphy', 'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings',
|
||||
'Necrozma-Dusk-Mane', 'Ogerpon-Hearthflame', 'Palafin', 'Palkia', 'Palkia-Origin', 'Primarina', 'Rayquaza', 'Regieleki', 'Regigigas', 'Reshiram', 'Shaymin-Sky',
|
||||
'Solgaleo', 'Slaking', 'Smeargle', 'Spectrier', 'Urshifu-Single-Strike', 'Urshifu-Rapid-Strike', 'Walking Wake', 'Zacian', 'Zacian-Crowned', 'Zamazenta',
|
||||
'Zamazenta-Crowned', 'Zekrom', 'Arena Trap', 'Comatose', 'Contrary', 'Drizzle', 'Imposter', 'Moody', 'Pure Power', 'Shadow Tag', 'Speed Boost', 'Unburden',
|
||||
'Heat Rock', 'King\'s Rock', 'Light Clay', 'Razor Fang', 'Baton Pass', 'Boomburst', 'Extreme Speed', 'Last Respects', 'Population Bomb', 'Quiver Dance',
|
||||
'Rage Fist', 'Shed Tail', 'Shell Smash', 'Spore', 'Transform',
|
||||
],
|
||||
restricted: [
|
||||
'Doom Desire', 'Dynamic Punch', 'Electro Ball', 'Explosion', 'Gyro Ball', 'Final Gambit', 'Flail', 'Flip Turn', 'Fury Cutter', 'Future Sight', 'Grass Knot',
|
||||
'Grassy Glide', 'Hard Press', 'Heavy Slam', 'Heat Crash', 'Inferno', 'Low Kick', 'Misty Explosion', 'Nuzzle', 'Power Trip', 'Reversal', 'Self-Destruct',
|
||||
'Spit Up', 'Stored Power', 'Tera Blast', 'U-turn', 'Weather Ball', 'Zap Cannon',
|
||||
],
|
||||
onValidateTeam(team) {
|
||||
const itemTable = new Set<string>();
|
||||
for (const set of team) {
|
||||
const forte = this.toID(set.item);
|
||||
if (!forte) continue;
|
||||
const move = this.dex.moves.get(forte);
|
||||
if (move.exists && move.id !== 'metronome') {
|
||||
if (itemTable.has(forte)) {
|
||||
return [
|
||||
`You are limited to one of each move in the item slot per team.`,
|
||||
`(You have more than one ${move.name}.)`,
|
||||
];
|
||||
}
|
||||
itemTable.add(forte);
|
||||
}
|
||||
}
|
||||
},
|
||||
validateSet(set, teamHas) {
|
||||
const item = set.item;
|
||||
const species = this.dex.species.get(set.species);
|
||||
const move = this.dex.moves.get(item);
|
||||
if (!move.exists || move.id === 'metronome' || move.category === 'Status') {
|
||||
return this.validateSet(set, teamHas);
|
||||
}
|
||||
set.item = '';
|
||||
const problems = this.validateSet(set, teamHas) || [];
|
||||
set.item = item;
|
||||
if (this.checkCanLearn(move, species, this.allSources(species), set)) {
|
||||
problems.push(`${species.name} can't learn ${move.name}.`);
|
||||
}
|
||||
if (set.moves.map(this.toID).includes(move.id)) {
|
||||
problems.push(`Moves in the item slot can't be in the moveslots as well.`);
|
||||
}
|
||||
if (this.ruleTable.has(`-move:${move.id}`)) {
|
||||
problems.push(`The move ${move.name} is fully banned.`);
|
||||
}
|
||||
const accuracyLoweringMove =
|
||||
move.secondaries?.some(secondary => secondary.boosts?.accuracy && secondary.boosts?.accuracy < 0);
|
||||
const flinchMove = move.secondaries?.some(secondary => secondary.volatileStatus === 'flinch');
|
||||
const freezeMove = move.secondaries?.some(secondary => secondary.status === 'frz') || move.id === 'triattack';
|
||||
if (
|
||||
this.ruleTable.isRestricted(`move:${move.id}`) ||
|
||||
((accuracyLoweringMove || move.ohko || move.multihit || move.id === 'beatup' || move.flags['charge'] ||
|
||||
move.priority > 0 || move.damageCallback || flinchMove || freezeMove) &&
|
||||
!this.ruleTable.has(`+move:${move.id}`))
|
||||
) {
|
||||
problems.push(`The move ${move.name} can't be used as an item.`);
|
||||
}
|
||||
return problems.length ? problems : null;
|
||||
},
|
||||
onBegin() {
|
||||
for (const pokemon of this.getAllPokemon()) {
|
||||
const move = this.dex.getActiveMove(pokemon.set.item);
|
||||
if (move.exists && move.category !== 'Status') {
|
||||
pokemon.m.forte = move;
|
||||
pokemon.item = 'mail' as ID;
|
||||
}
|
||||
}
|
||||
},
|
||||
onModifyMovePriority: 1,
|
||||
onModifyMove(move, pokemon, target) {
|
||||
const forte: ActiveMove = pokemon.m.forte;
|
||||
if (move.category !== 'Status' && forte) {
|
||||
move.flags = { ...move.flags, ...forte.flags };
|
||||
if (forte.self) {
|
||||
if (forte.self.onHit && move.self?.onHit) {
|
||||
for (const i in forte.self) {
|
||||
if (i.startsWith('onHit')) continue;
|
||||
(move.self as any)[i] = (forte.self as any)[i];
|
||||
}
|
||||
} else {
|
||||
move.self = { ...move.self, ...forte.self };
|
||||
}
|
||||
}
|
||||
if (forte.selfBoost?.boosts) {
|
||||
if (!move.selfBoost?.boosts) move.selfBoost = { boosts: {} };
|
||||
let boostid: BoostID;
|
||||
for (boostid in forte.selfBoost.boosts) {
|
||||
if (!move.selfBoost.boosts![boostid]) move.selfBoost.boosts![boostid] = 0;
|
||||
move.selfBoost.boosts![boostid]! += forte.selfBoost.boosts[boostid]!;
|
||||
}
|
||||
}
|
||||
if (forte.secondaries) {
|
||||
move.secondaries = [...(move.secondaries || []), ...forte.secondaries];
|
||||
}
|
||||
move.critRatio = (move.critRatio || 1) + (forte.critRatio || 1) - 1;
|
||||
const VALID_PROPERTIES = [
|
||||
'alwaysHit', 'basePowerCallback', 'breaksProtect', 'drain', 'forceSTAB', 'forceSwitch', 'hasCrashDamage', 'hasSheerForce',
|
||||
'ignoreAbility', 'ignoreAccuracy', 'ignoreDefensive', 'ignoreEvasion', 'ignoreImmunity', 'mindBlownRecoil', 'noDamageVariance',
|
||||
'ohko', 'overrideDefensivePokemon', 'overrideDefensiveStat', 'overrideOffensivePokemon', 'overrideOffensiveStat', 'pseudoWeather',
|
||||
'recoil', 'selfdestruct', 'selfSwitch', 'sleepUsable', 'smartTarget', 'stealsBoosts', 'thawsTarget', 'volatileStatus', 'willCrit',
|
||||
] as const;
|
||||
for (const property of VALID_PROPERTIES) {
|
||||
if (forte[property]) {
|
||||
move[property] = forte[property] as any;
|
||||
}
|
||||
}
|
||||
// Added here because onEffectiveness doesn't have an easy way to reference the source
|
||||
if (forte.onEffectiveness) {
|
||||
move.onEffectiveness = function (typeMod, t, type, m) {
|
||||
return forte.onEffectiveness!.call(this, typeMod, t, type, m);
|
||||
};
|
||||
}
|
||||
forte.onModifyMove?.call(this, move, pokemon, target);
|
||||
}
|
||||
},
|
||||
onModifyPriority(priority, source, target, move) {
|
||||
const forte = source?.m.forte;
|
||||
if (move.category !== 'Status' && forte) {
|
||||
if (source.hasAbility('Triage') && forte.flags['heal']) {
|
||||
return priority + (move.flags['heal'] ? 0 : 3);
|
||||
}
|
||||
return priority + forte.priority;
|
||||
}
|
||||
},
|
||||
onModifyTypePriority: 1,
|
||||
onModifyType(move, pokemon, target) {
|
||||
const forte = pokemon.m.forte;
|
||||
if (move.category !== 'Status' && forte) {
|
||||
this.singleEvent('ModifyType', forte, null, pokemon, target, move, move);
|
||||
}
|
||||
},
|
||||
onHitPriority: 1,
|
||||
onHit(target, source, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move?.category !== 'Status' && forte) {
|
||||
this.singleEvent('Hit', forte, {}, target, source, move);
|
||||
if (forte.self) this.singleEvent('Hit', forte.self, {}, source, source, move);
|
||||
this.singleEvent('AfterHit', forte, {}, target, source, move);
|
||||
}
|
||||
},
|
||||
onAfterSubDamage(damage, target, source, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move?.category !== 'Status' && forte) {
|
||||
this.singleEvent('AfterSubDamage', forte, null, target, source, move, damage);
|
||||
}
|
||||
},
|
||||
onModifySecondaries(secondaries, target, source, move) {
|
||||
if (secondaries.some(s => !!s.self)) move.selfDropped = false;
|
||||
},
|
||||
onAfterMoveSecondaryPriority: 1,
|
||||
onAfterMoveSecondarySelf(source, target, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move?.category !== 'Status' && forte) {
|
||||
this.singleEvent('AfterMoveSecondarySelf', forte, null, source, target, move);
|
||||
}
|
||||
},
|
||||
onBasePowerPriority: 1,
|
||||
onBasePower(basePower, source, target, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move.category !== 'Status' && forte?.onBasePower) {
|
||||
forte.onBasePower.call(this, basePower, source, target, move);
|
||||
}
|
||||
},
|
||||
pokemon: {
|
||||
getItem() {
|
||||
const move = this.battle.dex.moves.get(this.m.forte);
|
||||
if (!move.exists) return Object.getPrototypeOf(this).getItem.call(this);
|
||||
return {
|
||||
...this.battle.dex.items.get('mail'),
|
||||
name: move.name, id: move.id, ignoreKlutz: true, onTakeItem: false,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Camomons",
|
||||
desc: `Pokémon have their types set to match their first two moves.`,
|
||||
name: "[Gen 9] VoltTurn Mayhem",
|
||||
desc: `Every move that targets a foe causes the user to switch out after use.`,
|
||||
mod: 'gen9',
|
||||
// searchShow: false,
|
||||
ruleset: ['Standard OMs', 'Sleep Clause Mod', 'Evasion Items Clause', 'Evasion Abilities Clause', 'Terastal Clause', 'Camomons Mod'],
|
||||
ruleset: ['Standard OMs', 'Sleep Moves Clause', 'VoltTurn Mayhem Mod'],
|
||||
banlist: [
|
||||
'Arceus', 'Baxcalibur', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chi-Yu', 'Chien-Pao', 'Darkrai', 'Deoxys-Normal', 'Deoxys-Attack', 'Dialga', 'Dialga-Origin', 'Dragonite', 'Drednaw',
|
||||
'Enamorus-Incarnate', 'Espathra', 'Eternatus', 'Flutter Mane', 'Giratina', 'Giratina-Origin', 'Gouging Fire', 'Groudon', 'Ho-Oh', 'Iron Bundle', 'Kommo-o', 'Koraidon', 'Kyogre',
|
||||
'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Incarnate', 'Lugia', 'Lunala', 'Magearna', 'Manaphy', 'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
|
||||
'Palafin', 'Palkia', 'Palkia-Origin', 'Rayquaza', 'Reshiram', 'Roaring Moon', 'Shaymin-Sky', 'Sneasler', 'Solgaleo', 'Spectrier', 'Tornadus-Therian', 'Ursaluna-Bloodmoon',
|
||||
'Volcarona', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Crowned', 'Zekrom', 'Arena Trap', 'Moody', 'Shadow Tag', 'Booster Energy', 'King\'s Rock', 'Light Clay', 'Razor Fang',
|
||||
'Baton Pass', 'Last Respects', 'Shed Tail',
|
||||
'Arceus', 'Chi-Yu', 'Chien-Pao', 'Calyrex-Ice', 'Calyrex-Shadow', 'Darkrai', 'Deoxys-Attack', 'Deoxys-Normal', 'Deoxys-Speed', 'Dialga', 'Dialga-Origin', 'Dragonite',
|
||||
'Eternatus', 'Flutter Mane', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Iron Bundle', 'Koraidon', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Lunala', 'Magearna',
|
||||
'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palafin', 'Palkia', 'Palkia-Origin', 'Rayquaza', 'Regieleki', 'Reshiram', 'Shaymin-Sky', 'Solgaleo',
|
||||
'Terapagos', 'Zacian', 'Zacian-Crowned', 'Zekrom', 'King\'s Rock', 'Razor Fang', 'Fake Out', 'Last Respects', 'Revival Blessing',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1023,6 +853,21 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
side.sideConditions[sideCondition.id].duration = 0;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Camomons",
|
||||
desc: `Pokémon have their types set to match their first two moves.`,
|
||||
mod: 'gen9',
|
||||
searchShow: false,
|
||||
ruleset: ['Standard OMs', 'Sleep Clause Mod', 'Evasion Items Clause', 'Evasion Abilities Clause', 'Terastal Clause', 'Camomons Mod'],
|
||||
banlist: [
|
||||
'Arceus', 'Baxcalibur', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chi-Yu', 'Chien-Pao', 'Darkrai', 'Deoxys-Normal', 'Deoxys-Attack', 'Dialga', 'Dialga-Origin', 'Dragonite', 'Drednaw',
|
||||
'Enamorus-Incarnate', 'Espathra', 'Eternatus', 'Flutter Mane', 'Giratina', 'Giratina-Origin', 'Gouging Fire', 'Groudon', 'Ho-Oh', 'Iron Bundle', 'Kommo-o', 'Koraidon', 'Kyogre',
|
||||
'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Incarnate', 'Lugia', 'Lunala', 'Magearna', 'Manaphy', 'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
|
||||
'Palafin', 'Palkia', 'Palkia-Origin', 'Rayquaza', 'Reshiram', 'Roaring Moon', 'Shaymin-Sky', 'Sneasler', 'Solgaleo', 'Spectrier', 'Tornadus-Therian', 'Ursaluna-Bloodmoon',
|
||||
'Volcarona', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Crowned', 'Zekrom', 'Arena Trap', 'Moody', 'Shadow Tag', 'Booster Energy', 'King\'s Rock', 'Light Clay', 'Razor Fang',
|
||||
'Baton Pass', 'Last Respects', 'Shed Tail',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Category Swap",
|
||||
desc: `All Special moves become Physical, and all Physical moves become Special.`,
|
||||
@@ -1037,23 +882,6 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
'Razor Fang', 'Baton Pass', 'Draco Meteor', 'Last Respects', 'Overheat', 'Shed Tail',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Convergence",
|
||||
desc: `Allows all Pokémon that have identical types to share moves and abilities.`,
|
||||
mod: 'gen9',
|
||||
searchShow: false,
|
||||
ruleset: ['Standard OMs', 'Sleep Clause Mod', 'Convergence Legality', 'Terastal Clause', '!Obtainable Abilities'],
|
||||
banlist: [
|
||||
'Arceus', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chi-Yu', 'Chien-Pao', 'Darkrai', 'Deoxys-Normal', 'Deoxys-Attack', 'Deoxys-Speed', 'Dialga', 'Dialga-Origin',
|
||||
'Dondozo', 'Eternatus', 'Flutter Mane', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-oh', 'Inteleon', 'Iron Bundle', 'Iron Hands', 'Koraidon', 'Kyogre',
|
||||
'Kyurem-Black', 'Kyurem-White', 'Landorus-Incarnate', 'Lilligant-Hisui', 'Lugia', 'Lunala', 'Magearna', 'Manaphy', 'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings',
|
||||
'Necrozma-Dusk-Mane', 'Ogerpon-Hearthflame', 'Palafin', 'Palkia', 'Palkia-Origin', 'Primarina', 'Rayquaza', 'Regieleki', 'Regigigas', 'Reshiram', 'Shaymin-Sky',
|
||||
'Solgaleo', 'Slaking', 'Smeargle', 'Spectrier', 'Urshifu-Single-Strike', 'Urshifu-Rapid-Strike', 'Walking Wake', 'Zacian', 'Zacian-Crowned', 'Zamazenta',
|
||||
'Zamazenta-Crowned', 'Zekrom', 'Arena Trap', 'Comatose', 'Contrary', 'Drizzle', 'Imposter', 'Moody', 'Pure Power', 'Shadow Tag', 'Speed Boost', 'Unburden',
|
||||
'Heat Rock', 'King\'s Rock', 'Light Clay', 'Razor Fang', 'Baton Pass', 'Boomburst', 'Extreme Speed', 'Last Respects', 'Population Bomb', 'Quiver Dance',
|
||||
'Rage Fist', 'Shed Tail', 'Shell Smash', 'Spore', 'Transform',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Cross Evolution",
|
||||
desc: `Give a Pokémon a Pokémon name of the next evolution stage as a nickname to inherit stat changes, typing, abilities, and moves from the next stage Pokémon.`,
|
||||
@@ -1263,6 +1091,190 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Fortemons",
|
||||
desc: `Put an attacking move in the item slot to have all of a Pokémon's attacks inherit its properties.`,
|
||||
mod: 'gen9',
|
||||
searchShow: false,
|
||||
ruleset: ['Standard OMs', 'Sleep Moves Clause', 'Terastal Clause'],
|
||||
banlist: [
|
||||
'Annihilape', 'Arceus', 'Archaludon', 'Azumarill', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chi-Yu', 'Chien-Pao', 'Cloyster', 'Comfey', 'Deoxys-Normal', 'Deoxys-Attack',
|
||||
'Dialga-Base', 'Espathra', 'Eternatus', 'Flutter Mane', 'Giratina-Altered', 'Great Tusk', 'Groudon', 'Ho-Oh', 'Iron Bundle', 'Iron Treads', 'Koraidon', 'Kyogre',
|
||||
'Kyurem-Black', 'Kyurem-White', 'Landorus-Incarnate', 'Lugia', 'Lunala', 'Magearna', 'Meowscarada', 'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
|
||||
'Palafin', 'Palkia', 'Palkia-Origin', 'Quaquaval', 'Raging Bolt', 'Rayquaza', 'Reshiram', 'Samurott-Hisui', 'Shaymin-Sky', 'Skeledirge', 'Smeargle', 'Solgaleo',
|
||||
'Spectrier', 'Sneasler', 'Terapagos', 'Urshifu', 'Urshifu-Rapid-Strike', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Arena Trap',
|
||||
'Moody', 'Serene Grace', 'Shadow Tag', 'Damp Rock', 'Heat Rock', 'Light Clay', 'Baton Pass', 'Beat Up', 'Fake Out', 'Last Respects', 'move:Metronome', 'Shed Tail',
|
||||
],
|
||||
restricted: [
|
||||
'Doom Desire', 'Dynamic Punch', 'Electro Ball', 'Explosion', 'Gyro Ball', 'Final Gambit', 'Flail', 'Flip Turn', 'Fury Cutter', 'Future Sight', 'Grass Knot',
|
||||
'Grassy Glide', 'Hard Press', 'Heavy Slam', 'Heat Crash', 'Inferno', 'Low Kick', 'Misty Explosion', 'Nuzzle', 'Power Trip', 'Reversal', 'Self-Destruct',
|
||||
'Spit Up', 'Stored Power', 'Tera Blast', 'U-turn', 'Weather Ball', 'Zap Cannon',
|
||||
],
|
||||
onValidateTeam(team) {
|
||||
const itemTable = new Set<string>();
|
||||
for (const set of team) {
|
||||
const forte = this.toID(set.item);
|
||||
if (!forte) continue;
|
||||
const move = this.dex.moves.get(forte);
|
||||
if (move.exists && move.id !== 'metronome') {
|
||||
if (itemTable.has(forte)) {
|
||||
return [
|
||||
`You are limited to one of each move in the item slot per team.`,
|
||||
`(You have more than one ${move.name}.)`,
|
||||
];
|
||||
}
|
||||
itemTable.add(forte);
|
||||
}
|
||||
}
|
||||
},
|
||||
validateSet(set, teamHas) {
|
||||
const item = set.item;
|
||||
const species = this.dex.species.get(set.species);
|
||||
const move = this.dex.moves.get(item);
|
||||
if (!move.exists || move.id === 'metronome' || move.category === 'Status') {
|
||||
return this.validateSet(set, teamHas);
|
||||
}
|
||||
set.item = '';
|
||||
const problems = this.validateSet(set, teamHas) || [];
|
||||
set.item = item;
|
||||
if (this.checkCanLearn(move, species, this.allSources(species), set)) {
|
||||
problems.push(`${species.name} can't learn ${move.name}.`);
|
||||
}
|
||||
if (set.moves.map(this.toID).includes(move.id)) {
|
||||
problems.push(`Moves in the item slot can't be in the moveslots as well.`);
|
||||
}
|
||||
if (this.ruleTable.has(`-move:${move.id}`)) {
|
||||
problems.push(`The move ${move.name} is fully banned.`);
|
||||
}
|
||||
const accuracyLoweringMove =
|
||||
move.secondaries?.some(secondary => secondary.boosts?.accuracy && secondary.boosts?.accuracy < 0);
|
||||
const flinchMove = move.secondaries?.some(secondary => secondary.volatileStatus === 'flinch');
|
||||
const freezeMove = move.secondaries?.some(secondary => secondary.status === 'frz') || move.id === 'triattack';
|
||||
if (
|
||||
this.ruleTable.isRestricted(`move:${move.id}`) ||
|
||||
((accuracyLoweringMove || move.ohko || move.multihit || move.id === 'beatup' || move.flags['charge'] ||
|
||||
move.priority > 0 || move.damageCallback || flinchMove || freezeMove) &&
|
||||
!this.ruleTable.has(`+move:${move.id}`))
|
||||
) {
|
||||
problems.push(`The move ${move.name} can't be used as an item.`);
|
||||
}
|
||||
return problems.length ? problems : null;
|
||||
},
|
||||
onBegin() {
|
||||
for (const pokemon of this.getAllPokemon()) {
|
||||
const move = this.dex.getActiveMove(pokemon.set.item);
|
||||
if (move.exists && move.category !== 'Status') {
|
||||
pokemon.m.forte = move;
|
||||
pokemon.item = 'mail' as ID;
|
||||
}
|
||||
}
|
||||
},
|
||||
onModifyMovePriority: 1,
|
||||
onModifyMove(move, pokemon, target) {
|
||||
const forte: ActiveMove = pokemon.m.forte;
|
||||
if (move.category !== 'Status' && forte) {
|
||||
move.flags = { ...move.flags, ...forte.flags };
|
||||
if (forte.self) {
|
||||
if (forte.self.onHit && move.self?.onHit) {
|
||||
for (const i in forte.self) {
|
||||
if (i.startsWith('onHit')) continue;
|
||||
(move.self as any)[i] = (forte.self as any)[i];
|
||||
}
|
||||
} else {
|
||||
move.self = { ...move.self, ...forte.self };
|
||||
}
|
||||
}
|
||||
if (forte.selfBoost?.boosts) {
|
||||
if (!move.selfBoost?.boosts) move.selfBoost = { boosts: {} };
|
||||
let boostid: BoostID;
|
||||
for (boostid in forte.selfBoost.boosts) {
|
||||
if (!move.selfBoost.boosts![boostid]) move.selfBoost.boosts![boostid] = 0;
|
||||
move.selfBoost.boosts![boostid]! += forte.selfBoost.boosts[boostid]!;
|
||||
}
|
||||
}
|
||||
if (forte.secondaries) {
|
||||
move.secondaries = [...(move.secondaries || []), ...forte.secondaries];
|
||||
}
|
||||
move.critRatio = (move.critRatio || 1) + (forte.critRatio || 1) - 1;
|
||||
const VALID_PROPERTIES = [
|
||||
'alwaysHit', 'basePowerCallback', 'breaksProtect', 'drain', 'forceSTAB', 'forceSwitch', 'hasCrashDamage', 'hasSheerForce',
|
||||
'ignoreAbility', 'ignoreAccuracy', 'ignoreDefensive', 'ignoreEvasion', 'ignoreImmunity', 'mindBlownRecoil', 'noDamageVariance',
|
||||
'ohko', 'overrideDefensivePokemon', 'overrideDefensiveStat', 'overrideOffensivePokemon', 'overrideOffensiveStat', 'pseudoWeather',
|
||||
'recoil', 'selfdestruct', 'selfSwitch', 'sleepUsable', 'smartTarget', 'stealsBoosts', 'thawsTarget', 'volatileStatus', 'willCrit',
|
||||
] as const;
|
||||
for (const property of VALID_PROPERTIES) {
|
||||
if (forte[property]) {
|
||||
move[property] = forte[property] as any;
|
||||
}
|
||||
}
|
||||
// Added here because onEffectiveness doesn't have an easy way to reference the source
|
||||
if (forte.onEffectiveness) {
|
||||
move.onEffectiveness = function (typeMod, t, type, m) {
|
||||
return forte.onEffectiveness!.call(this, typeMod, t, type, m);
|
||||
};
|
||||
}
|
||||
forte.onModifyMove?.call(this, move, pokemon, target);
|
||||
}
|
||||
},
|
||||
onModifyPriority(priority, source, target, move) {
|
||||
const forte = source?.m.forte;
|
||||
if (move.category !== 'Status' && forte) {
|
||||
if (source.hasAbility('Triage') && forte.flags['heal']) {
|
||||
return priority + (move.flags['heal'] ? 0 : 3);
|
||||
}
|
||||
return priority + forte.priority;
|
||||
}
|
||||
},
|
||||
onModifyTypePriority: 1,
|
||||
onModifyType(move, pokemon, target) {
|
||||
const forte = pokemon.m.forte;
|
||||
if (move.category !== 'Status' && forte) {
|
||||
this.singleEvent('ModifyType', forte, null, pokemon, target, move, move);
|
||||
}
|
||||
},
|
||||
onHitPriority: 1,
|
||||
onHit(target, source, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move?.category !== 'Status' && forte) {
|
||||
this.singleEvent('Hit', forte, {}, target, source, move);
|
||||
if (forte.self) this.singleEvent('Hit', forte.self, {}, source, source, move);
|
||||
this.singleEvent('AfterHit', forte, {}, target, source, move);
|
||||
}
|
||||
},
|
||||
onAfterSubDamage(damage, target, source, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move?.category !== 'Status' && forte) {
|
||||
this.singleEvent('AfterSubDamage', forte, null, target, source, move, damage);
|
||||
}
|
||||
},
|
||||
onModifySecondaries(secondaries, target, source, move) {
|
||||
if (secondaries.some(s => !!s.self)) move.selfDropped = false;
|
||||
},
|
||||
onAfterMoveSecondaryPriority: 1,
|
||||
onAfterMoveSecondarySelf(source, target, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move?.category !== 'Status' && forte) {
|
||||
this.singleEvent('AfterMoveSecondarySelf', forte, null, source, target, move);
|
||||
}
|
||||
},
|
||||
onBasePowerPriority: 1,
|
||||
onBasePower(basePower, source, target, move) {
|
||||
const forte = source.m.forte;
|
||||
if (move.category !== 'Status' && forte?.onBasePower) {
|
||||
forte.onBasePower.call(this, basePower, source, target, move);
|
||||
}
|
||||
},
|
||||
pokemon: {
|
||||
getItem() {
|
||||
const move = this.battle.dex.moves.get(this.m.forte);
|
||||
if (!move.exists) return Object.getPrototypeOf(this).getItem.call(this);
|
||||
return {
|
||||
...this.battle.dex.items.get('mail'),
|
||||
name: move.name, id: move.id, ignoreKlutz: true, onTakeItem: false,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 9] Frantic Fusions",
|
||||
desc: `Pokémon nicknamed after another Pokémon get their stats buffed by 1/4 of that Pokémon's stats, barring HP, and access to one of their abilities.`,
|
||||
@@ -2705,7 +2717,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
name: "[Gen 9] National Dex Doubles Ubers",
|
||||
mod: 'gen9',
|
||||
gameType: 'doubles',
|
||||
searchShow: false,
|
||||
// searchShow: false,
|
||||
ruleset: ['Standard Doubles', 'NatDex Mod', '!Gravity Sleep Clause'],
|
||||
banlist: ['Shedinja', 'Assist'],
|
||||
},
|
||||
@@ -2816,7 +2828,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
{
|
||||
name: "[Gen 9] National Dex STABmons",
|
||||
mod: 'gen9',
|
||||
// searchShow: false,
|
||||
searchShow: false,
|
||||
ruleset: ['Standard NatDex', 'STABmons Move Legality', '!Sleep Clause Mod', 'Sleep Moves Clause', 'Terastal Clause'],
|
||||
banlist: [
|
||||
'Araquanid', 'Arceus', 'Azumarill', 'Baxcalibur', 'Blastoise-Mega', 'Blaziken-Mega', 'Basculegion', 'Basculegion-F', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chi-Yu', 'Chien-Pao',
|
||||
@@ -3635,19 +3647,26 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
column: 4,
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] UU",
|
||||
mod: 'gen8',
|
||||
name: "[Gen 1] Ubers",
|
||||
mod: 'gen1',
|
||||
// searchShow: false,
|
||||
ruleset: ['[Gen 8] OU'],
|
||||
banlist: ['OU', 'UUBL', 'Light Clay'],
|
||||
ruleset: ['Standard'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] CAP",
|
||||
desc: "The Create-A-Pokémon project is a community dedicated to exploring and understanding the competitive Pokémon metagame by designing, creating, and playtesting new Pokémon concepts.",
|
||||
mod: 'gen8',
|
||||
name: "[Gen 3] Orre Colosseum",
|
||||
mod: 'gen3colosseum',
|
||||
// searchShow: false,
|
||||
ruleset: ['[Gen 8] OU', '+CAP'],
|
||||
banlist: ['Crucibellite'],
|
||||
gameType: 'doubles',
|
||||
ruleset: [
|
||||
'Obtainable', 'Team Preview', 'Species Clause', 'Stadium Sleep Clause', 'Freeze Clause Mod', 'Max Team Size = 6', 'VGC Timer',
|
||||
'Nickname Clause', 'Endless Battle Clause', 'Cancel Mod', 'Picked Team Size = 4', 'Exact HP Mod', 'Item Clause = 1', 'Open Team Sheets',
|
||||
],
|
||||
banlist: ['Soul Dew', 'Deoxys-Defense', 'Deoxys-Attack', 'Deoxys-Speed', 'Restricted Legendary', 'Mythical'],
|
||||
unbanlist: ['Latios', 'Latias', 'Wobbuffet', 'Wynaut'],
|
||||
bestOfDefault: true,
|
||||
onBegin() {
|
||||
this.add('rule', 'Self-KO Clause: If your last Pok\u00e9mon faints to a self-KO move or effect, you will lose the battle');
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 6] VGC 2014",
|
||||
@@ -3783,6 +3802,13 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
ruleset: ['Standard', 'Dynamax Clause'],
|
||||
banlist: ['AG', 'Shadow Tag', 'Baton Pass'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] UU",
|
||||
mod: 'gen8',
|
||||
searchShow: false,
|
||||
ruleset: ['[Gen 8] OU'],
|
||||
banlist: ['OU', 'UUBL', 'Light Clay'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] RU",
|
||||
mod: 'gen8',
|
||||
@@ -3859,6 +3885,14 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
ruleset: ['[Gen 8] PU'],
|
||||
banlist: ['PU', 'ZUBL', 'Damp Rock', 'Grassy Seed'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] CAP",
|
||||
desc: "The Create-A-Pokémon project is a community dedicated to exploring and understanding the competitive Pokémon metagame by designing, creating, and playtesting new Pokémon concepts.",
|
||||
mod: 'gen8',
|
||||
searchShow: false,
|
||||
ruleset: ['[Gen 8] OU', '+CAP'],
|
||||
banlist: ['Crucibellite'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 8] Battle Stadium Singles",
|
||||
mod: 'gen8',
|
||||
@@ -4803,22 +4837,6 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
ruleset: ['Standard', 'One Boost Passer Clause'],
|
||||
banlist: ['Uber', 'Swagger'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 3] Orre Colosseum",
|
||||
mod: 'gen3colosseum',
|
||||
searchShow: false,
|
||||
gameType: 'doubles',
|
||||
ruleset: [
|
||||
'Obtainable', 'Team Preview', 'Species Clause', 'Stadium Sleep Clause', 'Freeze Clause Mod', 'Max Team Size = 6', 'VGC Timer',
|
||||
'Nickname Clause', 'Endless Battle Clause', 'Cancel Mod', 'Picked Team Size = 4', 'Exact HP Mod', 'Item Clause = 1', 'Open Team Sheets',
|
||||
],
|
||||
banlist: ['Soul Dew', 'Deoxys-Defense', 'Deoxys-Attack', 'Deoxys-Speed', 'Restricted Legendary', 'Mythical'],
|
||||
unbanlist: ['Latios', 'Latias', 'Wobbuffet', 'Wynaut'],
|
||||
bestOfDefault: true,
|
||||
onBegin() {
|
||||
this.add('rule', 'Self-KO Clause: If your last Pok\u00e9mon faints to a self-KO move or effect, you will lose the battle');
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "[Gen 3] Custom Game",
|
||||
mod: 'gen3',
|
||||
@@ -4913,12 +4931,6 @@ export const Formats: import('../sim/dex-formats').FormatList = [
|
||||
battle: { trunc: Math.trunc },
|
||||
ruleset: ['HP Percentage Mod', 'Cancel Mod', 'Max Team Size = 24', 'Max Move Count = 24', 'Max Level = 9999', 'Default Level = 100'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 1] Ubers",
|
||||
mod: 'gen1',
|
||||
searchShow: false,
|
||||
ruleset: ['Standard'],
|
||||
},
|
||||
{
|
||||
name: "[Gen 1] UU",
|
||||
mod: 'gen1',
|
||||
|
||||
Reference in New Issue
Block a user