@pkmn/sim 0.9.26 → 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 (189) hide show
  1. package/build/cjs/config/formats.js +79 -86
  2. package/build/cjs/config/formats.js.map +1 -1
  3. package/build/cjs/data/abilities.js +100 -116
  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 +12 -12
  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/gen2/moves.js +1 -1
  19. package/build/cjs/data/mods/gen2/moves.js.map +1 -1
  20. package/build/cjs/data/mods/gen3/abilities.js +0 -2
  21. package/build/cjs/data/mods/gen3/abilities.js.map +1 -1
  22. package/build/cjs/data/mods/gen3/moves.js.map +1 -1
  23. package/build/cjs/data/mods/gen4/abilities.js +1 -1
  24. package/build/cjs/data/mods/gen4/abilities.js.map +1 -1
  25. package/build/cjs/data/mods/gen4/formats-data.js +1 -1
  26. package/build/cjs/data/mods/gen4/formats-data.js.map +1 -1
  27. package/build/cjs/data/mods/gen4/moves.js +88 -0
  28. package/build/cjs/data/mods/gen4/moves.js.map +1 -1
  29. package/build/cjs/data/mods/gen4/scripts.js +26 -0
  30. package/build/cjs/data/mods/gen4/scripts.js.map +1 -1
  31. package/build/cjs/data/mods/gen5/conditions.js +1 -2
  32. package/build/cjs/data/mods/gen5/conditions.js.map +1 -1
  33. package/build/cjs/data/mods/gen5/formats-data.js +2 -2
  34. package/build/cjs/data/mods/gen5/formats-data.js.map +1 -1
  35. package/build/cjs/data/mods/gen6/moves.js.map +1 -1
  36. package/build/cjs/data/mods/gen8/abilities.js +0 -2
  37. package/build/cjs/data/mods/gen8/abilities.js.map +1 -1
  38. package/build/cjs/data/mods/gen8/moves.js +1 -1
  39. package/build/cjs/data/mods/gen8/moves.js.map +1 -1
  40. package/build/cjs/data/moves.js +22 -18
  41. package/build/cjs/data/moves.js.map +1 -1
  42. package/build/cjs/data/pokemongo.js +1 -1
  43. package/build/cjs/data/text/moves.js +1 -1
  44. package/build/cjs/data/text/moves.js.map +1 -1
  45. package/build/cjs/lib/utils.d.ts +8 -0
  46. package/build/cjs/lib/utils.js +21 -2
  47. package/build/cjs/lib/utils.js.map +1 -1
  48. package/build/cjs/sim/battle-actions.js +30 -39
  49. package/build/cjs/sim/battle-actions.js.map +1 -1
  50. package/build/cjs/sim/battle-queue.d.ts +1 -1
  51. package/build/cjs/sim/battle-queue.js +0 -2
  52. package/build/cjs/sim/battle-queue.js.map +1 -1
  53. package/build/cjs/sim/battle-stream.js +2 -3
  54. package/build/cjs/sim/battle-stream.js.map +1 -1
  55. package/build/cjs/sim/battle.d.ts +13 -7
  56. package/build/cjs/sim/battle.js +197 -70
  57. package/build/cjs/sim/battle.js.map +1 -1
  58. package/build/cjs/sim/dex-abilities.d.ts +0 -1
  59. package/build/cjs/sim/dex-abilities.js +2 -2
  60. package/build/cjs/sim/dex-abilities.js.map +1 -1
  61. package/build/cjs/sim/dex-conditions.d.ts +11 -3
  62. package/build/cjs/sim/dex-conditions.js +2 -2
  63. package/build/cjs/sim/dex-conditions.js.map +1 -1
  64. package/build/cjs/sim/dex-data.js +7 -7
  65. package/build/cjs/sim/dex-data.js.map +1 -1
  66. package/build/cjs/sim/dex-formats.d.ts +2 -1
  67. package/build/cjs/sim/dex-formats.js.map +1 -1
  68. package/build/cjs/sim/dex-items.d.ts +3 -1
  69. package/build/cjs/sim/dex-items.js +3 -2
  70. package/build/cjs/sim/dex-items.js.map +1 -1
  71. package/build/cjs/sim/dex-moves.js +4 -4
  72. package/build/cjs/sim/dex-moves.js.map +1 -1
  73. package/build/cjs/sim/exported-global-types.d.ts +6 -0
  74. package/build/cjs/sim/field.js +9 -9
  75. package/build/cjs/sim/field.js.map +1 -1
  76. package/build/cjs/sim/global-types.d.ts +6 -0
  77. package/build/cjs/sim/pokemon.d.ts +8 -4
  78. package/build/cjs/sim/pokemon.js +62 -47
  79. package/build/cjs/sim/pokemon.js.map +1 -1
  80. package/build/cjs/sim/prng.d.ts +57 -18
  81. package/build/cjs/sim/prng.js +171 -38
  82. package/build/cjs/sim/prng.js.map +1 -1
  83. package/build/cjs/sim/side.js +9 -6
  84. package/build/cjs/sim/side.js.map +1 -1
  85. package/build/cjs/sim/state.js +1 -1
  86. package/build/cjs/sim/state.js.map +1 -1
  87. package/build/cjs/sim/team-validator.js +16 -17
  88. package/build/cjs/sim/team-validator.js.map +1 -1
  89. package/build/cjs/sim/tools/exhaustive-runner.js +11 -12
  90. package/build/cjs/sim/tools/exhaustive-runner.js.map +1 -1
  91. package/build/cjs/sim/tools/random-player-ai.js +5 -5
  92. package/build/cjs/sim/tools/random-player-ai.js.map +1 -1
  93. package/build/cjs/sim/tools/runner.js +7 -8
  94. package/build/cjs/sim/tools/runner.js.map +1 -1
  95. package/build/esm/config/formats.mjs +79 -86
  96. package/build/esm/config/formats.mjs.map +1 -1
  97. package/build/esm/data/abilities.mjs +100 -116
  98. package/build/esm/data/abilities.mjs.map +1 -1
  99. package/build/esm/data/aliases.mjs +3 -2
  100. package/build/esm/data/aliases.mjs.map +1 -1
  101. package/build/esm/data/conditions.mjs +3 -3
  102. package/build/esm/data/conditions.mjs.map +1 -1
  103. package/build/esm/data/formats-data.mjs +12 -12
  104. package/build/esm/data/formats-data.mjs.map +1 -1
  105. package/build/esm/data/items.mjs +55 -25
  106. package/build/esm/data/items.mjs.map +1 -1
  107. package/build/esm/data/legality.mjs +275 -23
  108. package/build/esm/data/legality.mjs.map +1 -1
  109. package/build/esm/data/mods/gen1/moves.mjs.map +1 -1
  110. package/build/esm/data/mods/gen1/scripts.mjs +2 -0
  111. package/build/esm/data/mods/gen1/scripts.mjs.map +1 -1
  112. package/build/esm/data/mods/gen2/moves.mjs +1 -1
  113. package/build/esm/data/mods/gen2/moves.mjs.map +1 -1
  114. package/build/esm/data/mods/gen3/abilities.mjs +0 -2
  115. package/build/esm/data/mods/gen3/abilities.mjs.map +1 -1
  116. package/build/esm/data/mods/gen3/moves.mjs.map +1 -1
  117. package/build/esm/data/mods/gen4/abilities.mjs +1 -1
  118. package/build/esm/data/mods/gen4/abilities.mjs.map +1 -1
  119. package/build/esm/data/mods/gen4/formats-data.mjs +1 -1
  120. package/build/esm/data/mods/gen4/formats-data.mjs.map +1 -1
  121. package/build/esm/data/mods/gen4/moves.mjs +88 -0
  122. package/build/esm/data/mods/gen4/moves.mjs.map +1 -1
  123. package/build/esm/data/mods/gen4/scripts.mjs +26 -0
  124. package/build/esm/data/mods/gen4/scripts.mjs.map +1 -1
  125. package/build/esm/data/mods/gen5/conditions.mjs +1 -2
  126. package/build/esm/data/mods/gen5/conditions.mjs.map +1 -1
  127. package/build/esm/data/mods/gen5/formats-data.mjs +2 -2
  128. package/build/esm/data/mods/gen5/formats-data.mjs.map +1 -1
  129. package/build/esm/data/mods/gen6/moves.mjs.map +1 -1
  130. package/build/esm/data/mods/gen8/abilities.mjs +0 -2
  131. package/build/esm/data/mods/gen8/abilities.mjs.map +1 -1
  132. package/build/esm/data/mods/gen8/moves.mjs +1 -1
  133. package/build/esm/data/mods/gen8/moves.mjs.map +1 -1
  134. package/build/esm/data/moves.mjs +22 -18
  135. package/build/esm/data/moves.mjs.map +1 -1
  136. package/build/esm/data/pokemongo.mjs +1 -1
  137. package/build/esm/data/text/moves.mjs +1 -1
  138. package/build/esm/data/text/moves.mjs.map +1 -1
  139. package/build/esm/lib/utils.d.mts +8 -0
  140. package/build/esm/lib/utils.mjs +18 -2
  141. package/build/esm/lib/utils.mjs.map +1 -1
  142. package/build/esm/sim/battle-actions.mjs +30 -39
  143. package/build/esm/sim/battle-actions.mjs.map +1 -1
  144. package/build/esm/sim/battle-queue.d.mts +1 -1
  145. package/build/esm/sim/battle-queue.mjs +0 -2
  146. package/build/esm/sim/battle-queue.mjs.map +1 -1
  147. package/build/esm/sim/battle-stream.mjs +2 -3
  148. package/build/esm/sim/battle-stream.mjs.map +1 -1
  149. package/build/esm/sim/battle.d.mts +13 -7
  150. package/build/esm/sim/battle.mjs +196 -69
  151. package/build/esm/sim/battle.mjs.map +1 -1
  152. package/build/esm/sim/dex-abilities.d.mts +0 -1
  153. package/build/esm/sim/dex-abilities.mjs +1 -1
  154. package/build/esm/sim/dex-abilities.mjs.map +1 -1
  155. package/build/esm/sim/dex-conditions.d.mts +11 -3
  156. package/build/esm/sim/dex-conditions.mjs +1 -1
  157. package/build/esm/sim/dex-conditions.mjs.map +1 -1
  158. package/build/esm/sim/dex-data.mjs +1 -1
  159. package/build/esm/sim/dex-data.mjs.map +1 -1
  160. package/build/esm/sim/dex-formats.d.mts +2 -1
  161. package/build/esm/sim/dex-formats.mjs.map +1 -1
  162. package/build/esm/sim/dex-items.d.mts +3 -1
  163. package/build/esm/sim/dex-items.mjs +2 -1
  164. package/build/esm/sim/dex-items.mjs.map +1 -1
  165. package/build/esm/sim/dex-moves.mjs +1 -1
  166. package/build/esm/sim/dex-moves.mjs.map +1 -1
  167. package/build/esm/sim/exported-global-types.d.mts +6 -0
  168. package/build/esm/sim/field.mjs +9 -9
  169. package/build/esm/sim/field.mjs.map +1 -1
  170. package/build/esm/sim/global-types.d.mts +6 -0
  171. package/build/esm/sim/pokemon.d.mts +8 -4
  172. package/build/esm/sim/pokemon.mjs +62 -47
  173. package/build/esm/sim/pokemon.mjs.map +1 -1
  174. package/build/esm/sim/prng.d.mts +57 -18
  175. package/build/esm/sim/prng.mjs +134 -36
  176. package/build/esm/sim/prng.mjs.map +1 -1
  177. package/build/esm/sim/side.mjs +8 -5
  178. package/build/esm/sim/side.mjs.map +1 -1
  179. package/build/esm/sim/state.mjs +1 -1
  180. package/build/esm/sim/state.mjs.map +1 -1
  181. package/build/esm/sim/team-validator.mjs +10 -11
  182. package/build/esm/sim/team-validator.mjs.map +1 -1
  183. package/build/esm/sim/tools/exhaustive-runner.mjs +11 -12
  184. package/build/esm/sim/tools/exhaustive-runner.mjs.map +1 -1
  185. package/build/esm/sim/tools/random-player-ai.mjs +5 -5
  186. package/build/esm/sim/tools/random-player-ai.mjs.map +1 -1
  187. package/build/esm/sim/tools/runner.mjs +7 -8
  188. package/build/esm/sim/tools/runner.mjs.map +1 -1
  189. package/package.json +3 -2
@@ -203,6 +203,8 @@ interface ModdedBattleActions {
203
203
  getMixedSpecies?: (this: BattleActions, originalName: string, megaName: string, pokemon?: Pokemon) => Species;
204
204
  }
205
205
  interface ModdedBattleSide {
206
+ inherit?: true;
207
+ allies?: (this: Side, all?: boolean) => Pokemon[];
206
208
  canDynamaxNow?: (this: Side) => boolean;
207
209
  chooseSwitch?: (this: Side, slotText?: string) => any;
208
210
  getChoice?: (this: Side) => string;
@@ -277,9 +279,11 @@ interface ModdedBattlePokemon {
277
279
  hasLinkedMove?: (this: Pokemon, moveid: string) => boolean;
278
280
  }
279
281
  interface ModdedBattleQueue extends Partial<BattleQueue> {
282
+ inherit?: true;
280
283
  resolveAction?: (this: BattleQueue, action: ActionChoice, midTurn?: boolean) => Action[];
281
284
  }
282
285
  interface ModdedField extends Partial<Field> {
286
+ inherit?: true;
283
287
  suppressingWeather?: (this: Field) => boolean;
284
288
  }
285
289
  interface ModdedBattleScriptsData extends Partial<BattleScriptsData> {
@@ -306,6 +310,8 @@ interface ModdedBattleScriptsData extends Partial<BattleScriptsData> {
306
310
  tiebreak?: (this: Battle) => boolean;
307
311
  checkMoveMakesContact?: (this: Battle, move: ActiveMove, attacker: Pokemon, defender: Pokemon, announcePads?: boolean) => boolean;
308
312
  checkWin?: (this: Battle, faintQueue?: Battle['faintQueue'][0]) => true | undefined;
313
+ fieldEvent?: (this: Battle, eventid: string, targets?: Pokemon[]) => void;
314
+ getAllActive?: (this: Battle, includeFainted?: boolean, includeCommanding?: boolean) => Pokemon[];
309
315
  }
310
316
  type TypeInfo = import('./dex-data').TypeInfo;
311
317
  interface PlayerOptions {
@@ -20,7 +20,9 @@ interface Attacker {
20
20
  damageValue?: (number | boolean | undefined);
21
21
  }
22
22
  export interface EffectState {
23
- duration?: number | any;
23
+ id: string;
24
+ effectOrder: number;
25
+ duration?: number;
24
26
  [k: string]: any;
25
27
  }
26
28
  export declare const RESTORATIVE_BERRIES: Set<ID>;
@@ -101,6 +103,8 @@ export declare class Pokemon {
101
103
  fainted: boolean;
102
104
  faintQueued: boolean;
103
105
  subFainted: boolean | null;
106
+ /** If this Pokemon should revert to its set species when it faints */
107
+ regressionForme: boolean;
104
108
  types: string[];
105
109
  addedType: string;
106
110
  knownType: boolean;
@@ -213,7 +217,6 @@ export declare class Pokemon {
213
217
  duringMove: boolean;
214
218
  weighthg: number;
215
219
  speed: number;
216
- abilityOrder: number;
217
220
  canMegaEvo: string | null | undefined;
218
221
  canMegaEvoX: string | null | undefined;
219
222
  canMegaEvoY: string | null | undefined;
@@ -250,7 +253,8 @@ export declare class Pokemon {
250
253
  get baseMoves(): readonly string[];
251
254
  getSlot(): PokemonSlot;
252
255
  toString(): string;
253
- getDetails: () => {
256
+ getUpdatedDetails(level?: number): string;
257
+ getFullDetails: () => {
254
258
  side: SideID;
255
259
  secret: string;
256
260
  shared: string;
@@ -348,7 +352,7 @@ export declare class Pokemon {
348
352
  /**
349
353
  * Changes this Pokemon's species to the given speciesId (or species).
350
354
  * This function only handles changes to stats and type.
351
- * Use formChange to handle changes to ability and sending client messages.
355
+ * Use formeChange to handle changes to ability and sending client messages.
352
356
  */
353
357
  setSpecies(rawSpecies: Species, source?: Effect | null, isTransform?: boolean): any;
354
358
  /**
@@ -13,17 +13,11 @@ export const RESTORATIVE_BERRIES = new Set([
13
13
  ]);
14
14
  export class Pokemon {
15
15
  constructor(set, side) {
16
- this.getDetails = () => {
16
+ this.getFullDetails = () => {
17
17
  const health = this.getHealth();
18
18
  let details = this.details;
19
19
  if (this.illusion) {
20
- const level = this.battle.ruleTable.has('illusionlevelmod') ? this.illusion.level : this.level;
21
- let displayedSpeciesName = this.illusion.species.name;
22
- if (displayedSpeciesName === 'Greninja-Bond')
23
- displayedSpeciesName = 'Greninja';
24
- const illusionDetails = displayedSpeciesName + (level === 100 ? '' : ', L' + level) +
25
- (this.illusion.gender === '' ? '' : ', ' + this.illusion.gender) + (this.illusion.set.shiny ? ', shiny' : '');
26
- details = illusionDetails;
20
+ details = this.illusion.getUpdatedDetails(this.battle.ruleTable.has('illusionlevelmod') ? this.illusion.level : this.level);
27
21
  }
28
22
  if (this.terastallized)
29
23
  details += `, tera:${this.terastallized}`;
@@ -80,13 +74,13 @@ export class Pokemon {
80
74
  if (set.name === set.species || !set.name) {
81
75
  set.name = this.baseSpecies.baseSpecies;
82
76
  }
83
- this.speciesState = { id: this.species.id };
77
+ this.speciesState = this.battle.initEffectState({ id: this.species.id });
84
78
  this.name = set.name.substr(0, 20);
85
79
  this.fullname = this.side.id + ': ' + this.name;
86
80
  set.level = this.battle.clampIntRange(set.adjustLevel || set.level || 100, 1, 9999);
87
81
  this.level = set.level;
88
82
  const genders = { M: 'M', F: 'F', N: 'N' };
89
- this.gender = genders[set.gender] || this.species.gender || (this.battle.random() * 2 < 1 ? 'M' : 'F');
83
+ this.gender = genders[set.gender] || this.species.gender || (this.battle.random(2) ? 'F' : 'M');
90
84
  if (this.gender === 'N')
91
85
  this.gender = '';
92
86
  this.happiness = typeof set.happiness === 'number' ? this.battle.clampIntRange(set.happiness, 0, 255) : 255;
@@ -122,13 +116,9 @@ export class Pokemon {
122
116
  });
123
117
  }
124
118
  this.position = 0;
125
- let displayedSpeciesName = this.species.name;
126
- if (displayedSpeciesName === 'Greninja-Bond')
127
- displayedSpeciesName = 'Greninja';
128
- this.details = displayedSpeciesName + (this.level === 100 ? '' : ', L' + this.level) +
129
- (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : '');
119
+ this.details = this.getUpdatedDetails();
130
120
  this.status = '';
131
- this.statusState = {};
121
+ this.statusState = this.battle.initEffectState({});
132
122
  this.volatiles = {};
133
123
  this.showCure = undefined;
134
124
  if (!this.set.evs) {
@@ -168,9 +158,9 @@ export class Pokemon {
168
158
  this.boosts = { atk: 0, def: 0, spa: 0, spd: 0, spe: 0, accuracy: 0, evasion: 0 };
169
159
  this.baseAbility = toID(set.ability);
170
160
  this.ability = this.baseAbility;
171
- this.abilityState = { id: this.ability };
161
+ this.abilityState = this.battle.initEffectState({ id: this.ability, target: this });
172
162
  this.item = toID(set.item);
173
- this.itemState = { id: this.item };
163
+ this.itemState = this.battle.initEffectState({ id: this.item, target: this });
174
164
  this.lastItem = '';
175
165
  this.usedItemThisTurn = false;
176
166
  this.ateBerry = false;
@@ -182,6 +172,7 @@ export class Pokemon {
182
172
  this.fainted = false;
183
173
  this.faintQueued = false;
184
174
  this.subFainted = null;
175
+ this.regressionForme = false;
185
176
  this.types = this.baseSpecies.types;
186
177
  this.baseTypes = this.types;
187
178
  this.addedType = '';
@@ -221,12 +212,6 @@ export class Pokemon {
221
212
  this.duringMove = false;
222
213
  this.weighthg = 1;
223
214
  this.speed = 0;
224
- /**
225
- * Determines the order in which redirect abilities like Lightning Rod
226
- * activate if speed tied. Surprisingly not random like every other speed
227
- * tie, but based on who first switched in or acquired the ability!
228
- */
229
- this.abilityOrder = 0;
230
215
  this.canMegaEvo = this.battle.actions.canMegaEvo(this);
231
216
  this.canMegaEvoX = this.battle.actions.canMegaEvoX?.(this);
232
217
  this.canMegaEvoY = this.battle.actions.canMegaEvoY?.(this);
@@ -261,6 +246,13 @@ export class Pokemon {
261
246
  const fullname = (this.illusion) ? this.illusion.fullname : this.fullname;
262
247
  return this.isActive ? this.getSlot() + fullname.slice(2) : fullname;
263
248
  }
249
+ getUpdatedDetails(level = this.level) {
250
+ let name = this.species.name;
251
+ if (name === 'Greninja-Bond')
252
+ name = 'Greninja';
253
+ return name + (level === 100 ? '' : ', L' + level) +
254
+ (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : '');
255
+ }
264
256
  updateSpeed() {
265
257
  this.speed = this.getActionSpeed();
266
258
  }
@@ -567,7 +559,7 @@ export class Pokemon {
567
559
  return false;
568
560
  }
569
561
  ignoringItem() {
570
- return !!(this.itemState.knockedOff || // Gen 3-4
562
+ return !this.getItem().isPrimalOrb && !!(this.itemState.knockedOff || // Gen 3-4
571
563
  (this.battle.gen >= 5 && !this.isActive) ||
572
564
  (!this.getItem().ignoreKlutz && this.hasAbility('klutz')) ||
573
565
  this.volatiles['embargo'] || this.battle.field.pseudoWeather['magicroom']);
@@ -907,7 +899,7 @@ export class Pokemon {
907
899
  if (this.battle.dex.conditions.getByID(i).noCopy)
908
900
  continue;
909
901
  // shallow clones
910
- this.volatiles[i] = { ...pokemon.volatiles[i] };
902
+ this.volatiles[i] = this.battle.initEffectState({ ...pokemon.volatiles[i] });
911
903
  if (this.volatiles[i].linkedPokemon) {
912
904
  delete pokemon.volatiles[i].linkedPokemon;
913
905
  delete pokemon.volatiles[i].linkedStatus;
@@ -1024,16 +1016,14 @@ export class Pokemon {
1024
1016
  }
1025
1017
  // Pokemon transformed into Ogerpon cannot Terastallize
1026
1018
  // restoring their ability to tera after they untransform is handled ELSEWHERE
1027
- if (this.species.baseSpecies === 'Ogerpon' && this.canTerastallize)
1028
- this.canTerastallize = false;
1029
- if (this.species.baseSpecies === 'Terapagos' && this.canTerastallize)
1019
+ if (['Ogerpon', 'Terapagos'].includes(this.species.baseSpecies) && this.canTerastallize)
1030
1020
  this.canTerastallize = false;
1031
1021
  return true;
1032
1022
  }
1033
1023
  /**
1034
1024
  * Changes this Pokemon's species to the given speciesId (or species).
1035
1025
  * This function only handles changes to stats and type.
1036
- * Use formChange to handle changes to ability and sending client messages.
1026
+ * Use formeChange to handle changes to ability and sending client messages.
1037
1027
  */
1038
1028
  setSpecies(rawSpecies, source = this.battle.effect, isTransform = false) {
1039
1029
  const species = this.battle.runEvent('ModifySpecies', this, null, source, rawSpecies);
@@ -1086,9 +1076,10 @@ export class Pokemon {
1086
1076
  // The species the opponent sees
1087
1077
  const apparentSpecies = this.illusion ? this.illusion.species.name : species.baseSpecies;
1088
1078
  if (isPermanent) {
1079
+ if (!this.transformed)
1080
+ this.regressionForme = true;
1089
1081
  this.baseSpecies = rawSpecies;
1090
- this.details = species.name + (this.level === 100 ? '' : ', L' + this.level) +
1091
- (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : '');
1082
+ this.details = this.getUpdatedDetails();
1092
1083
  let details = (this.illusion || this).details;
1093
1084
  if (this.terastallized)
1094
1085
  details += `, tera:${this.terastallized}`;
@@ -1103,7 +1094,7 @@ export class Pokemon {
1103
1094
  this.battle.add('-burst', this, apparentSpecies, species.requiredItem);
1104
1095
  this.moveThisTurnResult = true; // Ultra Burst counts as an action for Truant
1105
1096
  }
1106
- else if (source.onPrimal) {
1097
+ else if (source.isPrimalOrb) {
1107
1098
  if (this.illusion) {
1108
1099
  this.ability = '';
1109
1100
  this.battle.add('-primal', this.illusion, species.requiredItem);
@@ -1200,6 +1191,8 @@ export class Pokemon {
1200
1191
  this.newlySwitched = true;
1201
1192
  this.beingCalledBack = false;
1202
1193
  this.volatileStaleness = undefined;
1194
+ delete this.abilityState.started;
1195
+ delete this.itemState.started;
1203
1196
  this.setSpecies(this.baseSpecies);
1204
1197
  }
1205
1198
  hasType(type) {
@@ -1370,7 +1363,7 @@ export class Pokemon {
1370
1363
  }
1371
1364
  }
1372
1365
  this.status = status.id;
1373
- this.statusState = { id: status.id, target: this };
1366
+ this.statusState = this.battle.initEffectState({ id: status.id, target: this });
1374
1367
  if (source)
1375
1368
  this.statusState.source = source;
1376
1369
  if (status.duration)
@@ -1415,6 +1408,10 @@ export class Pokemon {
1415
1408
  if (!source && this.battle.event && this.battle.event.target)
1416
1409
  source = this.battle.event.target;
1417
1410
  const item = this.getItem();
1411
+ if (sourceEffect?.effectType === 'Item' && this.item !== sourceEffect.id && source === this) {
1412
+ // if an item is telling us to eat it but we aren't holding it, we probably shouldn't eat what we are holding
1413
+ return false;
1414
+ }
1418
1415
  if (this.battle.runEvent('UseItem', this, null, null, item) &&
1419
1416
  (force || this.battle.runEvent('TryEatItem', this, null, null, item))) {
1420
1417
  this.battle.add('-enditem', this, item, '[eat]');
@@ -1434,7 +1431,7 @@ export class Pokemon {
1434
1431
  }
1435
1432
  this.lastItem = this.item;
1436
1433
  this.item = '';
1437
- this.itemState = { id: '', target: this };
1434
+ this.battle.clearEffectState(this.itemState);
1438
1435
  this.usedItemThisTurn = true;
1439
1436
  this.ateBerry = true;
1440
1437
  this.battle.runEvent('AfterUseItem', this, null, null, item);
@@ -1452,6 +1449,10 @@ export class Pokemon {
1452
1449
  if (!source && this.battle.event && this.battle.event.target)
1453
1450
  source = this.battle.event.target;
1454
1451
  const item = this.getItem();
1452
+ if (sourceEffect?.effectType === 'Item' && this.item !== sourceEffect.id && source === this) {
1453
+ // if an item is telling us to eat it but we aren't holding it, we probably shouldn't eat what we are holding
1454
+ return false;
1455
+ }
1455
1456
  if (this.battle.runEvent('UseItem', this, null, null, item)) {
1456
1457
  switch (item.id) {
1457
1458
  case 'redcard':
@@ -1472,7 +1473,7 @@ export class Pokemon {
1472
1473
  this.battle.singleEvent('Use', item, this.itemState, this, source, sourceEffect);
1473
1474
  this.lastItem = this.item;
1474
1475
  this.item = '';
1475
- this.itemState = { id: '', target: this };
1476
+ this.battle.clearEffectState(this.itemState);
1476
1477
  this.usedItemThisTurn = true;
1477
1478
  this.battle.runEvent('AfterUseItem', this, null, null, item);
1478
1479
  return true;
@@ -1496,7 +1497,7 @@ export class Pokemon {
1496
1497
  if (this.battle.runEvent('TakeItem', this, source, null, item)) {
1497
1498
  this.item = '';
1498
1499
  const oldItemState = this.itemState;
1499
- this.itemState = { id: '', target: this };
1500
+ this.battle.clearEffectState(this.itemState);
1500
1501
  this.pendingStaleness = undefined;
1501
1502
  this.battle.singleEvent('End', item, oldItemState, this);
1502
1503
  this.battle.runEvent('AfterTakeItem', this, null, null, item);
@@ -1523,7 +1524,7 @@ export class Pokemon {
1523
1524
  const oldItem = this.getItem();
1524
1525
  const oldItemState = this.itemState;
1525
1526
  this.item = item.id;
1526
- this.itemState = { id: item.id, target: this };
1527
+ this.itemState = this.battle.initEffectState({ id: item.id, target: this });
1527
1528
  if (oldItem.exists)
1528
1529
  this.battle.singleEvent('End', oldItem, oldItemState, this);
1529
1530
  if (item.id) {
@@ -1569,12 +1570,11 @@ export class Pokemon {
1569
1570
  this.battle.dex.moves.get(this.battle.effect.id));
1570
1571
  }
1571
1572
  this.ability = ability.id;
1572
- this.abilityState = { id: ability.id, target: this };
1573
+ this.abilityState = this.battle.initEffectState({ id: ability.id, target: this });
1573
1574
  if (ability.id && this.battle.gen > 3 &&
1574
1575
  (!isTransform || oldAbility !== ability.id || this.battle.gen <= 4)) {
1575
1576
  this.battle.singleEvent('Start', ability, this.abilityState, this, source);
1576
1577
  }
1577
- this.abilityOrder = this.battle.abilityOrder++;
1578
1578
  return oldAbility;
1579
1579
  }
1580
1580
  getAbility() {
@@ -1629,7 +1629,7 @@ export class Pokemon {
1629
1629
  this.battle.debug('add volatile [' + status.id + '] interrupted');
1630
1630
  return result;
1631
1631
  }
1632
- this.volatiles[status.id] = { id: status.id, name: status.name, target: this };
1632
+ this.volatiles[status.id] = this.battle.initEffectState({ id: status.id, name: status.name, target: this });
1633
1633
  if (source) {
1634
1634
  this.volatiles[status.id].source = source;
1635
1635
  this.volatiles[status.id].sourceSlot = source.getSlot();
@@ -1795,13 +1795,28 @@ export class Pokemon {
1795
1795
  return weather;
1796
1796
  }
1797
1797
  runEffectiveness(move) {
1798
- if (this.terastallized && move.type === 'Stellar')
1799
- return 1;
1800
1798
  let totalTypeMod = 0;
1801
- for (const type of this.getTypes()) {
1802
- let typeMod = this.battle.dex.getEffectiveness(move, type);
1803
- typeMod = this.battle.singleEvent('Effectiveness', move, null, this, type, move, typeMod);
1804
- totalTypeMod += this.battle.runEvent('Effectiveness', this, type, move, typeMod);
1799
+ if (this.terastallized && move.type === 'Stellar') {
1800
+ totalTypeMod = 1;
1801
+ }
1802
+ else {
1803
+ for (const type of this.getTypes()) {
1804
+ let typeMod = this.battle.dex.getEffectiveness(move, type);
1805
+ typeMod = this.battle.singleEvent('Effectiveness', move, null, this, type, move, typeMod);
1806
+ totalTypeMod += this.battle.runEvent('Effectiveness', this, type, move, typeMod);
1807
+ }
1808
+ }
1809
+ if (this.species.name === 'Terapagos-Terastal' && this.hasAbility('Tera Shell') &&
1810
+ !this.battle.suppressingAbility(this)) {
1811
+ if (this.abilityState.resisted)
1812
+ return -1; // all hits of multi-hit move should be not very effective
1813
+ if (move.category === 'Status' || move.id === 'struggle' || !this.runImmunity(move.type) ||
1814
+ totalTypeMod < 0 || this.hp < this.maxhp) {
1815
+ return totalTypeMod;
1816
+ }
1817
+ this.battle.add('-activate', this, 'ability: Tera Shell');
1818
+ this.abilityState.resisted = true;
1819
+ return -1;
1805
1820
  }
1806
1821
  return totalTypeMod;
1807
1822
  }