diff --git a/config/formats.ts b/config/formats.ts index f0520b943cfc..194d303fe5eb 100644 --- a/config/formats.ts +++ b/config/formats.ts @@ -948,9 +948,10 @@ export const Formats: import('../sim/dex-formats').FormatList = [ ruleset: ['Standard OMs', 'Sleep Moves Clause', 'Inverse Mod', 'Terastal Clause'], banlist: [ 'Arceus', 'Baxcalibur', 'Calyrex-Ice', 'Calyrex-Shadow', 'Chien-Pao', 'Deoxys-Attack', 'Deoxys-Normal', 'Deoxys-Speed', 'Espathra', 'Eternatus', 'Flutter Mane', - 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Koraidon', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Lunala', 'Maushold', 'Mewtwo', 'Miraidon', 'Necrozma-Dawn-Wings', - 'Palkia', 'Palkia-Origin', 'Porygon-Z', 'Rayquaza', 'Regidrago', 'Regieleki', 'Reshiram', 'Rillaboom', 'Shaymin-Sky', 'Ursaluna', 'Ursaluna-Bloodmoon', 'Zacian', - 'Zacian-Crowned', 'Zamazenta-Hero', 'Zekrom', 'Arena Trap', 'Moody', 'Shadow Tag', 'King\'s Rock', 'Light Clay', 'Baton Pass', 'Last Respects', 'Shed Tail', + 'Giratina-Origin', 'Groudon', 'Ho-Oh', 'Indeedee', 'Indeedee-F', 'Koraidon', 'Kyogre', 'Kyurem', 'Kyurem-Black', 'Kyurem-White', 'Lunala', 'Maushold', 'Mewtwo', + 'Miraidon', 'Necrozma-Dawn-Wings', 'Palafin', 'Palkia', 'Palkia-Origin', 'Porygon-Z', 'Rayquaza', 'Regidrago', 'Regieleki', 'Reshiram', 'Rillaboom', 'Shaymin-Sky', + 'Spectrier', 'Ursaluna', 'Ursaluna-Bloodmoon', 'Zacian', 'Zacian-Crowned', 'Zamazenta-Hero', 'Zekrom', 'Arena Trap', 'Moody', 'Shadow Tag', 'King\'s Rock', 'Light Clay', + 'Baton Pass', 'Last Respects', 'Shed Tail', ], }, { @@ -1164,7 +1165,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ 'Walking Wake', 'Weavile', 'Zacian', 'Zacian-Crowned', 'Zekrom', 'Arena Trap', 'Comatose', 'Contrary', 'Fur Coat', 'Good as Gold', 'Gorilla Tactics', 'Huge Power', 'Ice Scales', 'Illusion', 'Imposter', 'Innards Out', 'Magic Bounce', 'Magnet Pull', 'Moody', 'Neutralizing Gas', 'Orichalcum Pulse', 'Parental Bond', 'Poison Heal', 'Pure Power', 'Shadow Tag', 'Simple', 'Speed Boost', 'Stakeout', 'Toxic Debris', 'Triage', 'Unburden', 'Water Bubble', 'Wonder Guard', 'King\'s Rock', 'Razor Fang', 'Baton Pass', 'Last Respects', - 'Revival Blessing', 'Shed Tail', + 'Shed Tail', ], }, { diff --git a/data/formats-data.ts b/data/formats-data.ts index da17ad7226e0..d1325921c391 100644 --- a/data/formats-data.ts +++ b/data/formats-data.ts @@ -1555,8 +1555,6 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable = }, piloswine: { tier: "NFE", - doublesTier: "NFE", - natDexTier: "NFE", }, mamoswine: { tier: "UU", @@ -1714,8 +1712,6 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable = }, combusken: { tier: "NFE", - doublesTier: "NFE", - natDexTier: "NFE", }, blaziken: { tier: "UUBL", @@ -4661,7 +4657,7 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable = }, thwackey: { tier: "SU", - doublesTier: "DUU", + doublesTier: "NFE", natDexTier: "NFE", }, rillaboom: { @@ -5176,8 +5172,6 @@ export const FormatsData: import('../sim/dex-species').SpeciesFormatsDataTable = }, quaxwell: { tier: "NFE", - doublesTier: "NFE", - natDexTier: "NFE", }, quaquaval: { tier: "UU", diff --git a/data/mods/gen5bw1/pokedex.ts b/data/mods/gen5bw1/pokedex.ts index 2abc68d2220d..742f17ea99ff 100644 --- a/data/mods/gen5bw1/pokedex.ts +++ b/data/mods/gen5bw1/pokedex.ts @@ -219,7 +219,7 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable inherit: true, unreleasedHidden: true, }, - lillpup: { + lillipup: { inherit: true, unreleasedHidden: true, }, @@ -383,7 +383,7 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable inherit: true, unreleasedHidden: true, }, - lillgant: { + lilligant: { inherit: true, unreleasedHidden: true, }, diff --git a/data/mods/gen9predlc/abilities.ts b/data/mods/gen9predlc/abilities.ts index 0d989708d022..47e904d8d62c 100644 --- a/data/mods/gen9predlc/abilities.ts +++ b/data/mods/gen9predlc/abilities.ts @@ -38,7 +38,19 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa inherit: true, isNonstandard: "Future", }, - embodyaspect: { + embodyaspectcornerstone: { + inherit: true, + isNonstandard: "Future", + }, + embodyaspecthearthflame: { + inherit: true, + isNonstandard: "Future", + }, + embodyaspectteal: { + inherit: true, + isNonstandard: "Future", + }, + embodyaspectwellspring: { inherit: true, isNonstandard: "Future", }, diff --git a/data/mods/gen9ssb/items.ts b/data/mods/gen9ssb/items.ts index 51471555cbca..ba538d227f08 100644 --- a/data/mods/gen9ssb/items.ts +++ b/data/mods/gen9ssb/items.ts @@ -11,7 +11,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = { }, // Arya flygonite: { - inherit: true, + name: "Flygonite", spritenum: 111, itemUser: ["Flygon"], megaEvolves: "Flygon", diff --git a/data/mods/gen9ssb/pokedex.ts b/data/mods/gen9ssb/pokedex.ts index d90d815b148d..e353b7b6388b 100644 --- a/data/mods/gen9ssb/pokedex.ts +++ b/data/mods/gen9ssb/pokedex.ts @@ -1146,7 +1146,7 @@ export const Pokedex: import('../../../sim/dex-species').ModdedSpeciesDataTable abilities: {0: "Yellow Magic"}, }, - ninetaleslola: { + ninetalesalola: { inherit: true, abilities: {0: "Party Up"}, }, diff --git a/data/moves.ts b/data/moves.ts index 4e456df95da9..03ddeef307d4 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -3131,7 +3131,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { flags: {mirror: 1, metronome: 1}, onHitField(target, source) { const sideConditions = [ - 'mist', 'lightscreen', 'reflect', 'spikes', 'safeguard', 'tailwind', 'toxicspikes', 'stealthrock', 'waterpledge', 'firepledge', 'grasspledge', 'stickyweb', 'auroraveil', 'gmaxsteelsurge', 'gmaxcannonade', 'gmaxvinelash', 'gmaxwildfire', + 'mist', 'lightscreen', 'reflect', 'spikes', 'safeguard', 'tailwind', 'toxicspikes', 'stealthrock', 'waterpledge', 'firepledge', 'grasspledge', 'stickyweb', 'auroraveil', 'luckychant', 'gmaxsteelsurge', 'gmaxcannonade', 'gmaxvinelash', 'gmaxwildfire', 'gmaxvolcalith', ]; let success = false; if (this.gameType === "freeforall") { diff --git a/data/random-battles/gen2/sets.json b/data/random-battles/gen2/sets.json index baf1c90915ee..3f6c37ae811d 100644 --- a/data/random-battles/gen2/sets.json +++ b/data/random-battles/gen2/sets.json @@ -984,11 +984,7 @@ }, { "role": "Bulky Support", - "movepool": ["nightshade", "rest", "sleeptalk", "toxic"] - }, - { - "role": "Bulky Setup", - "movepool": ["curse", "rest", "return", "sleeptalk"] + "movepool": ["curse", "nightshade", "rest", "return", "sleeptalk"] } ] }, diff --git a/data/random-battles/gen3/sets.json b/data/random-battles/gen3/sets.json index 0dad4bf50a1b..f7b39451ad39 100644 --- a/data/random-battles/gen3/sets.json +++ b/data/random-battles/gen3/sets.json @@ -2590,9 +2590,8 @@ "sets": [ { "role": "Wallbreaker", - "movepool": ["dragonclaw", "earthquake", "fireblast", "hiddenpowerbug", "rockslide"], - "abilities": ["Levitate"], - "preferredTypes": ["Bug", "Rock"] + "movepool": ["earthquake", "hiddenpowerbug", "quickattack", "rockslide"], + "abilities": ["Levitate"] }, { "role": "Staller", diff --git a/data/random-battles/gen3/teams.ts b/data/random-battles/gen3/teams.ts index ad68b46f58e7..3570009cf673 100644 --- a/data/random-battles/gen3/teams.ts +++ b/data/random-battles/gen3/teams.ts @@ -663,6 +663,9 @@ export class RandomGen3Teams extends RandomGen4Teams { // Limit to one of each species (Species Clause) if (baseFormes[species.baseSpecies]) continue; + // Prevent Shedinja from generating after Tyranitar + if (species.name === 'Shedinja' && teamDetails.sand) continue; + // Limit to one Wobbuffet per battle (not just per team) if (species.name === 'Wobbuffet' && this.battleHasWobbuffet) continue; // Limit to one Ditto per battle in Gen 2 diff --git a/data/random-battles/gen4/sets.json b/data/random-battles/gen4/sets.json index 8d3f0bdca36d..168298e2a83b 100644 --- a/data/random-battles/gen4/sets.json +++ b/data/random-battles/gen4/sets.json @@ -1188,13 +1188,13 @@ "level": 85, "sets": [ { - "role": "Staller", - "movepool": ["healbell", "moonlight", "payback", "toxic"], + "role": "Bulky Support", + "movepool": ["curse", "healbell", "moonlight", "payback", "toxic"], "abilities": ["Synchronize"] }, { - "role": "Bulky Support", - "movepool": ["curse", "payback", "protect", "toxic", "wish"], + "role": "Staller", + "movepool": ["payback", "protect", "toxic", "wish"], "abilities": ["Synchronize"] } ] @@ -2936,7 +2936,7 @@ }, { "role": "Setup Sweeper", - "movepool": ["aquajet", "bulkup", "icepunch", "return", "substitute", "waterfall"], + "movepool": ["bulkup", "icepunch", "return", "substitute", "waterfall"], "abilities": ["Swift Swim"] } ] diff --git a/data/random-battles/gen4/teams.ts b/data/random-battles/gen4/teams.ts index f075e449d444..1b84d3bdeae6 100644 --- a/data/random-battles/gen4/teams.ts +++ b/data/random-battles/gen4/teams.ts @@ -163,7 +163,7 @@ export class RandomGen4Teams extends RandomGen5Teams { } // Develop additional move lists - const badWithSetup = ['healbell', 'pursuit', 'toxic']; + const badWithSetup = ['pursuit', 'toxic']; const statusMoves = this.dex.moves.all() .filter(move => move.category === 'Status') .map(move => move.id); diff --git a/data/random-battles/gen5/sets.json b/data/random-battles/gen5/sets.json index 73d8212db4f0..0ade8661b569 100644 --- a/data/random-battles/gen5/sets.json +++ b/data/random-battles/gen5/sets.json @@ -318,7 +318,7 @@ "sets": [ { "role": "Fast Attacker", - "movepool": ["calmmind", "encore", "focusblast", "hydropump", "icebeam", "psyshock", "scald"], + "movepool": ["calmmind", "encore", "focusblast", "hydropump", "icebeam", "scald"], "abilities": ["Cloud Nine", "Swift Swim"], "preferredTypes": ["Ice"] } @@ -2954,7 +2954,7 @@ }, { "role": "Setup Sweeper", - "movepool": ["aquajet", "bulkup", "crunch", "icepunch", "lowkick", "substitute", "waterfall"], + "movepool": ["bulkup", "crunch", "icepunch", "lowkick", "substitute", "waterfall"], "abilities": ["Water Veil"], "preferredTypes": ["Ice"] } diff --git a/data/random-battles/gen5/teams.ts b/data/random-battles/gen5/teams.ts index fe95873f50ed..4cc13067b4a2 100644 --- a/data/random-battles/gen5/teams.ts +++ b/data/random-battles/gen5/teams.ts @@ -871,6 +871,9 @@ export class RandomGen5Teams extends RandomGen6Teams { // Illusion shouldn't be in the last slot if (species.name === 'Zoroark' && pokemon.length >= (this.maxTeamSize - 1)) continue; + // Prevent Shedinja from generating after Sandstorm/Hail setters + if (species.name === 'Shedinja' && (teamDetails.sand || teamDetails.hail)) continue; + // Dynamically scale limits for different team sizes. The default and minimum value is 1. const limitFactor = Math.round(this.maxTeamSize / 6) || 1; diff --git a/data/random-battles/gen6/sets.json b/data/random-battles/gen6/sets.json index 90b93926ae08..f485a0dafc02 100644 --- a/data/random-battles/gen6/sets.json +++ b/data/random-battles/gen6/sets.json @@ -336,7 +336,7 @@ "sets": [ { "role": "Fast Attacker", - "movepool": ["calmmind", "encore", "focusblast", "hydropump", "icebeam", "psyshock", "scald"], + "movepool": ["calmmind", "encore", "focusblast", "hydropump", "icebeam", "scald"], "abilities": ["Cloud Nine", "Swift Swim"], "preferredTypes": ["Ice"] } @@ -1544,7 +1544,7 @@ "sets": [ { "role": "Wallbreaker", - "movepool": ["closecombat", "pinmissile", "rockblast", "substitute", "swordsdance"], + "movepool": ["closecombat", "earthquake", "knockoff", "pinmissile", "rockblast", "substitute", "swordsdance"], "abilities": ["Moxie"], "preferredTypes": ["Rock"] } @@ -2622,7 +2622,8 @@ { "role": "Bulky Attacker", "movepool": ["fireblast", "icebeam", "return", "scald", "thunderbolt", "thunderwave"], - "abilities": ["Forecast"] + "abilities": ["Forecast"], + "preferredTypes": ["Water"] } ] }, @@ -3310,7 +3311,7 @@ "sets": [ { "role": "Setup Sweeper", - "movepool": ["aquajet", "bulkup", "icepunch", "lowkick", "substitute", "waterfall"], + "movepool": ["bulkup", "icepunch", "lowkick", "substitute", "waterfall"], "abilities": ["Water Veil"], "preferredTypes": ["Ice"] }, diff --git a/data/random-battles/gen6/teams.ts b/data/random-battles/gen6/teams.ts index 758909cc88f9..e54839e0ce74 100644 --- a/data/random-battles/gen6/teams.ts +++ b/data/random-battles/gen6/teams.ts @@ -715,8 +715,14 @@ export class RandomGen6Teams extends RandomGen7Teams { } if (moves.has('outrage') && counter.get('setup')) return 'Lum Berry'; if ( - (ability === 'Rough Skin') || (species.id !== 'hooh' && - ability === 'Regenerator' && species.baseStats.hp + species.baseStats.def >= 180 && this.randomChance(1, 2)) + (ability === 'Rough Skin') || ( + species.id !== 'hooh' && + ability === 'Regenerator' && species.baseStats.hp + species.baseStats.def >= 180 && this.randomChance(1, 2) + ) || ( + ability !== 'Regenerator' && !counter.get('setup') && counter.get('recovery') && + this.dex.getEffectiveness('Fighting', species) < 1 && + (species.baseStats.hp + species.baseStats.def) > 200 && this.randomChance(1, 2) + ) ) return 'Rocky Helmet'; if (['kingsshield', 'protect', 'spikyshield', 'substitute'].some(m => moves.has(m))) return 'Leftovers'; if ( diff --git a/data/random-battles/gen7/sets.json b/data/random-battles/gen7/sets.json index d6f6b717d810..55d7cd0a0253 100644 --- a/data/random-battles/gen7/sets.json +++ b/data/random-battles/gen7/sets.json @@ -449,7 +449,7 @@ "sets": [ { "role": "Fast Attacker", - "movepool": ["calmmind", "encore", "focusblast", "hydropump", "icebeam", "psyshock", "scald"], + "movepool": ["calmmind", "encore", "focusblast", "hydropump", "icebeam", "scald"], "abilities": ["Cloud Nine", "Swift Swim"], "preferredTypes": ["Ice"] } @@ -1774,7 +1774,7 @@ "sets": [ { "role": "Wallbreaker", - "movepool": ["closecombat", "pinmissile", "rockblast", "substitute", "swordsdance"], + "movepool": ["closecombat", "earthquake", "knockoff", "pinmissile", "rockblast", "substitute", "swordsdance"], "abilities": ["Moxie"], "preferredTypes": ["Rock"] } @@ -2870,8 +2870,9 @@ "sets": [ { "role": "Bulky Attacker", - "movepool": ["fireblast", "icebeam", "return", "scald", "thunderbolt", "thunderwave"], - "abilities": ["Forecast"] + "movepool": ["defog", "fireblast", "icebeam", "return", "scald", "thunderbolt", "thunderwave"], + "abilities": ["Forecast"], + "preferredTypes": ["Water"] } ] }, @@ -3592,7 +3593,7 @@ "sets": [ { "role": "Setup Sweeper", - "movepool": ["aquajet", "bulkup", "icepunch", "liquidation", "lowkick", "substitute"], + "movepool": ["bulkup", "icepunch", "liquidation", "lowkick", "substitute"], "abilities": ["Water Veil"], "preferredTypes": ["Ice"] }, @@ -5163,6 +5164,11 @@ "movepool": ["airslash", "energyball", "heatwave", "icebeam", "psychic", "psyshock"], "abilities": ["Tinted Lens"], "preferredTypes": ["Psychic"] + }, + { + "role": "Bulky Setup", + "movepool": ["airslash", "cosmicpower", "roost", "storedpower"], + "abilities": ["Magic Guard"] } ] }, diff --git a/data/random-battles/gen7/teams.ts b/data/random-battles/gen7/teams.ts index 77f3a8743a51..fbd939b601a8 100644 --- a/data/random-battles/gen7/teams.ts +++ b/data/random-battles/gen7/teams.ts @@ -937,8 +937,14 @@ export class RandomGen7Teams extends RandomGen8Teams { } if (moves.has('outrage') && counter.get('setup')) return 'Lum Berry'; if ( - (ability === 'Rough Skin') || (species.id !== 'hooh' && - ability === 'Regenerator' && species.baseStats.hp + species.baseStats.def >= 180 && this.randomChance(1, 2)) + (ability === 'Rough Skin') || ( + species.id !== 'hooh' && + ability === 'Regenerator' && species.baseStats.hp + species.baseStats.def >= 180 && this.randomChance(1, 2) + ) || ( + ability !== 'Regenerator' && !counter.get('setup') && counter.get('recovery') && + this.dex.getEffectiveness('Fighting', species) < 1 && + (species.baseStats.hp + species.baseStats.def) > 200 && this.randomChance(1, 2) + ) ) return 'Rocky Helmet'; if (['kingsshield', 'protect', 'spikyshield', 'substitute'].some(m => moves.has(m))) return 'Leftovers'; if ( diff --git a/data/random-battles/gen8/data.json b/data/random-battles/gen8/data.json index cd12a0773d67..7c54448c39e8 100644 --- a/data/random-battles/gen8/data.json +++ b/data/random-battles/gen8/data.json @@ -149,7 +149,7 @@ }, "golduck": { "level": 85, - "moves": ["calmmind", "focusblast", "icebeam", "psyshock", "scald", "substitute"], + "moves": ["calmmind", "focusblast", "icebeam", "scald", "substitute"], "doublesLevel": 88, "doublesMoves": ["calmmind", "encore", "icebeam", "muddywater", "protect"] }, @@ -898,7 +898,7 @@ }, "salamence": { "level": 75, - "moves": ["dragondance", "dualwingbeat", "earthquake", "outrage", "roost"], + "moves": ["dragondance", "dualwingbeat", "earthquake", "outrage"], "doublesLevel": 79, "doublesMoves": ["dragonclaw", "fireblast", "hurricane", "protect", "tailwind"] }, @@ -953,7 +953,7 @@ }, "rayquaza": { "level": 73, - "moves": ["dracometeor", "dragonascent", "dragondance", "earthquake", "extremespeed", "swordsdance", "vcreate"], + "moves": ["dragonascent", "dragondance", "earthquake", "extremespeed", "swordsdance", "vcreate"], "doublesLevel": 74, "doublesMoves": ["dracometeor", "dragonascent", "dragonclaw", "dragondance", "earthpower", "extremespeed", "vcreate"], "noDynamaxMoves": ["dracometeor", "dragonascent", "dragondance", "earthquake", "extremespeed", "vcreate"] @@ -1533,7 +1533,7 @@ }, "accelgor": { "level": 90, - "moves": ["bugbuzz", "energyball", "focusblast", "sludgebomb", "spikes", "toxic", "yawn"], + "moves": ["bugbuzz", "energyball", "focusblast", "sludgebomb", "spikes", "toxicspikes", "yawn"], "doublesLevel": 88, "doublesMoves": ["acidspray", "bugbuzz", "encore", "energyball", "focusblast"], "noDynamaxMoves": ["bugbuzz", "encore", "energyball", "focusblast", "spikes", "toxic"] diff --git a/data/random-battles/gen9/doubles-sets.json b/data/random-battles/gen9/doubles-sets.json index 986f8dd7b47c..c9873a1ba9b0 100644 --- a/data/random-battles/gen9/doubles-sets.json +++ b/data/random-battles/gen9/doubles-sets.json @@ -6043,7 +6043,7 @@ "sets": [ { "role": "Choice Item user", - "movepool": ["Aqua Jet", "Liquidation", "Memento", "Stomping Tantrum", "Throat Chop"], + "movepool": ["Aqua Jet", "Liquidation", "Stomping Tantrum", "Throat Chop"], "abilities": ["Gooey"], "teraTypes": ["Dark", "Ground"] } diff --git a/data/random-battles/gen9/sets.json b/data/random-battles/gen9/sets.json index 8fe441f7ca16..fb985ea42843 100644 --- a/data/random-battles/gen9/sets.json +++ b/data/random-battles/gen9/sets.json @@ -151,7 +151,7 @@ "sets": [ { "role": "Bulky Support", - "movepool": ["Flamethrower", "Knock Off", "Moonblast", "Moonlight", "Stealth Rock", "Thunder Wave"], + "movepool": ["Fire Blast", "Knock Off", "Moonblast", "Moonlight", "Stealth Rock", "Thunder Wave"], "abilities": ["Magic Guard", "Unaware"], "teraTypes": ["Poison", "Steel"] }, @@ -319,7 +319,7 @@ "sets": [ { "role": "Bulky Attacker", - "movepool": ["Close Combat", "Extreme Speed", "Flare Blitz", "Morning Sun", "Roar", "Wild Charge", "Will-O-Wisp"], + "movepool": ["Close Combat", "Extreme Speed", "Flare Blitz", "Morning Sun", "Roar", "Will-O-Wisp"], "abilities": ["Intimidate"], "teraTypes": ["Fighting", "Normal"] }, @@ -653,10 +653,10 @@ "teraTypes": ["Fire"] }, { - "role": "Setup Sweeper", - "movepool": ["Dragon Hammer", "Earthquake", "Swords Dance", "Wood Hammer"], + "role": "Fast Attacker", + "movepool": ["Draco Meteor", "Dragon Tail", "Flamethrower", "Knock Off", "Moonlight", "Sleep Powder", "Stun Spore", "Wood Hammer"], "abilities": ["Harvest"], - "teraTypes": ["Steel"] + "teraTypes": ["Fire"] }, { "role": "Bulky Setup", @@ -1526,7 +1526,7 @@ }, { "role": "Setup Sweeper", - "movepool": ["Close Combat", "Facade", "Swords Dance", "Throat Chop"], + "movepool": ["Close Combat", "Crunch", "Facade", "Swords Dance", "Throat Chop"], "abilities": ["Quick Feet"], "teraTypes": ["Normal"] } @@ -1721,6 +1721,12 @@ "movepool": ["Calm Mind", "Scald", "Shadow Ball", "Thunderbolt", "Volt Switch"], "abilities": ["Pressure"], "teraTypes": ["Electric", "Water"] + }, + { + "role": "Tera Blast user", + "movepool": ["Calm Mind", "Scald", "Substitute", "Tera Blast", "Thunderbolt"], + "abilities": ["Pressure"], + "teraTypes": ["Ice"] } ] }, @@ -1752,7 +1758,7 @@ }, { "role": "Bulky Setup", - "movepool": ["Calm Mind", "Ice Beam", "Rest", "Scald", "Substitute"], + "movepool": ["Calm Mind", "Ice Beam", "Scald", "Substitute"], "abilities": ["Pressure"], "teraTypes": ["Dragon", "Steel"] }, @@ -1775,7 +1781,7 @@ }, { "role": "Bulky Support", - "movepool": ["Earthquake", "Fire Blast", "Ice Beam", "Knock Off", "Stealth Rock", "Stone Edge", "Thunder Wave"], + "movepool": ["Dragon Tail", "Earthquake", "Ice Beam", "Knock Off", "Stealth Rock", "Stone Edge", "Thunder Wave"], "abilities": ["Sand Stream"], "teraTypes": ["Ghost", "Rock"] } @@ -2011,7 +2017,7 @@ "sets": [ { "role": "Bulky Support", - "movepool": ["Encore", "Knock Off", "Recover", "Taunt", "Thunder Wave", "Will-O-Wisp"], + "movepool": ["Encore", "Knock Off", "Recover", "Thunder Wave", "Will-O-Wisp"], "abilities": ["Prankster"], "teraTypes": ["Steel"] } @@ -2973,7 +2979,7 @@ "sets": [ { "role": "Fast Attacker", - "movepool": ["Close Combat", "Dire Claw", "Gunk Shot", "Throat Chop", "U-turn"], + "movepool": ["Close Combat", "Dire Claw", "Gunk Shot", "Swords Dance", "Throat Chop", "U-turn"], "abilities": ["Poison Touch"], "teraTypes": ["Dark", "Fighting"] }, @@ -3069,10 +3075,10 @@ "teraTypes": ["Bug"] }, { - "role": "Tera Blast user", - "movepool": ["Air Slash", "Bug Buzz", "Protect", "Tera Blast"], - "abilities": ["Speed Boost"], - "teraTypes": ["Ground"] + "role": "Fast Attacker", + "movepool": ["Air Slash", "Bug Buzz", "Hypnosis", "U-turn"], + "abilities": ["Tinted Lens"], + "teraTypes": ["Bug"] } ] }, @@ -3499,12 +3505,6 @@ "movepool": ["Dark Pulse", "Focus Blast", "Hypnosis", "Nasty Plot", "Sludge Bomb", "Substitute"], "abilities": ["Bad Dreams"], "teraTypes": ["Poison"] - }, - { - "role": "Wallbreaker", - "movepool": ["Dark Pulse", "Focus Blast", "Sludge Bomb", "Trick"], - "abilities": ["Bad Dreams"], - "teraTypes": ["Poison"] } ] }, @@ -3530,7 +3530,7 @@ "sets": [ { "role": "Fast Attacker", - "movepool": ["Air Slash", "Dazzling Gleam", "Earth Power", "Seed Flare"], + "movepool": ["Air Slash", "Earth Power", "Healing Wish", "Seed Flare"], "abilities": ["Serene Grace"], "teraTypes": ["Flying", "Grass"] }, @@ -3907,10 +3907,16 @@ "level": 80, "sets": [ { - "role": "Setup Sweeper", - "movepool": ["Earthquake", "Iron Head", "Rapid Spin", "Rock Slide", "Swords Dance"], + "role": "Bulky Setup", + "movepool": ["Earthquake", "Iron Head", "Rapid Spin", "Swords Dance"], "abilities": ["Mold Breaker", "Sand Rush"], "teraTypes": ["Grass", "Ground", "Water"] + }, + { + "role": "AV Pivot", + "movepool": ["Earthquake", "Iron Head", "Rapid Spin", "Rock Slide"], + "abilities": ["Mold Breaker", "Sand Rush"], + "teraTypes": ["Grass", "Water"] } ] }, @@ -3952,7 +3958,7 @@ "sets": [ { "role": "Fast Support", - "movepool": ["Encore", "Giga Drain", "Moonblast", "Stun Spore", "Taunt", "U-turn"], + "movepool": ["Encore", "Giga Drain", "Moonblast", "Stun Spore", "U-turn"], "abilities": ["Prankster"], "teraTypes": ["Poison", "Steel"] }, @@ -4460,7 +4466,7 @@ "role": "AV Pivot", "movepool": ["Bleakwind Storm", "Heat Wave", "Knock Off", "U-turn"], "abilities": ["Regenerator"], - "teraTypes": ["Dark", "Fire", "Flying"] + "teraTypes": ["Dark", "Steel"] } ] }, @@ -5878,7 +5884,7 @@ }, { "role": "Setup Sweeper", - "movepool": ["Bug Buzz", "Giga Drain", "Ice Beam", "Quiver Dance"], + "movepool": ["Bug Buzz", "Giga Drain", "Hurricane", "Ice Beam", "Quiver Dance"], "abilities": ["Ice Scales"], "teraTypes": ["Water"] } @@ -5993,6 +5999,12 @@ "movepool": ["Dragon Dance", "Dragon Darts", "Fire Blast", "Tera Blast"], "abilities": ["Clear Body"], "teraTypes": ["Ghost"] + }, + { + "role": "Fast Support", + "movepool": ["Dragon Darts", "Hex", "U-turn", "Will-O-Wisp"], + "abilities": ["Cursed Body", "Infiltrator"], + "teraTypes": ["Dragon", "Fairy"] } ] }, @@ -6060,6 +6072,12 @@ "movepool": ["Dynamax Cannon", "Flamethrower", "Recover", "Toxic", "Toxic Spikes"], "abilities": ["Pressure"], "teraTypes": ["Dragon", "Water"] + }, + { + "role": "Setup Sweeper", + "movepool": ["Dynamax Cannon", "Fire Blast", "Meteor Beam", "Sludge Bomb"], + "abilities": ["Pressure"], + "teraTypes": ["Dragon", "Fire", "Poison"] } ] }, @@ -6578,7 +6596,7 @@ "sets": [ { "role": "Bulky Attacker", - "movepool": ["Crunch", "Play Rough", "Psychic Fangs", "Retaliate", "Wild Charge"], + "movepool": ["Crunch", "Play Rough", "Psychic Fangs", "Wild Charge"], "abilities": ["Stakeout"], "teraTypes": ["Dark", "Fairy"] } @@ -6746,10 +6764,16 @@ "level": 77, "sets": [ { - "role": "Bulky Attacker", - "movepool": ["Bulk Up", "Close Combat", "Flip Turn", "Ice Punch", "Jet Punch", "Wave Crash"], + "role": "Wallbreaker", + "movepool": ["Close Combat", "Flip Turn", "Jet Punch", "Wave Crash"], "abilities": ["Zero to Hero"], "teraTypes": ["Fighting", "Water"] + }, + { + "role": "Bulky Setup", + "movepool": ["Bulk Up", "Drain Punch", "Ice Punch", "Jet Punch", "Wave Crash"], + "abilities": ["Zero to Hero"], + "teraTypes": ["Dragon", "Steel"] } ] }, @@ -7051,8 +7075,8 @@ "teraTypes": ["Electric", "Fighting"] }, { - "role": "Wallbreaker", - "movepool": ["Close Combat", "Earthquake", "First Impression", "Flare Blitz", "U-turn", "Wild Charge"], + "role": "Fast Support", + "movepool": ["Close Combat", "Earthquake", "First Impression", "Flare Blitz", "Morning Sun", "U-turn", "Wild Charge"], "abilities": ["Protosynthesis"], "teraTypes": ["Bug", "Electric", "Fighting", "Fire"] } diff --git a/data/random-battles/gen9/teams.ts b/data/random-battles/gen9/teams.ts index 9128bc8db753..cbab9c31e234 100644 --- a/data/random-battles/gen9/teams.ts +++ b/data/random-battles/gen9/teams.ts @@ -137,7 +137,7 @@ const DOUBLES_NO_LEAD_POKEMON = [ ]; const DEFENSIVE_TERA_BLAST_USERS = [ - 'alcremie', 'bellossom', 'comfey', 'fezandipiti', 'florges', + 'alcremie', 'bellossom', 'comfey', 'fezandipiti', 'florges', 'raikou', ]; function sereneGraceBenefits(move: Move) { @@ -222,6 +222,7 @@ export class RandomTeams { }, Psychic: (movePool, moves, abilities, types, counter, species, teamDetails, isLead, isDoubles) => { if ((isDoubles || species.id === 'bruxish') && movePool.includes('psychicfangs')) return true; + if (species.id === 'hoopaunbound' && movePool.includes('psychic')) return true; if (['Dark', 'Steel', 'Water'].some(m => types.includes(m))) return false; return !counter.get('Psychic'); }, @@ -1262,7 +1263,7 @@ export class RandomTeams { } if ( (role === 'Bulky Protect' && counter.get('setup')) || moves.has('substitute') || moves.has('irondefense') || - species.id === 'eternatus' || species.id === 'regigigas' + moves.has('coil') || species.id === 'eternatus' || species.id === 'regigigas' ) return 'Leftovers'; if (species.id === 'sylveon') return 'Pixie Plate'; if (ability === 'Intimidate' && this.dex.getEffectiveness('Rock', species) >= 1) return 'Heavy-Duty Boots'; @@ -1496,7 +1497,7 @@ export class RandomTeams { const srImmunity = ability === 'Magic Guard' || item === 'Heavy-Duty Boots'; let srWeakness = srImmunity ? 0 : this.dex.getEffectiveness('Rock', species); // Crash damage move users want an odd HP to survive two misses - if (['axekick', 'highjumpkick', 'jumpkick'].some(m => moves.has(m))) srWeakness = 2; + if (['axekick', 'highjumpkick', 'jumpkick', 'supercellslam'].some(m => moves.has(m))) srWeakness = 2; while (evs.hp > 1) { const hp = Math.floor(Math.floor(2 * species.baseStats.hp + ivs.hp + Math.floor(evs.hp / 4) + 100) * level / 100 + 10); if ((moves.has('substitute') && ['Sitrus Berry', 'Salac Berry'].includes(item)) || species.id === 'minior') { diff --git a/data/random-battles/gen9baby/sets.json b/data/random-battles/gen9baby/sets.json index 77ce1bdc6a69..aaf470a2c877 100644 --- a/data/random-battles/gen9baby/sets.json +++ b/data/random-battles/gen9baby/sets.json @@ -312,7 +312,7 @@ "sets": [ { "role": "Bulky Support", - "movepool": ["Drain Punch", "Rock Slide", "Spikes", "Synthesis", "Wood Hammer"], + "movepool": ["Bullet Seed", "Drain Punch", "Rock Slide", "Spikes", "Synthesis"], "abilities": ["Bulletproof"], "teraTypes": ["Poison", "Steel"] } @@ -1201,7 +1201,7 @@ "sets": [ { "role": "Bulky Attacker", - "movepool": ["Close Combat", "Flare Blitz", "Morning Sun", "Roar", "Wild Charge", "Will-O-Wisp"], + "movepool": ["Close Combat", "Flamethrower", "Morning Sun", "Roar", "Wild Charge", "Will-O-Wisp"], "abilities": ["Intimidate"], "teraTypes": ["Dragon", "Fairy", "Fighting"] } @@ -2215,10 +2215,16 @@ "level": 6, "sets": [ { - "role": "Setup Sweeper", - "movepool": ["Close Combat", "Copycat", "Crunch", "Earthquake", "Ice Punch", "Swords Dance"], - "abilities": ["Inner Focus", "Prankster"], + "role": "Bulky Setup", + "movepool": ["Close Combat", "Crunch", "Earthquake", "Ice Punch", "Swords Dance"], + "abilities": ["Inner Focus"], "teraTypes": ["Dark", "Fighting", "Ground"] + }, + { + "role": "Fast Attacker", + "movepool": ["Close Combat", "Copycat", "Crunch", "Ice Punch"], + "abilities": ["Prankster"], + "teraTypes": ["Dark", "Fighting"] } ] }, @@ -2547,7 +2553,7 @@ ] }, "silicobra": { - "level": 7, + "level": 6, "sets": [ { "role": "Bulky Attacker", diff --git a/server/chat-plugins/suspect-tests.ts b/server/chat-plugins/suspect-tests.ts index 4a38a1a2f7df..ce02a8dd39fc 100644 --- a/server/chat-plugins/suspect-tests.ts +++ b/server/chat-plugins/suspect-tests.ts @@ -58,11 +58,11 @@ export const commands: Chat.ChatCommands = { }, edit: 'add', - add(target, room, user) { + async add(target, room, user) { checkPermissions(this); - const [tier, suspect, date, url, coil] = target.split(','); - if (!(tier && suspect && date && url)) { + const [tier, suspect, date, url, ...reqs] = target.split(',').map(x => x.trim()); + if (!(tier && suspect && date && url && reqs)) { return this.parse('/help suspects'); } @@ -81,6 +81,34 @@ export const commands: Chat.ChatCommands = { throw new Chat.ErrorMessage("Suspect test URLs must be Smogon threads or posts."); } + const reqData: Record = {}; + if (!reqs.length) { + return this.errorReply("At least one requirement for qualifying must be provided."); + } + for (const req of reqs) { + const [k, v] = req.split('=').map(toID); + if (!['elo', 'gxe', 'coil'].includes(k)) { + return this.errorReply(`Invalid requirement type: ${k}. Must be 'coil', 'gxe', or 'elo'.`); + } + const val = Number(v); + if (isNaN(val) || val < 0) { + return this.errorReply(`Invalid value: ${v}`); + } + if (reqData[k]) { + return this.errorReply(`Requirement type ${k} specified twice.`); + } + reqData[k] = val; + } + + const [out, error] = await LoginServer.request("suspects/add", { + format: format.id, + reqs: JSON.stringify(reqData), + url: urlActual, + }); + if (out?.actionerror || error) { + throw new Chat.ErrorMessage("Error adding suspect test: " + (out?.actionerror || error?.message)); + } + this.privateGlobalModAction(`${user.name} ${suspectTests.suspects[format.id] ? "edited the" : "added a"} ${format.name} suspect test.`); this.globalModlog('SUSPECTTEST', null, `${suspectTests.suspects[format.id] ? "edited" : "added"} ${format.name}`); @@ -92,20 +120,25 @@ export const commands: Chat.ChatCommands = { }; saveSuspectTests(); this.sendReply(`Added a suspect test notice for ${suspectString} in ${format.name}.`); - if (coil) { - this.parse(`/suspects setcoil ${format.id},${coil}`); - } + if (reqData.coil) this.sendReply('Remember to add a B value for your test\'s COIL setting with /suspects setcoil.'); }, end: 'remove', delete: 'remove', - remove(target, room, user) { + async remove(target, room, user) { checkPermissions(this); const format = toID(target); const test = suspectTests.suspects[format]; if (!test) return this.errorReply(`There is no suspect test for '${target}'. Check spelling?`); + const [out, error] = await LoginServer.request('suspects/end', { + format, + }); + if (out?.actionerror || error) { + throw new Chat.ErrorMessage(`Error ending suspect: ${out?.actionerror || error?.message}`); + } + this.privateGlobalModAction(`${user.name} removed the ${test.tier} suspect test.`); this.globalModlog('SUSPECTTEST', null, `removed ${test.tier}`); @@ -214,7 +247,9 @@ export const commands: Chat.ChatCommands = { this.sendReplyBox( `Commands to manage suspect tests:
` + `/suspects: displays currently running suspect tests.
` + - `/suspects add [tier], [suspect], [date], [link]: adds a suspect test. Date in the format MM/DD. Requires: ~
` + + `/suspects add [tier], [suspect], [date], [link], [...reqs]: adds a suspect test. Date in the format MM/DD. ` + + `Reqs in the format [key]=[value], where valid keys are 'coil', 'elo', and 'gxe', delimited by commas. At least one is required.
` + + `(note that if you are using COIL, you must set a B value indepedently with /suspects setcoil). Requires: ~
` + `/suspects remove [tier]: deletes a suspect test. Requires: ~
` + `/suspects whitelist [username]: allows [username] to add suspect tests. Requires: ~
` + `/suspects unwhitelist [username]: disallows [username] from adding suspect tests. Requires: ~
` + diff --git a/test/random-battles/tools.js b/test/random-battles/tools.js index 5fae1a81a89d..bb0c23e182ad 100644 --- a/test/random-battles/tools.js +++ b/test/random-battles/tools.js @@ -123,6 +123,7 @@ function testTeam(options, test) { function assertSetValidity(format, set) { const dex = Dex.forFormat(format); const species = dex.species.get(set.species || set.name); + const setString = JSON.stringify(set); // According to Random Battles room staff, we should not ensure that HP IVs are valid for // BSS formats. This is because level 100 Pokémon can be hypertrained @@ -132,25 +133,25 @@ function assertSetValidity(format, set) { .validateStats(set, species, new PokemonSources()) // Suppress errors about mistaken EV quantities .filter(f => !f.includes(' EVs')); - assert.equal(valid.length, 0, `Invalid stats: ${valid} (set: ${JSON.stringify(set)})`); + assert.equal(valid.length, 0, `Invalid stats: ${valid} (set: ${setString})`); } // We check `dex.gen` here because Format#gen is 0 in the current gen, while ModdedDex#gen is never 0. - assert(species.exists, `The species "${species.name}" does not exist. (set: ${JSON.stringify(set)})`); - assert(species.gen <= dex.gen, `The species "${species.name}" is from a newer generation. (set: ${JSON.stringify(set)})`); + assert(species.exists, `The species "${species.name}" does not exist. (set: ${setString})`); + assert(species.gen <= dex.gen, `The species "${species.name}" is from a newer generation. (set: ${setString})`); if (set.item) { const item = dex.items.get(set.item); - assert(item.exists, `The item "${item.name}" does not exist. (set: ${JSON.stringify(set)})`); - assert(item.gen <= dex.gen, `The item "${item.name}" is from a newer generation. (set: ${JSON.stringify(set)})`); + assert(item.exists, `The item "${item.name}" does not exist. (set: ${setString})`); + assert(item.gen <= dex.gen, `The item "${item.name}" is from a newer generation. (set: ${setString})`); } if (set.ability && set.ability !== 'None') { const ability = dex.abilities.get(set.ability); - assert(ability.exists, `The ability "${ability.name}" does not exist. (set: ${JSON.stringify(set)})`); - assert(ability.gen <= dex.gen, `The ability "${ability.name}" is from a newer generation. (set: ${JSON.stringify(set)})`); + assert(ability.exists, `The ability "${ability.name}" does not exist. (set: ${setString})`); + assert(ability.gen <= dex.gen, `The ability "${ability.name}" is from a newer generation. (set: ${setString})`); } else { - assert(dex.gen < 3, `This set does not have an ability, but is intended for use in Gen 3 or later. (set: ${JSON.stringify(set)})`); + assert(dex.gen < 3, `This set does not have an ability, but is intended for use in Gen 3 or later. (set: ${setString})`); } // Arceus plate check @@ -163,7 +164,7 @@ function assertSetValidity(format, set) { assert(set.item.endsWith(' Plate'), `${species.name} doesn't have a Plate (got "${set.item}" instead)`); } - assert(set.moves.filter(m => m.startsWith('hiddenpower')).length <= 1, `This set has multiple Hidden Power moves. (set: ${JSON.stringify(set)})`); + assert(set.moves.filter(m => m.startsWith('hiddenpower')).length <= 1, `This set has multiple Hidden Power moves. (set: ${setString})`); } /**