@pkmn/sim 0.5.3 → 0.5.7
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/config/formats.js +402 -332
- package/build/config/formats.js.map +1 -1
- package/build/data/aliases.js +4 -4
- package/build/data/aliases.js.map +1 -1
- package/build/data/formats-data.js +183 -70
- package/build/data/formats-data.js.map +1 -1
- package/build/data/mods/gen1/formats-data.js +190 -190
- package/build/data/mods/gen1/formats-data.js.map +1 -1
- package/build/data/mods/gen1/moves.js +1 -2
- package/build/data/mods/gen1/moves.js.map +1 -1
- package/build/data/mods/gen2/formats-data.js +1 -1
- package/build/data/mods/gen2/formats-data.js.map +1 -1
- package/build/data/mods/gen3/formats-data.js +13 -13
- package/build/data/mods/gen3/formats-data.js.map +1 -1
- package/build/data/mods/gen4/moves.js +22 -0
- package/build/data/mods/gen4/moves.js.map +1 -1
- package/build/data/mods/gen5/formats-data.js +173 -156
- package/build/data/mods/gen5/formats-data.js.map +1 -1
- package/build/data/mods/gen6/formats-data.js +4 -3
- package/build/data/mods/gen6/formats-data.js.map +1 -1
- package/build/data/mods/gen7/formats-data.js +3 -2
- package/build/data/mods/gen7/formats-data.js.map +1 -1
- package/build/data/mods/gen7/moves.js +154 -0
- package/build/data/mods/gen7/moves.js.map +1 -1
- package/build/data/moves.js +38 -7
- package/build/data/moves.js.map +1 -1
- package/build/data/pokedex.js +480 -11
- package/build/data/pokedex.js.map +1 -1
- package/build/data/rulesets.js +12 -1
- package/build/data/rulesets.js.map +1 -1
- package/build/data/tags.d.ts +1 -0
- package/build/data/tags.js +4 -3
- package/build/data/tags.js.map +1 -1
- package/build/data/text/abilities.js +4 -4
- package/build/data/text/abilities.js.map +1 -1
- package/build/data/text/moves.js +18 -18
- package/build/data/text/moves.js.map +1 -1
- package/build/sim/battle-actions.js +4 -1
- package/build/sim/battle-actions.js.map +1 -1
- package/build/sim/battle.js +23 -22
- package/build/sim/battle.js.map +1 -1
- package/build/sim/dex-formats.d.ts +1 -0
- package/build/sim/dex-formats.js +3 -2
- package/build/sim/dex-formats.js.map +1 -1
- package/build/sim/dex-species.js +5 -2
- package/build/sim/dex-species.js.map +1 -1
- package/build/sim/exported-global-types.d.ts +1 -0
- package/build/sim/global-types.d.ts +1 -0
- package/build/sim/index.d.ts +1 -0
- package/build/sim/index.js +3 -1
- package/build/sim/index.js.map +1 -1
- package/build/sim/team-validator.js +13 -0
- package/build/sim/team-validator.js.map +1 -1
- package/config/formats.ts +422 -352
- package/data/aliases.ts +4 -4
- package/data/formats-data.ts +183 -70
- package/data/mods/gen1/formats-data.ts +190 -190
- package/data/mods/gen1/moves.ts +1 -2
- package/data/mods/gen2/formats-data.ts +1 -1
- package/data/mods/gen3/formats-data.ts +13 -13
- package/data/mods/gen4/moves.ts +21 -0
- package/data/mods/gen5/formats-data.ts +173 -156
- package/data/mods/gen6/formats-data.ts +4 -3
- package/data/mods/gen7/formats-data.ts +3 -2
- package/data/mods/gen7/moves.ts +150 -0
- package/data/moves.ts +37 -7
- package/data/pokedex.ts +480 -11
- package/data/rulesets.ts +11 -1
- package/data/tags.ts +6 -3
- package/data/text/abilities.ts +4 -4
- package/data/text/moves.ts +18 -18
- package/package.json +2 -2
- package/sim/battle-actions.ts +4 -1
- package/sim/battle.ts +24 -23
- package/sim/dex-formats.ts +4 -1
- package/sim/dex-species.ts +5 -2
- package/sim/exported-global-types.ts +1 -0
- package/sim/global-types.ts +1 -0
- package/sim/index.ts +1 -0
- package/sim/team-validator.ts +12 -0
package/data/rulesets.ts
CHANGED
|
@@ -791,6 +791,15 @@ export const Rulesets: {[k: string]: FormatData} = {
|
|
|
791
791
|
];
|
|
792
792
|
},
|
|
793
793
|
},
|
|
794
|
+
onebatonpassclause: {
|
|
795
|
+
effectType: 'ValidatorRule',
|
|
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
|
+
},
|
|
794
803
|
oneboostpasserclause: {
|
|
795
804
|
effectType: 'ValidatorRule',
|
|
796
805
|
name: 'One Boost Passer Clause',
|
|
@@ -1825,7 +1834,7 @@ export const Rulesets: {[k: string]: FormatData} = {
|
|
|
1825
1834
|
name: "Revelationmons Mod",
|
|
1826
1835
|
desc: `The moves in the first slot(s) of a Pokémon's set have their types changed to match the Pokémon's type(s).`,
|
|
1827
1836
|
onBegin() {
|
|
1828
|
-
this.add('rule', 'Revelationmons Mod: The first moveslots have their types changed to match the Pok
|
|
1837
|
+
this.add('rule', 'Revelationmons Mod: The first moveslots have their types changed to match the Pok\u00e9mon\'s types');
|
|
1829
1838
|
},
|
|
1830
1839
|
onValidateSet(set) {
|
|
1831
1840
|
const species = this.dex.species.get(set.species);
|
|
@@ -1847,6 +1856,7 @@ export const Rulesets: {[k: string]: FormatData} = {
|
|
|
1847
1856
|
];
|
|
1848
1857
|
if (noModifyType.includes(move.id)) return;
|
|
1849
1858
|
for (const [i, type] of types.entries()) {
|
|
1859
|
+
if (!this.dex.types.isName(type)) continue;
|
|
1850
1860
|
if (pokemon.moveSlots[i] && move.id === pokemon.moveSlots[i].id) move.type = type;
|
|
1851
1861
|
}
|
|
1852
1862
|
},
|
package/data/tags.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {Ability, Item, Move, Species} from '../sim/exported-global-types';
|
|
2
|
+
|
|
1
3
|
interface TagData {
|
|
2
4
|
name: string;
|
|
3
5
|
desc?: string;
|
|
@@ -195,9 +197,10 @@ export const Tags: {[id: string]: TagData} = {
|
|
|
195
197
|
nduubl: {
|
|
196
198
|
name: "ND UUBL",
|
|
197
199
|
speciesFilter: species => [
|
|
198
|
-
'Aerodactyl-Mega', '
|
|
199
|
-
'Hawlucha', 'Heracross-Mega', 'Hoopa-Unbound', 'Hydreigon', 'Jirachi', 'Latias', 'Latias-Mega', 'Latios', 'Latios-Mega', 'Manaphy',
|
|
200
|
-
'Pinsir-Mega', 'Sableye-Mega', 'Slowbro-Mega', 'Slowking-Galar', 'Thundurus', 'Thundurus-Therian', 'Venusaur-Mega',
|
|
200
|
+
'Aerodactyl-Mega', 'Blacephalon', 'Diancie-Mega', 'Gallade-Mega', 'Gardevoir-Mega', 'Gengar', 'Gyarados', 'Gyarados-Mega',
|
|
201
|
+
'Hawlucha', 'Heracross-Mega', 'Hoopa-Unbound', 'Hydreigon', 'Jirachi', 'Latias', 'Latias-Mega', 'Latios', 'Latios-Mega', 'Manaphy',
|
|
202
|
+
'Medicham-Mega', 'Mew', 'Pinsir-Mega', 'Sableye-Mega', 'Slowbro-Mega', 'Slowking-Galar', 'Thundurus', 'Thundurus-Therian', 'Venusaur-Mega',
|
|
203
|
+
'Xurkitree', 'Zapdos-Galar',
|
|
201
204
|
].includes(species.name),
|
|
202
205
|
},
|
|
203
206
|
|
package/data/text/abilities.ts
CHANGED
|
@@ -270,8 +270,8 @@ export const AbilitiesText: {[k: string]: AbilityText} = {
|
|
|
270
270
|
},
|
|
271
271
|
dazzling: {
|
|
272
272
|
name: "Dazzling",
|
|
273
|
-
desc: "
|
|
274
|
-
shortDesc: "
|
|
273
|
+
desc: "Priority moves used by opposing Pokemon targeting this Pokemon or its allies are prevented from having an effect.",
|
|
274
|
+
shortDesc: "This Pokemon and its allies are protected from opposing priority moves.",
|
|
275
275
|
|
|
276
276
|
block: "#damp",
|
|
277
277
|
},
|
|
@@ -1088,8 +1088,8 @@ export const AbilitiesText: {[k: string]: AbilityText} = {
|
|
|
1088
1088
|
},
|
|
1089
1089
|
queenlymajesty: {
|
|
1090
1090
|
name: "Queenly Majesty",
|
|
1091
|
-
desc: "
|
|
1092
|
-
shortDesc: "
|
|
1091
|
+
desc: "Priority moves used by opposing Pokemon targeting this Pokemon or its allies are prevented from having an effect.",
|
|
1092
|
+
shortDesc: "This Pokemon and its allies are protected from opposing priority moves.",
|
|
1093
1093
|
|
|
1094
1094
|
block: "#damp",
|
|
1095
1095
|
},
|
package/data/text/moves.ts
CHANGED
|
@@ -3484,27 +3484,27 @@ export const MovesText: {[k: string]: MoveText} = {
|
|
|
3484
3484
|
},
|
|
3485
3485
|
maxairstream: {
|
|
3486
3486
|
name: "Max Airstream",
|
|
3487
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Speed of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute.",
|
|
3487
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Speed of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3488
3488
|
shortDesc: "Base move affects power. Allies: +1 Speed.",
|
|
3489
3489
|
},
|
|
3490
3490
|
maxdarkness: {
|
|
3491
3491
|
name: "Max Darkness",
|
|
3492
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Defense of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute.",
|
|
3492
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Defense of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3493
3493
|
shortDesc: "Base move affects power. Foes: -1 Sp. Def.",
|
|
3494
3494
|
},
|
|
3495
3495
|
maxflare: {
|
|
3496
3496
|
name: "Max Flare",
|
|
3497
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Sunny Day begins.",
|
|
3497
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Sunny Day begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3498
3498
|
shortDesc: "Base move affects power. Starts Sunny Day.",
|
|
3499
3499
|
},
|
|
3500
3500
|
maxflutterby: {
|
|
3501
3501
|
name: "Max Flutterby",
|
|
3502
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Attack of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute.",
|
|
3502
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Attack of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3503
3503
|
shortDesc: "Base move affects power. Foes: -1 Sp. Atk.",
|
|
3504
3504
|
},
|
|
3505
3505
|
maxgeyser: {
|
|
3506
3506
|
name: "Max Geyser",
|
|
3507
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Rain Dance begins.",
|
|
3507
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Rain Dance begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3508
3508
|
shortDesc: "Base move affects power. Starts Rain Dance.",
|
|
3509
3509
|
},
|
|
3510
3510
|
maxguard: {
|
|
@@ -3516,67 +3516,67 @@ export const MovesText: {[k: string]: MoveText} = {
|
|
|
3516
3516
|
},
|
|
3517
3517
|
maxhailstorm: {
|
|
3518
3518
|
name: "Max Hailstorm",
|
|
3519
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Hail begins.",
|
|
3519
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Hail begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3520
3520
|
shortDesc: "Base move affects power. Starts Hail.",
|
|
3521
3521
|
},
|
|
3522
3522
|
maxknuckle: {
|
|
3523
3523
|
name: "Max Knuckle",
|
|
3524
|
-
desc: "Boosts the user and its allies' Attack by 1 stage. BP scales with the base move's BP.",
|
|
3524
|
+
desc: "Boosts the user and its allies' Attack by 1 stage. BP scales with the base move's BP. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3525
3525
|
shortDesc: "Base move affects power. Allies: +1 Attack.",
|
|
3526
3526
|
},
|
|
3527
3527
|
maxlightning: {
|
|
3528
3528
|
name: "Max Lightning",
|
|
3529
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Electric Terrain begins.",
|
|
3529
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Electric Terrain begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3530
3530
|
shortDesc: "Base move affects power. Starts Electric Terrain.",
|
|
3531
3531
|
},
|
|
3532
3532
|
maxmindstorm: {
|
|
3533
3533
|
name: "Max Mindstorm",
|
|
3534
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Psychic Terrain begins.",
|
|
3534
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Psychic Terrain begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3535
3535
|
shortDesc: "Base move affects power. Starts Psychic Terrain.",
|
|
3536
3536
|
},
|
|
3537
3537
|
maxooze: {
|
|
3538
3538
|
name: "Max Ooze",
|
|
3539
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Attack of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute.",
|
|
3539
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Attack of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3540
3540
|
shortDesc: "Base move affects power. Allies: +1 Sp. Atk.",
|
|
3541
3541
|
},
|
|
3542
3542
|
maxovergrowth: {
|
|
3543
3543
|
name: "Max Overgrowth",
|
|
3544
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Grassy Terrain begins.",
|
|
3544
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Grassy Terrain begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3545
3545
|
shortDesc: "Base move affects power. Starts Grassy Terrain.",
|
|
3546
3546
|
},
|
|
3547
3547
|
maxphantasm: {
|
|
3548
3548
|
name: "Max Phantasm",
|
|
3549
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Defense of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute.",
|
|
3549
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Defense of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3550
3550
|
shortDesc: "Base move affects power. Foes: -1 Defense.",
|
|
3551
3551
|
},
|
|
3552
3552
|
maxquake: {
|
|
3553
3553
|
name: "Max Quake",
|
|
3554
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Defense of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute.",
|
|
3554
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Special Defense of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3555
3555
|
shortDesc: "Base move affects power. Allies: +1 Sp. Def.",
|
|
3556
3556
|
},
|
|
3557
3557
|
maxrockfall: {
|
|
3558
3558
|
name: "Max Rockfall",
|
|
3559
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Sandstorm begins.",
|
|
3559
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Sandstorm begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3560
3560
|
shortDesc: "Base move affects power. Starts Sandstorm.",
|
|
3561
3561
|
},
|
|
3562
3562
|
maxstarfall: {
|
|
3563
3563
|
name: "Max Starfall",
|
|
3564
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Misty Terrain begins.",
|
|
3564
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the effect of Misty Terrain begins. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3565
3565
|
shortDesc: "Base move affects power. Starts Misty Terrain.",
|
|
3566
3566
|
},
|
|
3567
3567
|
maxsteelspike: {
|
|
3568
3568
|
name: "Max Steelspike",
|
|
3569
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Defense of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute.",
|
|
3569
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Defense of each Pokemon on the user's side is raised by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3570
3570
|
shortDesc: "Base move affects power. Allies: +1 Defense.",
|
|
3571
3571
|
},
|
|
3572
3572
|
maxstrike: {
|
|
3573
3573
|
name: "Max Strike",
|
|
3574
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Speed of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute.",
|
|
3574
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Speed of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3575
3575
|
shortDesc: "Base move affects power. Foes: -1 Speed.",
|
|
3576
3576
|
},
|
|
3577
3577
|
maxwyrmwind: {
|
|
3578
3578
|
name: "Max Wyrmwind",
|
|
3579
|
-
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Attack of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute.",
|
|
3579
|
+
desc: "Power is equal to the base move's Max Move power. If this move is successful, the Attack of each Pokemon on the opposing side is lowered by 1 stage, even if they have a substitute. This effect does not happen if the user is not Dynamaxed. If this move is used as a base move, it deals damage with a power of 0.",
|
|
3580
3580
|
shortDesc: "Base move affects power. Foes: -1 Attack.",
|
|
3581
3581
|
},
|
|
3582
3582
|
meanlook: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pkmn/sim",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
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.
|
|
34
|
+
"mocha": "^9.2.0"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"compile": "tsc -p .",
|
package/sim/battle-actions.ts
CHANGED
|
@@ -1285,7 +1285,10 @@ export class BattleActions {
|
|
|
1285
1285
|
this.battle.runEvent('ModifySecondaries', target, source, moveData, moveData.secondaries.slice());
|
|
1286
1286
|
for (const secondary of secondaries) {
|
|
1287
1287
|
const secondaryRoll = this.battle.random(100);
|
|
1288
|
-
|
|
1288
|
+
// User stat boosts or target stat drops can possibly overflow if it goes beyond 256
|
|
1289
|
+
const secondaryOverflow = (secondary.boosts || secondary.self);
|
|
1290
|
+
if (typeof secondary.chance === 'undefined' ||
|
|
1291
|
+
secondaryRoll < (secondaryOverflow ? secondary.chance % 256 : secondary.chance)) {
|
|
1289
1292
|
this.moveHit(target, source, move, secondary, true, isSelf);
|
|
1290
1293
|
}
|
|
1291
1294
|
}
|
package/sim/battle.ts
CHANGED
|
@@ -1553,29 +1553,8 @@ export class Battle {
|
|
|
1553
1553
|
maybeTriggerEndlessBattleClause(
|
|
1554
1554
|
trappedBySide: boolean[], stalenessBySide: ('internal' | 'external' | undefined)[]
|
|
1555
1555
|
) {
|
|
1556
|
-
if (this.turn <= 100) return;
|
|
1557
|
-
|
|
1558
|
-
// the turn limit is not a part of Endless Battle Clause
|
|
1559
|
-
if (this.turn >= 1000) {
|
|
1560
|
-
this.add('message', `It is turn 1000. You have hit the turn limit!`);
|
|
1561
|
-
this.tie();
|
|
1562
|
-
return true;
|
|
1563
|
-
}
|
|
1564
|
-
if (
|
|
1565
|
-
(this.turn >= 500 && this.turn % 100 === 0) || // every 100 turns past turn 500,
|
|
1566
|
-
(this.turn >= 900 && this.turn % 10 === 0) || // every 10 turns past turn 900,
|
|
1567
|
-
this.turn >= 990 // every turn past turn 990
|
|
1568
|
-
) {
|
|
1569
|
-
const turnsLeft = 1000 - this.turn;
|
|
1570
|
-
const turnsLeftText = (turnsLeft === 1 ? `1 turn` : `${turnsLeft} turns`);
|
|
1571
|
-
this.add('bigerror', `You will auto-tie if the battle doesn't end in ${turnsLeftText} (on turn 1000).`);
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
if (!this.ruleTable.has('endlessbattleclause')) return;
|
|
1575
|
-
// for now, FFA doesn't support Endless Battle Clause
|
|
1576
|
-
if (this.format.gameType === 'freeforall') return;
|
|
1577
|
-
|
|
1578
1556
|
// Gen 1 Endless Battle Clause triggers
|
|
1557
|
+
// These are checked before the 100 turn minimum as the battle cannot progress if they are true
|
|
1579
1558
|
if (this.gen <= 1) {
|
|
1580
1559
|
const noProgressPossible = this.sides.every(side => {
|
|
1581
1560
|
const foeAllGhosts = side.foe.pokemon.every(pokemon => pokemon.types.includes('Ghost'));
|
|
@@ -1593,7 +1572,7 @@ export class Battle {
|
|
|
1593
1572
|
// a pokemon can't lose PP if it Transforms into a pokemon with only Transform
|
|
1594
1573
|
(pokemon.moves.every(moveid => moveid === 'transform') && foeAllTransform) ||
|
|
1595
1574
|
// Struggle can't damage yourself if every foe is a Ghost
|
|
1596
|
-
pokemon.moveSlots.every(slot => slot.pp === 0) && foeAllGhosts
|
|
1575
|
+
(pokemon.moveSlots.every(slot => slot.pp === 0) && foeAllGhosts)
|
|
1597
1576
|
));
|
|
1598
1577
|
});
|
|
1599
1578
|
if (noProgressPossible) {
|
|
@@ -1602,6 +1581,28 @@ export class Battle {
|
|
|
1602
1581
|
}
|
|
1603
1582
|
}
|
|
1604
1583
|
|
|
1584
|
+
if (this.turn <= 100) return;
|
|
1585
|
+
|
|
1586
|
+
// the turn limit is not a part of Endless Battle Clause
|
|
1587
|
+
if (this.turn >= 1000) {
|
|
1588
|
+
this.add('message', `It is turn 1000. You have hit the turn limit!`);
|
|
1589
|
+
this.tie();
|
|
1590
|
+
return true;
|
|
1591
|
+
}
|
|
1592
|
+
if (
|
|
1593
|
+
(this.turn >= 500 && this.turn % 100 === 0) || // every 100 turns past turn 500,
|
|
1594
|
+
(this.turn >= 900 && this.turn % 10 === 0) || // every 10 turns past turn 900,
|
|
1595
|
+
this.turn >= 990 // every turn past turn 990
|
|
1596
|
+
) {
|
|
1597
|
+
const turnsLeft = 1000 - this.turn;
|
|
1598
|
+
const turnsLeftText = (turnsLeft === 1 ? `1 turn` : `${turnsLeft} turns`);
|
|
1599
|
+
this.add('bigerror', `You will auto-tie if the battle doesn't end in ${turnsLeftText} (on turn 1000).`);
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
if (!this.ruleTable.has('endlessbattleclause')) return;
|
|
1603
|
+
// for now, FFA doesn't support Endless Battle Clause
|
|
1604
|
+
if (this.format.gameType === 'freeforall') return;
|
|
1605
|
+
|
|
1605
1606
|
// Are all Pokemon on every side stale, with at least one side containing an externally stale Pokemon?
|
|
1606
1607
|
if (!stalenessBySide.every(s => !!s) || !stalenessBySide.some(s => s === 'external')) return;
|
|
1607
1608
|
|
package/sim/dex-formats.ts
CHANGED
|
@@ -340,6 +340,10 @@ export class RuleTable extends Map<string, string> {
|
|
|
340
340
|
throw new Error(`maxForcedLevel is now a rule: "Adjust Level Down = NUMBER"`);
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
|
+
|
|
344
|
+
hasComplexBans() {
|
|
345
|
+
return (this.complexBans?.length > 0) || (this.complexTeamBans?.length > 0);
|
|
346
|
+
}
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
export class Format extends BasicEffect implements Readonly<BasicEffect> {
|
|
@@ -799,7 +803,6 @@ export class DexFormats {
|
|
|
799
803
|
case '-':
|
|
800
804
|
case '*':
|
|
801
805
|
case '+':
|
|
802
|
-
if (format?.team) throw new Error(`We don't currently support bans in generated teams`);
|
|
803
806
|
if (rule.slice(1).includes('>') || rule.slice(1).includes('+')) {
|
|
804
807
|
let buf = rule.slice(1);
|
|
805
808
|
const gtIndex = buf.lastIndexOf('>');
|
package/sim/dex-species.ts
CHANGED
|
@@ -295,7 +295,7 @@ export class Species extends BasicEffect implements Readonly<BasicEffect & Speci
|
|
|
295
295
|
if (Array.isArray(data.changesFrom)) this.changesFrom = data.changesFrom[0];
|
|
296
296
|
|
|
297
297
|
if (!this.gen && this.num >= 1) {
|
|
298
|
-
if (this.num >= 810 || ['Gmax', 'Galar', 'Galar-Zen'].includes(this.forme)) {
|
|
298
|
+
if (this.num >= 810 || ['Gmax', 'Galar', 'Galar-Zen', 'Hisui'].includes(this.forme)) {
|
|
299
299
|
this.gen = 8;
|
|
300
300
|
} else if (this.num >= 722 || this.forme.startsWith('Alola') || this.forme === 'Starter') {
|
|
301
301
|
this.gen = 7;
|
|
@@ -492,7 +492,10 @@ export class DexSpecies {
|
|
|
492
492
|
species.tier = species.doublesTier = 'Illegal';
|
|
493
493
|
}
|
|
494
494
|
}
|
|
495
|
-
species.nfe =
|
|
495
|
+
species.nfe = species.evos.some(evo => {
|
|
496
|
+
const evoSpecies = this.get(evo);
|
|
497
|
+
return !evoSpecies.isNonstandard || evoSpecies.isNonstandard === species?.isNonstandard;
|
|
498
|
+
});
|
|
496
499
|
species.canHatch = species.canHatch ||
|
|
497
500
|
(!['Ditto', 'Undiscovered'].includes(species.eggGroups[0]) && !species.prevo && species.name !== 'Manaphy');
|
|
498
501
|
if (this.dex.gen === 1) species.bst -= species.baseStats.spd;
|
|
@@ -373,6 +373,7 @@ export interface ModdedBattleScriptsData extends Partial<BattleScriptsData> {
|
|
|
373
373
|
init?: (this: ModdedDex) => void;
|
|
374
374
|
natureModify?: (this: Battle, stats: StatsTable, set: PokemonSet) => StatsTable;
|
|
375
375
|
nextTurn?: (this: Battle) => void;
|
|
376
|
+
runAction?: (this: Battle, action: Action) => void;
|
|
376
377
|
spreadModify?: (this: Battle, baseStats: StatsTable, set: PokemonSet) => StatsTable;
|
|
377
378
|
suppressingWeather?: (this: Battle) => boolean;
|
|
378
379
|
trunc?: (n: number) => number;
|
package/sim/global-types.ts
CHANGED
|
@@ -373,6 +373,7 @@ interface ModdedBattleScriptsData extends Partial<BattleScriptsData> {
|
|
|
373
373
|
init?: (this: ModdedDex) => void;
|
|
374
374
|
natureModify?: (this: Battle, stats: StatsTable, set: PokemonSet) => StatsTable;
|
|
375
375
|
nextTurn?: (this: Battle) => void;
|
|
376
|
+
runAction?: (this: Battle, action: Action) => void;
|
|
376
377
|
spreadModify?: (this: Battle, baseStats: StatsTable, set: PokemonSet) => StatsTable;
|
|
377
378
|
suppressingWeather?: (this: Battle) => boolean;
|
|
378
379
|
trunc?: (n: number) => number;
|
package/sim/index.ts
CHANGED
package/sim/team-validator.ts
CHANGED
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
import {Dex, toID} from './dex';
|
|
27
27
|
import {Utils} from '../lib';
|
|
28
28
|
import {Tags} from '../data/tags';
|
|
29
|
+
import {Teams} from './teams';
|
|
30
|
+
import {PRNG} from './prng';
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* Describes a possible way to get a pokemon. Is not exhaustive!
|
|
@@ -252,6 +254,16 @@ export class TeamValidator {
|
|
|
252
254
|
`If you're not using a custom client, please report this as a bug. If you are, remember to use \`/utm null\` before starting a game in this format.`,
|
|
253
255
|
];
|
|
254
256
|
}
|
|
257
|
+
const testTeamSeed = PRNG.generateSeed();
|
|
258
|
+
try {
|
|
259
|
+
const testTeamGenerator = Teams.getGenerator(format, testTeamSeed);
|
|
260
|
+
testTeamGenerator.getTeam(options as any); // Throws error if generation fails
|
|
261
|
+
} catch (e) {
|
|
262
|
+
return [
|
|
263
|
+
`${format.name}'s team generator (${format.team}) failed using these rules and seed (${testTeamSeed}):-`,
|
|
264
|
+
`${e}`,
|
|
265
|
+
];
|
|
266
|
+
}
|
|
255
267
|
return null;
|
|
256
268
|
}
|
|
257
269
|
if (!team) {
|