Add December 2025 rotational ladders

This commit is contained in:
Kris Johnson
2025-12-01 23:06:26 -07:00
parent b2b885d68c
commit b27e545e94

View File

@@ -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&eacute;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&eacute;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&eacute;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&eacute;mon a Pok&eacute;mon name of the next evolution stage as a nickname to inherit stat changes, typing, abilities, and moves from the next stage Pok&eacute;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&eacute;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&eacute;mon nicknamed after another Pok&eacute;mon get their stats buffed by 1/4 of that Pok&eacute;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&eacute;mon project is a community dedicated to exploring and understanding the competitive Pok&eacute;mon metagame by designing, creating, and playtesting new Pok&eacute;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&eacute;mon project is a community dedicated to exploring and understanding the competitive Pok&eacute;mon metagame by designing, creating, and playtesting new Pok&eacute;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',