@pkmn/sim 0.5.16 → 0.5.17

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 (72) hide show
  1. package/build/config/formats.js +32 -51
  2. package/build/config/formats.js.map +1 -1
  3. package/build/data/items.js +1 -3
  4. package/build/data/items.js.map +1 -1
  5. package/build/data/learnsets.js +2 -2
  6. package/build/data/learnsets.js.map +1 -1
  7. package/build/data/mods/gen1/formats-data.js +1 -1
  8. package/build/data/mods/gen1/formats-data.js.map +1 -1
  9. package/build/data/mods/gen1/moves.js +1 -4
  10. package/build/data/mods/gen1/moves.js.map +1 -1
  11. package/build/data/mods/gen3/moves.js +0 -7
  12. package/build/data/mods/gen3/moves.js.map +1 -1
  13. package/build/data/mods/gen3/scripts.js +2 -2
  14. package/build/data/mods/gen3/scripts.js.map +1 -1
  15. package/build/data/mods/gen4/moves.js +1 -1
  16. package/build/data/mods/gen4/moves.js.map +1 -1
  17. package/build/data/mods/gen4/rulesets.js +2 -1
  18. package/build/data/mods/gen4/rulesets.js.map +1 -1
  19. package/build/data/mods/gen5/rulesets.js +2 -1
  20. package/build/data/mods/gen5/rulesets.js.map +1 -1
  21. package/build/data/mods/gen7/formats-data.js +4 -4
  22. package/build/data/mods/gen7/formats-data.js.map +1 -1
  23. package/build/data/mods/gen7/rulesets.js +2 -1
  24. package/build/data/mods/gen7/rulesets.js.map +1 -1
  25. package/build/data/moves.js +55 -74
  26. package/build/data/moves.js.map +1 -1
  27. package/build/data/pokedex.js +2 -2
  28. package/build/data/pokedex.js.map +1 -1
  29. package/build/data/rulesets.js +3 -4
  30. package/build/data/rulesets.js.map +1 -1
  31. package/build/data/text/items.js +1 -0
  32. package/build/data/text/items.js.map +1 -1
  33. package/build/data/text/moves.js +5 -3
  34. package/build/data/text/moves.js.map +1 -1
  35. package/build/sim/battle-actions.js +9 -1
  36. package/build/sim/battle-actions.js.map +1 -1
  37. package/build/sim/battle.js +39 -1
  38. package/build/sim/battle.js.map +1 -1
  39. package/build/sim/dex-conditions.d.ts +1 -0
  40. package/build/sim/dex-conditions.js.map +1 -1
  41. package/build/sim/exported-global-types.d.ts +1 -0
  42. package/build/sim/global-types.d.ts +1 -0
  43. package/build/sim/team-validator.js +15 -4
  44. package/build/sim/team-validator.js.map +1 -1
  45. package/build/sim/tools/exhaustive-runner.d.ts +8 -0
  46. package/build/sim/tools/exhaustive-runner.js +18 -7
  47. package/build/sim/tools/exhaustive-runner.js.map +1 -1
  48. package/config/formats.ts +32 -51
  49. package/data/items.ts +1 -3
  50. package/data/learnsets.ts +2 -2
  51. package/data/mods/gen1/formats-data.ts +1 -1
  52. package/data/mods/gen1/moves.ts +1 -4
  53. package/data/mods/gen3/moves.ts +0 -7
  54. package/data/mods/gen3/scripts.ts +3 -3
  55. package/data/mods/gen4/moves.ts +1 -1
  56. package/data/mods/gen4/rulesets.ts +2 -1
  57. package/data/mods/gen5/rulesets.ts +2 -1
  58. package/data/mods/gen7/formats-data.ts +4 -4
  59. package/data/mods/gen7/rulesets.ts +2 -1
  60. package/data/moves.ts +55 -65
  61. package/data/pokedex.ts +2 -2
  62. package/data/rulesets.ts +3 -6
  63. package/data/text/items.ts +2 -0
  64. package/data/text/moves.ts +6 -3
  65. package/package.json +1 -1
  66. package/sim/battle-actions.ts +13 -1
  67. package/sim/battle.ts +38 -1
  68. package/sim/dex-conditions.ts +1 -0
  69. package/sim/exported-global-types.ts +3 -0
  70. package/sim/global-types.ts +3 -0
  71. package/sim/team-validator.ts +16 -4
  72. package/sim/tools/exhaustive-runner.ts +29 -11
package/config/formats.ts CHANGED
@@ -254,7 +254,7 @@ export const Formats: FormatList = [
254
254
  'Larvesta', 'Magby', 'Magnemite', 'Mareanie', 'Mienfoo', 'Mudbray', 'Munchlax', 'Natu', 'Onix', 'Pawniard',
255
255
  'Ponyta', 'Ponyta-Galar', 'Porygon', 'Slowpoke-Base', 'Staryu', 'Timburr', 'Trapinch', 'Tyrunt',
256
256
  // LC UUBL
257
- 'Farfetch\u2019d-Galar', 'Scorbunny', 'Shellder', 'Wingull',
257
+ 'Archen', 'Farfetch\u2019d-Galar', 'Scorbunny', 'Shellder', 'Wingull',
258
258
  ],
259
259
  },
260
260
  {
@@ -359,7 +359,7 @@ export const Formats: FormatList = [
359
359
  gameType: 'doubles',
360
360
  searchShow: false,
361
361
  ruleset: ['Standard Doubles', 'Little Cup', 'Dynamax Clause', 'Swagger Clause', 'Sleep Clause Mod'],
362
- banlist: ['Corsola-Galar', 'Cutiefly', 'Ponyta-Base', 'Scyther', 'Sneasel', 'Swirlix', 'Tangela', 'Vulpix', 'Vulpix-Alola', 'Ally Switch'],
362
+ banlist: ['Corsola-Galar', 'Cutiefly', 'Ponyta-Base', 'Scyther', 'Sneasel', 'Swirlix', 'Tangela', 'Vulpix-Base', 'Ally Switch'],
363
363
  },
364
364
  {
365
365
  name: "[Gen 8] VGC 2022",
@@ -644,17 +644,18 @@ export const Formats: FormatList = [
644
644
  mod: 'pokebilities',
645
645
  ruleset: ['[Gen 8] Pokebilities', '!Obtainable Abilities', 'AAA Restricted Abilities', '2 Ability Clause', 'Sleep Moves Clause', '!Sleep Clause Mod'],
646
646
  banlist: [
647
- 'Blacephalon', 'Buzzwole', 'Clefable', 'Dragapult', 'Dragonite', 'Kartana', 'Keldeo', 'Kyurem', 'Melmetal', 'Mienshao',
648
- 'Obstagoon', 'Noivern', 'Pangoro', 'Perrserker', 'Rillaboom', 'Tapu Bulu', 'Tapu Lele', 'Urshifu', 'Urshifu-Rapid-Strike',
649
- 'Victini', 'Weavile', 'Zamazenta-Crowned', 'Arena Trap', 'Moody', 'Shadow Tag', 'Wonder Guard', 'Chlorophyll + Desolate Land',
650
- 'Chlorophyll + Drought', 'Electric Surge + Surge Surfer', 'Regenerator + Emergency Exit', 'Regenerator + Multiscale',
651
- 'Regenerator + Shadow Shield', 'Regenerator + Wimp Out', 'Sand Rush + Sand Stream', 'Slush Rush + Snow Warning', 'Swift Swim + Drizzle',
652
- 'Swift Swim + Primordial Sea', 'Regenerator > 2',
647
+ 'Alakazam', 'Blacephalon', 'Buzzwole', 'Clefable', 'Dragapult', 'Dragonite', 'Gengar', 'Kartana', 'Keldeo', 'Kyurem', 'Melmetal', 'Mienshao',
648
+ 'Noivern', 'Obstagoon', 'Perrserker', 'Rillaboom', 'Tapu Lele', 'Urshifu', 'Urshifu-Rapid-Strike', 'Victini', 'Weavile', 'Zamazenta-Crowned',
649
+ 'Zapdos-Galar', 'Arena Trap', 'Moody', 'Shadow Tag', 'Wonder Guard', 'Chlorophyll + Desolate Land', 'Chlorophyll + Drought', 'Electric Surge + Surge Surfer',
650
+ 'Regenerator + Emergency Exit', 'Regenerator + Multiscale', 'Regenerator + Shadow Shield', 'Regenerator + Wimp Out', 'Sand Rush + Sand Stream',
651
+ 'Slush Rush + Snow Warning', 'Swift Swim + Drizzle', 'Swift Swim + Primordial Sea', 'Snow Cloak + Snow Warning', 'Sand Veil + Sand Stream',
652
+ 'Regenerator > 2', 'Bright Powder', 'Lax Incense', 'Quick Claw',
653
653
  ],
654
654
  restricted: [
655
655
  'Comatose', 'Contrary', 'Fluffy', 'Fur Coat', 'Gorilla Tactics', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out',
656
- 'Intrepid Sword', 'Libero', 'Magnet Pull', 'Neutralizing Gas', 'Parental Bond', 'Poison Heal', 'Prankster', 'Protean',
657
- 'Pure Power', 'Simple', 'Stakeout', 'Stench', 'Speed Boost', 'Tinted Lens', 'Unburden', 'Water Bubble',
656
+ 'Intrepid Sword', 'Libero', 'Magnet Pull', 'Neutralizing Gas', 'Parental Bond', 'Poison Heal', 'Prankster', 'Protean', 'Pure Power',
657
+ 'Quick Draw', 'Sand Veil', 'Serene Grace', 'Simple', 'Snow Cloak', 'Speed Boost', 'Stakeout', 'Stench', 'Tinted Lens', 'Triage',
658
+ 'Unburden', 'Water Bubble',
658
659
  ],
659
660
  },
660
661
 
@@ -682,25 +683,6 @@ export const Formats: FormatList = [
682
683
  'Water Bubble', 'Wonder Guard', 'Comatose + Sleep Talk', 'Rusted Sword', 'Court Change', 'Bolt Beak', 'Double Iron Bash',
683
684
  'Octolock', 'Shell Smash',
684
685
  ],
685
- onChangeSet(set) {
686
- const item = this.dex.toID(set.item);
687
- if (set.species === 'Zacian' && item === 'rustedsword') {
688
- set.species = 'Zacian-Crowned';
689
- set.ability = 'Intrepid Sword';
690
- const ironHead = set.moves.indexOf('ironhead');
691
- if (ironHead >= 0) {
692
- set.moves[ironHead] = 'behemothblade';
693
- }
694
- }
695
- if (set.species === 'Zamazenta' && item === 'rustedshield') {
696
- set.species = 'Zamazenta-Crowned';
697
- set.ability = 'Dauntless Shield';
698
- const ironHead = set.moves.indexOf('ironhead');
699
- if (ironHead >= 0) {
700
- set.moves[ironHead] = 'behemothbash';
701
- }
702
- }
703
- },
704
686
  },
705
687
  {
706
688
  name: "[Gen 8] Almost Any Ability",
@@ -722,15 +704,6 @@ export const Formats: FormatList = [
722
704
  'Innards Out', 'Intrepid Sword', 'Libero', 'Magnet Pull', 'Moody', 'Neutralizing Gas', 'Parental Bond', 'Poison Heal', 'Protean',
723
705
  'Pure Power', 'Shadow Tag', 'Simple', 'Stakeout', 'Speed Boost', 'Water Bubble', 'Wonder Guard', 'King\'s Rock', 'Baton Pass',
724
706
  ],
725
- onValidateSet(set) {
726
- // Temporary fix until battle-only is implemented properly
727
- if (this.toID(set.species) === 'zamazentacrowned' && this.toID(set.ability) !== 'dauntlessshield') {
728
- return [`Zamazenta-Crowned can only use Dauntless Shield because it is a battle-only forme.`];
729
- }
730
- if (this.toID(set.species) === 'zaciancrowned' && this.toID(set.ability) !== 'intrepidsword') {
731
- return [`Zacian-Crowned can only use Intrepid Sword because it is a battle-only forme.`];
732
- }
733
- },
734
707
  },
735
708
  {
736
709
  name: "[Gen 8] Mix and Mega",
@@ -901,9 +874,6 @@ export const Formats: FormatList = [
901
874
  const stat = Dex.stats.ids()[target.side.team.indexOf(target.set)];
902
875
  const newSpecies = this.dex.deepClone(species);
903
876
  let godSpecies = this.dex.species.get(god.species);
904
- if (godSpecies.forme === 'Crowned') {
905
- godSpecies = this.dex.species.get(godSpecies.changesFrom || godSpecies.baseSpecies);
906
- }
907
877
  if (typeof godSpecies.battleOnly === 'string') {
908
878
  godSpecies = this.dex.species.get(godSpecies.battleOnly);
909
879
  }
@@ -1757,6 +1727,17 @@ export const Formats: FormatList = [
1757
1727
  }
1758
1728
  }
1759
1729
  },
1730
+ onSwitchOut(pokemon) {
1731
+ for (const innate of Object.keys(pokemon.volatiles).filter(i => i.startsWith('ability:'))) {
1732
+ pokemon.removeVolatile(innate);
1733
+ }
1734
+ },
1735
+ onFaint(pokemon) {
1736
+ for (const innate of Object.keys(pokemon.volatiles).filter(i => i.startsWith('ability:'))) {
1737
+ const innateEffect = this.dex.conditions.get(innate) as Effect;
1738
+ this.singleEvent('End', innateEffect, null, pokemon);
1739
+ }
1740
+ },
1760
1741
  onAfterMega(pokemon) {
1761
1742
  for (const innate of Object.keys(pokemon.volatiles).filter(i => i.startsWith('ability:'))) {
1762
1743
  pokemon.removeVolatile(innate);
@@ -2496,7 +2477,7 @@ export const Formats: FormatList = [
2496
2477
 
2497
2478
  mod: 'gen3',
2498
2479
  ruleset: ['Standard', 'One Boost Passer Clause'],
2499
- banlist: ['Uber', 'Sand Veil', 'Soundproof', 'Assist', 'Baton Pass + Mean Look', 'Baton Pass + Spider Web', 'Smeargle + Ingrain'],
2480
+ banlist: ['Uber', 'Sand Veil', 'Soundproof', 'Assist', 'Baton Pass + Block', 'Baton Pass + Mean Look', 'Baton Pass + Spider Web', 'Smeargle + Ingrain'],
2500
2481
  },
2501
2482
  {
2502
2483
  name: "[Gen 2] OU",
@@ -3030,8 +3011,8 @@ export const Formats: FormatList = [
3030
3011
  searchShow: false,
3031
3012
  ruleset: ['Standard', 'Swagger Clause', 'Same Type Clause'],
3032
3013
  banlist: [
3033
- 'Aegislash', 'Altaria-Mega', 'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Dialga', 'Genesect', 'Gengar-Mega',
3034
- 'Giratina', 'Giratina-Origin', 'Greninja', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-White',
3014
+ 'Aegislash', 'Altaria-Mega', 'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Deoxys-Speed', 'Dialga', 'Genesect',
3015
+ 'Gengar-Mega', 'Giratina', 'Giratina-Origin', 'Greninja', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-White',
3035
3016
  'Lucario-Mega', 'Lugia', 'Mawile-Mega', 'Medicham-Mega', 'Metagross-Mega', 'Mewtwo', 'Palkia', 'Rayquaza', 'Reshiram', 'Sableye-Mega',
3036
3017
  'Salamence-Mega', 'Shaymin-Sky', 'Slowbro-Mega', 'Talonflame', 'Xerneas', 'Yveltal', 'Zekrom',
3037
3018
  'Shadow Tag', 'Bright Powder', 'Damp Rock', 'Focus Band', 'King\'s Rock', 'Lax Incense', 'Quick Claw', 'Razor Fang', 'Smooth Rock',
@@ -3055,8 +3036,8 @@ export const Formats: FormatList = [
3055
3036
  banlist: [
3056
3037
  'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Deoxys-Defense', 'Dialga', 'Giratina',
3057
3038
  'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-White', 'Lugia', 'Mewtwo',
3058
- 'Palkia', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky', 'Xerneas', 'Yveltal', 'Zekrom',
3059
- 'Focus Sash', 'Soul Dew', 'Grass Whistle', 'Hypnosis', 'Perish Song', 'Sing', 'Yawn',
3039
+ 'Palkia', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky', 'Snorlax', 'Xerneas', 'Yveltal',
3040
+ 'Zekrom', 'Focus Sash', 'Soul Dew', 'Grass Whistle', 'Hypnosis', 'Perish Song', 'Sing', 'Yawn',
3060
3041
  ],
3061
3042
  },
3062
3043
  {
@@ -3537,11 +3518,11 @@ export const Formats: FormatList = [
3537
3518
  searchShow: false,
3538
3519
  ruleset: ['[Gen 4] PU'],
3539
3520
  banlist: [
3540
- 'Ampharos', 'Armaldo', 'Bellossom', 'Dragonair', 'Gabite', 'Gastrodon', 'Glaceon', 'Glalie', 'Golduck',
3541
- 'Gorebyss', 'Hippopotas', 'Kadabra', 'Machoke', 'Magmar', 'Mantine', 'Marowak', 'Metang', 'Misdreavus',
3542
- 'Monferno', 'Mr. Mime', 'Muk', 'Murkrow', 'Pinsir', 'Politoed', 'Purugly', 'Quagsire', 'Raichu',
3543
- 'Rampardos', 'Rapidash', 'Regigigas', 'Relicanth', 'Rhydon', 'Scyther', 'Sneasel', 'Snover', 'Solrock',
3544
- 'Tangela', 'Torkoal', 'Victreebel', 'Xatu', 'Zangoose', 'Damp Rock',
3521
+ 'Ampharos', 'Armaldo', 'Bellossom', 'Dragonair', 'Electabuzz', 'Gabite', 'Gastrodon', 'Glaceon', 'Glalie',
3522
+ 'Golduck', 'Gorebyss', 'Hippopotas', 'Kadabra', 'Machoke', 'Magmar', 'Mantine', 'Marowak', 'Metang',
3523
+ 'Misdreavus', 'Monferno', 'Mr. Mime', 'Muk', 'Murkrow', 'Pinsir', 'Politoed', 'Purugly', 'Quagsire',
3524
+ 'Raichu', 'Rampardos', 'Rapidash', 'Regigigas', 'Relicanth', 'Rhydon', 'Scyther', 'Sneasel', 'Snover',
3525
+ 'Solrock', 'Tangela', 'Torkoal', 'Victreebel', 'Xatu', 'Zangoose', 'Damp Rock',
3545
3526
  ],
3546
3527
  },
3547
3528
  {
package/data/items.ts CHANGED
@@ -2349,7 +2349,7 @@ export const Items: {[itemid: string]: ItemData} = {
2349
2349
  },
2350
2350
  num: 1120,
2351
2351
  gen: 8,
2352
- // Hazard Immunity implemented in moves.js
2352
+ // Hazard Immunity implemented in moves.ts
2353
2353
  },
2354
2354
  helixfossil: {
2355
2355
  name: "Helix Fossil",
@@ -4664,7 +4664,6 @@ export const Items: {[itemid: string]: ItemData} = {
4664
4664
  }
4665
4665
  return true;
4666
4666
  },
4667
- forcedForme: "Zamazenta-Crowned",
4668
4667
  itemUser: ["Zamazenta-Crowned"],
4669
4668
  num: 1104,
4670
4669
  gen: 8,
@@ -4678,7 +4677,6 @@ export const Items: {[itemid: string]: ItemData} = {
4678
4677
  }
4679
4678
  return true;
4680
4679
  },
4681
- forcedForme: "Zacian-Crowned",
4682
4680
  itemUser: ["Zacian-Crowned"],
4683
4681
  num: 1103,
4684
4682
  gen: 8,
package/data/learnsets.ts CHANGED
@@ -76710,7 +76710,7 @@ export const Learnsets: {[speciesid: string]: LearnsetData} = {
76710
76710
  },
76711
76711
  zaciancrowned: {
76712
76712
  learnset: {
76713
- behemothblade: ["8M", "8L33"],
76713
+ behemothblade: ["8R"],
76714
76714
  },
76715
76715
  eventOnly: true,
76716
76716
  },
@@ -76781,7 +76781,7 @@ export const Learnsets: {[speciesid: string]: LearnsetData} = {
76781
76781
  },
76782
76782
  zamazentacrowned: {
76783
76783
  learnset: {
76784
- behemothbash: ["8M", "8L33"],
76784
+ behemothbash: ["8R"],
76785
76785
  },
76786
76786
  eventOnly: true,
76787
76787
  },
@@ -179,7 +179,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
179
179
  randomBattleMoves: ["bodyslam", "thunderbolt", "thunderwave"],
180
180
  essentialMove: "blizzard",
181
181
  exclusiveMoves: ["counter", "psychic", "seismictoss", "sing", "sing"],
182
- tier: "NFE",
182
+ tier: "LC",
183
183
  },
184
184
  clefable: {
185
185
  randomBattleMoves: ["bodyslam", "thunderbolt", "thunderwave"],
@@ -38,7 +38,7 @@ export const Moves: {[k: string]: ModdedMoveData} = {
38
38
  condition: {
39
39
  duration: 2,
40
40
  durationCallback(target, source, effect) {
41
- return this.random(3, 4);
41
+ return this.random(3, 5);
42
42
  },
43
43
  onStart(pokemon) {
44
44
  this.effectState.totalDamage = 0;
@@ -500,9 +500,6 @@ export const Moves: {[k: string]: ModdedMoveData} = {
500
500
  metronome: {
501
501
  inherit: true,
502
502
  noMetronome: ["Metronome", "Struggle"],
503
- secondary: null,
504
- target: "self",
505
- type: "Normal",
506
503
  },
507
504
  mimic: {
508
505
  inherit: true,
@@ -546,13 +546,6 @@ export const Moves: {[k: string]: ModdedMoveData} = {
546
546
  },
547
547
  sleeptalk: {
548
548
  inherit: true,
549
- beforeMoveCallback(pokemon) {
550
- if (pokemon.volatiles['choicelock'] || pokemon.volatiles['encore']) {
551
- this.addMove('move', pokemon, 'Sleep Talk');
552
- this.add('-fail', pokemon);
553
- return true;
554
- }
555
- },
556
549
  onHit(pokemon) {
557
550
  const moves = [];
558
551
  for (const moveSlot of pokemon.moveSlots) {
@@ -69,9 +69,6 @@ export const Scripts: ModdedBattleScriptsData = {
69
69
  // Mod 2 (Damage is floored after all multipliers are in)
70
70
  baseDamage = Math.floor(this.battle.runEvent('ModifyDamagePhase2', pokemon, target, move, baseDamage));
71
71
 
72
- // this is not a modifier
73
- baseDamage = this.battle.randomizer(baseDamage);
74
-
75
72
  // STAB
76
73
  if (move.forceSTAB || type !== '???' && pokemon.hasType(type)) {
77
74
  // The "???" type never gets STAB
@@ -104,6 +101,9 @@ export const Scripts: ModdedBattleScriptsData = {
104
101
  // Final modifier.
105
102
  baseDamage = this.battle.runEvent('ModifyDamage', pokemon, target, move, baseDamage);
106
103
 
104
+ // this is not a modifier
105
+ baseDamage = this.battle.randomizer(baseDamage);
106
+
107
107
  if (!Math.floor(baseDamage)) {
108
108
  return 1;
109
109
  }
@@ -1650,7 +1650,7 @@ export const Moves: {[k: string]: ModdedMoveData} = {
1650
1650
  this.add('-sidestart', side, 'move: Toxic Spikes');
1651
1651
  this.effectState.layers++;
1652
1652
  },
1653
- onSwitchIn(pokemon) {
1653
+ onEntryHazard(pokemon) {
1654
1654
  if (!pokemon.isGrounded()) return;
1655
1655
  if (pokemon.hasType('Poison')) {
1656
1656
  this.add('-sideend', pokemon.side, 'move: Toxic Spikes', '[of] ' + pokemon);
@@ -13,7 +13,8 @@ export const Rulesets: {[k: string]: ModdedFormatData} = {
13
13
  this.add('clearpoke');
14
14
  for (const pokemon of this.getAllPokemon()) {
15
15
  const details = pokemon.details.replace(', shiny', '')
16
- .replace(/(Arceus|Gourgeist|Genesect|Pumpkaboo|Silvally|Zacian|Zamazenta|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*');
16
+ .replace(/(Arceus|Gourgeist|Pumpkaboo|Xerneas|Silvally|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*')
17
+ .replace(/(Zacian|Zamazenta)(?!-Crowned)/g, '$1-*'); // Hacked-in Crowned formes will be revealed
17
18
  this.add('poke', pokemon.side.id, details, pokemon.item ? 'item' : '');
18
19
  }
19
20
  this.makeRequest('teampreview');
@@ -19,7 +19,8 @@ export const Rulesets: {[k: string]: ModdedFormatData} = {
19
19
  this.add('clearpoke');
20
20
  for (const pokemon of this.getAllPokemon()) {
21
21
  const details = pokemon.details.replace(', shiny', '')
22
- .replace(/(Arceus|Gourgeist|Genesect|Pumpkaboo|Silvally|Zacian|Zamazenta|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*');
22
+ .replace(/(Arceus|Gourgeist|Pumpkaboo|Xerneas|Silvally|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*')
23
+ .replace(/(Zacian|Zamazenta)(?!-Crowned)/g, '$1-*'); // Hacked-in Crowned formes will be revealed
23
24
  const item = pokemon.item.includes('mail') ? 'mail' : pokemon.item ? 'item' : '';
24
25
  this.add('poke', pokemon.side.id, details, item);
25
26
  }
@@ -3046,7 +3046,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3046
3046
  doublesTier: "(DUU)",
3047
3047
  },
3048
3048
  sawk: {
3049
- randomBattleMoves: ["bulkup", "closecombat", "earthquake", "icepunch", "knockoff", "poisonjab"],
3049
+ randomBattleMoves: ["bulkup", "closecombat", "earthquake", "icepunch", "knockoff", "poisonjab", "stoneedge"],
3050
3050
  randomDoubleBattleMoves: ["closecombat", "icepunch", "knockoff", "protect", "rockslide"],
3051
3051
  tier: "PUBL",
3052
3052
  doublesTier: "(DUU)",
@@ -3362,7 +3362,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3362
3362
  tier: "NFE",
3363
3363
  },
3364
3364
  chandelure: {
3365
- randomBattleMoves: ["calmmind", "energyball", "fireblast", "hiddenpowerground", "painsplit", "shadowball", "substitute", "trick"],
3365
+ randomBattleMoves: ["calmmind", "energyball", "fireblast", "hiddenpowerground", "shadowball", "substitute", "trick"],
3366
3366
  randomDoubleBattleMoves: ["energyball", "heatwave", "overheat", "protect", "shadowball", "trick"],
3367
3367
  tier: "UU",
3368
3368
  doublesTier: "DUU",
@@ -3485,7 +3485,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3485
3485
  tier: "NFE",
3486
3486
  },
3487
3487
  hydreigon: {
3488
- randomBattleMoves: ["darkpulse", "dracometeor", "dragonpulse", "earthpower", "fireblast", "flashcannon", "roost", "superpower", "uturn"],
3488
+ randomBattleMoves: ["darkpulse", "dracometeor", "earthpower", "fireblast", "flashcannon", "roost", "superpower", "uturn"],
3489
3489
  randomDoubleBattleMoves: ["darkpulse", "dracometeor", "fireblast", "flashcannon", "protect", "tailwind", "uturn"],
3490
3490
  tier: "UU",
3491
3491
  doublesTier: "DUU",
@@ -3904,7 +3904,7 @@ export const FormatsData: {[k: string]: ModdedSpeciesFormatsData} = {
3904
3904
  tier: "NFE",
3905
3905
  },
3906
3906
  goodra: {
3907
- randomBattleMoves: ["dracometeor", "dragonpulse", "dragontail", "earthquake", "fireblast", "sludgebomb", "thunderbolt"],
3907
+ randomBattleMoves: ["dracometeor", "dragontail", "earthquake", "fireblast", "sludgebomb", "thunderbolt"],
3908
3908
  randomDoubleBattleMoves: ["dracometeor", "dragonpulse", "fireblast", "muddywater", "powerwhip", "protect", "thunderbolt"],
3909
3909
  tier: "RU",
3910
3910
  doublesTier: "(DUU)",
@@ -36,7 +36,8 @@ export const Rulesets: {[k: string]: ModdedFormatData} = {
36
36
  this.add('clearpoke');
37
37
  for (const pokemon of this.getAllPokemon()) {
38
38
  const details = pokemon.details.replace(', shiny', '')
39
- .replace(/(Arceus|Gourgeist|Genesect|Pumpkaboo|Silvally|Zacian|Zamazenta|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*');
39
+ .replace(/(Arceus|Gourgeist|Pumpkaboo|Xerneas|Silvally|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*')
40
+ .replace(/(Zacian|Zamazenta)(?!-Crowned)/g, '$1-*'); // Hacked-in Crowned formes will be revealed
40
41
  this.add('poke', pokemon.side.id, details, pokemon.item ? 'item' : '');
41
42
  }
42
43
  this.makeRequest('teampreview');
package/data/moves.ts CHANGED
@@ -2689,53 +2689,50 @@ export const Moves: {[moveid: string]: MoveData} = {
2689
2689
  const offset = this.random(3) + 1;
2690
2690
  // the list of all sides in counterclockwise order
2691
2691
  const sides = [this.sides[0], this.sides[2]!, this.sides[1], this.sides[3]!];
2692
- for (const id of sideConditions) {
2693
- const effectName = this.dex.conditions.get(id).name;
2694
- const rotatedSides = [];
2695
- let someCondition = false;
2696
- for (let i = 0; i < 4; i++) {
2697
- const sourceSide = sides[i];
2698
- const targetSide = sides[(i + offset) % 4]; // the next side in rotation
2699
- rotatedSides.push(targetSide.sideConditions[id]);
2700
- if (sourceSide.sideConditions[id]) {
2701
- this.add('-sideend', sourceSide, effectName, '[silent]');
2702
- someCondition = true;
2703
- }
2692
+ const temp: {[k: number]: typeof source.side.sideConditions} = {0: {}, 1: {}, 2: {}, 3: {}};
2693
+ for (const side of sides) {
2694
+ for (const id in side.sideConditions) {
2695
+ if (!sideConditions.includes(id)) continue;
2696
+ temp[side.n][id] = side.sideConditions[id];
2697
+ delete side.sideConditions[id];
2698
+ const effectName = this.dex.conditions.get(id).name;
2699
+ this.add('-sideend', side, effectName, '[silent]');
2700
+ success = true;
2704
2701
  }
2705
- if (!someCondition) continue;
2706
- [
2707
- sides[0].sideConditions[id], sides[1].sideConditions[id],
2708
- sides[2]!.sideConditions[id], sides[3]!.sideConditions[id],
2709
- ] = [...rotatedSides];
2710
- for (const side of sides) {
2711
- if (side.sideConditions[id]) {
2712
- let layers = side.sideConditions[id].layers || 1;
2713
- for (; layers > 0; layers--) this.add('-sidestart', side, effectName, '[silent]');
2714
- } else {
2715
- delete side.sideConditions[id];
2716
- }
2702
+ }
2703
+ for (let i = 0; i < 4; i++) {
2704
+ const sourceSideConditions = temp[sides[i].n];
2705
+ const targetSide = sides[(i + offset) % 4]; // the next side in rotation
2706
+ for (const id in sourceSideConditions) {
2707
+ targetSide.sideConditions[id] = sourceSideConditions[id];
2708
+ const effectName = this.dex.conditions.get(id).name;
2709
+ let layers = sourceSideConditions[id].layers || 1;
2710
+ for (; layers > 0; layers--) this.add('-sidestart', targetSide, effectName, '[silent]');
2717
2711
  }
2718
- success = true;
2719
2712
  }
2720
2713
  } else {
2721
- const sourceSide = source.side;
2722
- const targetSide = source.side.foe;
2723
- for (const id of sideConditions) {
2724
- if (sourceSide.sideConditions[id] && targetSide.sideConditions[id]) {
2725
- [sourceSide.sideConditions[id], targetSide.sideConditions[id]] = [
2726
- targetSide.sideConditions[id], sourceSide.sideConditions[id],
2727
- ];
2728
- } else if (sourceSide.sideConditions[id] && !targetSide.sideConditions[id]) {
2729
- targetSide.sideConditions[id] = sourceSide.sideConditions[id];
2730
- delete sourceSide.sideConditions[id];
2731
- } else if (targetSide.sideConditions[id] && !sourceSide.sideConditions[id]) {
2732
- sourceSide.sideConditions[id] = targetSide.sideConditions[id];
2733
- delete targetSide.sideConditions[id];
2734
- } else {
2735
- continue;
2736
- }
2714
+ const sourceSideConditions = source.side.sideConditions;
2715
+ const targetSideConditions = source.side.foe.sideConditions;
2716
+ const sourceTemp: typeof sourceSideConditions = {};
2717
+ const targetTemp: typeof targetSideConditions = {};
2718
+ for (const id in sourceSideConditions) {
2719
+ if (!sideConditions.includes(id)) continue;
2720
+ sourceTemp[id] = sourceSideConditions[id];
2721
+ delete sourceSideConditions[id];
2737
2722
  success = true;
2738
2723
  }
2724
+ for (const id in targetSideConditions) {
2725
+ if (!sideConditions.includes(id)) continue;
2726
+ targetTemp[id] = targetSideConditions[id];
2727
+ delete targetSideConditions[id];
2728
+ success = true;
2729
+ }
2730
+ for (const id in sourceTemp) {
2731
+ targetSideConditions[id] = sourceTemp[id];
2732
+ }
2733
+ for (const id in targetTemp) {
2734
+ sourceSideConditions[id] = targetTemp[id];
2735
+ }
2739
2736
  this.add('-swapsideconditions');
2740
2737
  }
2741
2738
  if (!success) return false;
@@ -6719,7 +6716,7 @@ export const Moves: {[moveid: string]: MoveData} = {
6719
6716
  onSideStart(side) {
6720
6717
  this.add('-sidestart', side, 'move: G-Max Steelsurge');
6721
6718
  },
6722
- onSwitchIn(pokemon) {
6719
+ onEntryHazard(pokemon) {
6723
6720
  if (pokemon.hasItem('heavydutyboots')) return;
6724
6721
  // Ice Face and Disguise correctly get typed damage from Stealth Rock
6725
6722
  // because Stealth Rock bypasses Substitute.
@@ -11062,26 +11059,21 @@ export const Moves: {[moveid: string]: MoveData} = {
11062
11059
  priority: 0,
11063
11060
  flags: {},
11064
11061
  noMetronome: [
11065
- "After You", "Apple Acid", "Assist", "Astral Barrage", "Aura Wheel", "Baneful Bunker", "Beak Blast", "Behemoth Bash", "Behemoth Blade", "Belch", "Bestow", "Body Press", "Branch Poke", "Breaking Swipe", "Celebrate", "Chatter", "Clangorous Soul", "Copycat", "Counter", "Covet", "Crafty Shield", "Decorate", "Destiny Bond", "Detect", "Diamond Storm", "Double Iron Bash", "Dragon Ascent", "Dragon Energy", "Drum Beating", "Dynamax Cannon", "Endure", "Eternabeam", "False Surrender", "Feint", "Fiery Wrath", "Fleur Cannon", "Focus Punch", "Follow Me", "Freeze Shock", "Freezing Glare", "Glacial Lance", "Grav Apple", "Helping Hand", "Hold Hands", "Hyperspace Fury", "Hyperspace Hole", "Ice Burn", "Instruct", "Jungle Healing", "King's Shield", "Life Dew", "Light of Ruin", "Mat Block", "Me First", "Meteor Assault", "Metronome", "Mimic", "Mind Blown", "Mirror Coat", "Mirror Move", "Moongeist Beam", "Nature Power", "Nature's Madness", "Obstruct", "Origin Pulse", "Overdrive", "Photon Geyser", "Plasma Fists", "Precipice Blades", "Protect", "Pyro Ball", "Quash", "Quick Guard", "Rage Powder", "Relic Song", "Secret Sword", "Shell Trap", "Sketch", "Sleep Talk", "Snap Trap", "Snarl", "Snatch", "Snore", "Spectral Thief", "Spiky Shield", "Spirit Break", "Spotlight", "Steam Eruption", "Steel Beam", "Strange Steam", "Struggle", "Sunsteel Strike", "Surging Strikes", "Switcheroo", "Techno Blast", "Thief", "Thousand Arrows", "Thousand Waves", "Thunder Cage", "Thunderous Kick", "Transform", "Trick", "V-create", "Wicked Blow", "Wide Guard",
11062
+ "After You", "Apple Acid", "Assist", "Astral Barrage", "Aura Wheel", "Baneful Bunker", "Beak Blast", "Behemoth Bash", "Behemoth Blade", "Belch", "Bestow", "Body Press", "Branch Poke", "Breaking Swipe", "Celebrate", "Chatter", "Clangorous Soul", "Copycat", "Counter", "Covet", "Crafty Shield", "Decorate", "Destiny Bond", "Detect", "Diamond Storm", "Double Iron Bash", "Dragon Ascent", "Dragon Energy", "Dragon Hammer", "Drum Beating", "Dynamax Cannon", "Endure", "Eternabeam", "False Surrender", "Feint", "Fiery Wrath", "Fleur Cannon", "Focus Punch", "Follow Me", "Freeze Shock", "Freezing Glare", "Glacial Lance", "Grav Apple", "Helping Hand", "Hold Hands", "Hyperspace Fury", "Hyperspace Hole", "Ice Burn", "Instruct", "Jungle Healing", "King's Shield", "Life Dew", "Light of Ruin", "Mat Block", "Me First", "Meteor Assault", "Metronome", "Mimic", "Mind Blown", "Mirror Coat", "Mirror Move", "Moongeist Beam", "Nature Power", "Nature's Madness", "Obstruct", "Origin Pulse", "Overdrive", "Photon Geyser", "Plasma Fists", "Precipice Blades", "Protect", "Pyro Ball", "Quash", "Quick Guard", "Rage Powder", "Relic Song", "Secret Sword", "Shell Trap", "Sketch", "Sleep Talk", "Snap Trap", "Snarl", "Snatch", "Snore", "Spectral Thief", "Spiky Shield", "Spirit Break", "Spotlight", "Steam Eruption", "Steel Beam", "Strange Steam", "Struggle", "Sunsteel Strike", "Surging Strikes", "Switcheroo", "Techno Blast", "Thief", "Thousand Arrows", "Thousand Waves", "Thunder Cage", "Thunderous Kick", "Transform", "Trick", "V-create", "Wicked Blow", "Wide Guard",
11066
11063
  ],
11067
11064
  onHit(target, source, effect) {
11068
- const moves: MoveData[] = [];
11069
- for (const id in Moves) {
11070
- const move = Moves[id];
11071
- if (move.realMove) continue;
11072
- if (move.isZ || move.isMax || move.isNonstandard) continue;
11073
- if (effect.noMetronome!.includes(move.name)) continue;
11074
- if (this.dex.moves.get(id).gen > this.gen) continue;
11075
- moves.push(move);
11076
- }
11065
+ const moves = this.dex.moves.all().filter(move => (
11066
+ (![2, 4].includes(this.gen) || !source.moves.includes(move.id)) &&
11067
+ !move.realMove && !move.isZ && !move.isMax &&
11068
+ (!move.isNonstandard || move.isNonstandard === 'Unobtainable') &&
11069
+ !effect.noMetronome!.includes(move.name)
11070
+ ));
11077
11071
  let randomMove = '';
11078
11072
  if (moves.length) {
11079
- moves.sort((a, b) => a.num! - b.num!);
11080
- randomMove = this.sample(moves).name;
11081
- }
11082
- if (!randomMove) {
11083
- return false;
11073
+ moves.sort((a, b) => a.num - b.num);
11074
+ randomMove = this.sample(moves).id;
11084
11075
  }
11076
+ if (!randomMove) return false;
11085
11077
  this.actions.useMove(randomMove, target);
11086
11078
  },
11087
11079
  secondary: null,
@@ -16411,9 +16403,8 @@ export const Moves: {[moveid: string]: MoveData} = {
16411
16403
  this.add('-sidestart', side, 'Spikes');
16412
16404
  this.effectState.layers++;
16413
16405
  },
16414
- onSwitchIn(pokemon) {
16415
- if (!pokemon.isGrounded()) return;
16416
- if (pokemon.hasItem('heavydutyboots')) return;
16406
+ onEntryHazard(pokemon) {
16407
+ if (!pokemon.isGrounded() || pokemon.hasItem('heavydutyboots')) return;
16417
16408
  const damageAmounts = [0, 3, 4, 6]; // 1/8, 1/6, 1/4
16418
16409
  this.damage(damageAmounts[this.effectState.layers] * pokemon.maxhp / 24);
16419
16410
  },
@@ -16696,7 +16687,7 @@ export const Moves: {[moveid: string]: MoveData} = {
16696
16687
  onSideStart(side) {
16697
16688
  this.add('-sidestart', side, 'move: Stealth Rock');
16698
16689
  },
16699
- onSwitchIn(pokemon) {
16690
+ onEntryHazard(pokemon) {
16700
16691
  if (pokemon.hasItem('heavydutyboots')) return;
16701
16692
  const typeMod = this.clampIntRange(pokemon.runEffectiveness(this.dex.getActiveMove('stealthrock')), -6, 6);
16702
16693
  this.damage(pokemon.maxhp * Math.pow(2, typeMod) / 8);
@@ -16820,9 +16811,8 @@ export const Moves: {[moveid: string]: MoveData} = {
16820
16811
  onSideStart(side) {
16821
16812
  this.add('-sidestart', side, 'move: Sticky Web');
16822
16813
  },
16823
- onSwitchIn(pokemon) {
16824
- if (!pokemon.isGrounded()) return;
16825
- if (pokemon.hasItem('heavydutyboots')) return;
16814
+ onEntryHazard(pokemon) {
16815
+ if (!pokemon.isGrounded() || pokemon.hasItem('heavydutyboots')) return;
16826
16816
  this.add('-activate', pokemon, 'move: Sticky Web');
16827
16817
  this.boost({spe: -1}, pokemon, this.effectState.source, this.dex.getActiveMove('stickyweb'));
16828
16818
  },
@@ -18426,7 +18416,7 @@ export const Moves: {[moveid: string]: MoveData} = {
18426
18416
  this.add('-sidestart', side, 'move: Toxic Spikes');
18427
18417
  this.effectState.layers++;
18428
18418
  },
18429
- onSwitchIn(pokemon) {
18419
+ onEntryHazard(pokemon) {
18430
18420
  if (!pokemon.isGrounded()) return;
18431
18421
  if (pokemon.hasType('Poison')) {
18432
18422
  this.add('-sideend', pokemon.side, 'move: Toxic Spikes', '[of] ' + pokemon);
package/data/pokedex.ts CHANGED
@@ -16034,7 +16034,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
16034
16034
  color: "Blue",
16035
16035
  eggGroups: ["Undiscovered"],
16036
16036
  requiredItem: "Rusted Sword",
16037
- changesFrom: "Zacian",
16037
+ battleOnly: "Zacian",
16038
16038
  cannotDynamax: true,
16039
16039
  },
16040
16040
  zamazenta: {
@@ -16068,7 +16068,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
16068
16068
  color: "Red",
16069
16069
  eggGroups: ["Undiscovered"],
16070
16070
  requiredItem: "Rusted Shield",
16071
- changesFrom: "Zamazenta",
16071
+ battleOnly: "Zamazenta",
16072
16072
  cannotDynamax: true,
16073
16073
  },
16074
16074
  eternatus: {
package/data/rulesets.ts CHANGED
@@ -446,7 +446,8 @@ export const Rulesets: {[k: string]: FormatData} = {
446
446
  this.add('clearpoke');
447
447
  for (const pokemon of this.getAllPokemon()) {
448
448
  const details = pokemon.details.replace(', shiny', '')
449
- .replace(/(Arceus|Gourgeist|Pumpkaboo|Xerneas|Silvally|Zacian|Zamazenta|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*');
449
+ .replace(/(Arceus|Gourgeist|Pumpkaboo|Xerneas|Silvally|Urshifu)(-[a-zA-Z?-]+)?/g, '$1-*')
450
+ .replace(/(Zacian|Zamazenta)(?!-Crowned)/g, '$1-*'); // Hacked-in Crowned formes will be revealed
450
451
  this.add('poke', pokemon.side.id, details, '');
451
452
  }
452
453
  this.makeRequest('teampreview');
@@ -1146,11 +1147,7 @@ export const Rulesets: {[k: string]: FormatData} = {
1146
1147
  if (prevo.evos.includes(formeName)) continue;
1147
1148
  }
1148
1149
  const forme = dex.species.get(formeName);
1149
- if (
1150
- forme.changesFrom === originalForme.name && !forme.battleOnly &&
1151
- // Temporary workaround
1152
- forme.forme !== 'Crowned'
1153
- ) {
1150
+ if (forme.changesFrom === originalForme.name && !forme.battleOnly) {
1154
1151
  speciesTypes.push(...forme.types);
1155
1152
  }
1156
1153
  }
@@ -429,6 +429,8 @@ export const ItemsText: {[k: string]: ItemText} = {
429
429
  ejectpack: {
430
430
  name: "Eject Pack",
431
431
  desc: "If the holder's stat stages are lowered, it switches to a chosen ally. Single use.",
432
+
433
+ end: " [POKEMON] is switched out by the Eject Pack!",
432
434
  },
433
435
  electirizer: {
434
436
  name: "Electirizer",