@pkmn/sim 0.9.27 → 0.9.28

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 (169) hide show
  1. package/build/cjs/config/formats.js +51 -51
  2. package/build/cjs/config/formats.js.map +1 -1
  3. package/build/cjs/data/abilities.js +83 -84
  4. package/build/cjs/data/abilities.js.map +1 -1
  5. package/build/cjs/data/aliases.js +3 -2
  6. package/build/cjs/data/aliases.js.map +1 -1
  7. package/build/cjs/data/conditions.js +3 -3
  8. package/build/cjs/data/conditions.js.map +1 -1
  9. package/build/cjs/data/formats-data.js +6 -6
  10. package/build/cjs/data/formats-data.js.map +1 -1
  11. package/build/cjs/data/items.js +55 -25
  12. package/build/cjs/data/items.js.map +1 -1
  13. package/build/cjs/data/legality.js +275 -23
  14. package/build/cjs/data/legality.js.map +1 -1
  15. package/build/cjs/data/mods/gen1/moves.js.map +1 -1
  16. package/build/cjs/data/mods/gen1/scripts.js +2 -0
  17. package/build/cjs/data/mods/gen1/scripts.js.map +1 -1
  18. package/build/cjs/data/mods/gen3/abilities.js +0 -2
  19. package/build/cjs/data/mods/gen3/abilities.js.map +1 -1
  20. package/build/cjs/data/mods/gen3/moves.js.map +1 -1
  21. package/build/cjs/data/mods/gen4/abilities.js +1 -1
  22. package/build/cjs/data/mods/gen4/abilities.js.map +1 -1
  23. package/build/cjs/data/mods/gen4/moves.js +31 -0
  24. package/build/cjs/data/mods/gen4/moves.js.map +1 -1
  25. package/build/cjs/data/mods/gen4/scripts.js +26 -0
  26. package/build/cjs/data/mods/gen4/scripts.js.map +1 -1
  27. package/build/cjs/data/mods/gen5/formats-data.js +1 -1
  28. package/build/cjs/data/mods/gen5/formats-data.js.map +1 -1
  29. package/build/cjs/data/mods/gen6/moves.js.map +1 -1
  30. package/build/cjs/data/mods/gen8/moves.js +1 -1
  31. package/build/cjs/data/mods/gen8/moves.js.map +1 -1
  32. package/build/cjs/data/moves.js +15 -9
  33. package/build/cjs/data/moves.js.map +1 -1
  34. package/build/cjs/data/pokemongo.js +1 -1
  35. package/build/cjs/data/text/moves.js +1 -1
  36. package/build/cjs/data/text/moves.js.map +1 -1
  37. package/build/cjs/lib/utils.d.ts +2 -0
  38. package/build/cjs/lib/utils.js +1 -1
  39. package/build/cjs/lib/utils.js.map +1 -1
  40. package/build/cjs/sim/battle-actions.js +25 -36
  41. package/build/cjs/sim/battle-actions.js.map +1 -1
  42. package/build/cjs/sim/battle-queue.d.ts +1 -1
  43. package/build/cjs/sim/battle-queue.js +0 -2
  44. package/build/cjs/sim/battle-queue.js.map +1 -1
  45. package/build/cjs/sim/battle-stream.js +2 -3
  46. package/build/cjs/sim/battle-stream.js.map +1 -1
  47. package/build/cjs/sim/battle.d.ts +13 -7
  48. package/build/cjs/sim/battle.js +185 -60
  49. package/build/cjs/sim/battle.js.map +1 -1
  50. package/build/cjs/sim/dex-abilities.d.ts +0 -1
  51. package/build/cjs/sim/dex-abilities.js +2 -2
  52. package/build/cjs/sim/dex-abilities.js.map +1 -1
  53. package/build/cjs/sim/dex-conditions.d.ts +11 -3
  54. package/build/cjs/sim/dex-conditions.js +2 -2
  55. package/build/cjs/sim/dex-conditions.js.map +1 -1
  56. package/build/cjs/sim/dex-data.js +7 -7
  57. package/build/cjs/sim/dex-data.js.map +1 -1
  58. package/build/cjs/sim/dex-formats.d.ts +2 -1
  59. package/build/cjs/sim/dex-formats.js.map +1 -1
  60. package/build/cjs/sim/dex-items.d.ts +3 -1
  61. package/build/cjs/sim/dex-items.js +3 -2
  62. package/build/cjs/sim/dex-items.js.map +1 -1
  63. package/build/cjs/sim/dex-moves.js +4 -4
  64. package/build/cjs/sim/dex-moves.js.map +1 -1
  65. package/build/cjs/sim/exported-global-types.d.ts +6 -0
  66. package/build/cjs/sim/field.js +9 -9
  67. package/build/cjs/sim/field.js.map +1 -1
  68. package/build/cjs/sim/global-types.d.ts +6 -0
  69. package/build/cjs/sim/pokemon.d.ts +8 -4
  70. package/build/cjs/sim/pokemon.js +61 -46
  71. package/build/cjs/sim/pokemon.js.map +1 -1
  72. package/build/cjs/sim/prng.d.ts +7 -4
  73. package/build/cjs/sim/prng.js +67 -16
  74. package/build/cjs/sim/prng.js.map +1 -1
  75. package/build/cjs/sim/side.js +9 -6
  76. package/build/cjs/sim/side.js.map +1 -1
  77. package/build/cjs/sim/team-validator.js +16 -17
  78. package/build/cjs/sim/team-validator.js.map +1 -1
  79. package/build/cjs/sim/tools/exhaustive-runner.js +3 -4
  80. package/build/cjs/sim/tools/exhaustive-runner.js.map +1 -1
  81. package/build/cjs/sim/tools/random-player-ai.js +1 -1
  82. package/build/cjs/sim/tools/random-player-ai.js.map +1 -1
  83. package/build/cjs/sim/tools/runner.js +2 -3
  84. package/build/cjs/sim/tools/runner.js.map +1 -1
  85. package/build/esm/config/formats.mjs +51 -51
  86. package/build/esm/config/formats.mjs.map +1 -1
  87. package/build/esm/data/abilities.mjs +83 -84
  88. package/build/esm/data/abilities.mjs.map +1 -1
  89. package/build/esm/data/aliases.mjs +3 -2
  90. package/build/esm/data/aliases.mjs.map +1 -1
  91. package/build/esm/data/conditions.mjs +3 -3
  92. package/build/esm/data/conditions.mjs.map +1 -1
  93. package/build/esm/data/formats-data.mjs +6 -6
  94. package/build/esm/data/formats-data.mjs.map +1 -1
  95. package/build/esm/data/items.mjs +55 -25
  96. package/build/esm/data/items.mjs.map +1 -1
  97. package/build/esm/data/legality.mjs +275 -23
  98. package/build/esm/data/legality.mjs.map +1 -1
  99. package/build/esm/data/mods/gen1/moves.mjs.map +1 -1
  100. package/build/esm/data/mods/gen1/scripts.mjs +2 -0
  101. package/build/esm/data/mods/gen1/scripts.mjs.map +1 -1
  102. package/build/esm/data/mods/gen3/abilities.mjs +0 -2
  103. package/build/esm/data/mods/gen3/abilities.mjs.map +1 -1
  104. package/build/esm/data/mods/gen3/moves.mjs.map +1 -1
  105. package/build/esm/data/mods/gen4/abilities.mjs +1 -1
  106. package/build/esm/data/mods/gen4/abilities.mjs.map +1 -1
  107. package/build/esm/data/mods/gen4/moves.mjs +31 -0
  108. package/build/esm/data/mods/gen4/moves.mjs.map +1 -1
  109. package/build/esm/data/mods/gen4/scripts.mjs +26 -0
  110. package/build/esm/data/mods/gen4/scripts.mjs.map +1 -1
  111. package/build/esm/data/mods/gen5/formats-data.mjs +1 -1
  112. package/build/esm/data/mods/gen5/formats-data.mjs.map +1 -1
  113. package/build/esm/data/mods/gen6/moves.mjs.map +1 -1
  114. package/build/esm/data/mods/gen8/moves.mjs +1 -1
  115. package/build/esm/data/mods/gen8/moves.mjs.map +1 -1
  116. package/build/esm/data/moves.mjs +15 -9
  117. package/build/esm/data/moves.mjs.map +1 -1
  118. package/build/esm/data/pokemongo.mjs +1 -1
  119. package/build/esm/data/text/moves.mjs +1 -1
  120. package/build/esm/data/text/moves.mjs.map +1 -1
  121. package/build/esm/lib/utils.d.mts +2 -0
  122. package/build/esm/lib/utils.mjs +1 -1
  123. package/build/esm/lib/utils.mjs.map +1 -1
  124. package/build/esm/sim/battle-actions.mjs +25 -36
  125. package/build/esm/sim/battle-actions.mjs.map +1 -1
  126. package/build/esm/sim/battle-queue.d.mts +1 -1
  127. package/build/esm/sim/battle-queue.mjs +0 -2
  128. package/build/esm/sim/battle-queue.mjs.map +1 -1
  129. package/build/esm/sim/battle-stream.mjs +2 -3
  130. package/build/esm/sim/battle-stream.mjs.map +1 -1
  131. package/build/esm/sim/battle.d.mts +13 -7
  132. package/build/esm/sim/battle.mjs +184 -59
  133. package/build/esm/sim/battle.mjs.map +1 -1
  134. package/build/esm/sim/dex-abilities.d.mts +0 -1
  135. package/build/esm/sim/dex-abilities.mjs +1 -1
  136. package/build/esm/sim/dex-abilities.mjs.map +1 -1
  137. package/build/esm/sim/dex-conditions.d.mts +11 -3
  138. package/build/esm/sim/dex-conditions.mjs +1 -1
  139. package/build/esm/sim/dex-conditions.mjs.map +1 -1
  140. package/build/esm/sim/dex-data.mjs +1 -1
  141. package/build/esm/sim/dex-data.mjs.map +1 -1
  142. package/build/esm/sim/dex-formats.d.mts +2 -1
  143. package/build/esm/sim/dex-formats.mjs.map +1 -1
  144. package/build/esm/sim/dex-items.d.mts +3 -1
  145. package/build/esm/sim/dex-items.mjs +2 -1
  146. package/build/esm/sim/dex-items.mjs.map +1 -1
  147. package/build/esm/sim/dex-moves.mjs +1 -1
  148. package/build/esm/sim/dex-moves.mjs.map +1 -1
  149. package/build/esm/sim/exported-global-types.d.mts +6 -0
  150. package/build/esm/sim/field.mjs +9 -9
  151. package/build/esm/sim/field.mjs.map +1 -1
  152. package/build/esm/sim/global-types.d.mts +6 -0
  153. package/build/esm/sim/pokemon.d.mts +8 -4
  154. package/build/esm/sim/pokemon.mjs +61 -46
  155. package/build/esm/sim/pokemon.mjs.map +1 -1
  156. package/build/esm/sim/prng.d.mts +7 -4
  157. package/build/esm/sim/prng.mjs +34 -16
  158. package/build/esm/sim/prng.mjs.map +1 -1
  159. package/build/esm/sim/side.mjs +8 -5
  160. package/build/esm/sim/side.mjs.map +1 -1
  161. package/build/esm/sim/team-validator.mjs +10 -11
  162. package/build/esm/sim/team-validator.mjs.map +1 -1
  163. package/build/esm/sim/tools/exhaustive-runner.mjs +3 -4
  164. package/build/esm/sim/tools/exhaustive-runner.mjs.map +1 -1
  165. package/build/esm/sim/tools/random-player-ai.mjs +1 -1
  166. package/build/esm/sim/tools/random-player-ai.mjs.map +1 -1
  167. package/build/esm/sim/tools/runner.mjs +2 -3
  168. package/build/esm/sim/tools/runner.mjs.map +1 -1
  169. package/package.json +2 -2
@@ -92,15 +92,12 @@ exports.Abilities = {
92
92
  },
93
93
  airlock: {
94
94
  onSwitchIn(pokemon) {
95
- this.effectState.switchingIn = true;
95
+ // Air Lock does not activate when Skill Swapped or when Neutralizing Gas leaves the field
96
+ this.add('-ability', pokemon, 'Air Lock');
97
+ this.effect.onStart.call(this, pokemon);
96
98
  },
97
99
  onStart(pokemon) {
98
- // Air Lock does not activate when Skill Swapped or when Neutralizing Gas leaves the field
99
100
  pokemon.abilityState.ending = false; // Clear the ending flag
100
- if (this.effectState.switchingIn) {
101
- this.add('-ability', pokemon, 'Air Lock');
102
- this.effectState.switchingIn = false;
103
- }
104
101
  this.eachEvent('WeatherChange', this.effect);
105
102
  },
106
103
  onEnd(pokemon) {
@@ -262,11 +259,7 @@ exports.Abilities = {
262
259
  num: 165,
263
260
  },
264
261
  asoneglastrier: {
265
- onPreStart(pokemon) {
266
- this.add('-ability', pokemon, 'As One');
267
- this.add('-ability', pokemon, 'Unnerve');
268
- this.effectState.unnerved = true;
269
- },
262
+ onSwitchInPriority: 1,
270
263
  onStart(pokemon) {
271
264
  if (this.effectState.unnerved)
272
265
  return;
@@ -291,11 +284,7 @@ exports.Abilities = {
291
284
  num: 266,
292
285
  },
293
286
  asonespectrier: {
294
- onPreStart(pokemon) {
295
- this.add('-ability', pokemon, 'As One');
296
- this.add('-ability', pokemon, 'Unnerve');
297
- this.effectState.unnerved = true;
298
- },
287
+ onSwitchInPriority: 1,
299
288
  onStart(pokemon) {
300
289
  if (this.effectState.unnerved)
301
290
  return;
@@ -568,15 +557,12 @@ exports.Abilities = {
568
557
  },
569
558
  cloudnine: {
570
559
  onSwitchIn(pokemon) {
571
- this.effectState.switchingIn = true;
560
+ // Cloud Nine does not activate when Skill Swapped or when Neutralizing Gas leaves the field
561
+ this.add('-ability', pokemon, 'Cloud Nine');
562
+ this.effect.onStart.call(this, pokemon);
572
563
  },
573
564
  onStart(pokemon) {
574
- // Cloud Nine does not activate when Skill Swapped or when Neutralizing Gas leaves the field
575
565
  pokemon.abilityState.ending = false; // Clear the ending flag
576
- if (this.effectState.switchingIn) {
577
- this.add('-ability', pokemon, 'Cloud Nine');
578
- this.effectState.switchingIn = false;
579
- }
580
566
  this.eachEvent('WeatherChange', this.effect);
581
567
  },
582
568
  onEnd(pokemon) {
@@ -630,10 +616,22 @@ exports.Abilities = {
630
616
  num: 213,
631
617
  },
632
618
  commander: {
619
+ onAnySwitchInPriority: -2,
620
+ onAnySwitchIn() {
621
+ this.effect.onUpdate.call(this, this.effectState.target);
622
+ },
623
+ onStart(pokemon) {
624
+ this.effect.onUpdate.call(this, pokemon);
625
+ },
633
626
  onUpdate(pokemon) {
634
627
  if (this.gameType !== 'doubles')
635
628
  return;
629
+ // don't run between when a Pokemon switches in and the resulting onSwitchIn event
630
+ if (this.queue.peek()?.choice === 'runSwitch')
631
+ return;
636
632
  const ally = pokemon.allies()[0];
633
+ if (pokemon.switchFlag || ally?.switchFlag)
634
+ return;
637
635
  if (!ally || pokemon.baseSpecies.baseSpecies !== 'Tatsugiri' || ally.baseSpecies.baseSpecies !== 'Dondozo') {
638
636
  // Handle any edge cases
639
637
  if (pokemon.getVolatile('commanding'))
@@ -719,6 +717,7 @@ exports.Abilities = {
719
717
  num: 212,
720
718
  },
721
719
  costar: {
720
+ onSwitchInPriority: -2,
722
721
  onStart(pokemon) {
723
722
  const ally = pokemon.allies()[0];
724
723
  if (!ally)
@@ -1101,12 +1100,8 @@ exports.Abilities = {
1101
1100
  },
1102
1101
  drizzle: {
1103
1102
  onStart(source) {
1104
- for (const action of this.queue) {
1105
- if (action.choice === 'runPrimal' && action.pokemon === source && source.species.id === 'kyogre')
1106
- return;
1107
- if (action.choice !== 'runSwitch' && action.choice !== 'runPrimal')
1108
- break;
1109
- }
1103
+ if (source.species.id === 'kyogre' && source.item === 'blueorb')
1104
+ return;
1110
1105
  this.field.setWeather('raindance');
1111
1106
  },
1112
1107
  flags: {},
@@ -1116,12 +1111,8 @@ exports.Abilities = {
1116
1111
  },
1117
1112
  drought: {
1118
1113
  onStart(source) {
1119
- for (const action of this.queue) {
1120
- if (action.choice === 'runPrimal' && action.pokemon === source && source.species.id === 'groudon')
1121
- return;
1122
- if (action.choice !== 'runSwitch' && action.choice !== 'runPrimal')
1123
- break;
1124
- }
1114
+ if (source.species.id === 'groudon' && source.item === 'redorb')
1115
+ return;
1125
1116
  this.field.setWeather('sunnyday');
1126
1117
  },
1127
1118
  flags: {},
@@ -1388,6 +1379,7 @@ exports.Abilities = {
1388
1379
  num: 18,
1389
1380
  },
1390
1381
  flowergift: {
1382
+ onSwitchInPriority: -2,
1391
1383
  onStart(pokemon) {
1392
1384
  this.singleEvent('WeatherChange', this.effect, this.effectState, pokemon);
1393
1385
  },
@@ -1483,6 +1475,7 @@ exports.Abilities = {
1483
1475
  num: 218,
1484
1476
  },
1485
1477
  forecast: {
1478
+ onSwitchInPriority: -2,
1486
1479
  onStart(pokemon) {
1487
1480
  this.singleEvent('WeatherChange', this.effect, this.effectState, pokemon);
1488
1481
  },
@@ -1908,6 +1901,7 @@ exports.Abilities = {
1908
1901
  num: 118,
1909
1902
  },
1910
1903
  hospitality: {
1904
+ onSwitchInPriority: -2,
1911
1905
  onStart(pokemon) {
1912
1906
  for (const ally of pokemon.adjacentAllies()) {
1913
1907
  this.heal(ally.baseMaxhp / 4, ally, pokemon);
@@ -2005,6 +1999,7 @@ exports.Abilities = {
2005
1999
  num: 115,
2006
2000
  },
2007
2001
  iceface: {
2002
+ onSwitchInPriority: -2,
2008
2003
  onStart(pokemon) {
2009
2004
  if (this.field.isWeather(['hail', 'snow']) && pokemon.species.id === 'eiscuenoice') {
2010
2005
  this.add('-activate', pokemon, 'ability: Ice Face');
@@ -2123,8 +2118,7 @@ exports.Abilities = {
2123
2118
  if (pokemon.illusion) {
2124
2119
  this.debug('illusion cleared');
2125
2120
  pokemon.illusion = null;
2126
- const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) +
2127
- (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : '');
2121
+ const details = pokemon.getUpdatedDetails();
2128
2122
  this.add('replace', pokemon, details);
2129
2123
  this.add('-end', pokemon, 'Illusion');
2130
2124
  if (this.ruleTable.has('illusionlevelmod')) {
@@ -2162,20 +2156,14 @@ exports.Abilities = {
2162
2156
  },
2163
2157
  imposter: {
2164
2158
  onSwitchIn(pokemon) {
2165
- this.effectState.switchingIn = true;
2166
- },
2167
- onStart(pokemon) {
2168
2159
  // Imposter does not activate when Skill Swapped or when Neutralizing Gas leaves the field
2169
- if (!this.effectState.switchingIn)
2170
- return;
2171
- // copies across in doubles/triples
2160
+ // Imposter copies across in doubles/triples
2172
2161
  // (also copies across in multibattle and diagonally in free-for-all,
2173
2162
  // but side.foe already takes care of those)
2174
2163
  const target = pokemon.side.foe.active[pokemon.side.foe.active.length - 1 - pokemon.position];
2175
2164
  if (target) {
2176
2165
  pokemon.transformInto(target, this.dex.abilities.get('imposter'));
2177
2166
  }
2178
- this.effectState.switchingIn = false;
2179
2167
  },
2180
2168
  flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1 },
2181
2169
  name: "Imposter",
@@ -2334,6 +2322,9 @@ exports.Abilities = {
2334
2322
  num: 51,
2335
2323
  },
2336
2324
  klutz: {
2325
+ // Klutz isn't technically active immediately in-game, but it activates early enough to beat all items
2326
+ // we should keep an eye out in future gens for items that activate on switch-in before Unnerve
2327
+ onSwitchInPriority: 1,
2337
2328
  // Item suppression implemented in Pokemon.ignoringItem() within sim/pokemon.js
2338
2329
  onStart(pokemon) {
2339
2330
  this.singleEvent('End', pokemon.getItem(), pokemon.itemState, pokemon);
@@ -2634,6 +2625,7 @@ exports.Abilities = {
2634
2625
  num: 196,
2635
2626
  },
2636
2627
  mimicry: {
2628
+ onSwitchInPriority: -1,
2637
2629
  onStart(pokemon) {
2638
2630
  this.singleEvent('TerrainChange', this.effect, this.effectState, pokemon);
2639
2631
  },
@@ -2970,7 +2962,8 @@ exports.Abilities = {
2970
2962
  },
2971
2963
  neutralizinggas: {
2972
2964
  // Ability suppression implemented in sim/pokemon.ts:Pokemon#ignoringAbility
2973
- onPreStart(pokemon) {
2965
+ onSwitchInPriority: 2,
2966
+ onSwitchIn(pokemon) {
2974
2967
  this.add('-ability', pokemon, 'Neutralizing Gas');
2975
2968
  pokemon.abilityState.ending = false;
2976
2969
  const strongWeathers = ['desolateland', 'primordialsea', 'deltastream'];
@@ -3111,17 +3104,38 @@ exports.Abilities = {
3111
3104
  onFoeAfterBoost(boost, target, source, effect) {
3112
3105
  if (effect?.name === 'Opportunist' || effect?.name === 'Mirror Herb')
3113
3106
  return;
3114
- const pokemon = this.effectState.target;
3115
- const positiveBoosts = {};
3107
+ if (!this.effectState.boosts)
3108
+ this.effectState.boosts = {};
3109
+ const boostPlus = this.effectState.boosts;
3116
3110
  let i;
3117
3111
  for (i in boost) {
3118
3112
  if (boost[i] > 0) {
3119
- positiveBoosts[i] = boost[i];
3113
+ boostPlus[i] = (boostPlus[i] || 0) + boost[i];
3120
3114
  }
3121
3115
  }
3122
- if (Object.keys(positiveBoosts).length < 1)
3116
+ },
3117
+ onAnySwitchInPriority: -3,
3118
+ onAnySwitchIn() {
3119
+ if (!this.effectState.boosts)
3120
+ return;
3121
+ this.boost(this.effectState.boosts, this.effectState.target);
3122
+ delete this.effectState.boosts;
3123
+ },
3124
+ onAnyAfterMove() {
3125
+ if (!this.effectState.boosts)
3123
3126
  return;
3124
- this.boost(positiveBoosts, pokemon);
3127
+ this.boost(this.effectState.boosts, this.effectState.target);
3128
+ delete this.effectState.boosts;
3129
+ },
3130
+ onResidualOrder: 29,
3131
+ onResidual(pokemon) {
3132
+ if (!this.effectState.boosts)
3133
+ return;
3134
+ this.boost(this.effectState.boosts, this.effectState.target);
3135
+ delete this.effectState.boosts;
3136
+ },
3137
+ onEnd() {
3138
+ delete this.effectState.boosts;
3125
3139
  },
3126
3140
  flags: {},
3127
3141
  name: "Opportunist",
@@ -3248,11 +3262,8 @@ exports.Abilities = {
3248
3262
  pokemon.cureStatus();
3249
3263
  }
3250
3264
  },
3251
- onAllySwitchIn(pokemon) {
3252
- if (['psn', 'tox'].includes(pokemon.status)) {
3253
- this.add('-activate', this.effectState.target, 'ability: Pastel Veil');
3254
- pokemon.cureStatus();
3255
- }
3265
+ onAnySwitchIn() {
3266
+ this.effect.onStart.call(this, this.effectState.target);
3256
3267
  },
3257
3268
  onSetStatus(status, target, source, effect) {
3258
3269
  if (!['psn', 'tox'].includes(status.id))
@@ -3577,6 +3588,7 @@ exports.Abilities = {
3577
3588
  num: 168,
3578
3589
  },
3579
3590
  protosynthesis: {
3591
+ onSwitchInPriority: -2,
3580
3592
  onStart(pokemon) {
3581
3593
  this.singleEvent('WeatherChange', this.effect, this.effectState, pokemon);
3582
3594
  },
@@ -3720,6 +3732,7 @@ exports.Abilities = {
3720
3732
  num: 272,
3721
3733
  },
3722
3734
  quarkdrive: {
3735
+ onSwitchInPriority: -2,
3723
3736
  onStart(pokemon) {
3724
3737
  this.singleEvent('TerrainChange', this.effect, this.effectState, pokemon);
3725
3738
  },
@@ -4135,6 +4148,7 @@ exports.Abilities = {
4135
4148
  num: 157,
4136
4149
  },
4137
4150
  schooling: {
4151
+ onSwitchInPriority: -1,
4138
4152
  onStart(pokemon) {
4139
4153
  if (pokemon.baseSpecies.baseSpecies !== 'Wishiwashi' || pokemon.level < 20 || pokemon.transformed)
4140
4154
  return;
@@ -4338,6 +4352,7 @@ exports.Abilities = {
4338
4352
  num: 19,
4339
4353
  },
4340
4354
  shieldsdown: {
4355
+ onSwitchInPriority: -1,
4341
4356
  onStart(pokemon) {
4342
4357
  if (pokemon.baseSpecies.baseSpecies !== 'Minior' || pokemon.transformed)
4343
4358
  return;
@@ -5080,21 +5095,7 @@ exports.Abilities = {
5080
5095
  num: 309,
5081
5096
  },
5082
5097
  terashell: {
5083
- onEffectiveness(typeMod, target, type, move) {
5084
- if (!target || target.species.name !== 'Terapagos-Terastal')
5085
- return;
5086
- if (this.effectState.resisted)
5087
- return -1; // all hits of multi-hit move should be not very effective
5088
- if (move.category === 'Status' || move.id === 'struggle')
5089
- return;
5090
- if (!target.runImmunity(move.type))
5091
- return; // immunity has priority
5092
- if (target.hp < target.maxhp)
5093
- return;
5094
- this.add('-activate', target, 'ability: Tera Shell');
5095
- this.effectState.resisted = true;
5096
- return -1;
5097
- },
5098
+ // effectiveness implemented in sim/pokemon.ts:Pokemon#runEffectiveness
5098
5099
  onAnyAfterMove() {
5099
5100
  this.effectState.resisted = false;
5100
5101
  },
@@ -5104,12 +5105,14 @@ exports.Abilities = {
5104
5105
  num: 308,
5105
5106
  },
5106
5107
  terashift: {
5107
- onPreStart(pokemon) {
5108
+ onSwitchInPriority: 2,
5109
+ onSwitchIn(pokemon) {
5108
5110
  if (pokemon.baseSpecies.baseSpecies !== 'Terapagos')
5109
5111
  return;
5110
5112
  if (pokemon.species.forme !== 'Terastal') {
5111
5113
  this.add('-activate', pokemon, 'ability: Tera Shift');
5112
5114
  pokemon.formeChange('Terapagos-Terastal', this.effect, true);
5115
+ pokemon.regressionForme = false;
5113
5116
  pokemon.baseMaxhp = Math.floor(Math.floor(2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100) * pokemon.level / 100 + 10);
5114
5117
  const newMaxHP = pokemon.baseMaxhp;
5115
5118
  pokemon.hp = newMaxHP - (pokemon.maxhp - pokemon.hp);
@@ -5265,19 +5268,23 @@ exports.Abilities = {
5265
5268
  },
5266
5269
  trace: {
5267
5270
  onStart(pokemon) {
5271
+ this.effectState.seek = true;
5268
5272
  // n.b. only affects Hackmons
5269
5273
  // interaction with No Ability is complicated: https://www.smogon.com/forums/threads/pokemon-sun-moon-battle-mechanics-research.3586701/page-76#post-7790209
5270
5274
  if (pokemon.adjacentFoes().some(foeActive => foeActive.ability === 'noability')) {
5271
- this.effectState.gaveUp = true;
5275
+ this.effectState.seek = false;
5272
5276
  }
5273
5277
  // interaction with Ability Shield is similar to No Ability
5274
5278
  if (pokemon.hasItem('Ability Shield')) {
5275
5279
  this.add('-block', pokemon, 'item: Ability Shield');
5276
- this.effectState.gaveUp = true;
5280
+ this.effectState.seek = false;
5281
+ }
5282
+ if (this.effectState.seek) {
5283
+ this.singleEvent('Update', this.effect, this.effectState, pokemon);
5277
5284
  }
5278
5285
  },
5279
5286
  onUpdate(pokemon) {
5280
- if (!pokemon.isStarted || this.effectState.gaveUp)
5287
+ if (!this.effectState.seek)
5281
5288
  return;
5282
5289
  const possibleTargets = pokemon.adjacentFoes().filter(target => !target.getAbility().flags['notrace'] && target.ability !== 'noability');
5283
5290
  if (!possibleTargets.length)
@@ -5403,10 +5410,7 @@ exports.Abilities = {
5403
5410
  num: 84,
5404
5411
  },
5405
5412
  unnerve: {
5406
- onPreStart(pokemon) {
5407
- this.add('-ability', pokemon, 'Unnerve');
5408
- this.effectState.unnerved = true;
5409
- },
5413
+ onSwitchInPriority: 1,
5410
5414
  onStart(pokemon) {
5411
5415
  if (this.effectState.unnerved)
5412
5416
  return;
@@ -5813,15 +5817,10 @@ exports.Abilities = {
5813
5817
  return;
5814
5818
  if (pokemon.species.forme !== 'Hero') {
5815
5819
  pokemon.formeChange('Palafin-Hero', this.effect, true);
5820
+ pokemon.regressionForme = false;
5816
5821
  }
5817
5822
  },
5818
- onSwitchIn() {
5819
- this.effectState.switchingIn = true;
5820
- },
5821
- onStart(pokemon) {
5822
- if (!this.effectState.switchingIn)
5823
- return;
5824
- this.effectState.switchingIn = false;
5823
+ onSwitchIn(pokemon) {
5825
5824
  if (pokemon.baseSpecies.baseSpecies !== 'Palafin')
5826
5825
  return;
5827
5826
  if (!this.effectState.heroMessageDisplayed && pokemon.species.forme === 'Hero') {