@pkmn/sim 0.5.14 → 0.5.15

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 (86) hide show
  1. package/build/config/formats.js +146 -135
  2. package/build/config/formats.js.map +1 -1
  3. package/build/data/aliases.js +2 -2
  4. package/build/data/aliases.js.map +1 -1
  5. package/build/data/conditions.js +4 -1
  6. package/build/data/conditions.js.map +1 -1
  7. package/build/data/formats-data.js +2 -2
  8. package/build/data/formats-data.js.map +1 -1
  9. package/build/data/items.js +4 -2
  10. package/build/data/items.js.map +1 -1
  11. package/build/data/learnsets.js +5 -4
  12. package/build/data/learnsets.js.map +1 -1
  13. package/build/data/mods/gen1/scripts.js +1 -1
  14. package/build/data/mods/gen1/scripts.js.map +1 -1
  15. package/build/data/mods/gen2/items.js +28 -0
  16. package/build/data/mods/gen2/items.js.map +1 -1
  17. package/build/data/mods/gen2/moves.js +2 -2
  18. package/build/data/mods/gen2/moves.js.map +1 -1
  19. package/build/data/mods/gen3/items.js +28 -0
  20. package/build/data/mods/gen3/items.js.map +1 -1
  21. package/build/data/mods/gen4/abilities.js +20 -0
  22. package/build/data/mods/gen4/abilities.js.map +1 -1
  23. package/build/data/mods/gen4/items.js +28 -0
  24. package/build/data/mods/gen4/items.js.map +1 -1
  25. package/build/data/mods/gen4/moves.js +14 -6
  26. package/build/data/mods/gen4/moves.js.map +1 -1
  27. package/build/data/mods/gen5/items.js +0 -4
  28. package/build/data/mods/gen5/items.js.map +1 -1
  29. package/build/data/mods/gen6/items.js +24 -0
  30. package/build/data/mods/gen6/items.js.map +1 -1
  31. package/build/data/mods/gen7/abilities.js +31 -0
  32. package/build/data/mods/gen7/abilities.js.map +1 -1
  33. package/build/data/mods/gen7/items.js +12 -0
  34. package/build/data/mods/gen7/items.js.map +1 -1
  35. package/build/data/mods/gen7/moves.js +14 -0
  36. package/build/data/mods/gen7/moves.js.map +1 -1
  37. package/build/data/moves.js +25 -12
  38. package/build/data/moves.js.map +1 -1
  39. package/build/data/rulesets.js +71 -0
  40. package/build/data/rulesets.js.map +1 -1
  41. package/build/data/tags.js +3 -3
  42. package/build/data/tags.js.map +1 -1
  43. package/build/data/text/moves.js +8 -8
  44. package/build/data/text/moves.js.map +1 -1
  45. package/build/sim/battle-queue.d.ts +2 -2
  46. package/build/sim/battle-queue.js +8 -0
  47. package/build/sim/battle-queue.js.map +1 -1
  48. package/build/sim/battle.js +42 -2
  49. package/build/sim/battle.js.map +1 -1
  50. package/build/sim/dex-conditions.d.ts +2 -2
  51. package/build/sim/dex-conditions.js.map +1 -1
  52. package/build/sim/dex-moves.d.ts +1 -0
  53. package/build/sim/dex-moves.js.map +1 -1
  54. package/build/sim/pokemon.js +18 -5
  55. package/build/sim/pokemon.js.map +1 -1
  56. package/build/sim/team-validator.js +1 -1
  57. package/build/sim/team-validator.js.map +1 -1
  58. package/config/formats.ts +151 -140
  59. package/data/aliases.ts +2 -2
  60. package/data/conditions.ts +4 -1
  61. package/data/formats-data.ts +2 -2
  62. package/data/items.ts +4 -2
  63. package/data/learnsets.ts +5 -4
  64. package/data/mods/gen1/scripts.ts +1 -1
  65. package/data/mods/gen2/items.ts +28 -0
  66. package/data/mods/gen2/moves.ts +2 -2
  67. package/data/mods/gen3/items.ts +28 -0
  68. package/data/mods/gen4/abilities.ts +20 -0
  69. package/data/mods/gen4/items.ts +28 -0
  70. package/data/mods/gen4/moves.ts +14 -7
  71. package/data/mods/gen5/items.ts +0 -4
  72. package/data/mods/gen6/items.ts +24 -0
  73. package/data/mods/gen7/abilities.ts +31 -0
  74. package/data/mods/gen7/items.ts +12 -0
  75. package/data/mods/gen7/moves.ts +14 -0
  76. package/data/moves.ts +25 -11
  77. package/data/rulesets.ts +70 -0
  78. package/data/tags.ts +3 -3
  79. package/data/text/moves.ts +8 -8
  80. package/package.json +2 -2
  81. package/sim/battle-queue.ts +10 -2
  82. package/sim/battle.ts +39 -2
  83. package/sim/dex-conditions.ts +6 -2
  84. package/sim/dex-moves.ts +1 -0
  85. package/sim/pokemon.ts +19 -7
  86. package/sim/team-validator.ts +1 -1
@@ -296,7 +296,7 @@ export const MovesText: {[k: string]: MoveText} = {
296
296
  },
297
297
  banefulbunker: {
298
298
  name: "Baneful Bunker",
299
- desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon making contact with the user become poisoned. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
299
+ desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon making contact with the user become poisoned. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
300
300
  shortDesc: "Protects from moves. Contact: poison.",
301
301
  gen7: {
302
302
  desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon making contact with the user become poisoned. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
@@ -1159,7 +1159,7 @@ export const MovesText: {[k: string]: MoveText} = {
1159
1159
  },
1160
1160
  detect: {
1161
1161
  name: "Detect",
1162
- desc: "The user is protected from most attacks made by other Pokemon during this turn. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
1162
+ desc: "The user is protected from most attacks made by other Pokemon during this turn. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
1163
1163
  shortDesc: "Prevents moves from affecting the user this turn.",
1164
1164
  gen7: {
1165
1165
  desc: "The user is protected from most attacks made by other Pokemon during this turn. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
@@ -1583,7 +1583,7 @@ export const MovesText: {[k: string]: MoveText} = {
1583
1583
  },
1584
1584
  endure: {
1585
1585
  name: "Endure",
1586
- desc: "The user will survive attacks made by other Pokemon during this turn with at least 1 HP. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
1586
+ desc: "The user will survive attacks made by other Pokemon during this turn with at least 1 HP. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
1587
1587
  shortDesc: "User survives attacks this turn with at least 1 HP.",
1588
1588
  gen7: {
1589
1589
  desc: "The user will survive attacks made by other Pokemon during this turn with at least 1 HP. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
@@ -3145,7 +3145,7 @@ export const MovesText: {[k: string]: MoveText} = {
3145
3145
  },
3146
3146
  kingsshield: {
3147
3147
  name: "King's Shield",
3148
- desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon trying to make contact with the user have their Attack lowered by 1 stage. Non-damaging moves go through this protection. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
3148
+ desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon trying to make contact with the user have their Attack lowered by 1 stage. Non-damaging moves go through this protection. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
3149
3149
  shortDesc: "Protects from damaging attacks. Contact: -1 Atk.",
3150
3150
  gen7: {
3151
3151
  desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon trying to make contact with the user have their Attack lowered by 2 stages. Non-damaging moves go through this protection. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
@@ -4417,7 +4417,7 @@ export const MovesText: {[k: string]: MoveText} = {
4417
4417
  },
4418
4418
  protect: {
4419
4419
  name: "Protect",
4420
- desc: "The user is protected from most attacks made by other Pokemon during this turn. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
4420
+ desc: "The user is protected from most attacks made by other Pokemon during this turn. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
4421
4421
  shortDesc: "Prevents moves from affecting the user this turn.",
4422
4422
  gen7: {
4423
4423
  desc: "The user is protected from most attacks made by other Pokemon during this turn. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
@@ -4570,7 +4570,7 @@ export const MovesText: {[k: string]: MoveText} = {
4570
4570
  },
4571
4571
  quickguard: {
4572
4572
  name: "Quick Guard",
4573
- desc: "The user and its party members are protected from attacks with original or altered priority greater than 0 made by other Pokemon, including allies, during this turn. This move modifies the same 1/X chance of being successful used by other protection moves, where X starts at 1 and triples each time this move is successfully used, but does not use the chance to check for failure. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn or if this move is already in effect for the user's side.",
4573
+ desc: "The user and its party members are protected from attacks with original or altered priority greater than 0 made by other Pokemon, including allies, during this turn. This move modifies the same 1/X chance of being successful used by other protection moves, where X starts at 1 and triples each time this move is successfully used, but does not use the chance to check for failure. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn or if this move is already in effect for the user's side.",
4574
4574
  shortDesc: "Protects allies from priority attacks this turn.",
4575
4575
  gen7: {
4576
4576
  desc: "The user and its party members are protected from attacks with original or altered priority greater than 0 made by other Pokemon, including allies, during this turn. This move modifies the same 1/X chance of being successful used by other protection moves, where X starts at 1 and triples each time this move is successfully used, but does not use the chance to check for failure. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn or if this move is already in effect for the user's side.",
@@ -5613,7 +5613,7 @@ export const MovesText: {[k: string]: MoveText} = {
5613
5613
  },
5614
5614
  spikyshield: {
5615
5615
  name: "Spiky Shield",
5616
- desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon making contact with the user lose 1/8 of their maximum HP, rounded down. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
5616
+ desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon making contact with the user lose 1/8 of their maximum HP, rounded down. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
5617
5617
  shortDesc: "Protects from moves. Contact: loses 1/8 max HP.",
5618
5618
  gen7: {
5619
5619
  desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon making contact with the user lose 1/8 of their maximum HP, rounded down. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.",
@@ -6701,7 +6701,7 @@ export const MovesText: {[k: string]: MoveText} = {
6701
6701
  },
6702
6702
  wideguard: {
6703
6703
  name: "Wide Guard",
6704
- desc: "The user and its party members are protected from moves made by other Pokemon, including allies, during this turn that target all adjacent foes or all adjacent Pokemon. This move modifies the same 1/X chance of being successful used by other protection moves, where X starts at 1 and triples each time this move is successfully used, but does not use the chance to check for failure. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn or if this move is already in effect for the user's side.",
6704
+ desc: "The user and its party members are protected from moves made by other Pokemon, including allies, during this turn that target all adjacent foes or all adjacent Pokemon. This move modifies the same 1/X chance of being successful used by other protection moves, where X starts at 1 and triples each time this move is successfully used, but does not use the chance to check for failure. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Max Guard, Obstruct, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn or if this move is already in effect for the user's side.",
6705
6705
  shortDesc: "Protects allies from multi-target moves this turn.",
6706
6706
  gen7: {
6707
6707
  desc: "The user and its party members are protected from moves made by other Pokemon, including allies, during this turn that target all adjacent foes or all adjacent Pokemon. This move modifies the same 1/X chance of being successful used by other protection moves, where X starts at 1 and triples each time this move is successfully used, but does not use the chance to check for failure. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn or if this move is already in effect for the user's side.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/sim",
3
- "version": "0.5.14",
3
+ "version": "0.5.15",
4
4
  "description": "An automatically generated extraction of just the simulator portion of Pokémon Showdown",
5
5
  "homepage": "https://psim.us",
6
6
  "main": "build/sim/index.js",
@@ -31,7 +31,7 @@
31
31
  "@pkmn/streams": "^1.0.0"
32
32
  },
33
33
  "devDependencies": {
34
- "mocha": "^9.2.2"
34
+ "mocha": "^10.0.0"
35
35
  },
36
36
  "scripts": {
37
37
  "compile": "tsc -p .",
@@ -20,8 +20,8 @@ import type {Battle} from './battle';
20
20
  /** A move action */
21
21
  export interface MoveAction {
22
22
  /** action type */
23
- choice: 'move' | 'beforeTurnMove';
24
- order: 3 | 5 | 200 | 201 | 199;
23
+ choice: 'move' | 'beforeTurnMove' | 'priorityChargeMove';
24
+ order: 3 | 5 | 200 | 201 | 199 | 106;
25
25
  /** priority of the action (lower first) */
26
26
  priority: number;
27
27
  /** fractional priority of the action (lower first) */
@@ -181,6 +181,7 @@ export class BattleQueue {
181
181
  switch: 103,
182
182
  megaEvo: 104,
183
183
  runDynamax: 105,
184
+ priorityChargeMove: 106,
184
185
 
185
186
  shift: 200,
186
187
  // default is 200 (for moves)
@@ -215,6 +216,13 @@ export class BattleQueue {
215
216
  pokemon: action.pokemon,
216
217
  }));
217
218
  }
219
+ if (!action.maxMove && !action.zmove && action.move.priorityChargeCallback) {
220
+ actions.unshift(...this.resolveAction({
221
+ choice: 'priorityChargeMove',
222
+ pokemon: action.pokemon,
223
+ move: action.move,
224
+ }));
225
+ }
218
226
  action.fractionalPriority = this.battle.runEvent('FractionalPriority', action.pokemon, null, action.move, 0);
219
227
  } else if (['switch', 'instaswitch'].includes(action.choice)) {
220
228
  if (typeof action.pokemon.switchFlag === 'string') {
package/sim/battle.ts CHANGED
@@ -1419,6 +1419,20 @@ export class Battle {
1419
1419
  this.turn++;
1420
1420
  this.lastSuccessfulMoveThisTurn = null;
1421
1421
 
1422
+ const dynamaxEnding: Pokemon[] = [];
1423
+ for (const pokemon of this.getAllActive()) {
1424
+ if (pokemon.volatiles['dynamax']?.turns === 3) {
1425
+ dynamaxEnding.push(pokemon);
1426
+ }
1427
+ }
1428
+ if (dynamaxEnding.length > 1) {
1429
+ this.updateSpeed();
1430
+ this.speedSort(dynamaxEnding);
1431
+ }
1432
+ for (const pokemon of dynamaxEnding) {
1433
+ pokemon.removeVolatile('dynamax');
1434
+ }
1435
+
1422
1436
  const trappedBySide: boolean[] = [];
1423
1437
  const stalenessBySide: ('internal' | 'external' | undefined)[] = [];
1424
1438
  for (const side of this.sides) {
@@ -1548,6 +1562,23 @@ export class Battle {
1548
1562
  if (this.gen === 2) this.quickClawRoll = this.randomChance(60, 256);
1549
1563
  if (this.gen === 3) this.quickClawRoll = this.randomChance(1, 5);
1550
1564
 
1565
+ // Crazyhouse Progress checker because sidebars has trouble keeping track of Pokemon.
1566
+ // Please remove me once there is client support.
1567
+ if (this.ruleTable.has('crazyhouserule')) {
1568
+ for (const side of this.sides) {
1569
+ let buf = `raw|${side.name}'s team:<br />`;
1570
+ for (const pokemon of side.pokemon) {
1571
+ if (!buf.endsWith('<br />')) buf += '/</span>&#8203;';
1572
+ if (pokemon.fainted) {
1573
+ buf += `<span style="white-space:nowrap;"><span style="opacity:.3"><psicon pokemon="${pokemon.species.id}" /></span>`;
1574
+ } else {
1575
+ buf += `<span style="white-space:nowrap"><psicon pokemon="${pokemon.species.id}" />`;
1576
+ }
1577
+ }
1578
+ this.add(`${buf}</span>`);
1579
+ }
1580
+ }
1581
+
1551
1582
  this.makeRequest('move');
1552
1583
  }
1553
1584
 
@@ -2422,7 +2453,7 @@ export class Battle {
2422
2453
  action.pokemon.side.dynamaxUsed = true;
2423
2454
  if (action.pokemon.side.allySide) action.pokemon.side.allySide.dynamaxUsed = true;
2424
2455
  break;
2425
- case 'beforeTurnMove': {
2456
+ case 'beforeTurnMove':
2426
2457
  if (!action.pokemon.isActive) return false;
2427
2458
  if (action.pokemon.fainted) return false;
2428
2459
  this.debug('before turn callback: ' + action.move.id);
@@ -2431,7 +2462,13 @@ export class Battle {
2431
2462
  if (!action.move.beforeTurnCallback) throw new Error(`beforeTurnMove has no beforeTurnCallback`);
2432
2463
  action.move.beforeTurnCallback.call(this, action.pokemon, target);
2433
2464
  break;
2434
- }
2465
+ case 'priorityChargeMove':
2466
+ if (!action.pokemon.isActive) return false;
2467
+ if (action.pokemon.fainted) return false;
2468
+ this.debug('priority charge callback: ' + action.move.id);
2469
+ if (!action.move.priorityChargeCallback) throw new Error(`priorityChargeMove has no priorityChargeCallback`);
2470
+ action.move.priorityChargeCallback.call(this, action.pokemon);
2471
+ break;
2435
2472
 
2436
2473
  case 'event':
2437
2474
  this.runEvent(action.event!, action.pokemon);
@@ -635,8 +635,12 @@ export class Condition extends BasicEffect implements
635
635
  declare readonly durationCallback?: (this: Battle, target: Pokemon, source: Pokemon, effect: Effect | null) => number;
636
636
  declare readonly onCopy?: (this: Battle, pokemon: Pokemon) => void;
637
637
  declare readonly onEnd?: (this: Battle, target: Pokemon) => void;
638
- declare readonly onRestart?: (this: Battle, target: Pokemon, source: Pokemon, sourceEffect: Effect) => void;
639
- declare readonly onStart?: (this: Battle, target: Pokemon, source: Pokemon, sourceEffect: Effect) => void;
638
+ declare readonly onRestart?: (
639
+ this: Battle, target: Pokemon, source: Pokemon, sourceEffect: Effect
640
+ ) => boolean | null | void;
641
+ declare readonly onStart?: (
642
+ this: Battle, target: Pokemon, source: Pokemon, sourceEffect: Effect
643
+ ) => boolean | null | void;
640
644
 
641
645
  constructor(data: AnyObject) {
642
646
  super(data);
package/sim/dex-moves.ts CHANGED
@@ -105,6 +105,7 @@ export interface MoveEventMethods {
105
105
  beforeMoveCallback?: (this: Battle, pokemon: Pokemon, target: Pokemon | null, move: ActiveMove) => boolean | void;
106
106
  beforeTurnCallback?: (this: Battle, pokemon: Pokemon, target: Pokemon) => void;
107
107
  damageCallback?: (this: Battle, pokemon: Pokemon, target: Pokemon) => number | false;
108
+ priorityChargeCallback?: (this: Battle, pokemon: Pokemon) => void;
108
109
 
109
110
  onAfterHit?: CommonHandlers['VoidSourceMove'];
110
111
  onAfterSubDamage?: (this: Battle, damage: number, target: Pokemon, source: Pokemon, move: ActiveMove) => void;
package/sim/pokemon.ts CHANGED
@@ -809,9 +809,12 @@ export class Pokemon {
809
809
  }
810
810
 
811
811
  ignoringItem() {
812
- return !!((this.battle.gen >= 5 && !this.isActive) ||
812
+ return !!(
813
+ this.itemState.knockedOff || // Gen 3-4
814
+ (this.battle.gen >= 5 && !this.isActive) ||
813
815
  (this.hasAbility('klutz') && !this.getItem().ignoreKlutz) ||
814
- this.volatiles['embargo'] || this.battle.field.pseudoWeather['magicroom']);
816
+ this.volatiles['embargo'] || this.battle.field.pseudoWeather['magicroom']
817
+ );
815
818
  }
816
819
 
817
820
  deductPP(move: string | Move, amount?: number | null, target?: Pokemon | null | false) {
@@ -1198,7 +1201,15 @@ export class Pokemon {
1198
1201
  }
1199
1202
  let boostName: BoostID;
1200
1203
  for (boostName in pokemon.boosts) {
1201
- this.boosts[boostName] = pokemon.boosts[boostName]!;
1204
+ this.boosts[boostName] = pokemon.boosts[boostName];
1205
+ if (this.battle.gen <= 1) {
1206
+ if (boostName === 'evasion' || boostName === 'accuracy') continue;
1207
+ if (this.boosts[boostName] >= 0) {
1208
+ this.modifyStat!(boostName, [1, 1.5, 2, 2.5, 3, 3.5, 4][this.boosts[boostName]]);
1209
+ } else {
1210
+ this.modifyStat!(boostName, [100, 66, 50, 40, 33, 28, 25][-this.boosts[boostName]] / 100);
1211
+ }
1212
+ }
1202
1213
  }
1203
1214
  if (this.battle.gen >= 6) {
1204
1215
  const volatilesToCopy = ['focusenergy', 'gmaxchistrike', 'laserfocus'];
@@ -1596,7 +1607,7 @@ export class Pokemon {
1596
1607
  }
1597
1608
 
1598
1609
  eatItem(force?: boolean, source?: Pokemon, sourceEffect?: Effect) {
1599
- if (!this.item) return false;
1610
+ if (!this.item || this.itemState.knockedOff) return false;
1600
1611
  if ((!this.hp && this.item !== 'jabocaberry' && this.item !== 'rowapberry') || !this.isActive) return false;
1601
1612
 
1602
1613
  if (!sourceEffect && this.battle.effect) sourceEffect = this.battle.effect;
@@ -1636,7 +1647,7 @@ export class Pokemon {
1636
1647
 
1637
1648
  useItem(source?: Pokemon, sourceEffect?: Effect) {
1638
1649
  if ((!this.hp && !this.getItem().isGem) || !this.isActive) return false;
1639
- if (!this.item) return false;
1650
+ if (!this.item || this.itemState.knockedOff) return false;
1640
1651
 
1641
1652
  if (!sourceEffect && this.battle.effect) sourceEffect = this.battle.effect;
1642
1653
  if (!source && this.battle.event && this.battle.event.target) source = this.battle.event.target;
@@ -1672,11 +1683,11 @@ export class Pokemon {
1672
1683
 
1673
1684
  takeItem(source?: Pokemon) {
1674
1685
  if (!this.isActive) return false;
1675
- if (!this.item) return false;
1686
+ if (!this.item || this.itemState.knockedOff) return false;
1676
1687
  if (!source) source = this;
1677
1688
  if (this.battle.gen === 4) {
1678
1689
  if (toID(this.ability) === 'multitype') return false;
1679
- if (source && toID(source.ability) === 'multitype') return false;
1690
+ if (toID(source.ability) === 'multitype') return false;
1680
1691
  }
1681
1692
  const item = this.getItem();
1682
1693
  if (this.battle.runEvent('TakeItem', this, source, null, item)) {
@@ -1690,6 +1701,7 @@ export class Pokemon {
1690
1701
 
1691
1702
  setItem(item: string | Item, source?: Pokemon, effect?: Effect) {
1692
1703
  if (!this.hp || !this.isActive) return false;
1704
+ if (this.itemState.knockedOff) return false;
1693
1705
  if (typeof item === 'string') item = this.battle.dex.items.get(item);
1694
1706
 
1695
1707
  const effectid = this.battle.effect ? this.battle.effect.id : '';
@@ -1564,7 +1564,7 @@ export class TeamValidator {
1564
1564
 
1565
1565
  setHas['ability:' + ability.id] = true;
1566
1566
 
1567
- if (this.format.id === 'gen8pokebilities') {
1567
+ if (this.format.id.startsWith('gen8pokebilities')) {
1568
1568
  const species = dex.species.get(set.species);
1569
1569
  const unSeenAbilities = Object.keys(species.abilities)
1570
1570
  .filter(key => key !== 'S' && (key !== 'H' || !species.unreleasedHidden))