@pkmn/sim 0.7.47 → 0.7.48
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 +98 -56
- package/build/cjs/config/formats.js.map +1 -1
- package/build/cjs/data/abilities.js +4 -1
- package/build/cjs/data/abilities.js.map +1 -1
- package/build/cjs/data/aliases.js +1 -1
- package/build/cjs/data/formats-data.js +36 -23
- package/build/cjs/data/formats-data.js.map +1 -1
- package/build/cjs/data/learnsets.js +157 -4
- package/build/cjs/data/learnsets.js.map +1 -1
- package/build/cjs/data/legality.js +260 -50
- package/build/cjs/data/legality.js.map +1 -1
- package/build/cjs/data/mods/gen4/moves.js +3 -3
- package/build/cjs/data/mods/gen4/moves.js.map +1 -1
- package/build/cjs/data/pokedex.js +39 -3
- package/build/cjs/data/pokedex.js.map +1 -1
- package/build/cjs/sim/team-validator.js +100 -23
- package/build/cjs/sim/team-validator.js.map +1 -1
- package/build/esm/config/formats.mjs +98 -56
- package/build/esm/config/formats.mjs.map +1 -1
- package/build/esm/data/abilities.mjs +4 -1
- package/build/esm/data/abilities.mjs.map +1 -1
- package/build/esm/data/aliases.mjs +1 -1
- package/build/esm/data/formats-data.mjs +36 -23
- package/build/esm/data/formats-data.mjs.map +1 -1
- package/build/esm/data/learnsets.mjs +157 -4
- package/build/esm/data/learnsets.mjs.map +1 -1
- package/build/esm/data/legality.mjs +260 -50
- package/build/esm/data/legality.mjs.map +1 -1
- package/build/esm/data/mods/gen4/moves.mjs +3 -3
- package/build/esm/data/mods/gen4/moves.mjs.map +1 -1
- package/build/esm/data/pokedex.mjs +39 -3
- package/build/esm/data/pokedex.mjs.map +1 -1
- package/build/esm/sim/team-validator.mjs +100 -23
- package/build/esm/sim/team-validator.mjs.map +1 -1
- package/build/types/sim/exported-global-types.d.ts +14 -1
- package/build/types/sim/global-types.d.ts +14 -1
- package/build/types/sim/team-validator.d.ts +16 -0
- package/package.json +1 -1
|
@@ -48,6 +48,9 @@ class PokemonSources {
|
|
|
48
48
|
add(source, limitedEggMove) {
|
|
49
49
|
if (this.sources[this.sources.length - 1] !== source)
|
|
50
50
|
this.sources.push(source);
|
|
51
|
+
if (limitedEggMove && source.substr(0, 3) === '1ET') {
|
|
52
|
+
this.possiblyLimitedEggMoves = [limitedEggMove];
|
|
53
|
+
}
|
|
51
54
|
if (limitedEggMove && this.limitedEggMoves !== null) {
|
|
52
55
|
this.limitedEggMoves = [limitedEggMove];
|
|
53
56
|
}
|
|
@@ -82,6 +85,24 @@ class PokemonSources {
|
|
|
82
85
|
return max;
|
|
83
86
|
}
|
|
84
87
|
intersectWith(other) {
|
|
88
|
+
if (this.pomegEventEgg && other.pomegEggMoves) {
|
|
89
|
+
const newSources = [];
|
|
90
|
+
for (const source of other.sources) {
|
|
91
|
+
newSources.push(source.substr(0, 2) === '3E' ? this.pomegEventEgg : source);
|
|
92
|
+
}
|
|
93
|
+
other.sources = newSources;
|
|
94
|
+
}
|
|
95
|
+
else if (other.pomegEventEgg && this.pomegEventEgg !== null) {
|
|
96
|
+
const newSources = [];
|
|
97
|
+
for (const source of this.sources) {
|
|
98
|
+
newSources.push(source.substr(0, 2) === '3E' ? other.pomegEventEgg : source);
|
|
99
|
+
}
|
|
100
|
+
this.sources = newSources;
|
|
101
|
+
this.pomegEventEgg = other.pomegEventEgg;
|
|
102
|
+
}
|
|
103
|
+
else if (!other.pomegEggMoves && !other.sourcesBefore) {
|
|
104
|
+
this.pomegEventEgg = null;
|
|
105
|
+
}
|
|
85
106
|
if (other.sourcesBefore || this.sourcesBefore) {
|
|
86
107
|
// having sourcesBefore is the equivalent of having everything before that gen
|
|
87
108
|
// in sources, so we fill the other array in preparation for intersection
|
|
@@ -131,6 +152,37 @@ class PokemonSources {
|
|
|
131
152
|
this.limitedEggMoves.push(...other.limitedEggMoves);
|
|
132
153
|
}
|
|
133
154
|
}
|
|
155
|
+
if (other.possiblyLimitedEggMoves) {
|
|
156
|
+
if (!this.possiblyLimitedEggMoves) {
|
|
157
|
+
this.possiblyLimitedEggMoves = other.possiblyLimitedEggMoves;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
this.possiblyLimitedEggMoves.push(...other.possiblyLimitedEggMoves);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (other.pomegEggMoves) {
|
|
164
|
+
if (!this.pomegEggMoves) {
|
|
165
|
+
this.pomegEggMoves = other.pomegEggMoves;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
this.pomegEggMoves.push(...other.pomegEggMoves);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
let eggTradebackLegal = false;
|
|
172
|
+
for (const source of this.sources) {
|
|
173
|
+
if (source.substr(0, 3) === '1ET') {
|
|
174
|
+
eggTradebackLegal = true;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (!eggTradebackLegal && this.possiblyLimitedEggMoves) {
|
|
179
|
+
for (const eggMove of this.possiblyLimitedEggMoves) {
|
|
180
|
+
if (!this.limitedEggMoves)
|
|
181
|
+
this.limitedEggMoves = [];
|
|
182
|
+
if (!this.limitedEggMoves.includes(eggMove))
|
|
183
|
+
this.limitedEggMoves.push(eggMove);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
134
186
|
this.moveEvoCarryCount += other.moveEvoCarryCount;
|
|
135
187
|
this.dreamWorldMoveCount += other.dreamWorldMoveCount;
|
|
136
188
|
if (other.sourcesAfter > this.sourcesAfter)
|
|
@@ -644,20 +696,23 @@ class TeamValidator {
|
|
|
644
696
|
evoSpecies = dex.species.get(evoSpecies.prevo);
|
|
645
697
|
}
|
|
646
698
|
}
|
|
647
|
-
|
|
699
|
+
let moveProblems;
|
|
648
700
|
if (ruleTable.has('obtainablemoves')) {
|
|
701
|
+
moveProblems = this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist);
|
|
649
702
|
problems.push(...moveProblems);
|
|
650
703
|
}
|
|
651
704
|
let eventOnlyData;
|
|
652
705
|
if (!setSources.sourcesBefore && setSources.sources.length) {
|
|
653
|
-
|
|
706
|
+
const legalSources = [];
|
|
654
707
|
for (const source of setSources.sources) {
|
|
655
708
|
if (this.validateSource(set, source, setSources, outOfBattleSpecies))
|
|
656
709
|
continue;
|
|
657
|
-
|
|
658
|
-
break;
|
|
710
|
+
legalSources.push(source);
|
|
659
711
|
}
|
|
660
|
-
if (
|
|
712
|
+
if (legalSources.length) {
|
|
713
|
+
setSources.sources = legalSources;
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
661
716
|
let nonEggSource = null;
|
|
662
717
|
for (const source of setSources.sources) {
|
|
663
718
|
if (source.charAt(1) !== 'E') {
|
|
@@ -734,15 +789,6 @@ class TeamValidator {
|
|
|
734
789
|
}
|
|
735
790
|
}
|
|
736
791
|
}
|
|
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));
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
792
|
// Hardcoded forced validation for Pokemon GO
|
|
747
793
|
const pokemonGoOnlySpecies = ['meltan', 'melmetal', 'gimmighoulroaming'];
|
|
748
794
|
if (ruleTable.has('obtainablemisc') && (pokemonGoOnlySpecies.includes(species.id))) {
|
|
@@ -757,6 +803,15 @@ class TeamValidator {
|
|
|
757
803
|
if (ruleTable.isBanned('nonexistent')) {
|
|
758
804
|
problems.push(...this.validateStats(set, species, setSources, pokemonGoProblems));
|
|
759
805
|
}
|
|
806
|
+
// Attempt move validation again after verifying Pokemon GO origin
|
|
807
|
+
if (ruleTable.has('obtainablemoves') && setSources.isFromPokemonGo) {
|
|
808
|
+
setSources.restrictiveMoves = [];
|
|
809
|
+
setSources.sources = ['8V'];
|
|
810
|
+
setSources.sourcesBefore = 0;
|
|
811
|
+
if (moveProblems && !moveProblems.length) {
|
|
812
|
+
problems.push(...this.validateMoves(outOfBattleSpecies, set.moves, setSources, set, name, moveLegalityWhitelist));
|
|
813
|
+
}
|
|
814
|
+
}
|
|
760
815
|
if (ruleTable.has('obtainablemoves')) {
|
|
761
816
|
if (species.id === 'keldeo' && set.moves.includes('secretsword') && this.minSourceGen > 5 && dex.gen <= 7) {
|
|
762
817
|
problems.push(`${name} has Secret Sword, which is only compatible with Keldeo-Ordinary obtained from Gen 5.`);
|
|
@@ -822,7 +877,8 @@ class TeamValidator {
|
|
|
822
877
|
if (nameSpecies.baseSpecies === species.baseSpecies) {
|
|
823
878
|
set.name = species.baseSpecies;
|
|
824
879
|
}
|
|
825
|
-
else if (nameSpecies.name !== species.name &&
|
|
880
|
+
else if (nameSpecies.name !== species.name &&
|
|
881
|
+
nameSpecies.name !== species.baseSpecies && ruleTable.has('nicknameclause')) {
|
|
826
882
|
// nickname species doesn't match actual species
|
|
827
883
|
// Nickname Clause
|
|
828
884
|
problems.push(`${name} must not be nicknamed a different Pokémon species than what it actually is.`);
|
|
@@ -1149,16 +1205,18 @@ class TeamValidator {
|
|
|
1149
1205
|
const fathers = [];
|
|
1150
1206
|
// Gen 6+ don't have egg move incompatibilities
|
|
1151
1207
|
// (except for certain cases with baby Pokemon not handled here)
|
|
1152
|
-
if (!getAll && eggGen >= 6)
|
|
1208
|
+
if (!getAll && eggGen >= 6 && species.gender !== 'F')
|
|
1153
1209
|
return true;
|
|
1154
|
-
|
|
1210
|
+
let eggMoves = setSources.limitedEggMoves;
|
|
1211
|
+
if (eggGen === 3)
|
|
1212
|
+
eggMoves = eggMoves?.filter(eggMove => !setSources.pomegEggMoves?.includes(eggMove));
|
|
1155
1213
|
// must have 2 or more egg moves to have egg move incompatibilities
|
|
1156
1214
|
if (!eggMoves) {
|
|
1157
1215
|
// happens often in gen 1-6 LC if your only egg moves are level-up moves,
|
|
1158
1216
|
// which aren't limited and so aren't in `limitedEggMoves`
|
|
1159
1217
|
return getAll ? ['*'] : true;
|
|
1160
1218
|
}
|
|
1161
|
-
if (!getAll && eggMoves.length <= 1)
|
|
1219
|
+
if (!getAll && eggMoves.length <= 1 && species.gender !== 'F')
|
|
1162
1220
|
return true;
|
|
1163
1221
|
// gen 1 eggs come from gen 2 breeding
|
|
1164
1222
|
const dex = this.dex.gen === 1 ? this.dex.mod('gen2') : this.dex;
|
|
@@ -1249,6 +1307,8 @@ class TeamValidator {
|
|
|
1249
1307
|
learnset = this.dex.species.getLearnset(curSpecies.id);
|
|
1250
1308
|
if (learnset && learnset[move]) {
|
|
1251
1309
|
for (const moveSource of learnset[move]) {
|
|
1310
|
+
if (eggGen > 8 && parseInt(moveSource.charAt(0)) <= 8)
|
|
1311
|
+
continue;
|
|
1252
1312
|
if (parseInt(moveSource.charAt(0)) > eggGen)
|
|
1253
1313
|
continue;
|
|
1254
1314
|
const canLearnFromSmeargle = moveSource.charAt(1) === 'E' && canBreedWithSmeargle;
|
|
@@ -2200,7 +2260,8 @@ class TeamValidator {
|
|
|
2200
2260
|
// redundant
|
|
2201
2261
|
if (learnedGen <= moveSources.sourcesBefore)
|
|
2202
2262
|
continue;
|
|
2203
|
-
if (baseSpecies.evoRegion === 'Alola' && checkingPrevo && learnedGen >= 8
|
|
2263
|
+
if (baseSpecies.evoRegion === 'Alola' && checkingPrevo && learnedGen >= 8 &&
|
|
2264
|
+
(dex.gen < 9 || learned.charAt(1) !== 'E')) {
|
|
2204
2265
|
cantLearnReason = `is from a ${species.name} that can't be transferred to USUM to evolve into ${baseSpecies.name}.`;
|
|
2205
2266
|
continue;
|
|
2206
2267
|
}
|
|
@@ -2237,6 +2298,7 @@ class TeamValidator {
|
|
|
2237
2298
|
}
|
|
2238
2299
|
else if (level >= 5 && learnedGen === 3 && species.canHatch) {
|
|
2239
2300
|
// Pomeg Glitch
|
|
2301
|
+
learned = learnedGen + 'Epomeg';
|
|
2240
2302
|
}
|
|
2241
2303
|
else if ((!species.gender || species.gender === 'F') &&
|
|
2242
2304
|
learnedGen >= 2 && species.canHatch && !setSources.isFromPokemonGo) {
|
|
@@ -2251,7 +2313,8 @@ class TeamValidator {
|
|
|
2251
2313
|
}
|
|
2252
2314
|
}
|
|
2253
2315
|
// Gen 8+ egg moves can be taught to any pokemon from any source
|
|
2254
|
-
if (learnedGen >= 8 && learned.charAt(1) === 'E'
|
|
2316
|
+
if (learnedGen >= 8 && learned.charAt(1) === 'E' && learned.slice(1) !== 'Eany' &&
|
|
2317
|
+
learned.slice(1) !== 'Epomeg' || 'LMTR'.includes(learned.charAt(1))) {
|
|
2255
2318
|
if (learnedGen === dex.gen && learned.charAt(1) !== 'R') {
|
|
2256
2319
|
// current-gen level-up, TM or tutor moves:
|
|
2257
2320
|
// always available
|
|
@@ -2280,7 +2343,17 @@ class TeamValidator {
|
|
|
2280
2343
|
// only if hatched from an egg
|
|
2281
2344
|
let limitedEggMove = undefined;
|
|
2282
2345
|
if (learned.slice(1) === 'Eany') {
|
|
2283
|
-
|
|
2346
|
+
if (species.gender === 'F') {
|
|
2347
|
+
limitedEggMove = move.id;
|
|
2348
|
+
}
|
|
2349
|
+
else {
|
|
2350
|
+
limitedEggMove = null;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
else if (learned.slice(1) === 'Epomeg') {
|
|
2354
|
+
// Pomeg glitched moves have to be from an egg but since they aren't true egg moves,
|
|
2355
|
+
// there should be no breeding restrictions
|
|
2356
|
+
moveSources.pomegEggMoves = [move.id];
|
|
2284
2357
|
}
|
|
2285
2358
|
else if (learnedGen < 6) {
|
|
2286
2359
|
limitedEggMove = move.id;
|
|
@@ -2288,7 +2361,7 @@ class TeamValidator {
|
|
|
2288
2361
|
learned = learnedGen + 'E' + (species.prevo ? species.id : '');
|
|
2289
2362
|
if (tradebackEligible && learnedGen === 2 && move.gen <= 1) {
|
|
2290
2363
|
// can tradeback
|
|
2291
|
-
moveSources.add('1ET' + learned.slice(2));
|
|
2364
|
+
moveSources.add('1ET' + learned.slice(2), limitedEggMove);
|
|
2292
2365
|
}
|
|
2293
2366
|
moveSources.add(learned, limitedEggMove);
|
|
2294
2367
|
}
|
|
@@ -2302,6 +2375,10 @@ class TeamValidator {
|
|
|
2302
2375
|
moveSources.add('1ST' + learned.slice(2) + ' ' + species.id);
|
|
2303
2376
|
}
|
|
2304
2377
|
moveSources.add(learned + ' ' + species.id);
|
|
2378
|
+
const eventLearnset = dex.species.getLearnsetData(species.id);
|
|
2379
|
+
if (eventLearnset.eventData?.[parseInt(learned.charAt(2))].emeraldEventEgg && learnedGen === 3) {
|
|
2380
|
+
moveSources.pomegEventEgg = learned + ' ' + species.id;
|
|
2381
|
+
}
|
|
2305
2382
|
}
|
|
2306
2383
|
else if (learned.charAt(1) === 'D') {
|
|
2307
2384
|
// DW moves:
|
|
@@ -2428,7 +2505,7 @@ class TeamValidator {
|
|
|
2428
2505
|
// different learnsets. To prevent a leak, we make them show up as their
|
|
2429
2506
|
// base forme, but hardcode their learnsets into Rockruff-Dusk and
|
|
2430
2507
|
// Greninja-Ash
|
|
2431
|
-
if (['Gastrodon', 'Pumpkaboo', 'Sinistea'].includes(species.baseSpecies) && species.forme) {
|
|
2508
|
+
if (['Gastrodon', 'Pumpkaboo', 'Sinistea', 'Tatsugiri'].includes(species.baseSpecies) && species.forme) {
|
|
2432
2509
|
return this.dex.species.get(species.baseSpecies);
|
|
2433
2510
|
}
|
|
2434
2511
|
else if (species.name === 'Lycanroc-Dusk') {
|