@pkmn/sim 0.4.20 → 0.4.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/build/config/formats.js +415 -688
  2. package/build/config/formats.js.map +1 -1
  3. package/build/data/aliases.js +7 -5
  4. package/build/data/aliases.js.map +1 -1
  5. package/build/data/conditions.js +4 -1
  6. package/build/data/conditions.js.map +1 -1
  7. package/build/data/formats-data.js +18 -18
  8. package/build/data/formats-data.js.map +1 -1
  9. package/build/data/learnsets.js +10 -8
  10. package/build/data/learnsets.js.map +1 -1
  11. package/build/data/mods/gen1/moves.js +1 -1
  12. package/build/data/mods/gen1/moves.js.map +1 -1
  13. package/build/data/mods/gen1/scripts.js +18 -22
  14. package/build/data/mods/gen1/scripts.js.map +1 -1
  15. package/build/data/mods/gen2/scripts.js +16 -23
  16. package/build/data/mods/gen2/scripts.js.map +1 -1
  17. package/build/data/mods/gen3/moves.js +2 -1
  18. package/build/data/mods/gen3/moves.js.map +1 -1
  19. package/build/data/mods/gen4/conditions.js +6 -0
  20. package/build/data/mods/gen4/conditions.js.map +1 -1
  21. package/build/data/mods/gen4/moves.js +2 -1
  22. package/build/data/mods/gen4/moves.js.map +1 -1
  23. package/build/data/mods/gen4/scripts.js +2 -1
  24. package/build/data/mods/gen4/scripts.js.map +1 -1
  25. package/build/data/mods/gen6/conditions.js +4 -1
  26. package/build/data/mods/gen6/conditions.js.map +1 -1
  27. package/build/data/mods/gen7/formats-data.js +2 -2
  28. package/build/data/mods/gen7/formats-data.js.map +1 -1
  29. package/build/data/mods/gen7/moves.js +8 -0
  30. package/build/data/mods/gen7/moves.js.map +1 -1
  31. package/build/data/moves.js +25 -13
  32. package/build/data/moves.js.map +1 -1
  33. package/build/data/rulesets.js +221 -1
  34. package/build/data/rulesets.js.map +1 -1
  35. package/build/data/tags.js +2 -2
  36. package/build/data/tags.js.map +1 -1
  37. package/build/lib/streams.d.ts +1 -199
  38. package/build/lib/streams.js +11 -772
  39. package/build/lib/streams.js.map +1 -1
  40. package/build/sim/battle-actions.d.ts +1 -1
  41. package/build/sim/battle-actions.js +18 -42
  42. package/build/sim/battle-actions.js.map +1 -1
  43. package/build/sim/battle.d.ts +1 -0
  44. package/build/sim/battle.js +5 -0
  45. package/build/sim/battle.js.map +1 -1
  46. package/build/sim/dex-moves.d.ts +31 -11
  47. package/build/sim/dex-moves.js +4 -3
  48. package/build/sim/dex-moves.js.map +1 -1
  49. package/build/sim/dex-species.js +11 -1
  50. package/build/sim/dex-species.js.map +1 -1
  51. package/build/sim/exported-global-types.d.ts +1 -0
  52. package/build/sim/global-types.d.ts +1 -0
  53. package/build/sim/side.js +2 -2
  54. package/build/sim/side.js.map +1 -1
  55. package/build/sim/team-validator.js +2 -2
  56. package/build/sim/team-validator.js.map +1 -1
  57. package/build/sim/tools/runner.d.ts +1 -6
  58. package/build/sim/tools/runner.js +6 -6
  59. package/build/sim/tools/runner.js.map +1 -1
  60. package/config/formats.ts +393 -643
  61. package/data/aliases.ts +7 -5
  62. package/data/conditions.ts +4 -1
  63. package/data/formats-data.ts +18 -18
  64. package/data/learnsets.ts +10 -8
  65. package/data/mods/gen1/moves.ts +1 -1
  66. package/data/mods/gen1/scripts.ts +23 -19
  67. package/data/mods/gen2/scripts.ts +20 -19
  68. package/data/mods/gen3/moves.ts +2 -1
  69. package/data/mods/gen4/conditions.ts +6 -0
  70. package/data/mods/gen4/moves.ts +2 -1
  71. package/data/mods/gen4/scripts.ts +1 -1
  72. package/data/mods/gen6/conditions.ts +4 -1
  73. package/data/mods/gen7/formats-data.ts +2 -2
  74. package/data/mods/gen7/moves.ts +8 -0
  75. package/data/moves.ts +22 -13
  76. package/data/rulesets.ts +199 -1
  77. package/data/tags.ts +2 -2
  78. package/lib/streams.ts +1 -874
  79. package/package.json +3 -2
  80. package/sim/battle-actions.ts +19 -40
  81. package/sim/battle.ts +6 -0
  82. package/sim/dex-moves.ts +35 -13
  83. package/sim/dex-species.ts +10 -1
  84. package/sim/exported-global-types.ts +1 -0
  85. package/sim/global-types.ts +1 -0
  86. package/sim/side.ts +2 -2
  87. package/sim/team-validator.ts +2 -2
  88. package/sim/tools/runner.ts +2 -0
package/config/formats.ts CHANGED
@@ -55,6 +55,13 @@ export const Formats: FormatList = [
55
55
  rated: false,
56
56
  ruleset: ['Obtainable', 'Species Clause', 'HP Percentage Mod', 'Cancel Mod', 'Sleep Clause Mod'],
57
57
  },
58
+ {
59
+ name: "[Gen 8] Random Battle (Blitz)",
60
+
61
+ mod: 'gen8',
62
+ team: 'random',
63
+ ruleset: ['[Gen 8] Random Battle', 'Blitz'],
64
+ },
58
65
  {
59
66
  name: "[Gen 8] Multi Random Battle",
60
67
 
@@ -133,8 +140,8 @@ export const Formats: FormatList = [
133
140
 
134
141
  mod: 'gen8',
135
142
  ruleset: ['[Gen 8] RU'],
136
- banlist: ['RU', 'NUBL', 'Drizzle', 'Drought', 'Snow Warning'],
137
- unbanlist: ['Snorlax'],
143
+ banlist: ['RU', 'NUBL', 'Drizzle', 'Drought'],
144
+ unbanlist: ['Indeedee'],
138
145
  },
139
146
  {
140
147
  name: "[Gen 8] PU",
@@ -145,7 +152,7 @@ export const Formats: FormatList = [
145
152
 
146
153
  mod: 'gen8',
147
154
  ruleset: ['[Gen 8] NU'],
148
- banlist: ['NU', 'PUBL', 'Snorlax'],
155
+ banlist: ['NU', 'PUBL', 'Indeedee'],
149
156
  },
150
157
  {
151
158
  name: "[Gen 8] LC",
@@ -237,8 +244,8 @@ export const Formats: FormatList = [
237
244
  ruleset: ['[Gen 8] LC'],
238
245
  banlist: [
239
246
  // LC OU
240
- 'Abra', 'Archen', 'Carvanha', 'Dewpider', 'Diglett-Base', 'Dwebble', 'Ferroseed', 'Foongus', 'Frillish', 'Grookey',
241
- 'Koffing', 'Larvesta', 'Magnemite', 'Mareanie', 'Mienfoo', 'Mudbray', 'Munchlax', 'Natu', 'Onix', 'Pawniard', 'Ponyta',
247
+ 'Abra', 'Archen', 'Carvanha', 'Diglett-Base', 'Dwebble', 'Ferroseed', 'Foongus', 'Frillish', 'Grookey', 'Koffing',
248
+ 'Larvesta', 'Magnemite', 'Mareanie', 'Mienfoo', 'Mudbray', 'Munchlax', 'Natu', 'Onix', 'Pawniard', 'Ponyta',
242
249
  'Ponyta-Galar', 'Porygon', 'Slowpoke-Base', 'Spritzee', 'Staryu', 'Timburr', 'Trapinch', 'Tyrunt', 'Vulpix',
243
250
  // LC UUBL
244
251
  'Farfetch\u2019d-Galar', 'Scorbunny', 'Shellder', 'Wingull',
@@ -258,6 +265,11 @@ export const Formats: FormatList = [
258
265
  },
259
266
  {
260
267
  name: "[Gen 8] CAP LC",
268
+ threads: [
269
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3691918/">CAP LC Metagame Discussion</a>`,
270
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8997714/">CAP LC Sample Teams</a>`,
271
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8997713/">CAP LC Viability Rankings</a>`,
272
+ ],
261
273
 
262
274
  mod: 'gen8',
263
275
  searchShow: false,
@@ -267,7 +279,7 @@ export const Formats: FormatList = [
267
279
  name: "[Gen 8] Battle Stadium Singles",
268
280
 
269
281
  mod: 'gen8',
270
- ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'Limit One Restricted', 'Dynamax Clause'],
282
+ ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'Limit One Restricted'],
271
283
  restricted: ['Restricted Legendary'],
272
284
  },
273
285
  {
@@ -354,16 +366,11 @@ export const Formats: FormatList = [
354
366
  banlist: ['Corsola-Galar', 'Cutiefly', 'Ponyta-Base', 'Scyther', 'Sneasel', 'Swirlix', 'Tangela', 'Vulpix', 'Vulpix-Alola'],
355
367
  },
356
368
  {
357
- name: "[Gen 8] VGC 2021 Series 10",
358
- threads: [
359
- `&bullet; <a href="https://www.smogon.com/forums/threads/3677186/">VGC 2021 Series 10 Metagame Discussion</a>`,
360
- `&bullet; <a href="https://www.smogon.com/forums/threads/3689153/">VGC 2021 Series 10 Sample Teams</a>`,
361
- `&bullet; <a href="https://www.smogon.com/forums/threads/3688166/">VGC 2021 Series 10 Viability Rankings</a>`,
362
- ],
369
+ name: "[Gen 8] VGC 2021 Series 11",
363
370
 
364
371
  mod: 'gen8',
365
372
  gameType: 'doubles',
366
- ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'VGC Timer', 'Limit One Restricted', 'Dynamax Clause'],
373
+ ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'VGC Timer', 'Limit One Restricted'],
367
374
  restricted: ['Restricted Legendary'],
368
375
  },
369
376
  {
@@ -382,34 +389,6 @@ export const Formats: FormatList = [
382
389
  searchShow: false,
383
390
  ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8', 'VGC Timer'],
384
391
  },
385
- {
386
- name: "[Gen 8] Spooky Cup 2021",
387
- threads: [
388
- `&bull; <a href="https://www.smogon.com/forums/threads/3691909/">Spooky Cup 2021</a>`,
389
- ],
390
-
391
- mod: 'gen8',
392
- gameType: 'doubles',
393
- ruleset: ['Flat Rules', '!! Adjust Level = 50', 'Min Source Gen = 8'],
394
- onValidateSet(set) {
395
- const spookyMonsList = [
396
- 'Vileplume', 'Tentacruel', 'Gengar', 'Marowak', 'Weezing', 'Mr. Mime', 'Pinsir', 'Ditto', 'Omastar', 'Kabutops', 'Aerodactyl',
397
- 'Noctowl', 'Crobat', 'Espeon', 'Umbreon', 'Wobbuffet', 'Shiftry', 'Shedinja', 'Exploud', 'Sableye', 'Mawile', 'Sharpedo',
398
- 'Lunatone', 'Crawdaunt', 'Baltoy', 'Claydol', 'Absol', 'Glalie', 'Drifblim', 'Skuntank', 'Spiritomb', 'Drapion', 'Toxicroak',
399
- 'Abomasnow', 'Weavile', 'Tangrowth', 'Electivire', 'Magmortar', 'Dusknoir', 'Froslass', 'Rotom', 'Liepard', 'Gigalith',
400
- 'Swoobat', 'Scolipede', 'Basculin', 'Krookodile', 'Sigilyph', 'Cofagrigus', 'Garbodor', 'Zoroark', 'Gothitelle', 'Jellicent',
401
- 'Galvantula', 'Beheeyem', 'Chandelure', 'Golurk', 'Bisharp', 'Mandibuzz', 'Hydreigon', 'Volcarona', 'Pangoro', 'Meowstic',
402
- 'Aegislash', 'Slurpuff', 'Malamar', 'Trevenant', 'Gourgeist', 'Noivern', 'Decidueye', 'Incineroar', 'Toxapex', 'Araquanid',
403
- 'Shiinotic', 'Salazzle', 'Bewear', 'Golisopod', 'Palossand', 'Silvally', 'Mimikyu', 'Dhelmise', 'Nihilego', 'Xurkitree',
404
- 'Guzzlord', 'Poipole', 'Naganadel', 'Blacephalon', 'Corviknight', 'Orbeetle', 'Thievul', 'Coalossal', 'Centiskorch', 'Grapploct',
405
- 'Polteageist', 'Hatterene', 'Grimmsnarl', 'Obstagoon', 'Cursola', 'Mr. Rime', 'Runerigus', 'Dracovish', 'Dragapult', 'Spectrier',
406
- ];
407
- const species = this.dex.species.get(set.species);
408
- if (!spookyMonsList.includes(species.baseSpecies) && species.id !== 'lycanrocmidnight') {
409
- return [`${species.name} is banned for not looking spooky enough.`];
410
- }
411
- },
412
- },
413
392
  {
414
393
  name: "[Gen 8] 2v2 Doubles",
415
394
  desc: `Double battle where you bring four Pok&eacute;mon to Team Preview and choose only two.`,
@@ -554,8 +533,8 @@ export const Formats: FormatList = [
554
533
  'Arceus', 'Blastoise-Mega', 'Blaziken', 'Calyrex-Ice', 'Calyrex-Shadow', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Dialga', 'Dracovish', 'Dragapult',
555
534
  'Eternatus', 'Genesect', 'Gengar-Mega', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega', 'Kartana', 'Kyogre',
556
535
  'Kyurem-Black', 'Kyurem-White', 'Lucario-Mega', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Mawile-Mega', 'Medicham-Mega', 'Metagross-Mega', 'Mewtwo',
557
- 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky', 'Solgaleo',
558
- 'Spectrier', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base',
536
+ 'Moltres-Galar', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky',
537
+ 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base',
559
538
  'Battle Bond', 'Moody', 'Power Construct', 'Shadow Tag',
560
539
  'Bright Powder', 'Damp Rock', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw', 'Smooth Rock', 'Terrain Extender', 'Baton Pass',
561
540
  ],
@@ -583,6 +562,7 @@ export const Formats: FormatList = [
583
562
  ],
584
563
 
585
564
  mod: "fusionevolutionuu",
565
+ searchShow: false,
586
566
  ruleset: ['Standard NatDex', 'OHKO Clause', 'Evasion Moves Clause', 'Species Clause', 'Dynamax Clause', 'Sleep Clause Mod', 'Z-Move Clause', 'Data Mod', 'Mega Data Mod'],
587
567
  banlist: [
588
568
  'All Pokemon', 'Lopunnite', 'Tapu Lop-Mega', 'Red Orb', 'Grousle-Primal',
@@ -629,216 +609,45 @@ export const Formats: FormatList = [
629
609
  column: 2,
630
610
  },
631
611
  {
632
- name: "[Gen 8] Multibility",
633
- desc: `Run a second ability at the cost of giving up a Pok&eacute;mon's item slot.`,
612
+ name: "[Gen 8] Sketchmons",
613
+ desc: `Pok&eacute;mon can learn one of any move they don't normally learn, barring the few that are banned.`,
634
614
  threads: [
635
- `&bullet; <a href="https://www.smogon.com/forums/threads/3688892/">Multibility</a>`,
615
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3680298/">Sketchmons</a>`,
636
616
  ],
637
617
 
638
618
  mod: 'gen8',
639
- ruleset: ['Standard', 'Dynamax Clause', '2 Ability Clause', 'Sleep Moves Clause', '!Sleep Clause Mod'],
619
+ ruleset: ['Standard', 'Dynamax Clause', 'Sketchmons Move Legality'],
640
620
  banlist: [
641
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragonite', 'Eternatus',
642
- 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White',
643
- 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
644
- 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas',
645
- 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base', 'Arena Trap',
646
- 'Chlorophyll', 'Magnet Pull', 'Moody', 'Power Construct', 'Sand Rush', 'Shadow Tag', 'Slush Rush', 'Swift Swim',
647
- 'Stench', 'Trace', 'King\'s Rock', 'Baton Pass',
621
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Genesect',
622
+ 'Giratina', 'Giratina-Origin', 'Groudon', 'Hawlucha', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base',
623
+ 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa',
624
+ 'Porygon-Z', 'Rayquaza', 'Regieleki', 'Reshiram', 'Rillaboom', 'Shedinja', 'Solgaleo', 'Spectrier', 'Swoobat', 'Tapu Bulu',
625
+ 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base',
626
+ 'Arena Trap', 'Moody', 'Power Construct', 'Sand Rush', 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
648
627
  ],
649
628
  restricted: [
650
- 'Comatose', 'Contrary', 'Fluffy', 'Fur Coat', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out',
651
- 'Intrepid Sword', 'Libero', 'Neutralizing Gas', 'Parental Bond', 'Protean', 'Pure Power', 'Simple', 'Speed Boost',
652
- 'Stakeout', 'Tinted Lens', 'Unaware', 'Water Bubble', 'Wonder Guard',
653
- 'Emergency Exit + Regenerator', 'Wimp Out + Regenerator',
629
+ 'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Clangorous Soul', 'Double Iron Bash', 'Electrify', 'Extreme Speed',
630
+ 'Fishious Rend', 'Geomancy', 'Glacial Lance', 'Lovely Kiss', 'No Retreat', 'Oblivion Wing', 'Octolock', 'Quiver Dance', 'Secret Sword',
631
+ 'Shell Smash', 'Shift Gear', 'Sleep Powder', 'Spore', 'Thousand Arrows', 'Transform', 'V-create', 'Wicked Blow',
654
632
  ],
655
- validateSet(set, teamHas) {
656
- const ability = this.dex.abilities.get(set.ability);
657
- const item = this.dex.abilities.get(set.item);
658
- if (!item.exists) return this.validateSet(set, teamHas);
659
- const problems = [];
660
- if (item.isNonstandard && !this.ruleTable.has(`+ability:${item.id}`)) {
661
- problems.push(`${item.name} is banned.`);
662
- }
663
- if (ability.id === item.id) {
664
- problems.push(`${set.species} has ${ability.name} as an ability and as an item.`);
665
- }
666
- if (this.ruleTable.isRestricted(`ability:${item.id}`) || this.ruleTable.isBanned(`ability:${item.id}`)) {
667
- problems.push(`${set.species}'s second ability (${item.name}) can only be used as an ability.`);
668
- }
669
- if ((ability.id === 'regenerator' && ['emergencyexit', 'wimpout'].includes(item.id)) ||
670
- (item.id === 'regenerator' && ['emergencyexit', 'wimpout'].includes(ability.id))) {
671
- problems.push(`${ability.name} and ${item.name} are banned together.`);
672
- }
673
- const itemStr = set.item;
674
- set.item = '';
675
- const problem = this.validateSet(set, teamHas);
676
- if (problem?.length) problems.push(...problem);
677
- set.item = itemStr;
678
- return problems;
679
- },
680
- onValidateTeam(team) {
681
- if (!this.ruleTable.has('2abilityclause')) return;
682
- const abilityTable = new Map<string, number>();
683
- const base: {[k: string]: string} = {
684
- airlock: 'cloudnine',
685
- battlearmor: 'shellarmor',
686
- clearbody: 'whitesmoke',
687
- dazzling: 'queenlymajesty',
688
- emergencyexit: 'wimpout',
689
- filter: 'solidrock',
690
- gooey: 'tanglinghair',
691
- insomnia: 'vitalspirit',
692
- ironbarbs: 'roughskin',
693
- libero: 'protean',
694
- minus: 'plus',
695
- moxie: 'chillingneigh',
696
- powerofalchemy: 'receiver',
697
- propellertail: 'stalwart',
698
- teravolt: 'moldbreaker',
699
- turboblaze: 'moldbreaker',
700
- };
701
- const abilities: [string, string][] = [];
702
- for (const set of team) {
703
- abilities.push([set.ability, set.item].map((abil) => {
704
- const id = this.toID(abil);
705
- return base[id] || id;
706
- }) as [string, string]);
707
- }
708
- for (const [abilityid, itemid] of abilities) {
709
- const ability = this.dex.abilities.get(abilityid);
710
- const item = this.dex.abilities.get(itemid);
711
- if (ability.exists) abilityTable.set(ability.id, (abilityTable.get(ability.id) || 0) + 1);
712
- if (item.exists) abilityTable.set(item.id, (abilityTable.get(item.id) || 0) + 1);
713
- }
714
- for (const [abilityid, size] of abilityTable) {
715
- if (size > 2) {
716
- return [
717
- `You are limited to two of each ability by 2 Ability Clause.`,
718
- `(You have more than two ${this.dex.abilities.get(abilityid).name} variants)`,
719
- ];
720
- }
721
- }
722
- },
723
- onSwitchOut(pokemon) {
724
- const item = this.dex.abilities.get(pokemon.item);
725
- if (item.exists) {
726
- this.singleEvent('End', item, pokemon.itemState, pokemon);
727
- }
728
- },
729
- onFaint(pokemon) {
730
- const item = this.dex.abilities.get(pokemon.item);
731
- if (item.exists) {
732
- this.singleEvent('End', item, pokemon.itemState, pokemon);
733
- }
734
- },
735
- field: {
736
- suppressingWeather() {
737
- for (const pokemon of this.battle.getAllActive()) {
738
- const item = this.battle.dex.abilities.get(pokemon.item);
739
- if (pokemon && !pokemon.ignoringAbility() &&
740
- (pokemon.getAbility().suppressWeather || (item.exists && item.suppressWeather))) {
741
- return true;
742
- }
743
- }
744
- return false;
745
- },
746
- },
747
- pokemon: {
748
- getItem() {
749
- const ability = this.battle.dex.abilities.get(this.item);
750
- if (!ability.exists) return Object.getPrototypeOf(this).getItem.call(this);
751
- return {...ability, ignoreKlutz: true, onTakeItem: false};
752
- },
753
- hasItem(item) {
754
- const ownItem = this.item;
755
- if (this.battle.dex.abilities.get(ownItem).exists) return false;
756
- if (this.ignoringItem()) return false;
757
- if (!Array.isArray(item)) return ownItem === this.battle.toID(item);
758
- return item.map(this.battle.toID).includes(ownItem);
759
- },
760
- hasAbility(ability) {
761
- if (this.ignoringAbility()) return false;
762
- if (Array.isArray(ability)) return ability.some(abil => this.hasAbility(abil));
763
- const abilityid = this.battle.toID(ability);
764
- const item = this.battle.dex.abilities.get(this.item);
765
- return this.ability === abilityid || (item.exists && item.id === abilityid);
766
- },
767
- ignoringAbility() {
768
- // Check if any active pokemon have the ability Neutralizing Gas
769
- let neutralizinggas = false;
770
- for (const pokemon of this.battle.getAllActive()) {
771
- // can't use hasAbility because it would lead to infinite recursion
772
- if ((pokemon.ability === ('neutralizinggas' as ID) || pokemon.item === ('neutralizinggas' as ID)) &&
773
- !pokemon.volatiles['gastroacid'] && !pokemon.abilityState.ending) {
774
- neutralizinggas = true;
775
- break;
776
- }
777
- }
778
- return !!(
779
- (this.battle.gen >= 5 && !this.isActive) ||
780
- ((this.volatiles['gastroacid'] || (neutralizinggas && this.ability !== ('neutralizinggas' as ID) &&
781
- this.item !== ('neutralizinggas' as ID))) && !this.getAbility().isPermanent));
782
- },
783
- ignoringItem() {
784
- let nGas = false;
785
- for (const pokemon of this.battle.getAllActive()) {
786
- // can't use hasAbility because it would lead to infinite recursion
787
- if (((pokemon.ability === ('neutralizinggas' as ID) && !pokemon.abilityState.ending) ||
788
- (pokemon.item === ('neutralizinggas' as ID) && !pokemon.itemState.ending)) &&
789
- !pokemon.volatiles['gastroacid'] && !pokemon.abilityState.ending) {
790
- nGas = true;
791
- break;
792
- }
793
- }
794
- const item = this.battle.dex.abilities.get(this.item);
795
- return !!((this.battle.gen >= 5 && !this.isActive) ||
796
- (this.hasAbility('klutz') && !this.getItem().ignoreKlutz) ||
797
- this.volatiles['embargo'] || this.battle.field.pseudoWeather['magicroom'] ||
798
- (item.exists && item.id !== 'neutralizinggas' && (nGas || this.volatiles['gastroacid'])));
799
- },
800
- takeItem(source) {
801
- if (!this.isActive) return false;
802
- if (!this.item) return false;
803
- if (this.battle.dex.abilities.get(this.item).exists) return false;
804
- if (!source) source = this;
805
- if (this.battle.gen === 4) {
806
- if (this.battle.toID(this.ability) === 'multitype') return false;
807
- if (source && this.battle.toID(source.ability) === 'multitype') return false;
808
- }
809
- const item = this.getItem();
810
- if (this.battle.runEvent('TakeItem', this, source, null, item)) {
811
- this.item = '';
812
- this.itemState = {id: '', target: this};
813
- this.pendingStaleness = undefined;
814
- return item;
815
- }
816
- return false;
817
- },
818
- },
819
633
  },
820
634
  {
821
- name: "[Gen 8] 350 Cup",
822
- desc: `Pok&eacute;mon with a BST of 350 or lower get their base stats doubled.`,
635
+ name: "[Gen 8] AAA Doubles",
636
+ desc: `Pok&eacute;mon have access to almost any ability, in a doubles setting.`,
823
637
  threads: [
824
- `&bullet; <a href="https://www.smogon.com/forums/threads/3656554/">350 Cup</a>`,
638
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8299984">AAA Doubles</a>`,
825
639
  ],
826
640
 
827
641
  mod: 'gen8',
828
- ruleset: ['Standard', 'Dynamax Clause'],
829
- banlist: ['Abra', 'Gastly', 'Pawniard', 'Rufflet', 'Woobat', 'Arena Trap', 'Shadow Tag', 'Eviolite', 'Light Ball', 'Baton Pass'],
830
- onModifySpecies(species, target, source, effect) {
831
- if (effect && ['imposter', 'transform'].includes(effect.id)) return;
832
- const newSpecies = this.dex.deepClone(species);
833
- if (newSpecies.bst <= 350) {
834
- newSpecies.bst = 0;
835
- for (const stat in newSpecies.baseStats) {
836
- newSpecies.baseStats[stat] *= 2;
837
- newSpecies.bst += newSpecies.baseStats[stat];
838
- }
839
- }
840
- return newSpecies;
841
- },
642
+ gameType: 'doubles',
643
+ ruleset: ['[Gen 8] Doubles OU', 'Sleep Clause Mod', '2 Ability Clause', '!Obtainable Abilities'],
644
+ banlist: [
645
+ 'Kyurem-Black', 'Regigigas', 'Shedinja', 'Urshifu-Rapid-Strike', 'Zygarde-Base', 'Anger Point', 'Arena Trap', 'Comatose', 'Contrary',
646
+ 'Dancer', 'Desolate Land', 'Fluffy', 'Fur Coat', 'Gorilla Tactics', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out',
647
+ 'Intrepid Sword', 'Libero', 'Moody', 'Neutralizing Gas', 'Parental Bond', 'Prankster', 'Primordial Sea', 'Protean', 'Pure Power',
648
+ 'Rattled', 'Serene Grace', 'Simple', 'Soul-Heart', 'Stakeout', 'Steam Engine', 'Speed Boost', 'Water Bubble', 'Water Compaction',
649
+ 'Wonder Guard', 'King\'s Rock', 'Weakness Policy', 'Beat Up', 'Stored Power',
650
+ ],
842
651
  },
843
652
 
844
653
  // Other Metagames
@@ -909,7 +718,7 @@ export const Formats: FormatList = [
909
718
  const itemTable = new Set<ID>();
910
719
  for (const set of team) {
911
720
  const item = this.dex.items.get(set.item);
912
- if (!item?.megaStone) continue;
721
+ if (!item.megaStone) continue;
913
722
  const species = this.dex.species.get(set.species);
914
723
  if (species.isNonstandard) return [`${species.baseSpecies} does not exist in gen 8.`];
915
724
  if (this.ruleTable.isRestrictedSpecies(species) || this.toID(set.ability) === 'powerconstruct') {
@@ -960,7 +769,7 @@ export const Formats: FormatList = [
960
769
  'Archeops', 'Buzzwole', 'Calyrex-Ice', 'Calyrex-Shadow', 'Dialga', 'Dracovish', 'Dragapult', 'Dragonite', 'Eternatus', 'Gengar', 'Giratina', 'Giratina-Origin',
961
770
  'Groudon', 'Ho-Oh', 'Kartana', 'Keldeo', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Melmetal', 'Mewtwo',
962
771
  'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Noivern', 'Palkia', 'Pheromosa', 'Rayquaza', 'Regigigas', 'Reshiram', 'Shedinja', 'Solgaleo', 'Spectrier',
963
- 'Urshifu-Base', 'Urshifu-Rapid-Strike', 'Victini', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Base', 'Zekrom', 'Zeraora', 'Zygarde-Base',
772
+ 'Urshifu-Base', 'Urshifu-Rapid-Strike', 'Victini', 'Weavile', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Base', 'Zekrom', 'Zeraora', 'Zygarde-Base',
964
773
  'Arena Trap', 'Comatose', 'Contrary', 'Fluffy', 'Fur Coat', 'Gorilla Tactics', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out', 'Intrepid Sword',
965
774
  'Libero', 'Magnet Pull', 'Moody', 'Neutralizing Gas', 'Parental Bond', 'Poison Heal', 'Power Construct', 'Protean', 'Pure Power', 'Shadow Tag', 'Simple', 'Stakeout',
966
775
  'Speed Boost', 'Water Bubble', 'Wonder Guard', 'King\'s Rock', 'Baton Pass',
@@ -985,11 +794,12 @@ export const Formats: FormatList = [
985
794
  mod: 'gen8',
986
795
  ruleset: ['Standard', 'STABmons Move Legality', 'Dynamax Clause', 'Sleep Moves Clause'],
987
796
  banlist: [
988
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin',
989
- 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus', 'Landorus-Therian', 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo',
990
- 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Porygon-Z', 'Rayquaza', 'Reshiram', 'Silvally', 'Solgaleo',
991
- 'Spectrier', 'Tapu Koko', 'Thundurus-Base', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned',
992
- 'Zapdos-Galar', 'Zekrom', 'Zygarde-Base', 'Arena Trap', 'Magnet Pull', 'Moody', 'Power Construct', 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
797
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Genesect', 'Garchomp', 'Giratina',
798
+ 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus', 'Landorus-Therian', 'Lugia', 'Lunala',
799
+ 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Porygon-Z', 'Rayquaza', 'Reshiram',
800
+ 'Silvally', 'Solgaleo', 'Spectrier', 'Tapu Bulu', 'Tapu Koko', 'Thundurus-Base', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned',
801
+ 'Zamazenta', 'Zamazenta-Crowned', 'Zapdos-Galar', 'Zekrom', 'Zygarde-Base', 'Arena Trap', 'Magnet Pull', 'Moody', 'Power Construct', 'Shadow Tag',
802
+ 'King\'s Rock', 'Baton Pass',
993
803
  ],
994
804
  restricted: [
995
805
  'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Clangorous Soul', 'Double Iron Bash', 'Electrify', 'Extreme Speed', 'Fishious Rend',
@@ -1031,23 +841,62 @@ export const Formats: FormatList = [
1031
841
  ],
1032
842
  },
1033
843
  {
1034
- name: "[Gen 8] Bonus Type",
1035
- desc: `Pok&eacute;mon can be nicknamed the name of a type to have that type added onto their current ones.`,
844
+ section: "BD/SP",
845
+ column: 2,
846
+ },
847
+ {
848
+ name: "[Gen 8 BDSP] Random Battle",
849
+ desc: `Randomized teams of level-balanced Pok&eacute;mon with sets that are generated to be competitively viable.`,
850
+
851
+ mod: 'gen8bdsp',
852
+ team: 'random',
853
+ ruleset: ['[Gen 8] Random Battle', '!PotD'],
854
+ },
855
+ {
856
+ name: "[Gen 8 BDSP] OU",
1036
857
  threads: [
1037
- `&bullet; <a href="https://www.smogon.com/forums/threads/3683173/">Bonus Type</a>`,
858
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3693629/">BDSP OU Metagame Discussion</a>`,
859
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3693620/">BDSP OU Viability List</a>`,
1038
860
  ],
1039
861
 
1040
- mod: 'gen8',
862
+ mod: 'gen8bdsp',
863
+ ruleset: ['Standard'],
864
+ banlist: ['Uber', 'Arena Trap', 'Drizzle', 'Moody', 'Shadow Tag', 'King\'s Rock', 'Razor Fang', 'Baton Pass'],
865
+ },
866
+ {
867
+ name: "[Gen 8 BDSP] Doubles OU",
868
+ threads: [
869
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3693891/">BDSP Doubles OU</a>`,
870
+ ],
871
+
872
+ mod: 'gen8bdsp',
873
+ gameType: 'doubles',
1041
874
  searchShow: false,
1042
- ruleset: ['Standard', 'Dynamax Clause', 'Bonus Type Rule', '!Nickname Clause'],
1043
- banlist: [
1044
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Dragonite', 'Eternatus', 'Genesect',
1045
- 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia',
1046
- 'Lunala', 'Magearna', 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa',
1047
- 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned',
1048
- 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base', 'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'Baton Pass',
1049
- 'Final Gambit', 'Flower Shield',
875
+ ruleset: ['Standard Doubles'],
876
+ banlist: ['DUber', 'Swagger'],
877
+ },
878
+ {
879
+ name: "[Gen 8 BDSP] Battle Festival Doubles",
880
+
881
+ mod: 'gen8bdsp',
882
+ gameType: 'doubles',
883
+ // VGC Timer is temporary
884
+ ruleset: ['Flat Rules', 'Min Source Gen = 8', 'VGC Timer'],
885
+ },
886
+ {
887
+ name: "[Gen 8 BDSP] Pure Hackmons",
888
+ desc: `Anything that can be hacked in-game and is usable in local battles is allowed.`,
889
+ threads: [
890
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3693868/">Pure Hackmons</a>`,
1050
891
  ],
892
+
893
+ mod: 'gen8bdsp',
894
+ searchShow: false,
895
+ ruleset: ['-Nonexistent', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Endless Battle Clause'],
896
+ },
897
+ {
898
+ section: "Challengeable OMs",
899
+ column: 2,
1051
900
  },
1052
901
  {
1053
902
  name: "[Gen 8] Camomons",
@@ -1062,8 +911,8 @@ export const Formats: FormatList = [
1062
911
  banlist: [
1063
912
  'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragonite', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon',
1064
913
  'Ho-Oh', 'Hydreigon', 'Kartana', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Latias', 'Latios', 'Lugia', 'Lunala', 'Marshadow',
1065
- 'Mewtwo', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Slowking-Galar', 'Solgaleo', 'Xerneas',
1066
- 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base',
914
+ 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Slowking-Galar', 'Solgaleo',
915
+ 'Tornadus-Therian', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base',
1067
916
  'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'Baton Pass',
1068
917
  ],
1069
918
  onModifySpeciesPriority: 2,
@@ -1080,138 +929,6 @@ export const Formats: FormatList = [
1080
929
  this.add('-start', pokemon, 'typechange', (pokemon.illusion || pokemon).getTypes(true).join('/'), '[silent]');
1081
930
  },
1082
931
  },
1083
- {
1084
- name: "[Gen 8] Cross Evolution",
1085
- 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 up to 2 moves from the next stage Pok&eacute;mon.`,
1086
- threads: [
1087
- `&bullet; <a href="https://www.smogon.com/forums/threads/3657562/">Cross Evolution</a>`,
1088
- ],
1089
-
1090
- mod: 'gen8',
1091
- searchShow: false,
1092
- ruleset: ['Standard', 'Overflow Stat Mod', 'Dynamax Clause'],
1093
- banlist: ['Corsola-Galar', 'Sneasel', 'Type: Null', 'Arena Trap', 'Ice Scales', 'Moody', 'King\'s Rock', 'Baton Pass'],
1094
- restricted: ['Chansey', 'Lunala', 'Shedinja', 'Solgaleo', 'Gorilla Tactics', 'Huge Power', 'Pure Power', 'Shadow Tag'],
1095
- onValidateTeam(team) {
1096
- const names = new Set<ID>();
1097
- for (const set of team) {
1098
- const name = set.name;
1099
- if (names.has(this.dex.toID(name))) {
1100
- return [
1101
- `Your Pok\u00e9mon must have different nicknames.`,
1102
- `(You have more than one Pok\u00e9mon named '${name}')`,
1103
- ];
1104
- }
1105
- names.add(this.dex.toID(name));
1106
- }
1107
- if (!names.size) {
1108
- return [
1109
- `${this.format.name} works using nicknames; your team has 0 nicknamed Pok\u00e9mon.`,
1110
- `(If this was intentional, add a nickname to one Pok\u00e9mon that isn't the name of a Pok\u00e9mon species.)`,
1111
- ];
1112
- }
1113
- },
1114
- checkCanLearn(move, species, lsetData, set) {
1115
- // @ts-ignore
1116
- if (!set.sp?.exists || !set.crossSpecies?.exists) {
1117
- return this.checkCanLearn(move, species, lsetData, set);
1118
- }
1119
- // @ts-ignore
1120
- const problem = this.checkCanLearn(move, set.sp);
1121
- if (!problem) return null;
1122
- // @ts-ignore
1123
- if (!set.crossMovesLeft) return problem;
1124
- // @ts-ignore
1125
- if (this.checkCanLearn(move, set.crossSpecies)) return problem;
1126
- // @ts-ignore
1127
- set.crossMovesLeft--;
1128
- return null;
1129
- },
1130
- validateSet(set, teamHas) {
1131
- const crossSpecies = this.dex.species.get(set.name);
1132
- const onChangeSet = this.dex.formats.get('Pokemon').onChangeSet;
1133
- let problems = onChangeSet?.call(this, set, this.format) || null;
1134
- if (Array.isArray(problems) && problems.length) return problems;
1135
- const crossNonstandard = !this.ruleTable.has('standardnatdex') && crossSpecies.isNonstandard === 'Past';
1136
- const crossIsCap = !this.ruleTable.has('+pokemontag:cap') && crossSpecies.isNonstandard === 'CAP';
1137
- if (!crossSpecies.exists || crossNonstandard || crossIsCap) return this.validateSet(set, teamHas);
1138
- const species = this.dex.species.get(set.species);
1139
- const check = this.checkSpecies(set, species, species, {});
1140
- if (check) return [check];
1141
- const nonstandard = !this.ruleTable.has('standardnatdex') && species.isNonstandard === 'Past';
1142
- const isCap = !this.ruleTable.has('+pokemontag:cap') && species.isNonstandard === 'CAP';
1143
- if (!species.exists || nonstandard || isCap || species === crossSpecies) return this.validateSet(set, teamHas);
1144
- if (!species.nfe) return [`${species.name} cannot cross evolve because it doesn't evolve.`];
1145
- const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
1146
- if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo) {
1147
- return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it isn't an evolution.`];
1148
- }
1149
- if (this.ruleTable.isRestrictedSpecies(crossSpecies)) {
1150
- return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it is banned.`];
1151
- }
1152
- const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
1153
- if (!crossPrevoSpecies.prevo !== !species.prevo) {
1154
- return [
1155
- `${species.name} cannot cross evolve into ${crossSpecies.name} because they are not consecutive evolution stages.`,
1156
- ];
1157
- }
1158
- const ability = this.dex.abilities.get(set.ability);
1159
- if (!this.ruleTable.isRestricted(`ability:${ability.id}`) || Object.values(species.abilities).includes(ability.name)) {
1160
- set.species = crossSpecies.name;
1161
- }
1162
-
1163
- // @ts-ignore
1164
- set.sp = species;
1165
- // @ts-ignore
1166
- set.crossSpecies = crossSpecies;
1167
- // @ts-ignore
1168
- set.crossMovesLeft = 2;
1169
- problems = this.validateSet(set, teamHas);
1170
- set.name = crossSpecies.name;
1171
- set.species = species.name;
1172
- return problems;
1173
- },
1174
- onModifySpecies(species, target, source, effect) {
1175
- if (!target) return; // chat
1176
- if (effect && ['imposter', 'transform'].includes(effect.id)) return;
1177
- if (target.set.name === target.set.species) return;
1178
- const crossSpecies = this.dex.species.get(target.set.name);
1179
- if (!crossSpecies.exists) return;
1180
- if (species.battleOnly || !species.nfe) return;
1181
- const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
1182
- if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo) return;
1183
- const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
1184
- if (!crossPrevoSpecies.prevo !== !species.prevo) return;
1185
-
1186
- const mixedSpecies = this.dex.deepClone(species);
1187
- mixedSpecies.baseSpecies = mixedSpecies.name = `${species.name}-${crossSpecies.name}`;
1188
- mixedSpecies.weightkg =
1189
- Math.max(0.1, +(species.weightkg + crossSpecies.weightkg - crossPrevoSpecies.weightkg)).toFixed(1);
1190
- mixedSpecies.nfe = false;
1191
- mixedSpecies.evos = [];
1192
- mixedSpecies.eggGroups = crossSpecies.eggGroups;
1193
- mixedSpecies.abilities = crossSpecies.abilities;
1194
- mixedSpecies.bst = 0;
1195
- let i: StatID;
1196
- for (i in species.baseStats) {
1197
- const statChange = crossSpecies.baseStats[i] - crossPrevoSpecies.baseStats[i];
1198
- mixedSpecies.baseStats[i] = this.clampIntRange(species.baseStats[i] + statChange, 1, 255);
1199
- mixedSpecies.bst += mixedSpecies.baseStats[i];
1200
- }
1201
- if (crossSpecies.types[0] !== crossPrevoSpecies.types[0]) mixedSpecies.types[0] = crossSpecies.types[0];
1202
- if (crossSpecies.types[1] !== crossPrevoSpecies.types[1]) {
1203
- mixedSpecies.types[1] = crossSpecies.types[1] || crossSpecies.types[0];
1204
- }
1205
- if (mixedSpecies.types[0] === mixedSpecies.types[1]) mixedSpecies.types = [mixedSpecies.types[0]];
1206
-
1207
- return mixedSpecies;
1208
- },
1209
- onBegin() {
1210
- for (const pokemon of this.getAllPokemon()) {
1211
- pokemon.baseSpecies = pokemon.species;
1212
- }
1213
- },
1214
- },
1215
932
  {
1216
933
  name: "[Gen 8] Godly Gift",
1217
934
  desc: `Each Pok&eacute;mon receives one base stat from a God (AG/Uber Pok&eacute;mon) depending on its position in the team. If there is no Uber Pok&eacute;mon, it uses the Pok&eacute;mon in the first slot.`,
@@ -1371,7 +1088,7 @@ export const Formats: FormatList = [
1371
1088
  return null;
1372
1089
  },
1373
1090
  onValidateTeam(team, f, teamHas) {
1374
- if (this.format.ruleTable?.has('2abilityclause')) {
1091
+ if (this.ruleTable.has('2abilityclause')) {
1375
1092
  const abilityTable = new Map<string, number>();
1376
1093
  const base: {[k: string]: string} = {
1377
1094
  airlock: 'cloudnine',
@@ -1401,73 +1118,244 @@ export const Formats: FormatList = [
1401
1118
  `(You have more than two ${this.dex.abilities.get(ability).name} variants)`,
1402
1119
  ];
1403
1120
  }
1404
- abilityTable.set(ability, (abilityTable.get(ability) || 0) + 1);
1121
+ abilityTable.set(ability, (abilityTable.get(ability) || 0) + 1);
1122
+ }
1123
+ }
1124
+
1125
+ // Donor Clause
1126
+ const evoFamilyLists = [];
1127
+ for (const set of team) {
1128
+ const abilitySources = teamHas.abilitySources?.[this.dex.toID(set.species)];
1129
+ if (!abilitySources) continue;
1130
+ let format = this.format;
1131
+ if (!format.getEvoFamily) format = this.dex.formats.get('gen8inheritance');
1132
+ evoFamilyLists.push(abilitySources.map(format.getEvoFamily!));
1133
+ }
1134
+
1135
+ // Checking actual full incompatibility would require expensive algebra.
1136
+ // Instead, we only check the trivial case of multiple Pokémon only legal for exactly one family. FIXME?
1137
+ const requiredFamilies = Object.create(null);
1138
+ for (const evoFamilies of evoFamilyLists) {
1139
+ if (evoFamilies.length !== 1) continue;
1140
+ const [familyId] = evoFamilies;
1141
+ if (!(familyId in requiredFamilies)) requiredFamilies[familyId] = 1;
1142
+ requiredFamilies[familyId]++;
1143
+ if (requiredFamilies[familyId] > 2) {
1144
+ return [
1145
+ `You are limited to up to two inheritances from each evolution family by the Donor Clause.`,
1146
+ `(You inherit more than twice from ${this.dex.species.get(familyId).name}).`,
1147
+ ];
1148
+ }
1149
+ }
1150
+ },
1151
+ onBegin() {
1152
+ for (const pokemon of this.getAllPokemon()) {
1153
+ if (pokemon.baseAbility.includes('0')) {
1154
+ const donor = pokemon.baseAbility.split('0')[1];
1155
+ pokemon.m.donor = this.toID(donor);
1156
+ pokemon.baseAbility = this.toID(pokemon.baseAbility.split('0')[0]);
1157
+ pokemon.ability = pokemon.baseAbility;
1158
+ }
1159
+ }
1160
+ },
1161
+ onSwitchIn(pokemon) {
1162
+ if (!pokemon.m.donor) return;
1163
+ const donorTemplate = this.dex.species.get(pokemon.m.donor);
1164
+ if (!donorTemplate.exists) return;
1165
+ // Place volatiles on the Pokémon to show the donor details.
1166
+ this.add('-start', pokemon, donorTemplate.name, '[silent]');
1167
+ },
1168
+ },
1169
+ {
1170
+ name: "[Gen 8] Multibility",
1171
+ desc: `Run a second ability at the cost of giving up a Pok&eacute;mon's item slot.`,
1172
+ threads: [
1173
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3688892/">Multibility</a>`,
1174
+ ],
1175
+
1176
+ mod: 'gen8',
1177
+ searchShow: false,
1178
+ ruleset: ['Standard', 'Dynamax Clause', '2 Ability Clause', 'Sleep Moves Clause', '!Sleep Clause Mod'],
1179
+ banlist: [
1180
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragonite', 'Eternatus',
1181
+ 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White',
1182
+ 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
1183
+ 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas',
1184
+ 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base', 'Arena Trap',
1185
+ 'Chlorophyll', 'Magnet Pull', 'Moody', 'Power Construct', 'Sand Rush', 'Shadow Tag', 'Slush Rush', 'Swift Swim',
1186
+ 'Stench', 'Trace', 'King\'s Rock', 'Baton Pass',
1187
+ ],
1188
+ restricted: [
1189
+ 'Comatose', 'Contrary', 'Fluffy', 'Fur Coat', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out',
1190
+ 'Intrepid Sword', 'Libero', 'Neutralizing Gas', 'Parental Bond', 'Protean', 'Pure Power', 'Simple', 'Speed Boost',
1191
+ 'Stakeout', 'Tinted Lens', 'Unaware', 'Water Bubble', 'Wonder Guard',
1192
+ 'Emergency Exit + Regenerator', 'Wimp Out + Regenerator',
1193
+ ],
1194
+ validateSet(set, teamHas) {
1195
+ const ability = this.dex.abilities.get(set.ability);
1196
+ const item = this.dex.abilities.get(set.item);
1197
+ if (!item.exists) return this.validateSet(set, teamHas);
1198
+ const problems = [];
1199
+ if (item.isNonstandard && !this.ruleTable.has(`+ability:${item.id}`)) {
1200
+ problems.push(`${item.name} is banned.`);
1201
+ }
1202
+ if (ability.id === item.id) {
1203
+ problems.push(`${set.species} has ${ability.name} as an ability and as an item.`);
1204
+ }
1205
+ if (this.ruleTable.isRestricted(`ability:${item.id}`) || this.ruleTable.isBanned(`ability:${item.id}`)) {
1206
+ problems.push(`${set.species}'s second ability (${item.name}) can only be used as an ability.`);
1207
+ }
1208
+ if ((ability.id === 'regenerator' && ['emergencyexit', 'wimpout'].includes(item.id)) ||
1209
+ (item.id === 'regenerator' && ['emergencyexit', 'wimpout'].includes(ability.id))) {
1210
+ problems.push(`${ability.name} and ${item.name} are banned together.`);
1211
+ }
1212
+ const itemStr = set.item;
1213
+ set.item = '';
1214
+ const problem = this.validateSet(set, teamHas);
1215
+ if (problem?.length) problems.push(...problem);
1216
+ set.item = itemStr;
1217
+ return problems;
1218
+ },
1219
+ onValidateTeam(team) {
1220
+ if (!this.ruleTable.has('2abilityclause')) return;
1221
+ const abilityTable = new Map<string, number>();
1222
+ const base: {[k: string]: string} = {
1223
+ airlock: 'cloudnine',
1224
+ battlearmor: 'shellarmor',
1225
+ clearbody: 'whitesmoke',
1226
+ dazzling: 'queenlymajesty',
1227
+ emergencyexit: 'wimpout',
1228
+ filter: 'solidrock',
1229
+ gooey: 'tanglinghair',
1230
+ insomnia: 'vitalspirit',
1231
+ ironbarbs: 'roughskin',
1232
+ libero: 'protean',
1233
+ minus: 'plus',
1234
+ moxie: 'chillingneigh',
1235
+ powerofalchemy: 'receiver',
1236
+ propellertail: 'stalwart',
1237
+ teravolt: 'moldbreaker',
1238
+ turboblaze: 'moldbreaker',
1239
+ };
1240
+ const abilities: [string, string][] = [];
1241
+ for (const set of team) {
1242
+ abilities.push([set.ability, set.item].map((abil) => {
1243
+ const id = this.toID(abil);
1244
+ return base[id] || id;
1245
+ }) as [string, string]);
1246
+ }
1247
+ for (const [abilityid, itemid] of abilities) {
1248
+ const ability = this.dex.abilities.get(abilityid);
1249
+ const item = this.dex.abilities.get(itemid);
1250
+ if (ability.exists) abilityTable.set(ability.id, (abilityTable.get(ability.id) || 0) + 1);
1251
+ if (item.exists) abilityTable.set(item.id, (abilityTable.get(item.id) || 0) + 1);
1252
+ }
1253
+ for (const [abilityid, size] of abilityTable) {
1254
+ if (size > 2) {
1255
+ return [
1256
+ `You are limited to two of each ability by 2 Ability Clause.`,
1257
+ `(You have more than two ${this.dex.abilities.get(abilityid).name} variants)`,
1258
+ ];
1259
+ }
1260
+ }
1261
+ },
1262
+ onSwitchOut(pokemon) {
1263
+ const item = this.dex.abilities.get(pokemon.item);
1264
+ if (item.exists) {
1265
+ this.singleEvent('End', item, pokemon.itemState, pokemon);
1266
+ }
1267
+ },
1268
+ onFaint(pokemon) {
1269
+ const item = this.dex.abilities.get(pokemon.item);
1270
+ if (item.exists) {
1271
+ this.singleEvent('End', item, pokemon.itemState, pokemon);
1272
+ }
1273
+ },
1274
+ field: {
1275
+ suppressingWeather() {
1276
+ for (const pokemon of this.battle.getAllActive()) {
1277
+ const item = this.battle.dex.abilities.get(pokemon.item);
1278
+ if (pokemon && !pokemon.ignoringAbility() &&
1279
+ (pokemon.getAbility().suppressWeather || (item.exists && item.suppressWeather))) {
1280
+ return true;
1281
+ }
1282
+ }
1283
+ return false;
1284
+ },
1285
+ },
1286
+ pokemon: {
1287
+ getItem() {
1288
+ const ability = this.battle.dex.abilities.get(this.item);
1289
+ if (!ability.exists) return Object.getPrototypeOf(this).getItem.call(this);
1290
+ return {...ability, ignoreKlutz: true, onTakeItem: false};
1291
+ },
1292
+ hasItem(item) {
1293
+ const ownItem = this.item;
1294
+ if (this.battle.dex.abilities.get(ownItem).exists) return false;
1295
+ if (this.ignoringItem()) return false;
1296
+ if (!Array.isArray(item)) return ownItem === this.battle.toID(item);
1297
+ return item.map(this.battle.toID).includes(ownItem);
1298
+ },
1299
+ hasAbility(ability) {
1300
+ if (this.ignoringAbility()) return false;
1301
+ if (Array.isArray(ability)) return ability.some(abil => this.hasAbility(abil));
1302
+ const abilityid = this.battle.toID(ability);
1303
+ const item = this.battle.dex.abilities.get(this.item);
1304
+ return this.ability === abilityid || (item.exists && item.id === abilityid);
1305
+ },
1306
+ ignoringAbility() {
1307
+ // Check if any active pokemon have the ability Neutralizing Gas
1308
+ let neutralizinggas = false;
1309
+ for (const pokemon of this.battle.getAllActive()) {
1310
+ // can't use hasAbility because it would lead to infinite recursion
1311
+ if ((pokemon.ability === ('neutralizinggas' as ID) || pokemon.item === ('neutralizinggas' as ID)) &&
1312
+ !pokemon.volatiles['gastroacid'] && !pokemon.abilityState.ending) {
1313
+ neutralizinggas = true;
1314
+ break;
1315
+ }
1405
1316
  }
1406
- }
1407
-
1408
- // Donor Clause
1409
- const evoFamilyLists = [];
1410
- for (const set of team) {
1411
- const abilitySources = teamHas.abilitySources?.[this.dex.toID(set.species)];
1412
- if (!abilitySources) continue;
1413
- let format = this.format;
1414
- if (!format.getEvoFamily) format = this.dex.formats.get('gen8inheritance');
1415
- evoFamilyLists.push(abilitySources.map(format.getEvoFamily!));
1416
- }
1417
-
1418
- // Checking actual full incompatibility would require expensive algebra.
1419
- // Instead, we only check the trivial case of multiple Pokémon only legal for exactly one family. FIXME?
1420
- const requiredFamilies = Object.create(null);
1421
- for (const evoFamilies of evoFamilyLists) {
1422
- if (evoFamilies.length !== 1) continue;
1423
- const [familyId] = evoFamilies;
1424
- if (!(familyId in requiredFamilies)) requiredFamilies[familyId] = 1;
1425
- requiredFamilies[familyId]++;
1426
- if (requiredFamilies[familyId] > 2) {
1427
- return [
1428
- `You are limited to up to two inheritances from each evolution family by the Donor Clause.`,
1429
- `(You inherit more than twice from ${this.dex.species.get(familyId).name}).`,
1430
- ];
1317
+ return !!(
1318
+ (this.battle.gen >= 5 && !this.isActive) ||
1319
+ ((this.volatiles['gastroacid'] || (neutralizinggas && this.ability !== ('neutralizinggas' as ID) &&
1320
+ this.item !== ('neutralizinggas' as ID))) && !this.getAbility().isPermanent));
1321
+ },
1322
+ ignoringItem() {
1323
+ let nGas = false;
1324
+ for (const pokemon of this.battle.getAllActive()) {
1325
+ // can't use hasAbility because it would lead to infinite recursion
1326
+ if (((pokemon.ability === ('neutralizinggas' as ID) && !pokemon.abilityState.ending) ||
1327
+ (pokemon.item === ('neutralizinggas' as ID) && !pokemon.itemState.ending)) &&
1328
+ !pokemon.volatiles['gastroacid'] && !pokemon.abilityState.ending) {
1329
+ nGas = true;
1330
+ break;
1331
+ }
1431
1332
  }
1432
- }
1433
- },
1434
- onBegin() {
1435
- for (const pokemon of this.getAllPokemon()) {
1436
- if (pokemon.baseAbility.includes('0')) {
1437
- const donor = pokemon.baseAbility.split('0')[1];
1438
- pokemon.m.donor = this.toID(donor);
1439
- pokemon.baseAbility = this.toID(pokemon.baseAbility.split('0')[0]);
1440
- pokemon.ability = pokemon.baseAbility;
1333
+ const item = this.battle.dex.abilities.get(this.item);
1334
+ return !!((this.battle.gen >= 5 && !this.isActive) ||
1335
+ (this.hasAbility('klutz') && !this.getItem().ignoreKlutz) ||
1336
+ this.volatiles['embargo'] || this.battle.field.pseudoWeather['magicroom'] ||
1337
+ (item.exists && item.id !== 'neutralizinggas' && (nGas || this.volatiles['gastroacid'])));
1338
+ },
1339
+ takeItem(source) {
1340
+ if (!this.isActive) return false;
1341
+ if (!this.item) return false;
1342
+ if (this.battle.dex.abilities.get(this.item).exists) return false;
1343
+ if (!source) source = this;
1344
+ if (this.battle.gen === 4) {
1345
+ if (this.battle.toID(this.ability) === 'multitype') return false;
1346
+ if (source && this.battle.toID(source.ability) === 'multitype') return false;
1441
1347
  }
1442
- }
1443
- },
1444
- onSwitchIn(pokemon) {
1445
- if (!pokemon.m.donor) return;
1446
- const donorTemplate = this.dex.species.get(pokemon.m.donor);
1447
- if (!donorTemplate.exists) return;
1448
- // Place volatiles on the Pokémon to show the donor details.
1449
- this.add('-start', pokemon, donorTemplate.name, '[silent]');
1348
+ const item = this.getItem();
1349
+ if (this.battle.runEvent('TakeItem', this, source, null, item)) {
1350
+ this.item = '';
1351
+ this.itemState = {id: '', target: this};
1352
+ this.pendingStaleness = undefined;
1353
+ return item;
1354
+ }
1355
+ return false;
1356
+ },
1450
1357
  },
1451
1358
  },
1452
- {
1453
- name: "[Gen 8] Inverse",
1454
- desc: `The type chart is inverted. Normal is super effective against Ghost, and vice versa, etc.`,
1455
- threads: [
1456
- `&bullet; <a href="https://www.smogon.com/forums/threads/3666858/">Inverse</a>`,
1457
- ],
1458
- mod: 'gen8',
1459
- searchShow: false,
1460
- ruleset: ['Standard', 'Dynamax Clause', 'Inverse Mod'],
1461
- banlist: [
1462
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Diggersby', 'Dracovish',
1463
- 'Dracozolt', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana',
1464
- 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo',
1465
- 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Porygon-Z', 'Rayquaza',
1466
- 'Regidrago', 'Regieleki', 'Reshiram', 'Rillaboom', 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Xerneas',
1467
- 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Base', 'Zekrom', 'Arena Trap', 'Moody', 'Power Construct',
1468
- 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
1469
- ],
1470
- },
1471
1359
  {
1472
1360
  name: "[Gen 8] Nature Swap",
1473
1361
  desc: `Pok&eacute;mon have their base stats swapped depending on their nature.`,
@@ -1523,17 +1411,6 @@ export const Formats: FormatList = [
1523
1411
  },
1524
1412
  },
1525
1413
  },
1526
- {
1527
- name: "[Gen 8] Pure Hackmons",
1528
- desc: `Anything that can be hacked in-game and is usable in local battles is allowed.`,
1529
- threads: [
1530
- `&bullet; <a href="https://www.smogon.com/forums/threads/3656851/">Pure Hackmons</a>`,
1531
- ],
1532
-
1533
- mod: 'gen8',
1534
- searchShow: false,
1535
- ruleset: ['-Nonexistent', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Endless Battle Clause'],
1536
- },
1537
1414
  {
1538
1415
  name: "[Gen 8] Shared Power",
1539
1416
  desc: `Once a Pok&eacute;mon switches in, its ability is shared with the rest of the team.`,
@@ -1595,29 +1472,6 @@ export const Formats: FormatList = [
1595
1472
  }
1596
1473
  },
1597
1474
  },
1598
- {
1599
- name: "[Gen 8] Sketchmons",
1600
- desc: `Pok&eacute;mon can learn one of any move they don't normally learn, barring the few that are banned.`,
1601
- threads: [
1602
- `&bullet; <a href="https://www.smogon.com/forums/threads/3680298/">Sketchmons</a>`,
1603
- ],
1604
- mod: 'gen8',
1605
- searchShow: false,
1606
- ruleset: ['Standard', 'Dynamax Clause', 'Sketchmons Move Legality'],
1607
- banlist: [
1608
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Excadrill',
1609
- 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon', 'Hawlucha', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem-Black', 'Kyurem-White',
1610
- 'Landorus-Base', 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia',
1611
- 'Pheromosa', 'Porygon-Z', 'Rayquaza', 'Regieleki', 'Reshiram', 'Rillaboom', 'Shedinja', 'Solgaleo', 'Spectrier', 'Swoobat',
1612
- 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora',
1613
- 'Zygarde-Base', 'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'King\'s Rock', 'Baton Pass',
1614
- ],
1615
- restricted: [
1616
- 'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Clangorous Soul', 'Double Iron Bash', 'Electrify', 'Extreme Speed',
1617
- 'Fishious Rend', 'Geomancy', 'Glacial Lance', 'Lovely Kiss', 'No Retreat', 'Oblivion Wing', 'Octolock', 'Quiver Dance', 'Secret Sword',
1618
- 'Shell Smash', 'Shift Gear', 'Sleep Powder', 'Spore', 'Thousand Arrows', 'Transform', 'V-create', 'Wicked Blow',
1619
- ],
1620
- },
1621
1475
  {
1622
1476
  name: "[Gen 8] The Loser's Game",
1623
1477
  desc: `The first player to lose all of their Pok&eacute;mon wins.`,
@@ -1753,50 +1607,6 @@ export const Formats: FormatList = [
1753
1607
  },
1754
1608
  },
1755
1609
  },
1756
- {
1757
- name: "[Gen 8] Tier Shift",
1758
- desc: `Pok&eacute;mon below OU get their stats, excluding HP, boosted. UU/RUBL get +10, RU/NUBL get +20, NU/PUBL get +30, and PU or lower get +40.`,
1759
- threads: [
1760
- `&bullet; <a href="https://www.smogon.com/forums/threads/3662165/">Tier Shift</a>`,
1761
- ],
1762
-
1763
- mod: 'gen8',
1764
- searchShow: false,
1765
- ruleset: ['[Gen 8] OU', 'Overflow Stat Mod'],
1766
- banlist: ['Damp Rock', 'Eviolite', 'Heat Rock'],
1767
- unbanlist: ['Zamazenta-Crowned'],
1768
- onModifySpecies(species, target, source, effect) {
1769
- if (!species.baseStats) return;
1770
- const boosts: {[tier: string]: number} = {
1771
- uu: 10,
1772
- rubl: 10,
1773
- ru: 20,
1774
- nubl: 20,
1775
- nu: 30,
1776
- publ: 30,
1777
- pu: 40,
1778
- nfe: 40,
1779
- lc: 40,
1780
- };
1781
- let tier: string = this.toID(species.tier);
1782
- if (!(tier in boosts)) return;
1783
- // Non-Pokemon bans in lower tiers
1784
- if (target) {
1785
- if (target.set.item === 'lightclay') return;
1786
- if (['drizzle', 'drought', 'snowwarning'].includes(target.set.ability) && boosts[tier] > 20) tier = 'nubl';
1787
- }
1788
- const pokemon = this.dex.deepClone(species);
1789
- pokemon.bst = pokemon.baseStats['hp'];
1790
- const boost = boosts[tier];
1791
- let statName: StatID;
1792
- for (statName in pokemon.baseStats as StatsTable) {
1793
- if (statName === 'hp') continue;
1794
- pokemon.baseStats[statName] = this.clampIntRange(pokemon.baseStats[statName] + boost, 1, 255);
1795
- pokemon.bst += pokemon.baseStats[statName];
1796
- }
1797
- return pokemon;
1798
- },
1799
- },
1800
1610
  {
1801
1611
  name: "[Gen 8] Trademarked",
1802
1612
  desc: `Sacrifice your Pok&eacute;mon's ability for a status move that activates on switch-in.`,
@@ -1897,71 +1707,6 @@ export const Formats: FormatList = [
1897
1707
  },
1898
1708
  },
1899
1709
  },
1900
- {
1901
- name: "[Gen 8] STABmons Mix and Mega",
1902
- desc: `Pok&eacute;mon can use any move of their typing, in addition to the moves they can normally learn. Mega evolve any Pok&eacute;mon with any mega stone and no limit. Boosts based on mega evolution from gen 7.`,
1903
- threads: [
1904
- `&bullet; <a href="https://www.smogon.com/forums/posts/8299984/">STABmons Mix and Mega</a>`,
1905
- ],
1906
-
1907
- mod: 'mixandmega',
1908
- searchShow: false,
1909
- ruleset: ['Standard', 'Dynamax Clause', 'Overflow Stat Mod', 'STABmons Move Legality'],
1910
- banlist: [
1911
- 'Calyrex-Shadow', 'Kyogre', 'Zacian', 'Zacian-Crowned', 'Moody', 'Shadow Tag', 'Beedrillite', 'Blazikenite', 'Gengarite',
1912
- 'Kangaskhanite', 'Mawilite', 'Medichamite', 'Pidgeotite', 'Baton Pass', 'Electrify', 'King\'s Rock',
1913
- ],
1914
- restricted: [
1915
- 'Calyrex-Ice', 'Dialga', 'Dragapult', 'Dragonite', 'Eternatus', 'Genesect', 'Gengar', 'Giratina', 'Giratina-Origin',
1916
- 'Groudon', 'Ho-Oh', 'Kartana', 'Keldeo', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Therian', 'Lugia', 'Lunala',
1917
- 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Rayquaza',
1918
- 'Regigigas', 'Reshiram', 'Tapu Koko', 'Thundurus', 'Thundurus-Therian', 'Urshifu-Base', 'Xerneas', 'Yveltal', 'Zekrom',
1919
- 'Zeraora', 'Zygarde-Base', 'Zygarde-Complete',
1920
- 'Acupressure', 'Astral Barrage', 'Belly Drum', 'Bolt Beak', 'Boomburst', 'Clangorous Soul', 'Double Iron Bash',
1921
- 'Extreme Speed', 'Fishious Rend', 'Geomancy', 'Glacial Lance', 'Lovely Kiss', 'Precipice Blades', 'Shell Smash',
1922
- 'Shift Gear', 'Sleep Powder', 'Spore', 'Thousand Arrows', 'Transform', 'V-create', 'Wicked Blow',
1923
- ],
1924
- onValidateTeam(team) {
1925
- const itemTable = new Set<ID>();
1926
- for (const set of team) {
1927
- const item = this.dex.items.get(set.item);
1928
- if (!item?.megaStone) continue;
1929
- const species = this.dex.species.get(set.species);
1930
- if (species.isNonstandard) return [`${species.baseSpecies} does not exist in gen 8.`];
1931
- if (this.ruleTable.isRestrictedSpecies(species) || this.toID(set.ability) === 'powerconstruct') {
1932
- return [`${species.name} is not allowed to hold ${item.name}.`];
1933
- }
1934
- if (itemTable.has(item.id)) {
1935
- return [`You are limited to one of each mega stone.`, `(You have more than one ${item.name})`];
1936
- }
1937
- itemTable.add(item.id);
1938
- }
1939
- },
1940
- onBegin() {
1941
- for (const pokemon of this.getAllPokemon()) {
1942
- pokemon.m.originalSpecies = pokemon.baseSpecies.name;
1943
- }
1944
- },
1945
- onSwitchIn(pokemon) {
1946
- // @ts-ignore
1947
- const oMegaSpecies = this.dex.species.get(pokemon.species.originalMega);
1948
- if (oMegaSpecies.exists && pokemon.m.originalSpecies !== oMegaSpecies.baseSpecies) {
1949
- // Place volatiles on the Pokémon to show its mega-evolved condition and details
1950
- this.add('-start', pokemon, oMegaSpecies.requiredItem || oMegaSpecies.requiredMove, '[silent]');
1951
- const oSpecies = this.dex.species.get(pokemon.m.originalSpecies);
1952
- if (oSpecies.types.length !== pokemon.species.types.length || oSpecies.types[1] !== pokemon.species.types[1]) {
1953
- this.add('-start', pokemon, 'typechange', pokemon.species.types.join('/'), '[silent]');
1954
- }
1955
- }
1956
- },
1957
- onSwitchOut(pokemon) {
1958
- // @ts-ignore
1959
- const oMegaSpecies = this.dex.species.get(pokemon.species.originalMega);
1960
- if (oMegaSpecies.exists && pokemon.m.originalSpecies !== oMegaSpecies.baseSpecies) {
1961
- this.add('-end', pokemon, oMegaSpecies.requiredItem || oMegaSpecies.requiredMove, '[silent]');
1962
- }
1963
- },
1964
- },
1965
1710
 
1966
1711
  // Randomized Metas
1967
1712
  ///////////////////////////////////////////////////////////////////
@@ -1982,6 +1727,7 @@ export const Formats: FormatList = [
1982
1727
 
1983
1728
  mod: 'gen8',
1984
1729
  team: 'random',
1730
+ searchShow: false,
1985
1731
  ruleset: ['[Gen 8] Random Battle', 'Dynamax Clause'],
1986
1732
  },
1987
1733
  {
@@ -2257,36 +2003,40 @@ export const Formats: FormatList = [
2257
2003
  column: 3,
2258
2004
  },
2259
2005
  {
2260
- name: "[Gen 5] Ubers",
2006
+ name: "[Gen 6] Ubers",
2261
2007
  threads: [
2262
- `&bullet; <a href="https://www.smogon.com/forums/posts/8286278/">BW2 Ubers</a>`,
2008
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8286277/">ORAS Ubers</a>`,
2263
2009
  ],
2264
2010
 
2265
- mod: 'gen5',
2011
+ mod: 'gen6',
2266
2012
  // searchShow: false,
2267
- ruleset: ['Standard', 'Sleep Clause Mod'],
2013
+ ruleset: ['Standard', 'Swagger Clause', 'Mega Rayquaza Clause'],
2268
2014
  },
2269
2015
  {
2270
- name: "[Gen 7] PU",
2016
+ name: "[Gen 4] UU",
2271
2017
  threads: [
2272
- `&bullet; <a href="https://www.smogon.com/forums/threads/3611496/">USM PU Sample Teams</a>`,
2273
- `&bullet; <a href="https://www.smogon.com/forums/threads/3614892/">USM PU Viability Rankings</a>`,
2018
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3532624/">DPP UU Metagame Discussion</a>`,
2019
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3503638/">DPP UU Viability Rankings</a>`,
2274
2020
  ],
2275
2021
 
2276
- mod: 'gen7',
2022
+ mod: 'gen4',
2277
2023
  // searchShow: false,
2278
- ruleset: ['[Gen 7] NU'],
2279
- banlist: ['NU', 'PUBL'],
2024
+ ruleset: ['[Gen 4] OU'],
2025
+ banlist: ['OU', 'UUBL'],
2026
+ unbanlist: ['Arena Trap'],
2280
2027
  },
2281
2028
  {
2282
- name: "[Gen 2] NC2000 + Crystal Moves",
2029
+ name: "[Gen 3] Doubles OU",
2283
2030
  threads: [
2284
- `&bullet; <a href="https://www.smogon.com/forums/threads/3682691/">Nintendo Cup 2000 Resource Hub</a>`,
2285
- `&bullet; <a href="https://www.smogon.com/forums/threads/3677370/">Differences between Nintendo Cup 2000 and GSC OU</a>`,
2031
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3666831/">ADV Doubles OU</a>`,
2286
2032
  ],
2287
2033
 
2288
- mod: 'gen2stadium2',
2289
- ruleset: ['[Gen 2] Nintendo Cup 2000', 'Evasion Moves Clause', 'OHKO Clause', '!Nintendo Cup 2000 Move Legality'],
2034
+ mod: 'gen3',
2035
+ // searchShow: false,
2036
+ gameType: 'doubles',
2037
+ ruleset: ['Standard', '!Sleep Clause Mod', '!Switch Priority Clause Mod'],
2038
+ banlist: ['Uber'],
2039
+ unbanlist: ['Deoxys-Speed', 'Wobbuffet', 'Wynaut'],
2290
2040
  },
2291
2041
 
2292
2042
  // Past Gens OU
@@ -2557,6 +2307,18 @@ export const Formats: FormatList = [
2557
2307
  ruleset: ['[Gen 7] RU'],
2558
2308
  banlist: ['RU', 'NUBL', 'Drought'],
2559
2309
  },
2310
+ {
2311
+ name: "[Gen 7] PU",
2312
+ threads: [
2313
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3611496/">USM PU Sample Teams</a>`,
2314
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3614892/">USM PU Viability Rankings</a>`,
2315
+ ],
2316
+
2317
+ mod: 'gen7',
2318
+ searchShow: false,
2319
+ ruleset: ['[Gen 7] NU'],
2320
+ banlist: ['NU', 'PUBL'],
2321
+ },
2560
2322
  {
2561
2323
  name: "[Gen 7] LC",
2562
2324
  threads: [
@@ -2814,16 +2576,6 @@ export const Formats: FormatList = [
2814
2576
  section: "OR/AS Singles",
2815
2577
  column: 4,
2816
2578
  },
2817
- {
2818
- name: "[Gen 6] Ubers",
2819
- threads: [
2820
- `&bullet; <a href="https://www.smogon.com/forums/posts/8286277/">ORAS Ubers</a>`,
2821
- ],
2822
-
2823
- mod: 'gen6',
2824
- searchShow: false,
2825
- ruleset: ['Standard', 'Swagger Clause', 'Mega Rayquaza Clause'],
2826
- },
2827
2579
  {
2828
2580
  name: "[Gen 6] UU",
2829
2581
  threads: [
@@ -3089,6 +2841,16 @@ export const Formats: FormatList = [
3089
2841
  section: "B2/W2 Singles",
3090
2842
  column: 4,
3091
2843
  },
2844
+ {
2845
+ name: "[Gen 5] Ubers",
2846
+ threads: [
2847
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8286278/">BW2 Ubers</a>`,
2848
+ ],
2849
+
2850
+ mod: 'gen5',
2851
+ searchShow: false,
2852
+ ruleset: ['Standard', 'Sleep Clause Mod'],
2853
+ },
3092
2854
  {
3093
2855
  name: "[Gen 5] UU",
3094
2856
  threads: [
@@ -3098,8 +2860,8 @@ export const Formats: FormatList = [
3098
2860
 
3099
2861
  mod: 'gen5',
3100
2862
  searchShow: false,
3101
- ruleset: ['Standard', 'Evasion Abilities Clause', 'Baton Pass Clause', 'Swagger Clause', 'Sleep Clause Mod'],
3102
- banlist: ['Uber', 'OU', 'UUBL', 'Arena Trap', 'Drought', 'Sand Stream', 'Snow Warning'],
2863
+ ruleset: ['Standard', 'Evasion Abilities Clause', 'Swagger Clause', 'Sleep Clause Mod'],
2864
+ banlist: ['Uber', 'OU', 'UUBL', 'Arena Trap', 'Drought', 'Sand Stream', 'Snow Warning', 'Prankster + Assist', 'Prankster + Copycat', 'Baton Pass'],
3103
2865
  },
3104
2866
  {
3105
2867
  name: "[Gen 5] RU",
@@ -3110,8 +2872,9 @@ export const Formats: FormatList = [
3110
2872
 
3111
2873
  mod: 'gen5',
3112
2874
  searchShow: false,
3113
- ruleset: ['[Gen 5] UU', '!Sleep Clause Mod', 'Sleep Moves Clause'],
2875
+ ruleset: ['[Gen 5] UU', 'Baton Pass Clause', '!Sleep Clause Mod', 'Sleep Moves Clause'],
3114
2876
  banlist: ['UU', 'RUBL', 'Shadow Tag', 'Shell Smash + Baton Pass'],
2877
+ unbanlist: ['Prankster + Assist', 'Prankster + Copycat', 'Baton Pass'],
3115
2878
  },
3116
2879
  {
3117
2880
  name: "[Gen 5] NU",
@@ -3122,8 +2885,8 @@ export const Formats: FormatList = [
3122
2885
 
3123
2886
  mod: 'gen5',
3124
2887
  searchShow: false,
3125
- ruleset: ['[Gen 5] RU', '!Sleep Moves Clause', 'Sleep Clause Mod', '+Shadow Tag'],
3126
- banlist: ['RU', 'NUBL', 'Prankster + Assist'],
2888
+ ruleset: ['[Gen 5] RU', '!Sleep Moves Clause', 'Sleep Clause Mod'],
2889
+ banlist: ['RU', 'NUBL', 'Assist', 'Copycat'],
3127
2890
  },
3128
2891
  {
3129
2892
  name: "[Gen 5] PU",
@@ -3134,7 +2897,7 @@ export const Formats: FormatList = [
3134
2897
  mod: 'gen5',
3135
2898
  searchShow: false,
3136
2899
  ruleset: ['[Gen 5] NU', 'Sleep Moves Clause'],
3137
- banlist: ['NU', 'Combusken', 'Gothorita', 'Linoone', 'Riolu', 'Rotom-Frost', 'Throh', 'Vigoroth'],
2900
+ banlist: ['NU', 'Combusken', 'Gothorita', 'Linoone', 'Riolu', 'Rotom-Frost', 'Simipour', 'Throh', 'Vigoroth'],
3138
2901
  },
3139
2902
  {
3140
2903
  name: "[Gen 5] LC",
@@ -3286,19 +3049,6 @@ export const Formats: FormatList = [
3286
3049
  ruleset: ['Standard'],
3287
3050
  banlist: ['AG'],
3288
3051
  },
3289
- {
3290
- name: "[Gen 4] UU",
3291
- threads: [
3292
- `&bullet; <a href="https://www.smogon.com/forums/threads/3532624/">DPP UU Metagame Discussion</a>`,
3293
- `&bullet; <a href="https://www.smogon.com/forums/threads/3503638/">DPP UU Viability Rankings</a>`,
3294
- ],
3295
-
3296
- mod: 'gen4',
3297
- searchShow: false,
3298
- ruleset: ['[Gen 4] OU'],
3299
- banlist: ['OU', 'UUBL'],
3300
- unbanlist: ['Arena Trap'],
3301
- },
3302
3052
  {
3303
3053
  name: "[Gen 4] NU",
3304
3054
  threads: [
@@ -3541,7 +3291,7 @@ export const Formats: FormatList = [
3541
3291
  'Picked Team Size = 1', 'Max Team Size = 3',
3542
3292
  '[Gen 2] OU', 'Accuracy Moves Clause', 'Sleep Moves Clause', 'Team Preview',
3543
3293
  ],
3544
- banlist: ['Clefable', 'Snorlax', 'Zapdos', 'Berserk Gene', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Quick Claw', 'Destiny Bond', 'Explosion', 'Present', 'Self-Destruct'],
3294
+ banlist: ['Clefable', 'Snorlax', 'Zapdos', 'Berserk Gene', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Quick Claw', 'Destiny Bond', 'Explosion', 'Perish Song', 'Present', 'Self-Destruct'],
3545
3295
  },
3546
3296
  {
3547
3297
  name: "[Gen 2] Nintendo Cup 2000",