@pkmn/sim 0.5.8 → 0.5.11

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 (50) hide show
  1. package/build/config/formats.js +390 -238
  2. package/build/config/formats.js.map +1 -1
  3. package/build/data/aliases.js +1 -2
  4. package/build/data/aliases.js.map +1 -1
  5. package/build/data/formats-data.js +3 -3
  6. package/build/data/formats-data.js.map +1 -1
  7. package/build/data/learnsets.js +5 -6
  8. package/build/data/learnsets.js.map +1 -1
  9. package/build/data/mods/gen3/formats-data.js +1 -1
  10. package/build/data/mods/gen3/formats-data.js.map +1 -1
  11. package/build/data/mods/gen7/formats-data.js +1 -1
  12. package/build/data/mods/gen7/formats-data.js.map +1 -1
  13. package/build/data/mods/gen7/pokedex.js +1 -0
  14. package/build/data/mods/gen7/pokedex.js.map +1 -1
  15. package/build/data/pokedex.js +2 -2
  16. package/build/data/rulesets.js +0 -139
  17. package/build/data/rulesets.js.map +1 -1
  18. package/build/data/tags.js +4 -4
  19. package/build/data/tags.js.map +1 -1
  20. package/build/lib/index.js +5 -1
  21. package/build/lib/index.js.map +1 -1
  22. package/build/lib/streams.js +5 -1
  23. package/build/lib/streams.js.map +1 -1
  24. package/build/sim/battle-actions.js +0 -6
  25. package/build/sim/battle-actions.js.map +1 -1
  26. package/build/sim/battle-queue.js +1 -3
  27. package/build/sim/battle-queue.js.map +1 -1
  28. package/build/sim/dex.js +5 -1
  29. package/build/sim/dex.js.map +1 -1
  30. package/build/sim/index.js +5 -1
  31. package/build/sim/index.js.map +1 -1
  32. package/build/sim/teams.js +5 -1
  33. package/build/sim/teams.js.map +1 -1
  34. package/build/sim/tools/index.js +5 -1
  35. package/build/sim/tools/index.js.map +1 -1
  36. package/build/sim/tools/runner.js +5 -1
  37. package/build/sim/tools/runner.js.map +1 -1
  38. package/config/formats.ts +376 -237
  39. package/data/aliases.ts +1 -2
  40. package/data/formats-data.ts +3 -3
  41. package/data/learnsets.ts +5 -6
  42. package/data/mods/gen3/formats-data.ts +1 -1
  43. package/data/mods/gen7/formats-data.ts +1 -1
  44. package/data/mods/gen7/pokedex.ts +1 -0
  45. package/data/pokedex.ts +2 -2
  46. package/data/rulesets.ts +0 -125
  47. package/data/tags.ts +4 -4
  48. package/package.json +2 -2
  49. package/sim/battle-actions.ts +0 -7
  50. package/sim/battle-queue.ts +1 -3
@@ -191,7 +191,7 @@ exports.Formats = [
191
191
  ],
192
192
  banlist: [
193
193
  'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Dialga', 'Dragonite', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Jirachi',
194
- 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Melmetal', 'Mew', 'Mewtwo', 'Mimikyu', 'Necrozma-Dawn-Wings',
194
+ 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Melmetal', 'Mew', 'Mewtwo', 'Mimikyu', 'Necrozma', 'Necrozma-Dawn-Wings',
195
195
  'Necrozma-Dusk-Mane', 'Palkia', 'Rayquaza', 'Reshiram', 'Sableye', 'Snorlax', 'Solgaleo', 'Victini', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned',
196
196
  'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Moody', 'Power Construct', 'Bright Powder', 'Focus Band', 'Focus Sash', 'Lax Incense', 'Quick Claw', 'Perish Song',
197
197
  ],
@@ -217,8 +217,8 @@ exports.Formats = [
217
217
  mod: 'gen8',
218
218
  ruleset: ['[Gen 8] PU'],
219
219
  banlist: [
220
- 'PU', 'Aurorus', 'Centiskorch', 'Drampa', 'Exeggutor-Alola', 'Gallade', 'Haunter', 'Magmortar', 'Magneton', 'Omastar', 'Rotom-Frost',
221
- 'Turtonator', 'Vanilluxe', 'Vikavolt', 'Silvally-Dragon', 'Silvally-Ground', 'Sneasel', 'Damp Rock', 'Grassy Seed',
220
+ 'PU', 'Arctovish', 'Aurorus', 'Centiskorch', 'Drampa', 'Exeggutor-Alola', 'Gallade', 'Haunter', 'Magmortar', 'Magneton', 'Omastar',
221
+ 'Rotom-Frost', 'Turtonator', 'Vanilluxe', 'Vikavolt', 'Silvally-Dragon', 'Silvally-Ground', 'Sneasel', 'Damp Rock', 'Grassy Seed',
222
222
  ],
223
223
  },
224
224
  {
@@ -443,7 +443,7 @@ exports.Formats = [
443
443
  ruleset: ['Standard NatDex', 'OHKO Clause', 'Evasion Moves Clause', 'Species Clause', 'Dynamax Clause', 'Sleep Clause Mod'],
444
444
  banlist: [
445
445
  'Alakazam-Mega', 'Arceus', 'Blastoise-Mega', 'Blaziken-Mega', 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Darkrai',
446
- 'Darmanitan-Galar', 'Deoxys-Attack', 'Deoxys-Base', 'Deoxys-Speed', 'Dialga', 'Dracovish', 'Eternatus',
446
+ 'Darmanitan-Galar', 'Deoxys-Attack', 'Deoxys-Base', 'Deoxys-Speed', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus',
447
447
  'Genesect', 'Gengar-Mega', 'Giratina', 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-Black',
448
448
  'Kyurem-White', 'Landorus-Base', 'Lucario-Mega', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Metagross-Mega', 'Mewtwo',
449
449
  'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Necrozma-Ultra', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram',
@@ -472,16 +472,14 @@ exports.Formats = [
472
472
  'Drizzle', 'Drought',
473
473
  // Slowbronite is banned so it doesn't validate on Galarian Slowbro
474
474
  'Slowbronite',
475
- // NDOU suspect
476
- 'Dragapult',
477
475
  ],
478
476
  // Used to distinguish UU from below UU in the client
479
477
  restricted: [
480
- 'Aegislash', 'Alakazam-Base', 'Altaria-Mega', 'Amoonguss', 'Azumarill', 'Beedrill-Mega', 'Blaziken-Base', 'Breloom', 'Celesteela',
481
- 'Chandelure', 'Donphan', 'Dracozolt', 'Dragonite', 'Feraligatr', 'Gastrodon', 'Hatterene', 'Hippowdon', 'Infernape', 'Keldeo',
482
- 'Krookodile', 'Mamoswine', 'Mandibuzz', 'Manectric-Mega', 'Melmetal', 'Mienshao', 'Moltres-Base', 'Nidoking', 'Nidoqueen', 'Nihilego',
483
- 'Quagsire', 'Regieleki', 'Ribombee', 'Rotom-Heat', 'Rotom-Wash', 'Salamence', 'Scizor', 'Skarmory', 'Slowking-Base', 'Swampert-Base',
484
- 'Talonflame', 'Tangrowth', 'Tornadus-Base', 'Umbreon', 'Urshifu-Rapid-Strike',
478
+ 'Aegislash', 'Altaria-Mega', 'Amoonguss', 'Azumarill', 'Beedrill-Mega', 'Breloom', 'Celesteela', 'Chandelure', 'Donphan', 'Dracozolt',
479
+ 'Dragonite', 'Feraligatr', 'Gastrodon', 'Hatterene', 'Hippowdon', 'Infernape', 'Keldeo', 'Krookodile', 'Mamoswine', 'Mandibuzz',
480
+ 'Manectric-Mega', 'Melmetal', 'Mienshao', 'Moltres-Base', 'Nidoking', 'Nidoqueen', 'Nihilego', 'Quagsire', 'Regieleki', 'Ribombee',
481
+ 'Rotom-Heat', 'Rotom-Wash', 'Salamence', 'Scizor', 'Skarmory', 'Slowking-Base', 'Swampert-Base', 'Talonflame', 'Tangrowth', 'Tornadus-Base',
482
+ 'Umbreon', 'Urshifu-Rapid-Strike',
485
483
  ],
486
484
  },
487
485
  {
@@ -591,141 +589,217 @@ exports.Formats = [
591
589
  column: 2,
592
590
  },
593
591
  {
594
- name: "[Gen 8] Trademarked",
595
- desc: `Sacrifice your Pokémon's ability for a status move that activates on switch-in.`,
592
+ name: "[Gen 8] Shared Power",
593
+ desc: `Once a Pokémon switches in, its ability is shared with the rest of the team.`,
596
594
  threads: [
597
- `&bullet; <a href="https://www.smogon.com/forums/threads/3656980/">Trademarked</a>`,
595
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3660877/">Shared Power</a>`,
598
596
  ],
599
- mod: 'gen8',
597
+ mod: 'sharedpower',
600
598
  // searchShow: false,
601
599
  ruleset: ['Standard', 'Dynamax Clause'],
602
600
  banlist: [
603
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Kyurem-Black', 'Kyurem-White', 'Giratina',
604
- 'Giratina-Origin', 'Genesect', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Lugia', 'Lunala', 'Magearna', 'Marowak-Alola', 'Marshadow', 'Melmetal',
605
- 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Solgaleo', 'Spectrier',
606
- 'Urshifu-Base', 'Victini', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base',
607
- 'Arena Trap', 'Moody', 'Neutralizing Gas', 'Power Construct', 'Shadow Tag', 'Baton Pass',
601
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Eternatus', 'Genesect', 'Giratina',
602
+ 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Lugia', 'Lunala', 'Magearna',
603
+ 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia',
604
+ 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo', 'Urshifu-Base', 'Urshifu-Rapid-Strike',
605
+ 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom',
606
+ 'Arena Trap', 'Contrary', 'Drizzle ++ Swift Swim', 'Drought ++ Chlorophyll', 'Electric Surge ++ Surge Surfer',
607
+ 'Fur Coat', 'Guts', 'Harvest', 'Huge Power', 'Imposter', 'Innards Out', 'Libero', 'Magic Bounce', 'Magic Guard',
608
+ 'Magnet Pull', 'Mold Breaker', 'Moody', 'Neutralizing Gas', 'Power Construct', 'Queenly Majesty', 'Quick Draw',
609
+ 'Regenerator', 'Sand Rush', 'Sand Veil', 'Shadow Tag', 'Simple', 'Snow Cloak', 'Snow Warning ++ Slush Rush',
610
+ 'Speed Boost', 'Stakeout', 'Steelworker ++ Steely Spirit', 'Stench', 'Tinted Lens', 'Triage', 'Unaware',
611
+ 'Unburden', 'Water Bubble', 'King\'s Rock', 'Baton Pass',
608
612
  ],
609
- restricted: [
610
- 'Baneful Bunker', 'Block', 'Copycat', 'Corrosive Gas', 'Detect', 'Destiny Bond', 'Disable', 'Encore', 'Fairy Lock', 'Hypnosis', 'Ingrain',
611
- 'Instruct', 'Lovely Kiss', 'King\'s Shield', 'Mat Block', 'Mean Look', 'Memento', 'move:Metronome', 'Obstruct', 'Octolock', 'Nature Power',
612
- 'Parting Shot', 'Psycho Shift', 'Protect', 'Roar', 'Sing', 'Skill Swap', 'Sleep Powder', 'Sleep Talk', 'Spiky Shield', 'Spore', 'Substitute',
613
- 'Switcheroo', 'Teleport', 'Trick', 'Whirlwind', 'Wish', 'Yawn',
613
+ getSharedPower(pokemon) {
614
+ const sharedPower = new Set();
615
+ for (const ally of pokemon.side.pokemon) {
616
+ if (ally.previouslySwitchedIn > 0) {
617
+ if (pokemon.battle.dex.currentMod !== 'sharedpower' && ['trace', 'mirrorarmor'].includes(ally.baseAbility)) {
618
+ sharedPower.add('noability');
619
+ continue;
620
+ }
621
+ sharedPower.add(ally.baseAbility);
622
+ }
623
+ }
624
+ sharedPower.delete(pokemon.baseAbility);
625
+ return sharedPower;
626
+ },
627
+ onBeforeSwitchIn(pokemon) {
628
+ let format = this.format;
629
+ if (!format.getSharedPower)
630
+ format = this.dex.formats.get('gen8sharedpower');
631
+ for (const ability of format.getSharedPower(pokemon)) {
632
+ const effect = 'ability:' + ability;
633
+ pokemon.volatiles[effect] = { id: this.toID(effect), target: pokemon };
634
+ if (!pokemon.m.abils)
635
+ pokemon.m.abils = [];
636
+ if (!pokemon.m.abils.includes(effect))
637
+ pokemon.m.abils.push(effect);
638
+ }
639
+ },
640
+ onSwitchInPriority: 2,
641
+ onSwitchIn(pokemon) {
642
+ let format = this.format;
643
+ if (!format.getSharedPower)
644
+ format = this.dex.formats.get('gen8sharedpower');
645
+ for (const ability of format.getSharedPower(pokemon)) {
646
+ if (ability === 'noability') {
647
+ this.hint(`Mirror Armor and Trace break in Shared Power formats that don't use Shared Power as a base, so they get removed from non-base users.`);
648
+ }
649
+ const effect = 'ability:' + ability;
650
+ delete pokemon.volatiles[effect];
651
+ pokemon.addVolatile(effect);
652
+ }
653
+ },
654
+ },
655
+ {
656
+ name: "[Gen 8] Cross Evolution",
657
+ 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.`,
658
+ threads: [
659
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3657562/">Cross Evolution</a>`,
614
660
  ],
615
- onValidateTeam(team, format, teamHas) {
616
- const problems = [];
617
- for (const trademark in teamHas.trademarks) {
618
- if (teamHas.trademarks[trademark] > 1) {
619
- problems.push(`You are limited to 1 of each Trademark.`, `(You have ${teamHas.trademarks[trademark]} Pok\u00e9mon with ${trademark} as a Trademark.)`);
661
+ mod: 'gen8',
662
+ // searchShow: false,
663
+ ruleset: ['Standard', 'Overflow Stat Mod', 'Dynamax Clause', '2 Ability Clause'],
664
+ banlist: ['Corsola-Galar', 'Sneasel', 'Type: Null', 'Arena Trap', 'Ice Scales', 'Moody', 'King\'s Rock', 'Baton Pass'],
665
+ restricted: ['Chansey', 'Lunala', 'Shedinja', 'Solgaleo', 'Gorilla Tactics', 'Huge Power', 'Pure Power', 'Shadow Tag'],
666
+ onValidateTeam(team) {
667
+ const names = new Set();
668
+ for (const set of team) {
669
+ const name = set.name;
670
+ if (names.has(this.dex.toID(name))) {
671
+ return [
672
+ `Your Pok\u00e9mon must have different nicknames.`,
673
+ `(You have more than one Pok\u00e9mon named '${name}')`,
674
+ ];
620
675
  }
676
+ names.add(this.dex.toID(name));
677
+ }
678
+ if (!names.size) {
679
+ return [
680
+ `${this.format.name} works using nicknames; your team has 0 nicknamed Pok\u00e9mon.`,
681
+ `(If this was intentional, add a nickname to one Pok\u00e9mon that isn't the name of a Pok\u00e9mon species.)`,
682
+ ];
621
683
  }
622
- return problems;
684
+ },
685
+ checkCanLearn(move, species, lsetData, set) {
686
+ // @ts-ignore
687
+ if (!set.sp?.exists || !set.crossSpecies?.exists) {
688
+ return this.checkCanLearn(move, species, lsetData, set);
689
+ }
690
+ // @ts-ignore
691
+ const problem = this.checkCanLearn(move, set.sp);
692
+ if (!problem)
693
+ return null;
694
+ // @ts-ignore
695
+ if (!set.crossMovesLeft)
696
+ return problem;
697
+ // @ts-ignore
698
+ if (this.checkCanLearn(move, set.crossSpecies))
699
+ return problem;
700
+ // @ts-ignore
701
+ set.crossMovesLeft--;
702
+ return null;
623
703
  },
624
704
  validateSet(set, teamHas) {
625
- const dex = this.dex;
626
- const ability = dex.moves.get(set.ability);
627
- if (!ability.exists) { // Not even a real move
705
+ const crossSpecies = this.dex.species.get(set.name);
706
+ let problems = this.dex.formats.get('Pokemon').onChangeSet?.call(this, set, this.format) || null;
707
+ if (Array.isArray(problems) && problems.length)
708
+ return problems;
709
+ const crossNonstandard = (!this.ruleTable.has('standardnatdex') && crossSpecies.isNonstandard === 'Past') ||
710
+ crossSpecies.isNonstandard === 'Future';
711
+ const crossIsCap = !this.ruleTable.has('+pokemontag:cap') && crossSpecies.isNonstandard === 'CAP';
712
+ if (!crossSpecies.exists || crossNonstandard || crossIsCap)
713
+ return this.validateSet(set, teamHas);
714
+ const species = this.dex.species.get(set.species);
715
+ const check = this.checkSpecies(set, species, species, {});
716
+ if (check)
717
+ return [check];
718
+ const nonstandard = !this.ruleTable.has('standardnatdex') && species.isNonstandard === 'Past';
719
+ const isCap = !this.ruleTable.has('+pokemontag:cap') && species.isNonstandard === 'CAP';
720
+ if (!species.exists || nonstandard || isCap || species === crossSpecies)
628
721
  return this.validateSet(set, teamHas);
722
+ if (!species.nfe)
723
+ return [`${species.name} cannot cross evolve because it doesn't evolve.`];
724
+ const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
725
+ if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo) {
726
+ return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it isn't an evolution.`];
629
727
  }
630
- // Absolute trademark bans
631
- if (ability.category !== 'Status') {
632
- return [`${ability.name} is not a status move, and cannot be used as a trademark.`];
728
+ if (this.ruleTable.isRestrictedSpecies(crossSpecies)) {
729
+ return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it is banned.`];
633
730
  }
634
- if (ability.forceSwitch || ability.selfSwitch) {
731
+ const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
732
+ if (!crossPrevoSpecies.prevo !== !species.prevo) {
635
733
  return [
636
- `Force-switching and self-switching moves are banned from being used as trademarks.`,
637
- `(${ability.name} is a ${ability.forceSwitch ? 'force' : 'self'}-switching move.)`,
734
+ `${species.name} cannot cross evolve into ${crossSpecies.name} because they are not consecutive evolution stages.`,
638
735
  ];
639
736
  }
640
- const irrevokablyRestricted = [
641
- 'Assist', 'Copycat', 'Metronome', 'Mirror Move', 'Sleep Talk',
642
- 'Recycle', 'Trace',
643
- 'Skill Swap', // Self-propagates indefinitely
644
- ];
645
- for (const m of set.moves) {
646
- const move = dex.moves.get(m);
647
- if (irrevokablyRestricted.includes(move.name)) {
648
- return [`${move.name} is banned from Trademark, irrespective of custom rules, because it can cause endless turns.`];
737
+ const item = this.dex.items.get(set.item);
738
+ if (item.itemUser?.length) {
739
+ if (!item.itemUser.includes(crossSpecies.name) || crossSpecies.name !== species.name) {
740
+ return [`${species.name} cannot use ${item.name} because it is cross evolved into ${crossSpecies.name}.`];
649
741
  }
650
742
  }
651
- if (irrevokablyRestricted.includes(ability.name)) {
652
- return [`${ability.name} cannot safely function as a trademark.`];
653
- }
654
- // Contingent trademark bans
655
- if (this.ruleTable.isRestricted(`move:${ability.id}`)) {
656
- return [`${ability.name} is restricted from being used as a trademark.`];
657
- }
658
- if (set.moves.map(this.toID).includes(ability.id)) {
659
- return [`${set.name} may not use ${ability.name} as both a trademark and one of its moves simultaneously.`];
743
+ const ability = this.dex.abilities.get(set.ability);
744
+ if (!this.ruleTable.isRestricted(`ability:${ability.id}`) || Object.values(species.abilities).includes(ability.name)) {
745
+ set.species = crossSpecies.name;
660
746
  }
661
- const customRules = this.format.customRules || [];
662
- if (!customRules.includes('!obtainableabilities'))
663
- customRules.push('!obtainableabilities');
664
- const TeamValidator = require('../sim/team-validator').TeamValidator;
665
- const validator = new TeamValidator(dex.formats.get(`${this.format.id}@@@${customRules.join(',')}`));
666
- const moves = set.moves;
667
- set.moves = [ability.id];
668
- set.ability = dex.species.get(set.species).abilities['0'];
669
- let problems = validator.validateSet(set, {}) || [];
670
- if (problems.length)
671
- return problems;
672
- set.moves = moves;
673
- set.ability = dex.species.get(set.species).abilities['0'];
674
- problems = problems.concat(validator.validateSet(set, teamHas) || []);
675
- set.ability = ability.id;
676
- if (!teamHas.trademarks)
677
- teamHas.trademarks = {};
678
- teamHas.trademarks[ability.name] = (teamHas.trademarks[ability.name] || 0) + 1;
679
- return problems.length ? problems : null;
747
+ // @ts-ignore
748
+ set.sp = species;
749
+ // @ts-ignore
750
+ set.crossSpecies = crossSpecies;
751
+ // @ts-ignore
752
+ set.crossMovesLeft = 2;
753
+ problems = this.validateSet(set, teamHas);
754
+ set.name = crossSpecies.name;
755
+ set.species = species.name;
756
+ return problems;
680
757
  },
681
- pokemon: {
682
- getAbility() {
683
- const move = this.battle.dex.moves.get(this.battle.toID(this.ability));
684
- if (!move.exists)
685
- return Object.getPrototypeOf(this).getAbility.call(this);
686
- return {
687
- id: move.id,
688
- name: move.name,
689
- onStart(pokemon) {
690
- this.add('-activate', pokemon, 'ability: ' + move.name);
691
- this.actions.useMove(move, pokemon);
692
- },
693
- toString() {
694
- return "";
695
- },
696
- };
697
- },
758
+ onModifySpecies(species, target, source, effect) {
759
+ if (!target)
760
+ return; // chat
761
+ if (effect && ['imposter', 'transform'].includes(effect.id))
762
+ return;
763
+ if (target.set.name === target.set.species)
764
+ return;
765
+ const crossSpecies = this.dex.species.get(target.set.name);
766
+ if (!crossSpecies.exists)
767
+ return;
768
+ if (species.battleOnly || !species.nfe)
769
+ return;
770
+ const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
771
+ if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo)
772
+ return;
773
+ const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
774
+ if (!crossPrevoSpecies.prevo !== !species.prevo)
775
+ return;
776
+ const mixedSpecies = this.dex.deepClone(species);
777
+ mixedSpecies.weightkg =
778
+ Math.max(0.1, +(species.weightkg + crossSpecies.weightkg - crossPrevoSpecies.weightkg)).toFixed(1);
779
+ mixedSpecies.nfe = false;
780
+ mixedSpecies.evos = [];
781
+ mixedSpecies.eggGroups = crossSpecies.eggGroups;
782
+ mixedSpecies.abilities = crossSpecies.abilities;
783
+ mixedSpecies.bst = 0;
784
+ let i;
785
+ for (i in species.baseStats) {
786
+ const statChange = crossSpecies.baseStats[i] - crossPrevoSpecies.baseStats[i];
787
+ mixedSpecies.baseStats[i] = this.clampIntRange(species.baseStats[i] + statChange, 1, 255);
788
+ mixedSpecies.bst += mixedSpecies.baseStats[i];
789
+ }
790
+ if (crossSpecies.types[0] !== crossPrevoSpecies.types[0])
791
+ mixedSpecies.types[0] = crossSpecies.types[0];
792
+ if (crossSpecies.types[1] !== crossPrevoSpecies.types[1]) {
793
+ mixedSpecies.types[1] = crossSpecies.types[1] || crossSpecies.types[0];
794
+ }
795
+ if (mixedSpecies.types[0] === mixedSpecies.types[1])
796
+ mixedSpecies.types = [mixedSpecies.types[0]];
797
+ return mixedSpecies;
698
798
  },
699
- },
700
- {
701
- name: "[Gen 8] Linked",
702
- desc: `The first two moves in a Pok&eacute;mon's moveset are used simultaneously.`,
703
- threads: [
704
- `&bullet; <a href="https://www.smogon.com/forums/threads/3660421/">Linked</a>`,
705
- ],
706
- mod: 'linked',
707
- ruleset: ['Standard', 'Dynamax Clause'],
708
- banlist: [
709
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Cloyster', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Eternatus', 'Genesect', 'Giratina',
710
- 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia', 'Lunala', 'Magearna',
711
- 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Solgaleo',
712
- 'Spectrier', 'Urshifu-Base', 'Volcarona', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom',
713
- 'Zygarde-Base', 'Zygarde-Complete', 'Arena Trap', 'Chlorophyll', 'Moody', 'Power Construct', 'Sand Rush', 'Sand Veil', 'Shadow Tag', 'Slush Rush',
714
- 'Snow Cloak', 'Speed Boost', 'Surge Surfer', 'Swift Swim', 'Unburden', 'Bright Powder', 'King\'s Rock', 'Lax Incense', 'Baton Pass',
715
- ],
716
- restricted: [
717
- 'Baneful Bunker', 'Bounce', 'Protect', 'Detect', 'Dig', 'Dive', 'Fly', 'King\'s Shield', 'Nature\'s Madness', 'Night Shade',
718
- 'Obstruct', 'Phantom Force', 'Seismic Toss', 'Shadow Force', 'Sky Drop', 'Spiky Shield', 'Super Fang', 'Trick Room',
719
- ],
720
- onValidateSet(set) {
721
- const problems = [];
722
- for (const [i, moveid] of set.moves.entries()) {
723
- const move = this.dex.moves.get(moveid);
724
- if ([0, 1].includes(i) && this.ruleTable.isRestricted(`move:${move.id}`)) {
725
- problems.push(`${set.name || set.species}'s move ${move.name} cannot be linked.`);
726
- }
799
+ onBegin() {
800
+ for (const pokemon of this.getAllPokemon()) {
801
+ pokemon.baseSpecies = pokemon.species;
727
802
  }
728
- return problems;
729
803
  },
730
804
  },
731
805
  // Other Metagames
@@ -808,12 +882,12 @@ exports.Formats = [
808
882
  mod: 'mixandmega',
809
883
  ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Overflow Stat Mod', 'Dynamax Clause', 'Sleep Clause Mod', 'Endless Battle Clause'],
810
884
  banlist: [
811
- 'Calyrex-Shadow', 'Kyogre', 'Zacian',
885
+ 'Calyrex-Shadow', 'Eternatus', 'Kyogre', 'Zacian',
812
886
  'Beedrillite', 'Blazikenite', 'Gengarite', 'Kangaskhanite', 'Mawilite', 'Medichamite', 'Pidgeotite',
813
887
  'Moody', 'Shadow Tag', 'Baton Pass', 'Electrify',
814
888
  ],
815
889
  restricted: [
816
- 'Calyrex-Ice', 'Dialga', 'Eternatus', 'Gengar', 'Giratina', 'Groudon', 'Ho-Oh', 'Kyurem-Black', 'Kyurem-White',
890
+ 'Calyrex-Ice', 'Dialga', 'Gengar', 'Giratina', 'Groudon', 'Ho-Oh', 'Kyurem-Black', 'Kyurem-White',
817
891
  'Lugia', 'Lunala', 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane',
818
892
  'Palkia', 'Pheromosa', 'Rayquaza', 'Regigigas', 'Reshiram', 'Urshifu', 'Urshifu-Rapid-Strike', 'Xerneas',
819
893
  'Yveltal', 'Zekrom', 'Zygarde-Complete',
@@ -907,9 +981,10 @@ exports.Formats = [
907
981
  mod: 'gen8',
908
982
  ruleset: ['Standard', 'Dynamax Clause', 'Sleep Moves Clause'],
909
983
  banlist: [
910
- 'Blissey', 'Calyrex-Shadow', 'Chansey', 'Dragapult', 'Hawlucha', 'Marowak-Alola', 'Melmetal', 'Pikachu', 'Toxapex',
911
- 'Xerneas', 'Zacian', 'Zacian-Crowned', 'Uber > 1', 'AG ++ Uber > 1', 'Arena Trap', 'Huge Power', 'Moody', 'Pure Power',
912
- 'Shadow Tag', 'Swift Swim', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw', 'Baton Pass',
984
+ 'Blissey', 'Calyrex-Shadow', 'Chansey', 'Dragapult', 'Eternatus', 'Hawlucha', 'Marowak-Alola', 'Melmetal', 'Pikachu',
985
+ 'Toxapex', 'Xerneas', 'Zacian', 'Zacian-Crowned', 'Uber > 1', 'AG ++ Uber > 1', 'Arena Trap', 'Huge Power', 'Moody',
986
+ 'Pure Power', 'Shadow Tag', 'Swift Swim', 'Bright Powder', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw',
987
+ 'Baton Pass',
913
988
  ],
914
989
  onValidateTeam(team) {
915
990
  const gods = new Set();
@@ -1034,9 +1109,8 @@ exports.Formats = [
1034
1109
  `&bullet; <a href="https://www.smogon.com/forums/threads/3697080/">BDSP NU</a>`,
1035
1110
  ],
1036
1111
  mod: 'gen8bdsp',
1037
- searchShow: false,
1038
1112
  ruleset: ['[Gen 8 BDSP] RU'],
1039
- banlist: ['RU', 'NUBL'],
1113
+ banlist: ['RU', 'NUBL', 'Damp Rock', 'Heat Rock'],
1040
1114
  },
1041
1115
  {
1042
1116
  name: "[Gen 8 BDSP] LC",
@@ -1045,7 +1119,7 @@ exports.Formats = [
1045
1119
  ],
1046
1120
  mod: 'gen8bdsp',
1047
1121
  ruleset: ['Little Cup', 'Standard'],
1048
- banlist: ['Gligar', 'Meditite', 'Misdreavus', 'Murkrow', 'Scyther', 'Sneasel', 'Tangela', 'Vulpix', 'Yanma', 'Moody', 'Baton Pass'],
1122
+ banlist: ['Gligar', 'Meditite', 'Misdreavus', 'Murkrow', 'Scyther', 'Sneasel', 'Tangela', 'Vulpix', 'Yanma', 'Moody', 'Baton Pass', 'Sticky Web'],
1049
1123
  },
1050
1124
  {
1051
1125
  name: "[Gen 8 BDSP] Monotype",
@@ -1120,10 +1194,10 @@ exports.Formats = [
1120
1194
  ruleset: ['Standard', 'Dynamax Clause', 'Camomons Mod'],
1121
1195
  banlist: [
1122
1196
  'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragonite', 'Eternatus', 'Genesect', 'Giratina', 'Giratina-Origin',
1123
- 'Groudon', 'Ho-Oh', 'Hydreigon', 'Kartana', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Latias', 'Latios', 'Lugia',
1124
- 'Lunala', 'Marshadow', 'Mew', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram',
1125
- 'Reuniclus', 'Shedinja', 'Slowking-Galar', 'Solgaleo', 'Spectrier', 'Tornadus-Therian', 'Volcarona', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned',
1126
- 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora', 'Zygarde-Base', 'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'Baton Pass',
1197
+ 'Groudon', 'Ho-Oh', 'Hydreigon', 'Kartana', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia', 'Lunala', 'Marshadow',
1198
+ 'Mew', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo',
1199
+ 'Spectrier', 'Tornadus-Therian', 'Volcarona', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zeraora',
1200
+ 'Zygarde-Base', 'Arena Trap', 'Moody', 'Power Construct', 'Shadow Tag', 'Baton Pass', 'Calm Mind',
1127
1201
  ],
1128
1202
  },
1129
1203
  {
@@ -1314,6 +1388,38 @@ exports.Formats = [
1314
1388
  this.add('-start', pokemon, donorTemplate.name, '[silent]');
1315
1389
  },
1316
1390
  },
1391
+ {
1392
+ name: "[Gen 8] Linked",
1393
+ desc: `The first two moves in a Pok&eacute;mon's moveset are used simultaneously.`,
1394
+ threads: [
1395
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3660421/">Linked</a>`,
1396
+ ],
1397
+ mod: 'linked',
1398
+ searchShow: false,
1399
+ ruleset: ['Standard', 'Dynamax Clause'],
1400
+ banlist: [
1401
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Cinderace', 'Cloyster', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Eternatus', 'Genesect', 'Giratina',
1402
+ 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Landorus-Base', 'Lugia', 'Lunala',
1403
+ 'Magearna', 'Marshadow', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram',
1404
+ 'Solgaleo', 'Spectrier', 'Urshifu-Base', 'Volcarona', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned',
1405
+ 'Zekrom', 'Zygarde-Base', 'Zygarde-Complete', 'Arena Trap', 'Chlorophyll', 'Moody', 'Power Construct', 'Sand Rush', 'Sand Veil', 'Shadow Tag',
1406
+ 'Slush Rush', 'Snow Cloak', 'Speed Boost', 'Surge Surfer', 'Swift Swim', 'Unburden', 'Bright Powder', 'King\'s Rock', 'Lax Incense', 'Baton Pass',
1407
+ ],
1408
+ restricted: [
1409
+ 'Baneful Bunker', 'Bounce', 'Protect', 'Detect', 'Dig', 'Dive', 'Fly', 'King\'s Shield', 'Nature\'s Madness', 'Night Shade',
1410
+ 'Obstruct', 'Phantom Force', 'Seismic Toss', 'Shadow Force', 'Sky Drop', 'Spiky Shield', 'Super Fang', 'Trick Room',
1411
+ ],
1412
+ onValidateSet(set) {
1413
+ const problems = [];
1414
+ for (const [i, moveid] of set.moves.entries()) {
1415
+ const move = this.dex.moves.get(moveid);
1416
+ if ([0, 1].includes(i) && this.ruleTable.isRestricted(`move:${move.id}`)) {
1417
+ problems.push(`${set.name || set.species}'s move ${move.name} cannot be linked.`);
1418
+ }
1419
+ }
1420
+ return problems;
1421
+ },
1422
+ },
1317
1423
  {
1318
1424
  name: "[Gen 8] Multibility",
1319
1425
  desc: `Run a second ability at the cost of giving up a Pok&eacute;mon's item slot.`,
@@ -1637,67 +1743,113 @@ exports.Formats = [
1637
1743
  },
1638
1744
  },
1639
1745
  {
1640
- name: "[Gen 8] Shared Power",
1641
- desc: `Once a Pok&eacute;mon switches in, its ability is shared with the rest of the team.`,
1746
+ name: "[Gen 8] Trademarked",
1747
+ desc: `Sacrifice your Pok&eacute;mon's ability for a status move that activates on switch-in.`,
1642
1748
  threads: [
1643
- `&bullet; <a href="https://www.smogon.com/forums/threads/3660877/">Shared Power</a>`,
1749
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3656980/">Trademarked</a>`,
1644
1750
  ],
1645
- mod: 'sharedpower',
1751
+ mod: 'gen8',
1752
+ // While bugs are being fixed
1646
1753
  searchShow: false,
1754
+ challengeShow: false,
1755
+ tournamentShow: false,
1647
1756
  ruleset: ['Standard', 'Dynamax Clause'],
1648
1757
  banlist: [
1649
- 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Eternatus', 'Genesect', 'Giratina',
1650
- 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Lugia', 'Lunala', 'Magearna',
1651
- 'Marshadow', 'Melmetal', 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia',
1652
- 'Pheromosa', 'Rayquaza', 'Reshiram', 'Shedinja', 'Solgaleo', 'Urshifu-Base', 'Urshifu-Rapid-Strike',
1653
- 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom',
1654
- 'Arena Trap', 'Contrary', 'Drizzle ++ Swift Swim', 'Drought ++ Chlorophyll', 'Electric Surge ++ Surge Surfer',
1655
- 'Fur Coat', 'Guts', 'Harvest', 'Huge Power', 'Imposter', 'Innards Out', 'Libero', 'Magic Bounce', 'Magic Guard',
1656
- 'Magnet Pull', 'Mold Breaker', 'Moody', 'Neutralizing Gas', 'Power Construct', 'Queenly Majesty', 'Quick Draw',
1657
- 'Regenerator', 'Sand Rush', 'Sand Veil', 'Shadow Tag', 'Simple', 'Snow Cloak', 'Snow Warning ++ Slush Rush', 'Speed Boost',
1658
- 'Stakeout', 'Steelworker ++ Steely Spirit', 'Tinted Lens', 'Triage', 'Unaware', 'Unburden', 'Water Bubble',
1659
- 'Baton Pass',
1758
+ 'Calyrex-Ice', 'Calyrex-Shadow', 'Darmanitan-Galar', 'Dialga', 'Dracovish', 'Dragapult', 'Eternatus', 'Kyurem-Black', 'Kyurem-White', 'Giratina',
1759
+ 'Giratina-Origin', 'Genesect', 'Groudon', 'Ho-Oh', 'Kartana', 'Kyogre', 'Lugia', 'Lunala', 'Magearna', 'Marowak-Alola', 'Marshadow', 'Melmetal',
1760
+ 'Mewtwo', 'Naganadel', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Pheromosa', 'Rayquaza', 'Reshiram', 'Solgaleo', 'Spectrier',
1761
+ 'Urshifu-Base', 'Victini', 'Xerneas', 'Yveltal', 'Zacian', 'Zacian-Crowned', 'Zamazenta', 'Zamazenta-Crowned', 'Zekrom', 'Zygarde-Base',
1762
+ 'Arena Trap', 'Moody', 'Neutralizing Gas', 'Power Construct', 'Shadow Tag', 'Baton Pass',
1660
1763
  ],
1661
- getSharedPower(pokemon) {
1662
- const sharedPower = new Set();
1663
- for (const ally of pokemon.side.pokemon) {
1664
- if (ally.previouslySwitchedIn > 0) {
1665
- if (pokemon.battle.dex.currentMod !== 'sharedpower' && ['trace', 'mirrorarmor'].includes(ally.baseAbility)) {
1666
- sharedPower.add('noability');
1667
- continue;
1668
- }
1669
- sharedPower.add(ally.baseAbility);
1764
+ restricted: [
1765
+ 'Baneful Bunker', 'Block', 'Copycat', 'Corrosive Gas', 'Detect', 'Destiny Bond', 'Disable', 'Encore', 'Fairy Lock', 'Hypnosis', 'Ingrain',
1766
+ 'Instruct', 'Lovely Kiss', 'King\'s Shield', 'Mat Block', 'Mean Look', 'Memento', 'move:Metronome', 'Obstruct', 'Octolock', 'Nature Power',
1767
+ 'Parting Shot', 'Psycho Shift', 'Protect', 'Roar', 'Sing', 'Skill Swap', 'Sleep Powder', 'Sleep Talk', 'Spiky Shield', 'Spore', 'Substitute',
1768
+ 'Switcheroo', 'Teleport', 'Trick', 'Whirlwind', 'Wish', 'Yawn',
1769
+ ],
1770
+ onValidateTeam(team, format, teamHas) {
1771
+ const problems = [];
1772
+ for (const trademark in teamHas.trademarks) {
1773
+ if (teamHas.trademarks[trademark] > 1) {
1774
+ problems.push(`You are limited to 1 of each Trademark.`, `(You have ${teamHas.trademarks[trademark]} Pok\u00e9mon with ${trademark} as a Trademark.)`);
1670
1775
  }
1671
1776
  }
1672
- sharedPower.delete(pokemon.baseAbility);
1673
- return sharedPower;
1777
+ return problems;
1674
1778
  },
1675
- onBeforeSwitchIn(pokemon) {
1676
- let format = this.format;
1677
- if (!format.getSharedPower)
1678
- format = this.dex.formats.get('gen8sharedpower');
1679
- for (const ability of format.getSharedPower(pokemon)) {
1680
- const effect = 'ability:' + ability;
1681
- pokemon.volatiles[effect] = { id: this.toID(effect), target: pokemon };
1682
- if (!pokemon.m.abils)
1683
- pokemon.m.abils = [];
1684
- if (!pokemon.m.abils.includes(effect))
1685
- pokemon.m.abils.push(effect);
1779
+ validateSet(set, teamHas) {
1780
+ const dex = this.dex;
1781
+ const ability = dex.moves.get(set.ability);
1782
+ if (!ability.exists) { // Not even a real move
1783
+ return this.validateSet(set, teamHas);
1686
1784
  }
1687
- },
1688
- onSwitchInPriority: 2,
1689
- onSwitchIn(pokemon) {
1690
- let format = this.format;
1691
- if (!format.getSharedPower)
1692
- format = this.dex.formats.get('gen8sharedpower');
1693
- for (const ability of format.getSharedPower(pokemon)) {
1694
- if (ability === 'noability') {
1695
- this.hint(`Mirror Armor and Trace break in Shared Power formats that don't use Shared Power as a base, so they get removed from non-base users.`);
1785
+ // Absolute trademark bans
1786
+ if (ability.category !== 'Status') {
1787
+ return [`${ability.name} is not a status move, and cannot be used as a trademark.`];
1788
+ }
1789
+ if (ability.forceSwitch || ability.selfSwitch) {
1790
+ return [
1791
+ `Force-switching and self-switching moves are banned from being used as trademarks.`,
1792
+ `(${ability.name} is a ${ability.forceSwitch ? 'force' : 'self'}-switching move.)`,
1793
+ ];
1794
+ }
1795
+ const irrevokablyRestricted = [
1796
+ 'Assist', 'Copycat', 'Metronome', 'Mirror Move', 'Sleep Talk',
1797
+ 'Recycle', 'Trace',
1798
+ 'Skill Swap', // Self-propagates indefinitely
1799
+ ];
1800
+ for (const m of set.moves) {
1801
+ const move = dex.moves.get(m);
1802
+ if (irrevokablyRestricted.includes(move.name)) {
1803
+ return [`${move.name} is banned from Trademark, irrespective of custom rules, because it can cause endless turns.`];
1696
1804
  }
1697
- const effect = 'ability:' + ability;
1698
- delete pokemon.volatiles[effect];
1699
- pokemon.addVolatile(effect);
1700
1805
  }
1806
+ if (irrevokablyRestricted.includes(ability.name)) {
1807
+ return [`${ability.name} cannot safely function as a trademark.`];
1808
+ }
1809
+ // Contingent trademark bans
1810
+ if (this.ruleTable.isRestricted(`move:${ability.id}`)) {
1811
+ return [`${ability.name} is restricted from being used as a trademark.`];
1812
+ }
1813
+ if (set.moves.map(this.toID).includes(ability.id)) {
1814
+ return [`${set.name} may not use ${ability.name} as both a trademark and one of its moves simultaneously.`];
1815
+ }
1816
+ const customRules = this.format.customRules || [];
1817
+ if (!customRules.includes('!obtainableabilities'))
1818
+ customRules.push('!obtainableabilities');
1819
+ const TeamValidator = require('../sim/team-validator').TeamValidator;
1820
+ const validator = new TeamValidator(dex.formats.get(`${this.format.id}@@@${customRules.join(',')}`));
1821
+ const moves = set.moves;
1822
+ set.moves = [ability.id];
1823
+ set.ability = dex.species.get(set.species).abilities['0'];
1824
+ let problems = validator.validateSet(set, {}) || [];
1825
+ if (problems.length)
1826
+ return problems;
1827
+ set.moves = moves;
1828
+ set.ability = dex.species.get(set.species).abilities['0'];
1829
+ problems = problems.concat(validator.validateSet(set, teamHas) || []);
1830
+ set.ability = ability.id;
1831
+ if (!teamHas.trademarks)
1832
+ teamHas.trademarks = {};
1833
+ teamHas.trademarks[ability.name] = (teamHas.trademarks[ability.name] || 0) + 1;
1834
+ return problems.length ? problems : null;
1835
+ },
1836
+ pokemon: {
1837
+ getAbility() {
1838
+ const move = this.battle.dex.moves.get(this.battle.toID(this.ability));
1839
+ if (!move.exists)
1840
+ return Object.getPrototypeOf(this).getAbility.call(this);
1841
+ return {
1842
+ id: move.id,
1843
+ name: move.name,
1844
+ onStart(pokemon) {
1845
+ this.add('-activate', pokemon, 'ability: ' + move.name);
1846
+ this.actions.useMove(move, pokemon);
1847
+ },
1848
+ toString() {
1849
+ return "";
1850
+ },
1851
+ };
1852
+ },
1701
1853
  },
1702
1854
  },
1703
1855
  {
@@ -1846,7 +1998,6 @@ exports.Formats = [
1846
1998
  desc: `[Gen 8] Random Battle (No Dmax) with Team Preview and elements of Camomons, Inverse, Scalemons, and Shared Power.`,
1847
1999
  mod: 'sharedpower',
1848
2000
  team: 'random',
1849
- searchShow: false,
1850
2001
  ruleset: ['[Gen 8] Random Battle', 'Team Preview', 'Dynamax Clause', 'Camomons Mod', 'Inverse Mod', 'Scalemons Mod'],
1851
2002
  onBeforeSwitchIn(pokemon) {
1852
2003
  let format = this.format;
@@ -2132,36 +2283,42 @@ exports.Formats = [
2132
2283
  column: 3,
2133
2284
  },
2134
2285
  {
2135
- name: "[Gen 3] UU",
2286
+ name: "[Gen 4] UU",
2136
2287
  threads: [
2137
- `&bullet; <a href="https://www.smogon.com/forums/threads/3585923/">ADV UU Metagame Discussion</a>`,
2138
- `&bullet; <a href="https://www.smogon.com/forums/threads/3548578/">ADV UU Viability Rankings</a>`,
2288
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3532624/">DPP UU Metagame Discussion</a>`,
2289
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3503638/">DPP UU Viability Rankings</a>`,
2139
2290
  ],
2140
- mod: 'gen3',
2291
+ mod: 'gen4',
2141
2292
  // searchShow: false,
2142
- ruleset: ['Standard', 'NFE Clause'],
2143
- banlist: ['Uber', 'OU', 'UUBL', 'Smeargle + Ingrain', 'Baton Pass'],
2144
- unbanlist: ['Scyther', 'Sand Veil'],
2293
+ ruleset: ['[Gen 4] OU'],
2294
+ banlist: ['OU', 'UUBL'],
2295
+ unbanlist: ['Arena Trap', 'Swagger'],
2145
2296
  },
2146
2297
  {
2147
- name: "[Gen 1] NU",
2298
+ name: "[Gen 7] LC",
2148
2299
  threads: [
2149
- `&bullet; <a href="https://www.smogon.com/forums/threads/3668913/">RBY NU Viability Rankings</a>`,
2300
+ `&bullet; <a href="https://www.smogon.com/dex/sm/formats/lc/">USM LC Banlist</a>`,
2301
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3639319/">USM LC Sample Teams</a>`,
2302
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3621440/">USM LC Viability Rankings</a>`,
2150
2303
  ],
2151
- mod: 'gen1',
2304
+ mod: 'gen7',
2152
2305
  // searchShow: false,
2153
- ruleset: ['[Gen 1] UU'],
2154
- banlist: ['UU', 'NUBL'],
2306
+ ruleset: ['Little Cup', 'Standard', 'Swagger Clause'],
2307
+ banlist: [
2308
+ 'Aipom', 'Cutiefly', 'Drifloon', 'Gligar', 'Gothita', 'Meditite', 'Misdreavus', 'Murkrow', 'Porygon',
2309
+ 'Scyther', 'Sneasel', 'Swirlix', 'Tangela', 'Trapinch', 'Vulpix-Base', 'Wingull', 'Yanma',
2310
+ 'Eevium Z', 'Baton Pass', 'Dragon Rage', 'Sonic Boom', 'Sticky Web',
2311
+ ],
2155
2312
  },
2156
2313
  {
2157
- name: "[Gen 4] Ubers",
2314
+ name: "[Gen 5] PU",
2158
2315
  threads: [
2159
- `&bullet; <a href="https://www.smogon.com/forums/posts/8286279/">DPP Ubers</a>`,
2316
+ `&bullet; <a href="https://www.smogon.com/forums/posts/7326932/">BW2 PU</a>`,
2160
2317
  ],
2161
- mod: 'gen4',
2318
+ mod: 'gen5',
2162
2319
  // searchShow: false,
2163
- ruleset: ['Standard'],
2164
- banlist: ['AG'],
2320
+ ruleset: ['[Gen 5] NU', 'Sleep Moves Clause'],
2321
+ banlist: ['NU', 'PUBL'],
2165
2322
  },
2166
2323
  // Past Gens OU
2167
2324
  ///////////////////////////////////////////////////////////////////
@@ -2434,22 +2591,6 @@ exports.Formats = [
2434
2591
  ruleset: ['[Gen 7] NU'],
2435
2592
  banlist: ['NU', 'PUBL'],
2436
2593
  },
2437
- {
2438
- name: "[Gen 7] LC",
2439
- threads: [
2440
- `&bullet; <a href="https://www.smogon.com/dex/sm/formats/lc/">USM LC Banlist</a>`,
2441
- `&bullet; <a href="https://www.smogon.com/forums/threads/3639319/">USM LC Sample Teams</a>`,
2442
- `&bullet; <a href="https://www.smogon.com/forums/threads/3621440/">USM LC Viability Rankings</a>`,
2443
- ],
2444
- mod: 'gen7',
2445
- searchShow: false,
2446
- ruleset: ['Little Cup', 'Standard', 'Swagger Clause'],
2447
- banlist: [
2448
- 'Aipom', 'Cutiefly', 'Drifloon', 'Gligar', 'Gothita', 'Meditite', 'Misdreavus', 'Murkrow', 'Porygon',
2449
- 'Scyther', 'Sneasel', 'Swirlix', 'Tangela', 'Trapinch', 'Vulpix-Base', 'Wingull', 'Yanma',
2450
- 'Eevium Z', 'Baton Pass', 'Dragon Rage', 'Sonic Boom', 'Sticky Web',
2451
- ],
2452
- },
2453
2594
  {
2454
2595
  name: "[Gen 7] Monotype",
2455
2596
  desc: `All the Pok&eacute;mon on a team must share a type.`,
@@ -2766,14 +2907,15 @@ exports.Formats = [
2766
2907
  mod: 'gen6',
2767
2908
  searchShow: false,
2768
2909
  ruleset: [
2769
- 'Max Team Size = 3', 'Picked Team Size = 1',
2770
- 'Obtainable', 'Nickname Clause', 'Moody Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Accuracy Moves Clause', 'Swagger Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview',
2910
+ 'Max Team Size = 3', 'Picked Team Size = 1', 'Obtainable', 'Nickname Clause', 'Moody Clause', 'OHKO Clause',
2911
+ 'Evasion Moves Clause', 'Accuracy Moves Clause', 'Swagger Clause', 'Endless Battle Clause', 'HP Percentage Mod',
2912
+ 'Cancel Mod', 'Team Preview',
2771
2913
  ],
2772
2914
  banlist: [
2773
2915
  'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Deoxys-Defense', 'Dialga', 'Giratina',
2774
2916
  'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-White', 'Lugia', 'Mewtwo',
2775
2917
  'Palkia', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky', 'Xerneas', 'Yveltal', 'Zekrom',
2776
- 'Focus Sash', 'Soul Dew', 'Perish Song',
2918
+ 'Focus Sash', 'Soul Dew', 'Grass Whistle', 'Hypnosis', 'Perish Song', 'Sing', 'Yawn',
2777
2919
  ],
2778
2920
  },
2779
2921
  {
@@ -2966,16 +3108,6 @@ exports.Formats = [
2966
3108
  ruleset: ['[Gen 5] RU', '!Sleep Moves Clause', 'Sleep Clause Mod'],
2967
3109
  banlist: ['RU', 'NUBL', 'Assist', 'Copycat'],
2968
3110
  },
2969
- {
2970
- name: "[Gen 5] PU",
2971
- threads: [
2972
- `&bullet; <a href="https://www.smogon.com/forums/posts/7326932/">BW2 PU</a>`,
2973
- ],
2974
- mod: 'gen5',
2975
- searchShow: false,
2976
- ruleset: ['[Gen 5] NU', 'Sleep Moves Clause'],
2977
- banlist: ['NU', 'PUBL'],
2978
- },
2979
3111
  {
2980
3112
  name: "[Gen 5] LC",
2981
3113
  threads: [
@@ -3012,7 +3144,7 @@ exports.Formats = [
3012
3144
  'Picked Team Size = 1', 'Max Team Size = 3',
3013
3145
  'Standard', 'Baton Pass Clause', 'Swagger Clause', 'Accuracy Moves Clause',
3014
3146
  ],
3015
- banlist: ['Uber', 'Cottonee', 'Dragonite', 'Kyurem-Black', 'Mew', 'Togekiss', 'Whimsicott', 'Victini', 'Bright Powder', 'Focus Band', 'Focus Sash', 'Lax Incense', 'Quick Claw', 'Soul Dew', 'Perish Song'],
3147
+ banlist: ['Uber', 'Cottonee', 'Dragonite', 'Jirachi', 'Kyurem-Black', 'Mew', 'Togekiss', 'Whimsicott', 'Victini', 'Bright Powder', 'Focus Band', 'Focus Sash', 'Lax Incense', 'Quick Claw', 'Soul Dew', 'Perish Song'],
3016
3148
  unbanlist: ['Genesect', 'Landorus', 'Manaphy', 'Thundurus', 'Tornadus-Therian'],
3017
3149
  },
3018
3150
  {
@@ -3101,16 +3233,14 @@ exports.Formats = [
3101
3233
  column: 5,
3102
3234
  },
3103
3235
  {
3104
- name: "[Gen 4] UU",
3236
+ name: "[Gen 4] Ubers",
3105
3237
  threads: [
3106
- `&bullet; <a href="https://www.smogon.com/forums/threads/3532624/">DPP UU Metagame Discussion</a>`,
3107
- `&bullet; <a href="https://www.smogon.com/forums/threads/3503638/">DPP UU Viability Rankings</a>`,
3238
+ `&bullet; <a href="https://www.smogon.com/forums/posts/8286279/">DPP Ubers</a>`,
3108
3239
  ],
3109
3240
  mod: 'gen4',
3110
3241
  searchShow: false,
3111
- ruleset: ['[Gen 4] OU'],
3112
- banlist: ['OU', 'UUBL'],
3113
- unbanlist: ['Arena Trap', 'Swagger'],
3242
+ ruleset: ['Standard'],
3243
+ banlist: ['AG'],
3114
3244
  },
3115
3245
  {
3116
3246
  name: "[Gen 4] NU",
@@ -3243,6 +3373,18 @@ exports.Formats = [
3243
3373
  ruleset: ['Standard', 'Deoxys Camouflage Clause', 'One Baton Pass Clause'],
3244
3374
  banlist: ['Wobbuffet + Leftovers'],
3245
3375
  },
3376
+ {
3377
+ name: "[Gen 3] UU",
3378
+ threads: [
3379
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3585923/">ADV UU Metagame Discussion</a>`,
3380
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3548578/">ADV UU Viability Rankings</a>`,
3381
+ ],
3382
+ mod: 'gen3',
3383
+ searchShow: false,
3384
+ ruleset: ['Standard', 'NFE Clause'],
3385
+ banlist: ['Uber', 'OU', 'UUBL', 'Smeargle + Ingrain', 'Baton Pass'],
3386
+ unbanlist: ['Scyther', 'Sand Veil'],
3387
+ },
3246
3388
  {
3247
3389
  name: "[Gen 3] NU",
3248
3390
  threads: [
@@ -3388,6 +3530,16 @@ exports.Formats = [
3388
3530
  ruleset: ['[Gen 1] OU'],
3389
3531
  banlist: ['OU', 'UUBL'],
3390
3532
  },
3533
+ {
3534
+ name: "[Gen 1] NU",
3535
+ threads: [
3536
+ `&bullet; <a href="https://www.smogon.com/forums/threads/3668913/">RBY NU Viability Rankings</a>`,
3537
+ ],
3538
+ mod: 'gen1',
3539
+ searchShow: false,
3540
+ ruleset: ['[Gen 1] UU'],
3541
+ banlist: ['UU', 'NUBL'],
3542
+ },
3391
3543
  {
3392
3544
  name: "[Gen 1] Japanese OU",
3393
3545
  desc: `Generation 1 with Japanese battle mechanics.`,