@pkmn/sim 0.4.20 → 0.4.24
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 +415 -688
- package/build/config/formats.js.map +1 -1
- package/build/data/aliases.js +7 -5
- package/build/data/aliases.js.map +1 -1
- package/build/data/conditions.js +4 -1
- package/build/data/conditions.js.map +1 -1
- package/build/data/formats-data.js +18 -18
- package/build/data/formats-data.js.map +1 -1
- package/build/data/learnsets.js +10 -8
- package/build/data/learnsets.js.map +1 -1
- package/build/data/mods/gen1/moves.js +1 -1
- package/build/data/mods/gen1/moves.js.map +1 -1
- package/build/data/mods/gen1/scripts.js +18 -22
- package/build/data/mods/gen1/scripts.js.map +1 -1
- package/build/data/mods/gen2/scripts.js +16 -23
- package/build/data/mods/gen2/scripts.js.map +1 -1
- package/build/data/mods/gen3/moves.js +2 -1
- package/build/data/mods/gen3/moves.js.map +1 -1
- package/build/data/mods/gen4/conditions.js +6 -0
- package/build/data/mods/gen4/conditions.js.map +1 -1
- package/build/data/mods/gen4/moves.js +2 -1
- package/build/data/mods/gen4/moves.js.map +1 -1
- package/build/data/mods/gen4/scripts.js +2 -1
- package/build/data/mods/gen4/scripts.js.map +1 -1
- package/build/data/mods/gen6/conditions.js +4 -1
- package/build/data/mods/gen6/conditions.js.map +1 -1
- package/build/data/mods/gen7/formats-data.js +2 -2
- package/build/data/mods/gen7/formats-data.js.map +1 -1
- package/build/data/mods/gen7/moves.js +8 -0
- package/build/data/mods/gen7/moves.js.map +1 -1
- package/build/data/moves.js +25 -13
- package/build/data/moves.js.map +1 -1
- package/build/data/rulesets.js +221 -1
- package/build/data/rulesets.js.map +1 -1
- package/build/data/tags.js +2 -2
- package/build/data/tags.js.map +1 -1
- package/build/lib/streams.d.ts +1 -199
- package/build/lib/streams.js +11 -772
- package/build/lib/streams.js.map +1 -1
- package/build/sim/battle-actions.d.ts +1 -1
- package/build/sim/battle-actions.js +18 -42
- package/build/sim/battle-actions.js.map +1 -1
- package/build/sim/battle.d.ts +1 -0
- package/build/sim/battle.js +5 -0
- package/build/sim/battle.js.map +1 -1
- package/build/sim/dex-moves.d.ts +31 -11
- package/build/sim/dex-moves.js +4 -3
- package/build/sim/dex-moves.js.map +1 -1
- package/build/sim/dex-species.js +11 -1
- 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/side.js +2 -2
- package/build/sim/side.js.map +1 -1
- package/build/sim/team-validator.js +2 -2
- package/build/sim/team-validator.js.map +1 -1
- package/build/sim/tools/runner.d.ts +1 -6
- package/build/sim/tools/runner.js +6 -6
- package/build/sim/tools/runner.js.map +1 -1
- package/config/formats.ts +393 -643
- package/data/aliases.ts +7 -5
- package/data/conditions.ts +4 -1
- package/data/formats-data.ts +18 -18
- package/data/learnsets.ts +10 -8
- package/data/mods/gen1/moves.ts +1 -1
- package/data/mods/gen1/scripts.ts +23 -19
- package/data/mods/gen2/scripts.ts +20 -19
- package/data/mods/gen3/moves.ts +2 -1
- package/data/mods/gen4/conditions.ts +6 -0
- package/data/mods/gen4/moves.ts +2 -1
- package/data/mods/gen4/scripts.ts +1 -1
- package/data/mods/gen6/conditions.ts +4 -1
- package/data/mods/gen7/formats-data.ts +2 -2
- package/data/mods/gen7/moves.ts +8 -0
- package/data/moves.ts +22 -13
- package/data/rulesets.ts +199 -1
- package/data/tags.ts +2 -2
- package/lib/streams.ts +1 -874
- package/package.json +3 -2
- package/sim/battle-actions.ts +19 -40
- package/sim/battle.ts +6 -0
- package/sim/dex-moves.ts +35 -13
- package/sim/dex-species.ts +10 -1
- package/sim/exported-global-types.ts +1 -0
- package/sim/global-types.ts +1 -0
- package/sim/side.ts +2 -2
- package/sim/team-validator.ts +2 -2
- package/sim/tools/runner.ts +2 -0
package/build/data/rulesets.js
CHANGED
|
@@ -1104,7 +1104,9 @@ exports.Rulesets = {
|
|
|
1104
1104
|
if (!nonstandard && !move.isZ && !move.isMax && !this.ruleTable.isRestricted(`move:${move.id}`)) {
|
|
1105
1105
|
const speciesTypes = [];
|
|
1106
1106
|
const moveTypes = [];
|
|
1107
|
-
|
|
1107
|
+
// BDSP can't import Pokemon from Home, so it shouldn't grant moves from archaic species types
|
|
1108
|
+
const minObtainableSpeciesGen = this.dex.currentMod === 'gen8bdsp' ? this.dex.gen : species.gen;
|
|
1109
|
+
for (let i = this.dex.gen; i >= minObtainableSpeciesGen && i >= move.gen; i--) {
|
|
1108
1110
|
const dex = this.dex.forGen(i);
|
|
1109
1111
|
moveTypes.push(dex.moves.get(move.name).type);
|
|
1110
1112
|
const pokemon = dex.species.get(species.name);
|
|
@@ -1641,5 +1643,223 @@ exports.Rulesets = {
|
|
|
1641
1643
|
this.lose(target.side);
|
|
1642
1644
|
},
|
|
1643
1645
|
},
|
|
1646
|
+
tiershiftmod: {
|
|
1647
|
+
effectType: "Rule",
|
|
1648
|
+
name: "Tier Shift Mod",
|
|
1649
|
+
desc: `Pokémon below OU get their stats, excluding HP, boosted. UU/RUBL get +10, RU/NUBL get +20, NU/PUBL get +30, and PU or lower get +40.`,
|
|
1650
|
+
ruleset: ['Overflow Stat Mod'],
|
|
1651
|
+
onBegin() {
|
|
1652
|
+
this.add('rule', 'Tier Shift Mod: Pok\u00e9mon get stat buffs depending on their tier, excluding HP.');
|
|
1653
|
+
},
|
|
1654
|
+
onModifySpecies(species, target, source, effect) {
|
|
1655
|
+
if (!species.baseStats)
|
|
1656
|
+
return;
|
|
1657
|
+
const boosts = {
|
|
1658
|
+
uu: 10,
|
|
1659
|
+
rubl: 10,
|
|
1660
|
+
ru: 20,
|
|
1661
|
+
nubl: 20,
|
|
1662
|
+
nu: 30,
|
|
1663
|
+
publ: 30,
|
|
1664
|
+
pu: 40,
|
|
1665
|
+
nfe: 40,
|
|
1666
|
+
lc: 40,
|
|
1667
|
+
};
|
|
1668
|
+
let tier = this.toID(species.tier);
|
|
1669
|
+
if (!(tier in boosts))
|
|
1670
|
+
return;
|
|
1671
|
+
// Non-Pokemon bans in lower tiers
|
|
1672
|
+
if (target) {
|
|
1673
|
+
if (target.set.item === 'lightclay')
|
|
1674
|
+
return;
|
|
1675
|
+
if (['drizzle', 'drought', 'snowwarning'].includes(target.set.ability) && boosts[tier] > 20)
|
|
1676
|
+
tier = 'nubl';
|
|
1677
|
+
}
|
|
1678
|
+
const pokemon = this.dex.deepClone(species);
|
|
1679
|
+
pokemon.bst = pokemon.baseStats['hp'];
|
|
1680
|
+
const boost = boosts[tier];
|
|
1681
|
+
let statName;
|
|
1682
|
+
for (statName in pokemon.baseStats) {
|
|
1683
|
+
if (statName === 'hp')
|
|
1684
|
+
continue;
|
|
1685
|
+
pokemon.baseStats[statName] = this.clampIntRange(pokemon.baseStats[statName] + boost, 1, 255);
|
|
1686
|
+
pokemon.bst += pokemon.baseStats[statName];
|
|
1687
|
+
}
|
|
1688
|
+
return pokemon;
|
|
1689
|
+
},
|
|
1690
|
+
},
|
|
1691
|
+
crossevolutionmod: {
|
|
1692
|
+
effectType: "Rule",
|
|
1693
|
+
name: "Cross Evolution Mod",
|
|
1694
|
+
desc: "Give a Pokémon a Pokémon name of the next evolution stage as a nickname to inherit stat changes, typing, abilities, and up to 2 moves from the next stage Pokémon.",
|
|
1695
|
+
ruleset: ['Overflow Stat Mod'],
|
|
1696
|
+
onValidateTeam(team) {
|
|
1697
|
+
const names = new Set();
|
|
1698
|
+
for (const set of team) {
|
|
1699
|
+
const name = set.name;
|
|
1700
|
+
if (names.has(this.dex.toID(name))) {
|
|
1701
|
+
return [
|
|
1702
|
+
`Your Pok\u00e9mon must have different nicknames.`,
|
|
1703
|
+
`(You have more than one Pok\u00e9mon named '${name}')`,
|
|
1704
|
+
];
|
|
1705
|
+
}
|
|
1706
|
+
names.add(this.dex.toID(name));
|
|
1707
|
+
}
|
|
1708
|
+
if (!names.size) {
|
|
1709
|
+
return [
|
|
1710
|
+
`${this.format.name} works using nicknames; your team has 0 nicknamed Pok\u00e9mon.`,
|
|
1711
|
+
`(If this was intentional, add a nickname to one Pok\u00e9mon that isn't the name of a Pok\u00e9mon species.)`,
|
|
1712
|
+
];
|
|
1713
|
+
}
|
|
1714
|
+
},
|
|
1715
|
+
checkCanLearn(move, species, lsetData, set) {
|
|
1716
|
+
// @ts-ignore
|
|
1717
|
+
if (!set.sp?.exists || !set.crossSpecies?.exists) {
|
|
1718
|
+
return this.checkCanLearn(move, species, lsetData, set);
|
|
1719
|
+
}
|
|
1720
|
+
// @ts-ignore
|
|
1721
|
+
const problem = this.checkCanLearn(move, set.sp);
|
|
1722
|
+
if (!problem)
|
|
1723
|
+
return null;
|
|
1724
|
+
// @ts-ignore
|
|
1725
|
+
if (!set.crossMovesLeft)
|
|
1726
|
+
return problem;
|
|
1727
|
+
// @ts-ignore
|
|
1728
|
+
if (this.checkCanLearn(move, set.crossSpecies))
|
|
1729
|
+
return problem;
|
|
1730
|
+
// @ts-ignore
|
|
1731
|
+
set.crossMovesLeft--;
|
|
1732
|
+
return null;
|
|
1733
|
+
},
|
|
1734
|
+
validateSet(set, teamHas) {
|
|
1735
|
+
const crossSpecies = this.dex.species.get(set.name);
|
|
1736
|
+
const onChangeSet = this.dex.formats.get('Pokemon').onChangeSet;
|
|
1737
|
+
let problems = onChangeSet?.call(this, set, this.format) || null;
|
|
1738
|
+
if (Array.isArray(problems) && problems.length)
|
|
1739
|
+
return problems;
|
|
1740
|
+
const crossNonstandard = !this.ruleTable.has('standardnatdex') && crossSpecies.isNonstandard === 'Past';
|
|
1741
|
+
const crossIsCap = !this.ruleTable.has('+pokemontag:cap') && crossSpecies.isNonstandard === 'CAP';
|
|
1742
|
+
if (!crossSpecies.exists || crossNonstandard || crossIsCap)
|
|
1743
|
+
return this.validateSet(set, teamHas);
|
|
1744
|
+
const species = this.dex.species.get(set.species);
|
|
1745
|
+
const check = this.checkSpecies(set, species, species, {});
|
|
1746
|
+
if (check)
|
|
1747
|
+
return [check];
|
|
1748
|
+
const nonstandard = !this.ruleTable.has('standardnatdex') && species.isNonstandard === 'Past';
|
|
1749
|
+
const isCap = !this.ruleTable.has('+pokemontag:cap') && species.isNonstandard === 'CAP';
|
|
1750
|
+
if (!species.exists || nonstandard || isCap || species === crossSpecies)
|
|
1751
|
+
return this.validateSet(set, teamHas);
|
|
1752
|
+
if (!species.nfe)
|
|
1753
|
+
return [`${species.name} cannot cross evolve because it doesn't evolve.`];
|
|
1754
|
+
const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
|
|
1755
|
+
if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo) {
|
|
1756
|
+
return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it isn't an evolution.`];
|
|
1757
|
+
}
|
|
1758
|
+
if (this.ruleTable.isRestrictedSpecies(crossSpecies)) {
|
|
1759
|
+
return [`${species.name} cannot cross evolve into ${crossSpecies.name} because it is banned.`];
|
|
1760
|
+
}
|
|
1761
|
+
const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
|
|
1762
|
+
if (!crossPrevoSpecies.prevo !== !species.prevo) {
|
|
1763
|
+
return [
|
|
1764
|
+
`${species.name} cannot cross evolve into ${crossSpecies.name} because they are not consecutive evolution stages.`,
|
|
1765
|
+
];
|
|
1766
|
+
}
|
|
1767
|
+
const ability = this.dex.abilities.get(set.ability);
|
|
1768
|
+
if (!this.ruleTable.isRestricted(`ability:${ability.id}`) || Object.values(species.abilities).includes(ability.name)) {
|
|
1769
|
+
set.species = crossSpecies.name;
|
|
1770
|
+
}
|
|
1771
|
+
// @ts-ignore
|
|
1772
|
+
set.sp = species;
|
|
1773
|
+
// @ts-ignore
|
|
1774
|
+
set.crossSpecies = crossSpecies;
|
|
1775
|
+
// @ts-ignore
|
|
1776
|
+
set.crossMovesLeft = 2;
|
|
1777
|
+
problems = this.validateSet(set, teamHas);
|
|
1778
|
+
set.name = crossSpecies.name;
|
|
1779
|
+
set.species = species.name;
|
|
1780
|
+
return problems;
|
|
1781
|
+
},
|
|
1782
|
+
onModifySpecies(species, target, source, effect) {
|
|
1783
|
+
if (!target)
|
|
1784
|
+
return; // chat
|
|
1785
|
+
if (effect && ['imposter', 'transform'].includes(effect.id))
|
|
1786
|
+
return;
|
|
1787
|
+
if (target.set.name === target.set.species)
|
|
1788
|
+
return;
|
|
1789
|
+
const crossSpecies = this.dex.species.get(target.set.name);
|
|
1790
|
+
if (!crossSpecies.exists)
|
|
1791
|
+
return;
|
|
1792
|
+
if (species.battleOnly || !species.nfe)
|
|
1793
|
+
return;
|
|
1794
|
+
const crossIsUnreleased = (crossSpecies.tier === "Unreleased" && crossSpecies.isNonstandard === "Unobtainable");
|
|
1795
|
+
if (crossSpecies.battleOnly || crossIsUnreleased || !crossSpecies.prevo)
|
|
1796
|
+
return;
|
|
1797
|
+
const crossPrevoSpecies = this.dex.species.get(crossSpecies.prevo);
|
|
1798
|
+
if (!crossPrevoSpecies.prevo !== !species.prevo)
|
|
1799
|
+
return;
|
|
1800
|
+
const mixedSpecies = this.dex.deepClone(species);
|
|
1801
|
+
mixedSpecies.baseSpecies = mixedSpecies.name = `${species.name}-${crossSpecies.name}`;
|
|
1802
|
+
mixedSpecies.weightkg =
|
|
1803
|
+
Math.max(0.1, +(species.weightkg + crossSpecies.weightkg - crossPrevoSpecies.weightkg)).toFixed(1);
|
|
1804
|
+
mixedSpecies.nfe = false;
|
|
1805
|
+
mixedSpecies.evos = [];
|
|
1806
|
+
mixedSpecies.eggGroups = crossSpecies.eggGroups;
|
|
1807
|
+
mixedSpecies.abilities = crossSpecies.abilities;
|
|
1808
|
+
mixedSpecies.bst = 0;
|
|
1809
|
+
let i;
|
|
1810
|
+
for (i in species.baseStats) {
|
|
1811
|
+
const statChange = crossSpecies.baseStats[i] - crossPrevoSpecies.baseStats[i];
|
|
1812
|
+
mixedSpecies.baseStats[i] = this.clampIntRange(species.baseStats[i] + statChange, 1, 255);
|
|
1813
|
+
mixedSpecies.bst += mixedSpecies.baseStats[i];
|
|
1814
|
+
}
|
|
1815
|
+
if (crossSpecies.types[0] !== crossPrevoSpecies.types[0])
|
|
1816
|
+
mixedSpecies.types[0] = crossSpecies.types[0];
|
|
1817
|
+
if (crossSpecies.types[1] !== crossPrevoSpecies.types[1]) {
|
|
1818
|
+
mixedSpecies.types[1] = crossSpecies.types[1] || crossSpecies.types[0];
|
|
1819
|
+
}
|
|
1820
|
+
if (mixedSpecies.types[0] === mixedSpecies.types[1])
|
|
1821
|
+
mixedSpecies.types = [mixedSpecies.types[0]];
|
|
1822
|
+
return mixedSpecies;
|
|
1823
|
+
},
|
|
1824
|
+
onBegin() {
|
|
1825
|
+
for (const pokemon of this.getAllPokemon()) {
|
|
1826
|
+
pokemon.baseSpecies = pokemon.species;
|
|
1827
|
+
}
|
|
1828
|
+
},
|
|
1829
|
+
},
|
|
1830
|
+
revelationmonsmod: {
|
|
1831
|
+
effectType: "Rule",
|
|
1832
|
+
name: "Revelationmons Mod",
|
|
1833
|
+
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).`,
|
|
1834
|
+
onBegin() {
|
|
1835
|
+
this.add('rule', 'Revelationmons Mod: The first moveslots have their types changed to match the Pokémon\'s types');
|
|
1836
|
+
},
|
|
1837
|
+
onValidateSet(set) {
|
|
1838
|
+
const species = this.dex.species.get(set.species);
|
|
1839
|
+
const slotIndex = species.types.length - 1;
|
|
1840
|
+
const problems = [];
|
|
1841
|
+
for (const [i, moveid] of set.moves.entries()) {
|
|
1842
|
+
const move = this.dex.moves.get(moveid);
|
|
1843
|
+
if (!this.ruleTable.isRestricted(`move:${move.id}`))
|
|
1844
|
+
continue;
|
|
1845
|
+
if (i <= slotIndex) {
|
|
1846
|
+
problems.push(`${move.name} can't be in moveslot ${i + 1} because it's restricted from being in the first ${slotIndex + 1 > 1 ? `${slotIndex + 1} slots` : 'slot'}.`);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
return problems;
|
|
1850
|
+
},
|
|
1851
|
+
onModifyMove(move, pokemon, target) {
|
|
1852
|
+
const types = pokemon.getTypes(true);
|
|
1853
|
+
const noModifyType = [
|
|
1854
|
+
'judgment', 'multiattack', 'naturalgift', 'revelationdance', 'technoblast', 'terrainpulse', 'weatherball',
|
|
1855
|
+
];
|
|
1856
|
+
if (noModifyType.includes(move.id))
|
|
1857
|
+
return;
|
|
1858
|
+
for (const [i, type] of types.entries()) {
|
|
1859
|
+
if (pokemon.moveSlots[i] && move.id === pokemon.moveSlots[i].id)
|
|
1860
|
+
move.type = type;
|
|
1861
|
+
}
|
|
1862
|
+
},
|
|
1863
|
+
},
|
|
1644
1864
|
};
|
|
1645
1865
|
//# sourceMappingURL=rulesets.js.map
|