@pkmn/sim 0.5.0 → 0.5.4

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 (75) hide show
  1. package/build/config/formats.js +356 -266
  2. package/build/config/formats.js.map +1 -1
  3. package/build/data/abilities.js +5 -1
  4. package/build/data/abilities.js.map +1 -1
  5. package/build/data/aliases.js +2 -2
  6. package/build/data/aliases.js.map +1 -1
  7. package/build/data/formats-data.js +91 -92
  8. package/build/data/formats-data.js.map +1 -1
  9. package/build/data/items.js +5 -5
  10. package/build/data/items.js.map +1 -1
  11. package/build/data/learnsets.js +1 -1
  12. package/build/data/learnsets.js.map +1 -1
  13. package/build/data/mods/gen1/formats-data.js +190 -190
  14. package/build/data/mods/gen1/formats-data.js.map +1 -1
  15. package/build/data/mods/gen1/moves.js +1 -2
  16. package/build/data/mods/gen1/moves.js.map +1 -1
  17. package/build/data/mods/gen1/scripts.js +12 -0
  18. package/build/data/mods/gen1/scripts.js.map +1 -1
  19. package/build/data/mods/gen2/formats-data.js +2 -2
  20. package/build/data/mods/gen2/formats-data.js.map +1 -1
  21. package/build/data/mods/gen3/formats-data.js +12 -12
  22. package/build/data/mods/gen3/formats-data.js.map +1 -1
  23. package/build/data/mods/gen4/moves.js +22 -0
  24. package/build/data/mods/gen4/moves.js.map +1 -1
  25. package/build/data/mods/gen5/formats-data.js +15 -15
  26. package/build/data/mods/gen5/formats-data.js.map +1 -1
  27. package/build/data/mods/gen6/formats-data.js +1 -1
  28. package/build/data/mods/gen7/formats-data.js +1 -1
  29. package/build/data/mods/gen7/formats-data.js.map +1 -1
  30. package/build/data/mods/gen7/moves.js +154 -0
  31. package/build/data/mods/gen7/moves.js.map +1 -1
  32. package/build/data/moves.js +47 -20
  33. package/build/data/moves.js.map +1 -1
  34. package/build/data/pokedex.js +2 -2
  35. package/build/data/rulesets.js +48 -5
  36. package/build/data/rulesets.js.map +1 -1
  37. package/build/data/tags.js +3 -2
  38. package/build/data/tags.js.map +1 -1
  39. package/build/data/text/moves.js +1 -1
  40. package/build/data/text/moves.js.map +1 -1
  41. package/build/sim/battle-actions.js +8 -3
  42. package/build/sim/battle-actions.js.map +1 -1
  43. package/build/sim/exported-global-types.d.ts +1 -0
  44. package/build/sim/global-types.d.ts +1 -0
  45. package/build/sim/pokemon.js +1 -1
  46. package/build/sim/pokemon.js.map +1 -1
  47. package/build/sim/team-validator.js +3 -0
  48. package/build/sim/team-validator.js.map +1 -1
  49. package/config/formats.ts +363 -269
  50. package/data/abilities.ts +3 -1
  51. package/data/aliases.ts +2 -2
  52. package/data/formats-data.ts +91 -92
  53. package/data/items.ts +5 -5
  54. package/data/learnsets.ts +1 -1
  55. package/data/mods/gen1/formats-data.ts +190 -190
  56. package/data/mods/gen1/moves.ts +1 -2
  57. package/data/mods/gen1/scripts.ts +11 -0
  58. package/data/mods/gen2/formats-data.ts +2 -2
  59. package/data/mods/gen3/formats-data.ts +12 -12
  60. package/data/mods/gen4/moves.ts +21 -0
  61. package/data/mods/gen5/formats-data.ts +15 -15
  62. package/data/mods/gen6/formats-data.ts +1 -1
  63. package/data/mods/gen7/formats-data.ts +1 -1
  64. package/data/mods/gen7/moves.ts +150 -0
  65. package/data/moves.ts +46 -20
  66. package/data/pokedex.ts +2 -2
  67. package/data/rulesets.ts +44 -6
  68. package/data/tags.ts +3 -2
  69. package/data/text/moves.ts +1 -1
  70. package/package.json +1 -1
  71. package/sim/battle-actions.ts +8 -3
  72. package/sim/exported-global-types.ts +1 -0
  73. package/sim/global-types.ts +1 -0
  74. package/sim/pokemon.ts +1 -1
  75. package/sim/team-validator.ts +3 -0
package/data/moves.ts CHANGED
@@ -4574,7 +4574,7 @@ export const Moves: {[moveid: string]: MoveData} = {
4574
4574
  pseudoWeather: 'fairylock',
4575
4575
  condition: {
4576
4576
  duration: 2,
4577
- onStart(target) {
4577
+ onFieldStart(target) {
4578
4578
  this.add('-fieldactivate', 'move: Fairy Lock');
4579
4579
  },
4580
4580
  onTrapPokemon(pokemon) {
@@ -5320,6 +5320,10 @@ export const Moves: {[moveid: string]: MoveData} = {
5320
5320
  if (success && !target.isAlly(source)) {
5321
5321
  target.staleness = 'external';
5322
5322
  }
5323
+ if (!success) {
5324
+ this.add('-fail', target, 'heal');
5325
+ return this.NOT_FAIL;
5326
+ }
5323
5327
  return success;
5324
5328
  },
5325
5329
  secondary: null,
@@ -7854,6 +7858,10 @@ export const Moves: {[moveid: string]: MoveData} = {
7854
7858
  if (success && !target.isAlly(source)) {
7855
7859
  target.staleness = 'external';
7856
7860
  }
7861
+ if (!success) {
7862
+ this.add('-fail', target, 'heal');
7863
+ return this.NOT_FAIL;
7864
+ }
7857
7865
  return success;
7858
7866
  },
7859
7867
  secondary: null,
@@ -9077,7 +9085,7 @@ export const Moves: {[moveid: string]: MoveData} = {
9077
9085
  pseudoWeather: 'iondeluge',
9078
9086
  condition: {
9079
9087
  duration: 1,
9080
- onStart(target, source, sourceEffect) {
9088
+ onFieldStart(target, source, sourceEffect) {
9081
9089
  this.add('-fieldactivate', 'move: Ion Deluge');
9082
9090
  this.hint(`Normal-type moves become Electric-type after using ${sourceEffect}.`);
9083
9091
  },
@@ -10420,16 +10428,10 @@ export const Moves: {[moveid: string]: MoveData} = {
10420
10428
  },
10421
10429
  onTryHitPriority: 3,
10422
10430
  onTryHit(target, source, move) {
10423
- if (['gmaxoneblow', 'gmaxrapidflow'].includes(move.id)) return;
10424
- /** moves blocked by Max Guard but not Protect */
10425
- const overrideBypassProtect = [
10426
- 'block', 'flowershield', 'gearup', 'magneticflux', 'phantomforce', 'psychup', 'shadowforce', 'teatime', 'transform', 'whirlwind',
10431
+ const bypassesMaxGuard = [
10432
+ 'acupressure', 'afteryou', 'allyswitch', 'aromatherapy', 'aromaticmist', 'coaching', 'confide', 'copycat', 'curse', 'decorate', 'doomdesire', 'feint', 'futuresight', 'gmaxoneblow', 'gmaxrapidflow', 'healbell', 'holdhands', 'howl', 'junglehealing', 'lifedew', 'meanlook', 'perishsong', 'playnice', 'powertrick', 'roar', 'roleplay', 'tearfullook',
10427
10433
  ];
10428
- const blockedByMaxGuard = (this.dex.moves.get(move.id).flags['protect'] ||
10429
- move.isZ || move.isMax || overrideBypassProtect.includes(move.id));
10430
- if (!blockedByMaxGuard) {
10431
- return;
10432
- }
10434
+ if (bypassesMaxGuard.includes(move.id)) return;
10433
10435
  if (move.smartTarget) {
10434
10436
  move.smartTarget = false;
10435
10437
  } else {
@@ -11090,7 +11092,9 @@ export const Moves: {[moveid: string]: MoveData} = {
11090
11092
  priority: 0,
11091
11093
  flags: {protect: 1, bypasssub: 1, allyanim: 1},
11092
11094
  onHit(target, source) {
11093
- const disallowedMoves = ['chatter', 'dynamaxcannon', 'mimic', 'sketch', 'struggle', 'transform'];
11095
+ const disallowedMoves = [
11096
+ 'behemothbash', 'behemothblade', 'chatter', 'dynamaxcannon', 'mimic', 'sketch', 'struggle', 'transform',
11097
+ ];
11094
11098
  const move = target.lastMove;
11095
11099
  if (source.transformed || !move || disallowedMoves.includes(move.id) || source.moves.includes(move.id)) {
11096
11100
  return false;
@@ -11518,7 +11522,12 @@ export const Moves: {[moveid: string]: MoveData} = {
11518
11522
  factor = 0.25;
11519
11523
  break;
11520
11524
  }
11521
- return !!this.heal(this.modify(pokemon.maxhp, factor));
11525
+ const success = !!this.heal(this.modify(pokemon.maxhp, factor));
11526
+ if (!success) {
11527
+ this.add('-fail', pokemon, 'heal');
11528
+ return this.NOT_FAIL;
11529
+ }
11530
+ return success;
11522
11531
  },
11523
11532
  secondary: null,
11524
11533
  target: "self",
@@ -11549,7 +11558,12 @@ export const Moves: {[moveid: string]: MoveData} = {
11549
11558
  factor = 0.25;
11550
11559
  break;
11551
11560
  }
11552
- return !!this.heal(this.modify(pokemon.maxhp, factor));
11561
+ const success = !!this.heal(this.modify(pokemon.maxhp, factor));
11562
+ if (!success) {
11563
+ this.add('-fail', pokemon, 'heal');
11564
+ return this.NOT_FAIL;
11565
+ }
11566
+ return success;
11553
11567
  },
11554
11568
  secondary: null,
11555
11569
  target: "self",
@@ -12738,6 +12752,7 @@ export const Moves: {[moveid: string]: MoveData} = {
12738
12752
  if (source.isAlly(target)) {
12739
12753
  if (!this.heal(Math.floor(target.baseMaxhp * 0.5))) {
12740
12754
  this.add('-immune', target);
12755
+ return this.NOT_FAIL;
12741
12756
  }
12742
12757
  }
12743
12758
  },
@@ -13400,7 +13415,7 @@ export const Moves: {[moveid: string]: MoveData} = {
13400
13415
  priority: 0,
13401
13416
  flags: {protect: 1, reflectable: 1, heal: 1},
13402
13417
  onHit(target, source) {
13403
- if (!target.cureStatus()) return false;
13418
+ if (!target.cureStatus()) return this.NOT_FAIL;
13404
13419
  this.heal(Math.ceil(source.maxhp * 0.5), source);
13405
13420
  },
13406
13421
  secondary: null,
@@ -15259,7 +15274,12 @@ export const Moves: {[moveid: string]: MoveData} = {
15259
15274
  if (this.field.isWeather('sandstorm')) {
15260
15275
  factor = 0.667;
15261
15276
  }
15262
- return !!this.heal(this.modify(pokemon.maxhp, factor));
15277
+ const success = !!this.heal(this.modify(pokemon.maxhp, factor));
15278
+ if (!success) {
15279
+ this.add('-fail', pokemon, 'heal');
15280
+ return this.NOT_FAIL;
15281
+ }
15282
+ return success;
15263
15283
  },
15264
15284
  secondary: null,
15265
15285
  target: "self",
@@ -15752,7 +15772,7 @@ export const Moves: {[moveid: string]: MoveData} = {
15752
15772
  const moveid = moveSlot.id;
15753
15773
  if (!moveid) continue;
15754
15774
  const move = this.dex.moves.get(moveid);
15755
- if (noSleepTalk.includes(moveid) || move.flags['charge'] || (move.isZ && move.basePower !== 1)) {
15775
+ if (noSleepTalk.includes(moveid) || move.flags['charge'] || (move.isZ && move.basePower !== 1) || move.isMax) {
15756
15776
  continue;
15757
15777
  }
15758
15778
  moves.push(moveid);
@@ -17389,9 +17409,10 @@ export const Moves: {[moveid: string]: MoveData} = {
17389
17409
  },
17390
17410
  onHit(pokemon) {
17391
17411
  const healAmount = [0.25, 0.5, 1];
17392
- const healedBy = this.heal(this.modify(pokemon.maxhp, healAmount[(pokemon.volatiles['stockpile'].layers - 1)]));
17412
+ const success = !!this.heal(this.modify(pokemon.maxhp, healAmount[(pokemon.volatiles['stockpile'].layers - 1)]));
17413
+ if (!success) this.add('-fail', pokemon, 'heal');
17393
17414
  pokemon.removeVolatile('stockpile');
17394
- return !!healedBy;
17415
+ return success || this.NOT_FAIL;
17395
17416
  },
17396
17417
  secondary: null,
17397
17418
  target: "self",
@@ -17554,7 +17575,12 @@ export const Moves: {[moveid: string]: MoveData} = {
17554
17575
  factor = 0.25;
17555
17576
  break;
17556
17577
  }
17557
- return !!this.heal(this.modify(pokemon.maxhp, factor));
17578
+ const success = !!this.heal(this.modify(pokemon.maxhp, factor));
17579
+ if (!success) {
17580
+ this.add('-fail', pokemon, 'heal');
17581
+ return this.NOT_FAIL;
17582
+ }
17583
+ return success;
17558
17584
  },
17559
17585
  secondary: null,
17560
17586
  target: "self",
package/data/pokedex.ts CHANGED
@@ -16911,7 +16911,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
16911
16911
  gen: 4,
16912
16912
  },
16913
16913
  venomicon: {
16914
- num: -67,
16914
+ num: -66,
16915
16915
  name: "Venomicon",
16916
16916
  baseForme: "Prologue",
16917
16917
  types: ["Poison", "Flying"],
@@ -16927,7 +16927,7 @@ export const Pokedex: {[speciesid: string]: SpeciesData} = {
16927
16927
  gen: 8,
16928
16928
  },
16929
16929
  venomiconepilogue: {
16930
- num: -67,
16930
+ num: -66,
16931
16931
  name: "Venomicon-Epilogue",
16932
16932
  baseSpecies: "Venomicon",
16933
16933
  forme: "Epilogue",
package/data/rulesets.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Note: These are the rules that formats use
1
+ // Note: These are the rules that formats use
2
2
 
3
3
  import {Utils} from "../lib";
4
4
 
@@ -791,13 +791,51 @@ export const Rulesets: {[k: string]: FormatData} = {
791
791
  ];
792
792
  },
793
793
  },
794
- "3batonpassclause": {
794
+ onebatonpassclause: {
795
795
  effectType: 'ValidatorRule',
796
- name: '3 Baton Pass Clause',
797
- desc: "Stops teams from having more than three Pokémon with Baton Pass",
798
- banlist: ["Baton Pass > 3"],
796
+ name: 'One Baton Pass Clause',
797
+ desc: "Stops teams from having more than one Pokémon with Baton Pass",
798
+ banlist: ["Baton Pass > 1"],
799
+ onBegin() {
800
+ this.add('rule', 'One Baton Pass Clause: Limit one Baton Passer');
801
+ },
802
+ },
803
+ oneboostpasserclause: {
804
+ effectType: 'ValidatorRule',
805
+ name: 'One Boost Passer Clause',
806
+ desc: "Stops teams from having a Pokémon with Baton Pass that has multiple ways to boost its stats, and no more than one Baton Passer may be able to boost its stats",
799
807
  onBegin() {
800
- this.add('rule', '3 Baton Pass Clause: Limit three Baton Passers');
808
+ this.add('rule', 'One Boost Passer Clause: Limit one Baton Passer that has a way to boost its stats');
809
+ },
810
+ onValidateTeam(team) {
811
+ const boostingEffects = [
812
+ 'acidarmor', 'agility', 'amnesia', 'apicotberry', 'barrier', 'bellydrum', 'bulkup', 'calmmind', 'cosmicpower', 'curse',
813
+ 'defensecurl', 'dragondance', 'ganlonberry', 'growth', 'harden', 'howl', 'irondefense', 'liechiberry', 'meditate',
814
+ 'petayaberry', 'salacberry', 'sharpen', 'speedboost', 'starfberry', 'swordsdance', 'tailglow', 'withdraw',
815
+ ];
816
+ let passers = 0;
817
+ for (const set of team) {
818
+ if (!set.moves.includes('Baton Pass')) continue;
819
+ let passableBoosts = 0;
820
+ const item = this.toID(set.item);
821
+ const ability = this.toID(set.ability);
822
+ for (const move of set.moves) {
823
+ if (boostingEffects.includes(this.toID(move))) passableBoosts++;
824
+ }
825
+ if (boostingEffects.includes(item)) passableBoosts++;
826
+ if (boostingEffects.includes(ability)) passableBoosts++;
827
+ if (passableBoosts === 1) passers++;
828
+ if (passableBoosts > 1) {
829
+ return [
830
+ `${set.name || set.species} has Baton Pass and multiple ways to boost its stats, which is banned by One Boost Passer Clause.`,
831
+ ];
832
+ }
833
+ if (passers > 1) {
834
+ return [
835
+ `Multiple Pokemon have Baton Pass and a way to boost their stats, which is banned by One Boost Passer Clause.`,
836
+ ];
837
+ }
838
+ }
801
839
  },
802
840
  },
803
841
  cfzclause: {
package/data/tags.ts CHANGED
@@ -196,8 +196,9 @@ export const Tags: {[id: string]: TagData} = {
196
196
  name: "ND UUBL",
197
197
  speciesFilter: species => [
198
198
  'Aerodactyl-Mega', 'Azumarill', 'Blacephalon', 'Diancie-Mega', 'Gallade-Mega', 'Gardevoir-Mega', 'Gengar', 'Gyarados', 'Gyarados-Mega',
199
- 'Hawlucha', 'Heracross-Mega', 'Hoopa-Unbound', 'Hydreigon', 'Jirachi', 'Latias', 'Latias-Mega', 'Latios', 'Latios-Mega', 'Manaphy', 'Mew',
200
- 'Pinsir-Mega', 'Sableye-Mega', 'Slowbro-Mega', 'Slowking-Galar', 'Thundurus', 'Thundurus-Therian', 'Venusaur-Mega', 'Xurkitree', 'Zapdos-Galar',
199
+ 'Hawlucha', 'Heracross-Mega', 'Hoopa-Unbound', 'Hydreigon', 'Jirachi', 'Latias', 'Latias-Mega', 'Latios', 'Latios-Mega', 'Manaphy',
200
+ 'Medicham-Mega', 'Mew', 'Pinsir-Mega', 'Sableye-Mega', 'Slowbro-Mega', 'Slowking-Galar', 'Thundurus', 'Thundurus-Therian', 'Venusaur-Mega',
201
+ 'Xurkitree', 'Zapdos-Galar',
201
202
  ].includes(species.name),
202
203
  },
203
204
 
@@ -3729,7 +3729,7 @@ export const MovesText: {[k: string]: MoveText} = {
3729
3729
  },
3730
3730
  mimic: {
3731
3731
  name: "Mimic",
3732
- desc: "While the user remains active, this move is replaced by the last move used by the target. The copied move has the maximum PP for that move. Fails if the target has not made a move, if the user has Transformed, if the user already knows the move, or if the move is Chatter, Dynamax Cannon, Mimic, Sketch, Struggle, Transform, or any Z-Move.",
3732
+ desc: "While the user remains active, this move is replaced by the last move used by the target. The copied move has the maximum PP for that move. Fails if the target has not made a move, if the user has Transformed, if the user already knows the move, or if the move is Behemoth Bash, Behemoth Blade, Chatter, Dynamax Cannon, Mimic, Sketch, Struggle, Transform, or any Z-Move.",
3733
3733
  shortDesc: "The last move the target used replaces this one.",
3734
3734
  gen6: {
3735
3735
  desc: "While the user remains active, this move is replaced by the last move used by the target. The copied move has the maximum PP for that move. Fails if the target has not made a move, if the user has Transformed, if the user already knows the move, or if the move is Chatter, Mimic, Sketch, Struggle, or Transform.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/sim",
3
- "version": "0.5.0",
3
+ "version": "0.5.4",
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",
@@ -438,7 +438,8 @@ export class BattleActions {
438
438
  target = targets[targets.length - 1]; // in case of redirection
439
439
  }
440
440
 
441
- if (!sourceEffect || sourceEffect.id === 'pursuit') {
441
+ const callerMoveForPressure = sourceEffect && (sourceEffect as ActiveMove).pp ? sourceEffect as ActiveMove : null;
442
+ if (!sourceEffect || callerMoveForPressure || sourceEffect.id === 'pursuit') {
442
443
  let extraPP = 0;
443
444
  for (const source of pressureTargets) {
444
445
  const ppDrop = this.battle.runEvent('DeductPP', source, pokemon, move);
@@ -447,7 +448,7 @@ export class BattleActions {
447
448
  }
448
449
  }
449
450
  if (extraPP > 0) {
450
- pokemon.deductPP(moveOrMoveName, extraPP);
451
+ pokemon.deductPP(callerMoveForPressure || moveOrMoveName, extraPP);
451
452
  }
452
453
  }
453
454
 
@@ -1447,7 +1448,7 @@ export class BattleActions {
1447
1448
  this.battle.heal(pokemon.maxhp, pokemon, pokemon, zPower);
1448
1449
  break;
1449
1450
  case 'healreplacement':
1450
- move.self = {slotCondition: 'healreplacement'};
1451
+ pokemon.side.addSlotCondition(pokemon, 'healreplacement', pokemon, move);
1451
1452
  break;
1452
1453
  case 'clearnegativeboost':
1453
1454
  const boosts: SparseBoostsTable = {};
@@ -1575,6 +1576,10 @@ export class BattleActions {
1575
1576
 
1576
1577
  if (!basePower) return 0;
1577
1578
  basePower = this.battle.clampIntRange(basePower, 1);
1579
+ // Hacked Max Moves have 0 base power, even if you Dynamax
1580
+ if ((!source.volatiles['dynamax'] && move.isMax) || (move.isMax && this.dex.moves.get(move.baseMove).isMax)) {
1581
+ basePower = 0;
1582
+ }
1578
1583
 
1579
1584
  const level = source.level;
1580
1585
 
@@ -309,6 +309,7 @@ export interface ModdedBattlePokemon {
309
309
  inherit?: true;
310
310
  lostItemForDelibird?: Item | null;
311
311
  boostBy?: (this: Pokemon, boost: SparseBoostsTable) => boolean | number;
312
+ clearBoosts?: (this: Pokemon) => void;
312
313
  calculateStat?: (this: Pokemon, statName: StatIDExceptHP, boost: number, modifier?: number) => number;
313
314
  cureStatus?: (this: Pokemon, silent?: boolean) => boolean;
314
315
  getAbility?: (this: Pokemon) => Ability;
@@ -309,6 +309,7 @@ interface ModdedBattlePokemon {
309
309
  inherit?: true;
310
310
  lostItemForDelibird?: Item | null;
311
311
  boostBy?: (this: Pokemon, boost: SparseBoostsTable) => boolean | number;
312
+ clearBoosts?: (this: Pokemon) => void;
312
313
  calculateStat?: (this: Pokemon, statName: StatIDExceptHP, boost: number, modifier?: number) => number;
313
314
  cureStatus?: (this: Pokemon, silent?: boolean) => boolean;
314
315
  getAbility?: (this: Pokemon) => Ability;
package/sim/pokemon.ts CHANGED
@@ -794,7 +794,7 @@ export class Pokemon {
794
794
  for (const pokemon of this.battle.getAllActive()) {
795
795
  // can't use hasAbility because it would lead to infinite recursion
796
796
  if (pokemon.ability === ('neutralizinggas' as ID) && !pokemon.volatiles['gastroacid'] &&
797
- !pokemon.abilityState.ending) {
797
+ !pokemon.transformed && !pokemon.abilityState.ending) {
798
798
  neutralizinggas = true;
799
799
  break;
800
800
  }
@@ -540,6 +540,9 @@ export class TeamValidator {
540
540
  problem = this.checkItem(set, item, setHas);
541
541
  if (problem) problems.push(problem);
542
542
  if (ruleTable.has('obtainablemisc')) {
543
+ if (dex.gen === 4 && item.id === 'griseousorb' && species.num !== 487) {
544
+ problems.push(`${set.name} cannot hold the Griseous Orb.`, `(In Gen 4, only Giratina could hold the Griseous Orb).`);
545
+ }
543
546
  if (dex.gen <= 1) {
544
547
  if (item.id) {
545
548
  // no items allowed