@pkmn/sim 0.7.46 → 0.7.47
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.
- package/build/cjs/config/formats.js +154 -102
- package/build/cjs/config/formats.js.map +1 -1
- package/build/cjs/data/abilities.js +5 -5
- package/build/cjs/data/abilities.js.map +1 -1
- package/build/cjs/data/aliases.js +2 -2
- package/build/cjs/data/aliases.js.map +1 -1
- package/build/cjs/data/formats-data.js +159 -161
- package/build/cjs/data/formats-data.js.map +1 -1
- package/build/cjs/data/items.js +25 -4
- package/build/cjs/data/items.js.map +1 -1
- package/build/cjs/data/mods/gen2/scripts.js +3 -3
- package/build/cjs/data/mods/gen2/scripts.js.map +1 -1
- package/build/cjs/data/mods/gen3/formats-data.js +2 -2
- package/build/cjs/data/mods/gen3/formats-data.js.map +1 -1
- package/build/cjs/data/mods/gen3/scripts.js +1 -1
- package/build/cjs/data/mods/gen3/scripts.js.map +1 -1
- package/build/cjs/data/mods/gen4/moves.js +1 -1
- package/build/cjs/data/mods/gen4/moves.js.map +1 -1
- package/build/cjs/data/mods/gen5/formats-data.js +1 -1
- package/build/cjs/data/mods/gen5/formats-data.js.map +1 -1
- package/build/cjs/data/mods/gen5/moves.js +1 -1
- package/build/cjs/data/mods/gen5/moves.js.map +1 -1
- package/build/cjs/data/moves.js +13 -18
- package/build/cjs/data/moves.js.map +1 -1
- package/build/cjs/data/pokemongo.js +987 -0
- package/build/cjs/data/pokemongo.js.map +1 -0
- package/build/cjs/data/rulesets.js +51 -0
- package/build/cjs/data/rulesets.js.map +1 -1
- package/build/cjs/sim/battle-actions.js +8 -7
- package/build/cjs/sim/battle-actions.js.map +1 -1
- package/build/cjs/sim/dex-species.js +4 -0
- package/build/cjs/sim/dex-species.js.map +1 -1
- package/build/cjs/sim/dex.js +3 -2
- package/build/cjs/sim/dex.js.map +1 -1
- package/build/cjs/sim/pokemon.js +3 -0
- package/build/cjs/sim/pokemon.js.map +1 -1
- package/build/cjs/sim/team-validator.js +299 -54
- package/build/cjs/sim/team-validator.js.map +1 -1
- package/build/esm/config/formats.mjs +154 -102
- package/build/esm/config/formats.mjs.map +1 -1
- package/build/esm/data/abilities.mjs +5 -5
- package/build/esm/data/abilities.mjs.map +1 -1
- package/build/esm/data/aliases.mjs +2 -2
- package/build/esm/data/aliases.mjs.map +1 -1
- package/build/esm/data/formats-data.mjs +159 -161
- package/build/esm/data/formats-data.mjs.map +1 -1
- package/build/esm/data/items.mjs +25 -4
- package/build/esm/data/items.mjs.map +1 -1
- package/build/esm/data/mods/gen2/scripts.mjs +3 -3
- package/build/esm/data/mods/gen2/scripts.mjs.map +1 -1
- package/build/esm/data/mods/gen3/formats-data.mjs +2 -2
- package/build/esm/data/mods/gen3/formats-data.mjs.map +1 -1
- package/build/esm/data/mods/gen3/scripts.mjs +1 -1
- package/build/esm/data/mods/gen3/scripts.mjs.map +1 -1
- package/build/esm/data/mods/gen4/moves.mjs +1 -1
- package/build/esm/data/mods/gen4/moves.mjs.map +1 -1
- package/build/esm/data/mods/gen5/formats-data.mjs +1 -1
- package/build/esm/data/mods/gen5/formats-data.mjs.map +1 -1
- package/build/esm/data/mods/gen5/moves.mjs +1 -1
- package/build/esm/data/mods/gen5/moves.mjs.map +1 -1
- package/build/esm/data/moves.mjs +13 -18
- package/build/esm/data/moves.mjs.map +1 -1
- package/build/esm/data/pokemongo.mjs +984 -0
- package/build/esm/data/pokemongo.mjs.map +1 -0
- package/build/esm/data/rulesets.mjs +51 -0
- package/build/esm/data/rulesets.mjs.map +1 -1
- package/build/esm/sim/battle-actions.mjs +8 -7
- package/build/esm/sim/battle-actions.mjs.map +1 -1
- package/build/esm/sim/dex-species.mjs +4 -0
- package/build/esm/sim/dex-species.mjs.map +1 -1
- package/build/esm/sim/dex.mjs +3 -2
- package/build/esm/sim/dex.mjs.map +1 -1
- package/build/esm/sim/pokemon.mjs +3 -0
- package/build/esm/sim/pokemon.mjs.map +1 -1
- package/build/esm/sim/team-validator.mjs +299 -54
- package/build/esm/sim/team-validator.mjs.map +1 -1
- package/build/types/data/pokemongo.d.ts +31 -0
- package/build/types/sim/battle-actions.d.ts +1 -1
- package/build/types/sim/dex-species.d.ts +12 -0
- package/build/types/sim/dex.d.ts +3 -2
- package/build/types/sim/exported-global-types.d.ts +2 -1
- package/build/types/sim/global-types.d.ts +2 -1
- package/build/types/sim/pokemon.d.ts +2 -0
- package/build/types/sim/team-validator.d.ts +8 -1
- package/package.json +1 -1
|
@@ -575,9 +575,6 @@ class TeamValidator {
|
|
|
575
575
|
problems.push(`${name} has ${set.moves.length} moves, which is more than the limit of ${ruleTable.maxMoveCount}.`);
|
|
576
576
|
return problems;
|
|
577
577
|
}
|
|
578
|
-
if (ruleTable.isBanned('nonexistent')) {
|
|
579
|
-
problems.push(...this.validateStats(set, species, setSources));
|
|
580
|
-
}
|
|
581
578
|
const moveLegalityWhitelist = {};
|
|
582
579
|
for (const moveName of set.moves) {
|
|
583
580
|
if (!moveName)
|
|
@@ -601,10 +598,56 @@ class TeamValidator {
|
|
|
601
598
|
}
|
|
602
599
|
}
|
|
603
600
|
}
|
|
601
|
+
const pokemonGoProblems = this.validatePokemonGo(outOfBattleSpecies, set, setSources);
|
|
602
|
+
const learnsetSpecies = dex.species.getLearnsetData(outOfBattleSpecies.id);
|
|
603
|
+
let isFromRBYEncounter = false;
|
|
604
|
+
if (this.gen === 1 && ruleTable.has('obtainablemisc') && !this.ruleTable.has('allowtradeback')) {
|
|
605
|
+
let lowestEncounterLevel;
|
|
606
|
+
for (const encounter of learnsetSpecies.encounters || []) {
|
|
607
|
+
if (encounter.generation !== 1)
|
|
608
|
+
continue;
|
|
609
|
+
if (!encounter.level)
|
|
610
|
+
continue;
|
|
611
|
+
if (lowestEncounterLevel && encounter.level > lowestEncounterLevel)
|
|
612
|
+
continue;
|
|
613
|
+
lowestEncounterLevel = encounter.level;
|
|
614
|
+
}
|
|
615
|
+
if (lowestEncounterLevel) {
|
|
616
|
+
if (set.level < lowestEncounterLevel) {
|
|
617
|
+
problems.push(`${name} is not obtainable at levels below ${lowestEncounterLevel} in Gen 1.`);
|
|
618
|
+
}
|
|
619
|
+
isFromRBYEncounter = true;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (!isFromRBYEncounter && ruleTable.has('obtainablemisc')) {
|
|
623
|
+
// FIXME: Event pokemon given at a level under what it normally can be attained at gives a false positive
|
|
624
|
+
let evoSpecies = species;
|
|
625
|
+
while (evoSpecies.prevo) {
|
|
626
|
+
if (set.level < (evoSpecies.evoLevel || 0)) {
|
|
627
|
+
if (!pokemonGoProblems || (pokemonGoProblems && pokemonGoProblems.length)) {
|
|
628
|
+
problems.push(`${name} must be at least level ${evoSpecies.evoLevel} to be evolved.`);
|
|
629
|
+
if (pokemonGoProblems && pokemonGoProblems.length) {
|
|
630
|
+
problems.push(`It failed to validate as a Pokemon from Pokemon GO because:`);
|
|
631
|
+
for (const pokemonGoProblem of pokemonGoProblems) {
|
|
632
|
+
problems.push(pokemonGoProblem);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
// Pokemon from Pokemon GO can be transferred to LGPE
|
|
638
|
+
setSources.isFromPokemonGo = true;
|
|
639
|
+
setSources.sources.push('8V');
|
|
640
|
+
setSources.sourcesBefore = 0;
|
|
641
|
+
}
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
evoSpecies = dex.species.get(evoSpecies.prevo);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const moveProblems = this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist);
|
|
604
648
|
if (ruleTable.has('obtainablemoves')) {
|
|
605
|
-
problems.push(...
|
|
649
|
+
problems.push(...moveProblems);
|
|
606
650
|
}
|
|
607
|
-
const learnsetSpecies = dex.species.getLearnsetData(outOfBattleSpecies.id);
|
|
608
651
|
let eventOnlyData;
|
|
609
652
|
if (!setSources.sourcesBefore && setSources.sources.length) {
|
|
610
653
|
let legal = false;
|
|
@@ -628,12 +671,24 @@ class TeamValidator {
|
|
|
628
671
|
problems.push(`(Is this incorrect? If so, post the chainbreeding instructions in Bug Reports)`);
|
|
629
672
|
}
|
|
630
673
|
else {
|
|
631
|
-
if (
|
|
632
|
-
|
|
674
|
+
if (species.id === 'mew' && pokemonGoProblems && !pokemonGoProblems.length) {
|
|
675
|
+
// Whitelist Pokemon GO Mew, which cannot be sent to Let's Go
|
|
676
|
+
setSources.isFromPokemonGo = true;
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
if (setSources.sources.length > 1) {
|
|
680
|
+
problems.push(`${name} has an event-exclusive move that it doesn't qualify for (only one of several ways to get the move will be listed):`);
|
|
681
|
+
}
|
|
682
|
+
const eventProblems = this.validateSource(set, nonEggSource, setSources, outOfBattleSpecies, ` because it has a move only available`);
|
|
683
|
+
if (eventProblems)
|
|
684
|
+
problems.push(...eventProblems);
|
|
685
|
+
if (species.id === 'mew' && pokemonGoProblems && pokemonGoProblems.length) {
|
|
686
|
+
problems.push(`Additionally, it failed to validate as a Pokemon from Pokemon GO because:`);
|
|
687
|
+
for (const pokemonGoProblem of pokemonGoProblems) {
|
|
688
|
+
problems.push(pokemonGoProblem);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
633
691
|
}
|
|
634
|
-
const eventProblems = this.validateSource(set, nonEggSource, setSources, outOfBattleSpecies, ` because it has a move only available`);
|
|
635
|
-
if (eventProblems)
|
|
636
|
-
problems.push(...eventProblems);
|
|
637
692
|
}
|
|
638
693
|
}
|
|
639
694
|
}
|
|
@@ -650,54 +705,58 @@ class TeamValidator {
|
|
|
650
705
|
legal = true;
|
|
651
706
|
}
|
|
652
707
|
if (!legal) {
|
|
653
|
-
if (
|
|
654
|
-
|
|
708
|
+
if (!pokemonGoProblems || (pokemonGoProblems && pokemonGoProblems.length)) {
|
|
709
|
+
if (eventData.length === 1) {
|
|
710
|
+
problems.push(`${species.name} is only obtainable from an event - it needs to match its event:`);
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
problems.push(`${species.name} is only obtainable from events - it needs to match one of its events:`);
|
|
714
|
+
}
|
|
715
|
+
for (const [i, event] of eventData.entries()) {
|
|
716
|
+
if (event.generation <= dex.gen && event.generation >= this.minSourceGen) {
|
|
717
|
+
const eventInfo = event;
|
|
718
|
+
const eventNum = i + 1;
|
|
719
|
+
const eventName = eventData.length > 1 ? ` #${eventNum}` : ``;
|
|
720
|
+
const eventProblems = this.validateEvent(set, setSources, eventInfo, eventSpecies, ` to be`, `from its event${eventName}`);
|
|
721
|
+
if (eventProblems)
|
|
722
|
+
problems.push(...eventProblems);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (pokemonGoProblems && pokemonGoProblems.length) {
|
|
726
|
+
problems.push(`Additionally, it failed to validate as a Pokemon from Pokemon GO because:`);
|
|
727
|
+
for (const pokemonGoProblem of pokemonGoProblems) {
|
|
728
|
+
problems.push(pokemonGoProblem);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
655
731
|
}
|
|
656
732
|
else {
|
|
657
|
-
|
|
658
|
-
}
|
|
659
|
-
for (const [i, event] of eventData.entries()) {
|
|
660
|
-
if (event.generation <= dex.gen && event.generation >= this.minSourceGen) {
|
|
661
|
-
const eventInfo = event;
|
|
662
|
-
const eventNum = i + 1;
|
|
663
|
-
const eventName = eventData.length > 1 ? ` #${eventNum}` : ``;
|
|
664
|
-
const eventProblems = this.validateEvent(set, setSources, eventInfo, eventSpecies, ` to be`, `from its event${eventName}`);
|
|
665
|
-
if (eventProblems)
|
|
666
|
-
problems.push(...eventProblems);
|
|
667
|
-
}
|
|
733
|
+
setSources.isFromPokemonGo = true;
|
|
668
734
|
}
|
|
669
735
|
}
|
|
670
736
|
}
|
|
671
|
-
|
|
672
|
-
if (
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
continue;
|
|
679
|
-
if (lowestEncounterLevel && encounter.level > lowestEncounterLevel)
|
|
680
|
-
continue;
|
|
681
|
-
lowestEncounterLevel = encounter.level;
|
|
682
|
-
}
|
|
683
|
-
if (lowestEncounterLevel) {
|
|
684
|
-
if (set.level < lowestEncounterLevel) {
|
|
685
|
-
problems.push(`${name} is not obtainable at levels below ${lowestEncounterLevel} in Gen 1.`);
|
|
686
|
-
}
|
|
687
|
-
isFromRBYEncounter = true;
|
|
737
|
+
// Attempt move validation again after verifying Pokemon GO origin
|
|
738
|
+
if (setSources.isFromPokemonGo) {
|
|
739
|
+
setSources.restrictiveMoves = [];
|
|
740
|
+
setSources.sources = ['8V'];
|
|
741
|
+
setSources.sourcesBefore = 0;
|
|
742
|
+
if (!moveProblems.length && ruleTable.has('obtainablemoves')) {
|
|
743
|
+
problems.push(...this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist));
|
|
688
744
|
}
|
|
689
745
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
746
|
+
// Hardcoded forced validation for Pokemon GO
|
|
747
|
+
const pokemonGoOnlySpecies = ['meltan', 'melmetal', 'gimmighoulroaming'];
|
|
748
|
+
if (ruleTable.has('obtainablemisc') && (pokemonGoOnlySpecies.includes(species.id))) {
|
|
749
|
+
setSources.isFromPokemonGo = true;
|
|
750
|
+
if (pokemonGoProblems && pokemonGoProblems.length) {
|
|
751
|
+
problems.push(`${name} is only obtainable from Pokemon GO, and failed to validate because:`);
|
|
752
|
+
for (const pokemonGoProblem of pokemonGoProblems) {
|
|
753
|
+
problems.push(pokemonGoProblem);
|
|
697
754
|
}
|
|
698
|
-
evoSpecies = dex.species.get(evoSpecies.prevo);
|
|
699
755
|
}
|
|
700
756
|
}
|
|
757
|
+
if (ruleTable.isBanned('nonexistent')) {
|
|
758
|
+
problems.push(...this.validateStats(set, species, setSources, pokemonGoProblems));
|
|
759
|
+
}
|
|
701
760
|
if (ruleTable.has('obtainablemoves')) {
|
|
702
761
|
if (species.id === 'keldeo' && set.moves.includes('secretsword') && this.minSourceGen > 5 && dex.gen <= 7) {
|
|
703
762
|
problems.push(`${name} has Secret Sword, which is only compatible with Keldeo-Ordinary obtained from Gen 5.`);
|
|
@@ -776,7 +835,7 @@ class TeamValidator {
|
|
|
776
835
|
}
|
|
777
836
|
return problems;
|
|
778
837
|
}
|
|
779
|
-
validateStats(set, species, setSources) {
|
|
838
|
+
validateStats(set, species, setSources, pokemonGoProblems) {
|
|
780
839
|
const ruleTable = this.ruleTable;
|
|
781
840
|
const dex = this.dex;
|
|
782
841
|
const allowAVs = ruleTable.has('allowavs');
|
|
@@ -835,8 +894,19 @@ class TeamValidator {
|
|
|
835
894
|
perfectIVs++;
|
|
836
895
|
}
|
|
837
896
|
if (perfectIVs < 3) {
|
|
838
|
-
|
|
839
|
-
|
|
897
|
+
if (!pokemonGoProblems || (pokemonGoProblems && pokemonGoProblems.length)) {
|
|
898
|
+
const reason = (this.minSourceGen === 6 ? ` and this format requires Gen ${dex.gen} Pokémon` : ` in Gen 6 or later`);
|
|
899
|
+
problems.push(`${name} must have at least three perfect IVs because it's a legendary${reason}.`);
|
|
900
|
+
if (pokemonGoProblems && pokemonGoProblems.length) {
|
|
901
|
+
problems.push(`Additionally, it failed to validate as a Pokemon from Pokemon GO because:`);
|
|
902
|
+
for (const pokemonGoProblem of pokemonGoProblems) {
|
|
903
|
+
problems.push(pokemonGoProblem);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
else {
|
|
908
|
+
setSources.isFromPokemonGo = true;
|
|
909
|
+
}
|
|
840
910
|
}
|
|
841
911
|
}
|
|
842
912
|
if (set.hpType && !canBottleCap) {
|
|
@@ -850,6 +920,24 @@ class TeamValidator {
|
|
|
850
920
|
problems.push(`${name} has Hidden Power ${set.hpType}, but its IVs don't allow this even with (Bottle Cap) Hyper Training.`);
|
|
851
921
|
}
|
|
852
922
|
}
|
|
923
|
+
if (setSources.isFromPokemonGo) {
|
|
924
|
+
// Pokemon from Pokemon GO must have odd IVs in non-Spe stats
|
|
925
|
+
// Since the set can be fixed while making minimal changes, it does not force the IVs to be manually fixed
|
|
926
|
+
for (const stat in set.ivs) {
|
|
927
|
+
if (set.ivs[stat] % 2 === 0 && stat !== 'spe') {
|
|
928
|
+
set.ivs[stat]++;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
if (set.ivs.atk !== set.ivs.spa && !(canBottleCap && (set.ivs.atk === 31 || set.ivs.spa === 31))) {
|
|
932
|
+
problems.push(`${name}'s Atk and Spa IVs must match because it is from Pokemon GO.`);
|
|
933
|
+
}
|
|
934
|
+
if (set.ivs.def !== set.ivs.spd && !(canBottleCap && (set.ivs.def === 31 || set.ivs.spd === 31))) {
|
|
935
|
+
problems.push(`${name}'s Def and Spd IVs must match because it is from Pokemon GO.`);
|
|
936
|
+
}
|
|
937
|
+
if (set.hpType && set.hpType !== 'Dark' && set.hpType !== 'Ice') {
|
|
938
|
+
problems.push(`${name} must have Hidden Power Dark or Ice because it is from Pokemon GO.`);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
853
941
|
if (dex.gen <= 2) {
|
|
854
942
|
// validate DVs
|
|
855
943
|
const ivs = set.ivs;
|
|
@@ -1875,6 +1963,114 @@ class TeamValidator {
|
|
|
1875
1963
|
}
|
|
1876
1964
|
return problems;
|
|
1877
1965
|
}
|
|
1966
|
+
/**
|
|
1967
|
+
* Returns a list of problems regarding a Pokemon's avilability in Pokemon GO (empty list if no problems)
|
|
1968
|
+
* If the Pokemon cannot be obtained from Pokemon GO, returns null
|
|
1969
|
+
*/
|
|
1970
|
+
validatePokemonGo(species, set, setSources, name = species.name) {
|
|
1971
|
+
let problems = [];
|
|
1972
|
+
let minLevel = 50; // maximum level a Pokemon can be in Pokemon GO
|
|
1973
|
+
let minIVs = 15; // IVs range from 0 to 15 in Pokemon GO
|
|
1974
|
+
const dex = this.dex;
|
|
1975
|
+
const pokemonGoData = dex.species.getPokemonGoData(species.id);
|
|
1976
|
+
if (dex.gen < 8 || this.format.mod === 'gen8dlc1')
|
|
1977
|
+
return null;
|
|
1978
|
+
if (!pokemonGoData) {
|
|
1979
|
+
// Handles forms and evolutions not obtainable from Pokemon GO
|
|
1980
|
+
const otherSpecies = this.learnsetParent(species);
|
|
1981
|
+
// If a Pokemon is somehow not obtainable from Pokemon GO and it must be leveled up to be evolved,
|
|
1982
|
+
// validation for the game should stop because it's more optimal to get the Pokemon outside of the game
|
|
1983
|
+
if (otherSpecies && !species.evoLevel) {
|
|
1984
|
+
const otherProblems = this.validatePokemonGo(otherSpecies, set, setSources, name);
|
|
1985
|
+
if (otherProblems) {
|
|
1986
|
+
problems = otherProblems;
|
|
1987
|
+
}
|
|
1988
|
+
else {
|
|
1989
|
+
return null;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
else {
|
|
1993
|
+
return null;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
else {
|
|
1997
|
+
const pokemonGoSources = pokemonGoData.encounters;
|
|
1998
|
+
// should never happen
|
|
1999
|
+
if (!pokemonGoSources)
|
|
2000
|
+
throw new Error(`Species with no Pokemon GO data: ${species.id}`);
|
|
2001
|
+
if (set.shiny)
|
|
2002
|
+
name = "Shiny " + name;
|
|
2003
|
+
if (set.shiny && pokemonGoSources.includes('noshiny')) {
|
|
2004
|
+
problems.push(`${name} is not obtainable from Pokemon GO.`);
|
|
2005
|
+
}
|
|
2006
|
+
else {
|
|
2007
|
+
if (pokemonGoSources.includes('wild') && !((set.shiny && pokemonGoSources.includes('nowildshiny')))) {
|
|
2008
|
+
minLevel = 1;
|
|
2009
|
+
minIVs = 0;
|
|
2010
|
+
}
|
|
2011
|
+
if (pokemonGoSources.includes('egg')) {
|
|
2012
|
+
/**
|
|
2013
|
+
* A Pokemon's level when hatched is determined by the trainer's level when it is obtained
|
|
2014
|
+
* It is no longer possible for new accounts to obtain eggs at level 1 because they will have reached
|
|
2015
|
+
* level 2 by the time they can spin a PokeStop. However, it might be possible for a sleeper account
|
|
2016
|
+
* from before XP changes to get a level 1 egg from spinning a PokeStop that sends the account to
|
|
2017
|
+
* level 2, but this needs research
|
|
2018
|
+
*/
|
|
2019
|
+
minLevel = Math.min(minLevel, 2);
|
|
2020
|
+
minIVs = Math.min(minIVs, 10);
|
|
2021
|
+
}
|
|
2022
|
+
if (pokemonGoSources.includes('12kmegg')) {
|
|
2023
|
+
minLevel = Math.min(minLevel, 8);
|
|
2024
|
+
minIVs = Math.min(minIVs, 10);
|
|
2025
|
+
}
|
|
2026
|
+
if (pokemonGoSources.includes('raid')) {
|
|
2027
|
+
minLevel = Math.min(minLevel, 20);
|
|
2028
|
+
minIVs = Math.min(minIVs, 10);
|
|
2029
|
+
}
|
|
2030
|
+
if (species.id === 'mewtwo' && set.level && set.level >= 20) {
|
|
2031
|
+
// A bug allowed Mewtwo to be encountered with an IV floor of 0 from GO Battle League
|
|
2032
|
+
minIVs = Math.min(minIVs, 0);
|
|
2033
|
+
}
|
|
2034
|
+
if (pokemonGoSources.includes('research')) {
|
|
2035
|
+
minLevel = Math.min(minLevel, 15);
|
|
2036
|
+
minIVs = Math.min(minIVs, 10);
|
|
2037
|
+
}
|
|
2038
|
+
if (pokemonGoSources.includes('giovanni') && !set.shiny) {
|
|
2039
|
+
/**
|
|
2040
|
+
* Purified Pokemon can be leveled down to level 8 after trading; they are forced to
|
|
2041
|
+
* special trades, but currently all Giovanni Shadow Pokemon are already forced special trades
|
|
2042
|
+
*/
|
|
2043
|
+
minLevel = Math.min(minLevel, 8);
|
|
2044
|
+
minIVs = Math.min(minIVs, 1);
|
|
2045
|
+
if (set.level && set.level < 12)
|
|
2046
|
+
setSources.pokemonGoSource = "purified";
|
|
2047
|
+
}
|
|
2048
|
+
// Attempt to trade the Pokemon to reduce level and IVs
|
|
2049
|
+
if (!pokemonGoSources.includes('notrade')) {
|
|
2050
|
+
// Special trades require a good friend
|
|
2051
|
+
// Trading with a friend of this level has an IV floor of 1
|
|
2052
|
+
// Note that (non-shiny) Deoxys could be traded for a short time when it was introduced
|
|
2053
|
+
if (!set.shiny || species.id !== 'deoxys') {
|
|
2054
|
+
const specialTrade = pokemonGoSources.includes('specialtrade') || set.shiny;
|
|
2055
|
+
minLevel = Math.min(minLevel, 12);
|
|
2056
|
+
minIVs = Math.min(minIVs, specialTrade ? 1 : 0);
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
if (set.level && set.level < minLevel) {
|
|
2060
|
+
problems.push(`${name} must be at least level ${minLevel} to be from Pokemon GO.`);
|
|
2061
|
+
}
|
|
2062
|
+
const ivs = set.ivs || TeamValidator.fillStats(null, 31);
|
|
2063
|
+
for (const stat in ivs) {
|
|
2064
|
+
if (Math.floor(ivs[stat] / 2) < minIVs && stat !== 'spe') {
|
|
2065
|
+
problems.push(`${name} must have at least ${minIVs} ` +
|
|
2066
|
+
(minIVs === 1 ? `IV` : `IVs`) + ` in non-Speed stats to be from Pokemon GO.`);
|
|
2067
|
+
break;
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
return problems;
|
|
2073
|
+
}
|
|
1878
2074
|
omCheckCanLearn(move, s, setSources = this.allSources(s), set = {}, problem = `${set.name || s.name} can't learn ${move.name}`) {
|
|
1879
2075
|
if (!this.ruleTable.checkCanLearn?.[0])
|
|
1880
2076
|
return problem;
|
|
@@ -2042,7 +2238,8 @@ class TeamValidator {
|
|
|
2042
2238
|
else if (level >= 5 && learnedGen === 3 && species.canHatch) {
|
|
2043
2239
|
// Pomeg Glitch
|
|
2044
2240
|
}
|
|
2045
|
-
else if ((!species.gender || species.gender === 'F') &&
|
|
2241
|
+
else if ((!species.gender || species.gender === 'F') &&
|
|
2242
|
+
learnedGen >= 2 && species.canHatch && !setSources.isFromPokemonGo) {
|
|
2046
2243
|
// available as egg move
|
|
2047
2244
|
learned = learnedGen + 'Eany';
|
|
2048
2245
|
// falls through to E check below
|
|
@@ -2058,8 +2255,15 @@ class TeamValidator {
|
|
|
2058
2255
|
if (learnedGen === dex.gen && learned.charAt(1) !== 'R') {
|
|
2059
2256
|
// current-gen level-up, TM or tutor moves:
|
|
2060
2257
|
// always available
|
|
2061
|
-
if (!(learnedGen >= 8 && learned.charAt(1) === 'E') && babyOnly)
|
|
2062
|
-
setSources.
|
|
2258
|
+
if (!(learnedGen >= 8 && learned.charAt(1) === 'E') && babyOnly) {
|
|
2259
|
+
if (setSources.isFromPokemonGo && species.evoLevel) {
|
|
2260
|
+
cantLearnReason = `is from a prevo, which is incompatible with its Pokemon GO origin.`;
|
|
2261
|
+
continue;
|
|
2262
|
+
}
|
|
2263
|
+
else {
|
|
2264
|
+
setSources.babyOnly = babyOnly;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2063
2267
|
if (!moveSources.moveEvoCarryCount)
|
|
2064
2268
|
return null;
|
|
2065
2269
|
}
|
|
@@ -2108,6 +2312,10 @@ class TeamValidator {
|
|
|
2108
2312
|
else if (learned.charAt(1) === 'V' && this.minSourceGen < learnedGen) {
|
|
2109
2313
|
// Virtual Console or Let's Go transfer moves:
|
|
2110
2314
|
// only if that was the source
|
|
2315
|
+
if (learned === '8V' && setSources.isFromPokemonGo && babyOnly && species.evoLevel) {
|
|
2316
|
+
cantLearnReason = `is from a prevo, which is incompatible with its Pokemon GO origin.`;
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2111
2319
|
moveSources.add(learned);
|
|
2112
2320
|
}
|
|
2113
2321
|
}
|
|
@@ -2157,6 +2365,41 @@ class TeamValidator {
|
|
|
2157
2365
|
setSources.restrictiveMoves = [];
|
|
2158
2366
|
}
|
|
2159
2367
|
setSources.restrictiveMoves.push(move.name);
|
|
2368
|
+
const checkedSpecies = babyOnly ? species : baseSpecies;
|
|
2369
|
+
if (checkedSpecies && setSources.isFromPokemonGo &&
|
|
2370
|
+
(setSources.pokemonGoSource === 'purified' || checkedSpecies.id === 'mew')) {
|
|
2371
|
+
// Pokemon that cannot be sent from Pokemon GO to Let's Go can only access Let's Go moves through HOME
|
|
2372
|
+
// It can only obtain a chain of four level up moves and cannot have TM moves
|
|
2373
|
+
const pokemonGoData = dex.species.getPokemonGoData(checkedSpecies.id);
|
|
2374
|
+
if (pokemonGoData.LGPERestrictiveMoves) {
|
|
2375
|
+
let levelUpMoveCount = 0;
|
|
2376
|
+
const restrictiveMovesToID = [];
|
|
2377
|
+
for (const moveName of setSources.restrictiveMoves) {
|
|
2378
|
+
restrictiveMovesToID.push((0, dex_1.toID)(moveName));
|
|
2379
|
+
}
|
|
2380
|
+
for (const restrictiveMove in pokemonGoData.LGPERestrictiveMoves) {
|
|
2381
|
+
const moveLevel = pokemonGoData.LGPERestrictiveMoves[restrictiveMove];
|
|
2382
|
+
if ((0, dex_1.toID)(move) === restrictiveMove) {
|
|
2383
|
+
if (!moveLevel) {
|
|
2384
|
+
return `'s move ${move.name} is incompatible with its Pokemon GO origin.`;
|
|
2385
|
+
}
|
|
2386
|
+
else if (set.level && set.level < moveLevel) {
|
|
2387
|
+
return ` must be at least level ${moveLevel} to learn ${move.name} due to its Pokemon GO origin.`;
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
if (levelUpMoveCount)
|
|
2391
|
+
levelUpMoveCount++;
|
|
2392
|
+
if (restrictiveMovesToID.includes(restrictiveMove)) {
|
|
2393
|
+
if (!levelUpMoveCount) {
|
|
2394
|
+
levelUpMoveCount++;
|
|
2395
|
+
}
|
|
2396
|
+
else if (levelUpMoveCount > 4) {
|
|
2397
|
+
return `'s moves ${(setSources.restrictiveMoves || []).join(', ')} are incompatible with its Pokemon GO origin.`;
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2160
2403
|
// Now that we have our list of possible sources, intersect it with the current list
|
|
2161
2404
|
if (!moveSources.size()) {
|
|
2162
2405
|
if (cantLearnReason)
|
|
@@ -2171,6 +2414,8 @@ class TeamValidator {
|
|
|
2171
2414
|
// prevents a crash if OMs override `checkCanLearn` to keep validating after an error
|
|
2172
2415
|
setSources.sources = backupSources;
|
|
2173
2416
|
setSources.sourcesBefore = backupSourcesBefore;
|
|
2417
|
+
if (setSources.isFromPokemonGo)
|
|
2418
|
+
return `'s move ${move.name} is incompatible with its Pokemon GO origin.`;
|
|
2174
2419
|
return `'s moves ${(setSources.restrictiveMoves || []).join(', ')} are incompatible.`;
|
|
2175
2420
|
}
|
|
2176
2421
|
if (babyOnly)
|