@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
@@ -89,15 +89,12 @@ export const Abilities = {
89
89
  },
90
90
  airlock: {
91
91
  onSwitchIn(pokemon) {
92
- this.effectState.switchingIn = true;
92
+ // Air Lock does not activate when Skill Swapped or when Neutralizing Gas leaves the field
93
+ this.add('-ability', pokemon, 'Air Lock');
94
+ this.effect.onStart.call(this, pokemon);
93
95
  },
94
96
  onStart(pokemon) {
95
- // Air Lock does not activate when Skill Swapped or when Neutralizing Gas leaves the field
96
97
  pokemon.abilityState.ending = false; // Clear the ending flag
97
- if (this.effectState.switchingIn) {
98
- this.add('-ability', pokemon, 'Air Lock');
99
- this.effectState.switchingIn = false;
100
- }
101
98
  this.eachEvent('WeatherChange', this.effect);
102
99
  },
103
100
  onEnd(pokemon) {
@@ -259,11 +256,7 @@ export const Abilities = {
259
256
  num: 165,
260
257
  },
261
258
  asoneglastrier: {
262
- onPreStart(pokemon) {
263
- this.add('-ability', pokemon, 'As One');
264
- this.add('-ability', pokemon, 'Unnerve');
265
- this.effectState.unnerved = true;
266
- },
259
+ onSwitchInPriority: 1,
267
260
  onStart(pokemon) {
268
261
  if (this.effectState.unnerved)
269
262
  return;
@@ -288,11 +281,7 @@ export const Abilities = {
288
281
  num: 266,
289
282
  },
290
283
  asonespectrier: {
291
- onPreStart(pokemon) {
292
- this.add('-ability', pokemon, 'As One');
293
- this.add('-ability', pokemon, 'Unnerve');
294
- this.effectState.unnerved = true;
295
- },
284
+ onSwitchInPriority: 1,
296
285
  onStart(pokemon) {
297
286
  if (this.effectState.unnerved)
298
287
  return;
@@ -565,15 +554,12 @@ export const Abilities = {
565
554
  },
566
555
  cloudnine: {
567
556
  onSwitchIn(pokemon) {
568
- this.effectState.switchingIn = true;
557
+ // Cloud Nine does not activate when Skill Swapped or when Neutralizing Gas leaves the field
558
+ this.add('-ability', pokemon, 'Cloud Nine');
559
+ this.effect.onStart.call(this, pokemon);
569
560
  },
570
561
  onStart(pokemon) {
571
- // Cloud Nine does not activate when Skill Swapped or when Neutralizing Gas leaves the field
572
562
  pokemon.abilityState.ending = false; // Clear the ending flag
573
- if (this.effectState.switchingIn) {
574
- this.add('-ability', pokemon, 'Cloud Nine');
575
- this.effectState.switchingIn = false;
576
- }
577
563
  this.eachEvent('WeatherChange', this.effect);
578
564
  },
579
565
  onEnd(pokemon) {
@@ -627,10 +613,22 @@ export const Abilities = {
627
613
  num: 213,
628
614
  },
629
615
  commander: {
616
+ onAnySwitchInPriority: -2,
617
+ onAnySwitchIn() {
618
+ this.effect.onUpdate.call(this, this.effectState.target);
619
+ },
620
+ onStart(pokemon) {
621
+ this.effect.onUpdate.call(this, pokemon);
622
+ },
630
623
  onUpdate(pokemon) {
631
624
  if (this.gameType !== 'doubles')
632
625
  return;
626
+ // don't run between when a Pokemon switches in and the resulting onSwitchIn event
627
+ if (this.queue.peek()?.choice === 'runSwitch')
628
+ return;
633
629
  const ally = pokemon.allies()[0];
630
+ if (pokemon.switchFlag || ally?.switchFlag)
631
+ return;
634
632
  if (!ally || pokemon.baseSpecies.baseSpecies !== 'Tatsugiri' || ally.baseSpecies.baseSpecies !== 'Dondozo') {
635
633
  // Handle any edge cases
636
634
  if (pokemon.getVolatile('commanding'))
@@ -716,6 +714,7 @@ export const Abilities = {
716
714
  num: 212,
717
715
  },
718
716
  costar: {
717
+ onSwitchInPriority: -2,
719
718
  onStart(pokemon) {
720
719
  const ally = pokemon.allies()[0];
721
720
  if (!ally)
@@ -1098,12 +1097,8 @@ export const Abilities = {
1098
1097
  },
1099
1098
  drizzle: {
1100
1099
  onStart(source) {
1101
- for (const action of this.queue) {
1102
- if (action.choice === 'runPrimal' && action.pokemon === source && source.species.id === 'kyogre')
1103
- return;
1104
- if (action.choice !== 'runSwitch' && action.choice !== 'runPrimal')
1105
- break;
1106
- }
1100
+ if (source.species.id === 'kyogre' && source.item === 'blueorb')
1101
+ return;
1107
1102
  this.field.setWeather('raindance');
1108
1103
  },
1109
1104
  flags: {},
@@ -1113,12 +1108,8 @@ export const Abilities = {
1113
1108
  },
1114
1109
  drought: {
1115
1110
  onStart(source) {
1116
- for (const action of this.queue) {
1117
- if (action.choice === 'runPrimal' && action.pokemon === source && source.species.id === 'groudon')
1118
- return;
1119
- if (action.choice !== 'runSwitch' && action.choice !== 'runPrimal')
1120
- break;
1121
- }
1111
+ if (source.species.id === 'groudon' && source.item === 'redorb')
1112
+ return;
1122
1113
  this.field.setWeather('sunnyday');
1123
1114
  },
1124
1115
  flags: {},
@@ -1385,6 +1376,7 @@ export const Abilities = {
1385
1376
  num: 18,
1386
1377
  },
1387
1378
  flowergift: {
1379
+ onSwitchInPriority: -2,
1388
1380
  onStart(pokemon) {
1389
1381
  this.singleEvent('WeatherChange', this.effect, this.effectState, pokemon);
1390
1382
  },
@@ -1480,6 +1472,7 @@ export const Abilities = {
1480
1472
  num: 218,
1481
1473
  },
1482
1474
  forecast: {
1475
+ onSwitchInPriority: -2,
1483
1476
  onStart(pokemon) {
1484
1477
  this.singleEvent('WeatherChange', this.effect, this.effectState, pokemon);
1485
1478
  },
@@ -1905,6 +1898,7 @@ export const Abilities = {
1905
1898
  num: 118,
1906
1899
  },
1907
1900
  hospitality: {
1901
+ onSwitchInPriority: -2,
1908
1902
  onStart(pokemon) {
1909
1903
  for (const ally of pokemon.adjacentAllies()) {
1910
1904
  this.heal(ally.baseMaxhp / 4, ally, pokemon);
@@ -2002,6 +1996,7 @@ export const Abilities = {
2002
1996
  num: 115,
2003
1997
  },
2004
1998
  iceface: {
1999
+ onSwitchInPriority: -2,
2005
2000
  onStart(pokemon) {
2006
2001
  if (this.field.isWeather(['hail', 'snow']) && pokemon.species.id === 'eiscuenoice') {
2007
2002
  this.add('-activate', pokemon, 'ability: Ice Face');
@@ -2120,8 +2115,7 @@ export const Abilities = {
2120
2115
  if (pokemon.illusion) {
2121
2116
  this.debug('illusion cleared');
2122
2117
  pokemon.illusion = null;
2123
- const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) +
2124
- (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : '');
2118
+ const details = pokemon.getUpdatedDetails();
2125
2119
  this.add('replace', pokemon, details);
2126
2120
  this.add('-end', pokemon, 'Illusion');
2127
2121
  if (this.ruleTable.has('illusionlevelmod')) {
@@ -2159,20 +2153,14 @@ export const Abilities = {
2159
2153
  },
2160
2154
  imposter: {
2161
2155
  onSwitchIn(pokemon) {
2162
- this.effectState.switchingIn = true;
2163
- },
2164
- onStart(pokemon) {
2165
2156
  // Imposter does not activate when Skill Swapped or when Neutralizing Gas leaves the field
2166
- if (!this.effectState.switchingIn)
2167
- return;
2168
- // copies across in doubles/triples
2157
+ // Imposter copies across in doubles/triples
2169
2158
  // (also copies across in multibattle and diagonally in free-for-all,
2170
2159
  // but side.foe already takes care of those)
2171
2160
  const target = pokemon.side.foe.active[pokemon.side.foe.active.length - 1 - pokemon.position];
2172
2161
  if (target) {
2173
2162
  pokemon.transformInto(target, this.dex.abilities.get('imposter'));
2174
2163
  }
2175
- this.effectState.switchingIn = false;
2176
2164
  },
2177
2165
  flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1 },
2178
2166
  name: "Imposter",
@@ -2331,6 +2319,9 @@ export const Abilities = {
2331
2319
  num: 51,
2332
2320
  },
2333
2321
  klutz: {
2322
+ // Klutz isn't technically active immediately in-game, but it activates early enough to beat all items
2323
+ // we should keep an eye out in future gens for items that activate on switch-in before Unnerve
2324
+ onSwitchInPriority: 1,
2334
2325
  // Item suppression implemented in Pokemon.ignoringItem() within sim/pokemon.js
2335
2326
  onStart(pokemon) {
2336
2327
  this.singleEvent('End', pokemon.getItem(), pokemon.itemState, pokemon);
@@ -2631,6 +2622,7 @@ export const Abilities = {
2631
2622
  num: 196,
2632
2623
  },
2633
2624
  mimicry: {
2625
+ onSwitchInPriority: -1,
2634
2626
  onStart(pokemon) {
2635
2627
  this.singleEvent('TerrainChange', this.effect, this.effectState, pokemon);
2636
2628
  },
@@ -2967,7 +2959,8 @@ export const Abilities = {
2967
2959
  },
2968
2960
  neutralizinggas: {
2969
2961
  // Ability suppression implemented in sim/pokemon.ts:Pokemon#ignoringAbility
2970
- onPreStart(pokemon) {
2962
+ onSwitchInPriority: 2,
2963
+ onSwitchIn(pokemon) {
2971
2964
  this.add('-ability', pokemon, 'Neutralizing Gas');
2972
2965
  pokemon.abilityState.ending = false;
2973
2966
  const strongWeathers = ['desolateland', 'primordialsea', 'deltastream'];
@@ -3108,17 +3101,38 @@ export const Abilities = {
3108
3101
  onFoeAfterBoost(boost, target, source, effect) {
3109
3102
  if (effect?.name === 'Opportunist' || effect?.name === 'Mirror Herb')
3110
3103
  return;
3111
- const pokemon = this.effectState.target;
3112
- const positiveBoosts = {};
3104
+ if (!this.effectState.boosts)
3105
+ this.effectState.boosts = {};
3106
+ const boostPlus = this.effectState.boosts;
3113
3107
  let i;
3114
3108
  for (i in boost) {
3115
3109
  if (boost[i] > 0) {
3116
- positiveBoosts[i] = boost[i];
3110
+ boostPlus[i] = (boostPlus[i] || 0) + boost[i];
3117
3111
  }
3118
3112
  }
3119
- if (Object.keys(positiveBoosts).length < 1)
3113
+ },
3114
+ onAnySwitchInPriority: -3,
3115
+ onAnySwitchIn() {
3116
+ if (!this.effectState.boosts)
3117
+ return;
3118
+ this.boost(this.effectState.boosts, this.effectState.target);
3119
+ delete this.effectState.boosts;
3120
+ },
3121
+ onAnyAfterMove() {
3122
+ if (!this.effectState.boosts)
3120
3123
  return;
3121
- this.boost(positiveBoosts, pokemon);
3124
+ this.boost(this.effectState.boosts, this.effectState.target);
3125
+ delete this.effectState.boosts;
3126
+ },
3127
+ onResidualOrder: 29,
3128
+ onResidual(pokemon) {
3129
+ if (!this.effectState.boosts)
3130
+ return;
3131
+ this.boost(this.effectState.boosts, this.effectState.target);
3132
+ delete this.effectState.boosts;
3133
+ },
3134
+ onEnd() {
3135
+ delete this.effectState.boosts;
3122
3136
  },
3123
3137
  flags: {},
3124
3138
  name: "Opportunist",
@@ -3245,11 +3259,8 @@ export const Abilities = {
3245
3259
  pokemon.cureStatus();
3246
3260
  }
3247
3261
  },
3248
- onAllySwitchIn(pokemon) {
3249
- if (['psn', 'tox'].includes(pokemon.status)) {
3250
- this.add('-activate', this.effectState.target, 'ability: Pastel Veil');
3251
- pokemon.cureStatus();
3252
- }
3262
+ onAnySwitchIn() {
3263
+ this.effect.onStart.call(this, this.effectState.target);
3253
3264
  },
3254
3265
  onSetStatus(status, target, source, effect) {
3255
3266
  if (!['psn', 'tox'].includes(status.id))
@@ -3574,6 +3585,7 @@ export const Abilities = {
3574
3585
  num: 168,
3575
3586
  },
3576
3587
  protosynthesis: {
3588
+ onSwitchInPriority: -2,
3577
3589
  onStart(pokemon) {
3578
3590
  this.singleEvent('WeatherChange', this.effect, this.effectState, pokemon);
3579
3591
  },
@@ -3717,6 +3729,7 @@ export const Abilities = {
3717
3729
  num: 272,
3718
3730
  },
3719
3731
  quarkdrive: {
3732
+ onSwitchInPriority: -2,
3720
3733
  onStart(pokemon) {
3721
3734
  this.singleEvent('TerrainChange', this.effect, this.effectState, pokemon);
3722
3735
  },
@@ -4132,6 +4145,7 @@ export const Abilities = {
4132
4145
  num: 157,
4133
4146
  },
4134
4147
  schooling: {
4148
+ onSwitchInPriority: -1,
4135
4149
  onStart(pokemon) {
4136
4150
  if (pokemon.baseSpecies.baseSpecies !== 'Wishiwashi' || pokemon.level < 20 || pokemon.transformed)
4137
4151
  return;
@@ -4335,6 +4349,7 @@ export const Abilities = {
4335
4349
  num: 19,
4336
4350
  },
4337
4351
  shieldsdown: {
4352
+ onSwitchInPriority: -1,
4338
4353
  onStart(pokemon) {
4339
4354
  if (pokemon.baseSpecies.baseSpecies !== 'Minior' || pokemon.transformed)
4340
4355
  return;
@@ -5077,21 +5092,7 @@ export const Abilities = {
5077
5092
  num: 309,
5078
5093
  },
5079
5094
  terashell: {
5080
- onEffectiveness(typeMod, target, type, move) {
5081
- if (!target || target.species.name !== 'Terapagos-Terastal')
5082
- return;
5083
- if (this.effectState.resisted)
5084
- return -1; // all hits of multi-hit move should be not very effective
5085
- if (move.category === 'Status' || move.id === 'struggle')
5086
- return;
5087
- if (!target.runImmunity(move.type))
5088
- return; // immunity has priority
5089
- if (target.hp < target.maxhp)
5090
- return;
5091
- this.add('-activate', target, 'ability: Tera Shell');
5092
- this.effectState.resisted = true;
5093
- return -1;
5094
- },
5095
+ // effectiveness implemented in sim/pokemon.ts:Pokemon#runEffectiveness
5095
5096
  onAnyAfterMove() {
5096
5097
  this.effectState.resisted = false;
5097
5098
  },
@@ -5101,12 +5102,14 @@ export const Abilities = {
5101
5102
  num: 308,
5102
5103
  },
5103
5104
  terashift: {
5104
- onPreStart(pokemon) {
5105
+ onSwitchInPriority: 2,
5106
+ onSwitchIn(pokemon) {
5105
5107
  if (pokemon.baseSpecies.baseSpecies !== 'Terapagos')
5106
5108
  return;
5107
5109
  if (pokemon.species.forme !== 'Terastal') {
5108
5110
  this.add('-activate', pokemon, 'ability: Tera Shift');
5109
5111
  pokemon.formeChange('Terapagos-Terastal', this.effect, true);
5112
+ pokemon.regressionForme = false;
5110
5113
  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);
5111
5114
  const newMaxHP = pokemon.baseMaxhp;
5112
5115
  pokemon.hp = newMaxHP - (pokemon.maxhp - pokemon.hp);
@@ -5262,19 +5265,23 @@ export const Abilities = {
5262
5265
  },
5263
5266
  trace: {
5264
5267
  onStart(pokemon) {
5268
+ this.effectState.seek = true;
5265
5269
  // n.b. only affects Hackmons
5266
5270
  // interaction with No Ability is complicated: https://www.smogon.com/forums/threads/pokemon-sun-moon-battle-mechanics-research.3586701/page-76#post-7790209
5267
5271
  if (pokemon.adjacentFoes().some(foeActive => foeActive.ability === 'noability')) {
5268
- this.effectState.gaveUp = true;
5272
+ this.effectState.seek = false;
5269
5273
  }
5270
5274
  // interaction with Ability Shield is similar to No Ability
5271
5275
  if (pokemon.hasItem('Ability Shield')) {
5272
5276
  this.add('-block', pokemon, 'item: Ability Shield');
5273
- this.effectState.gaveUp = true;
5277
+ this.effectState.seek = false;
5278
+ }
5279
+ if (this.effectState.seek) {
5280
+ this.singleEvent('Update', this.effect, this.effectState, pokemon);
5274
5281
  }
5275
5282
  },
5276
5283
  onUpdate(pokemon) {
5277
- if (!pokemon.isStarted || this.effectState.gaveUp)
5284
+ if (!this.effectState.seek)
5278
5285
  return;
5279
5286
  const possibleTargets = pokemon.adjacentFoes().filter(target => !target.getAbility().flags['notrace'] && target.ability !== 'noability');
5280
5287
  if (!possibleTargets.length)
@@ -5400,10 +5407,7 @@ export const Abilities = {
5400
5407
  num: 84,
5401
5408
  },
5402
5409
  unnerve: {
5403
- onPreStart(pokemon) {
5404
- this.add('-ability', pokemon, 'Unnerve');
5405
- this.effectState.unnerved = true;
5406
- },
5410
+ onSwitchInPriority: 1,
5407
5411
  onStart(pokemon) {
5408
5412
  if (this.effectState.unnerved)
5409
5413
  return;
@@ -5810,15 +5814,10 @@ export const Abilities = {
5810
5814
  return;
5811
5815
  if (pokemon.species.forme !== 'Hero') {
5812
5816
  pokemon.formeChange('Palafin-Hero', this.effect, true);
5817
+ pokemon.regressionForme = false;
5813
5818
  }
5814
5819
  },
5815
- onSwitchIn() {
5816
- this.effectState.switchingIn = true;
5817
- },
5818
- onStart(pokemon) {
5819
- if (!this.effectState.switchingIn)
5820
- return;
5821
- this.effectState.switchingIn = false;
5820
+ onSwitchIn(pokemon) {
5822
5821
  if (pokemon.baseSpecies.baseSpecies !== 'Palafin')
5823
5822
  return;
5824
5823
  if (!this.effectState.heroMessageDisplayed && pokemon.species.forme === 'Hero') {