// Used Snaquaza's move import {RandomStaffBrosTeams} from './random-teams'; import {Pokemon} from '../../../sim/pokemon'; export const Moves: {[k: string]: ModdedMoveData} = { /* // Example "moveid": { accuracy: 100, // a number or true for always hits basePower: 100, // Not used for Status moves, base power of the move, number category: "Physical", // "Physical", "Special", or "Status" desc: "", // long description shortDesc: "", // short description, shows up in /dt name: "Move Name", pp: 10, // unboosted PP count priority: 0, // move priority, -6 -> 6 flags: {}, // Move flags https://github.com/smogon/pokemon-showdown/blob/master/data/moves.js#L1-L27 secondary: { status: "tox", chance: 20, }, // secondary, set to null to not use one. Exact usage varies, check data/moves.js for examples target: "normal", // What does this move hit? // normal = the targeted foe, self = the user, allySide = your side (eg light screen), foeSide = the foe's side (eg spikes), all = the field (eg raindance). More can be found in data/moves.js type: "Water", // The move's type // Other useful things noPPBoosts: true, // add this to not boost the PP of a move, not needed for Z moves, dont include it otherwise isZ: "crystalname", // marks a move as a z move, list the crystal name inside zMove: {effect: ''}, // for status moves, what happens when this is used as a Z move? check data/moves.js for examples zMove: {boost: {atk: 2}}, // for status moves, stat boost given when used as a z move critRatio: 2, // The higher the number (above 1) the higher the ratio, lowering it lowers the crit ratio drain: [1, 2], // recover first num / second num % of the damage dealt heal: [1, 2], // recover first num / second num % of the target's HP }, */ // Please keep sets organized alphabetically based on staff member name! // 2xTheTap noblehowl: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Attack by two stages and cures the user of burns, paralysis, and poison. Removes Reflect, Light Screen, Aurora Veil, Safeguard, and Mist from the opponent's side and removes Spikes, Toxic Spikes, Stealth Rock, and Sticky Web from both sides.", shortDesc: "Raises Attack by 2, clears hazards/user status.", name: "Noble Howl", isNonstandard: "Custom", pp: 3, noPPBoosts: true, priority: 0, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Howl', source); this.add('-anim', source, 'Boomburst', source); }, onHit(target, source, move) { this.boost({atk: 2}, source, source, this.dex.getActiveMove('Noble Howl')); if (!(['', 'slp', 'frz'].includes(source.status))) { source.cureStatus(); } const removeTarget = [ 'reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist', 'spikes', 'toxicspikes', 'stealthrock', 'stickyweb', ]; const removeAll = ['spikes', 'toxicspikes', 'stealthrock', 'stickyweb']; for (const targetCondition of removeTarget) { if (target.side.removeSideCondition(targetCondition)) { if (!removeAll.includes(targetCondition)) continue; this.add('-sideend', target.side, this.dex.getEffect(targetCondition).name, '[from] move: Noble Howl', '[of] ' + target); } } for (const sideCondition of removeAll) { if (source.side.removeSideCondition(sideCondition)) { this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Noble Howl', '[of] ' + source); } } }, flags: {mirror: 1, snatch: 1, authentic: 1}, secondary: null, target: "normal", type: "Normal", }, // 5gen toomuchsaws: { accuracy: 100, basePower: 85, basePowerCallback(pokemon, target, move) { if (target.newlySwitched) { return move.basePower * 2; } return move.basePower; }, category: "Physical", desc: "Base Power doubles if the foe switches out the turn this move is used.", shortDesc: "Power doubles if foe switches out.", name: "Too Much Saws", isNonstandard: "Custom", pp: 10, priority: 0, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Headbutt', target); }, flags: {protect: 1, mirror: 1, contact: 1}, secondary: null, target: "normal", type: "Grass", }, // Aelita energyfield: { accuracy: 100, basePower: 140, category: "Special", desc: "Has a 40% chance to paralyze the target. Lowers the user's Special Attack, Special Defense, and Speed by one stage.", shortDesc: "40% to paralyze. Lowers user's SpA, SpD, Spe.", name: "Energy Field", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Electro Ball", target); this.add('-anim', source, "Ion Deluge", target); }, self: {boosts: {spa: -1, spd: -1, spe: -1}}, secondary: { chance: 40, status: 'par', }, target: "normal", type: "Electric", zMove: {basePower: 200}, }, // Aeonic shitpost: { accuracy: true, basePower: 0, category: "Physical", desc: "50% chance to OHKO the user, 50% chance to OHKO the target.", shortDesc: "OHKOs user or target (50% chance each).", name: "Shitpost", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Skill Swap", target); }, onHit(target, source) { let koed: Pokemon; if (Math.round(this.random())) { koed = target; this.add(`c|@Aeonic|What a buncha jokers`); } else { koed = source; this.add(`c|@Aeonic|haha yeah`); } this.add('-anim', koed, "Explosion", koed); koed.faint(); }, isZ: "noseiumz", secondary: null, target: "normal", type: "???", }, // Aethernum cataclysm: { accuracy: 90, basePower: 140, category: "Physical", desc: "After dealing damage, resets all of the user's boosts to 0, then Attack, Defense, and Speed get lowered by one stage.", shortDesc: "Clears user's boosts; lowers Atk, Def and Spe.", name: "Cataclysm", isNonstandard: "Custom", pp: 5, priority: 0, flags: {contact: 1, protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Earth Power", target); this.add('-anim', source, "Continental Crush", target); this.add('-anim', source, "Giga Impact", target); }, onAfterMoveSecondarySelf(pokemon) { pokemon.clearBoosts(); this.add('-clearboost', pokemon); this.boost({atk: -1, def: -1, spe: -1}, pokemon, pokemon, this.dex.getActiveMove('Cataclysm')); }, secondary: null, target: "normal", type: "Normal", }, // Akiamara x1: { accuracy: 100, basePower: 100, category: "Special", desc: "This move becomes a physical attack if the user's Attack is greater than its Special Attack, including stat stage changes. This move and its effects ignore the abilities and stat changes of other Pokemon.", shortDesc: "Phys if Atk > SpA; ignores boosts, abilities.", isNonstandard: "Custom", name: "x1", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onModifyMove(move, pokemon) { if (pokemon.getStat('atk', false, true) > pokemon.getStat('spa', false, true)) move.category = 'Physical'; }, onPrepareHit(target, source) { this.add('-anim', source, 'Focus Punch', target); }, ignoreAbility: true, ignoreEvasion: true, ignoreDefensive: true, secondary: null, target: "normal", type: "Fighting", }, // Akir compost: { accuracy: true, basePower: 0, category: "Status", desc: "The user recovers half its HP. If any Pokemon fainted the previous turn, this move heals the active Pokemon by 50% of the user's HP on the following turn. Cures the user's party of all status conditions.", shortDesc: "Heal 50%, Heal Bell; any fainted: Wish.", name: "Compost", isNonstandard: "Custom", pp: 5, priority: 0, flags: {snatch: 1, heal: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Ingrain", target); }, onHit(target, source) { let didSomething = false; const side = source.side; if (side.faintedLastTurn || side.foe.faintedLastTurn) { this.add('-anim', source, "Wish", target); side.addSlotCondition(source, 'wish', source); this.add('-message', `${source.name} made a wish!`); didSomething = true; } for (const ally of side.pokemon) { if (ally.cureStatus()) didSomething = true; } if (this.heal(source.baseMaxhp / 2, source)) didSomething = true; return didSomething; }, secondary: null, target: "self", type: "Ghost", }, // Alpha nekoveil: { accuracy: true, basePower: 0, category: "Status", desc: "The user sets up Light Screen, Reflect, and Sunny Day for 5 turns. The effects of Light Screen and reflect are extended to 8 turns if the user is holding Light Clay, and Sunny Day remains for 8 turns if the user is holding a Heat Rock.", shortDesc: "Light Screen, Reflect, and Sunny Day for 5 turns.", name: "Neko Veil", isNonstandard: "Custom", pp: 5, priority: 0, flags: {snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Geomancy", source); }, onHit(target, source) { source.side.addSideCondition('lightscreen', source); source.side.addSideCondition('reflect', source); }, weather: 'sunnyday', secondary: null, target: "self", type: "Psychic", }, // Andrew backoffgrrr: { accuracy: true, basePower: 0, category: "Status", desc: "The user is protected from most moves made by other Pokemon during this turn, and if targeted with a move, the opposing Pokemon is forced to switch to a random ally. Non-damaging moves go through this protection. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, Wide Guard, or this move, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.", shortDesc: "Protects from moves. Targeted: Force switch foe.", name: "Back Off! GRRR!", isNonstandard: "Custom", pp: 15, priority: 4, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Protect", source); this.add('-anim', source, "Defense Curl", source); }, stallingMove: true, volatileStatus: 'backoffgrrr', onTryHit(target, source, move) { return !!this.queue.willAct() && this.runEvent('StallMove', target); }, onHit(pokemon) { pokemon.addVolatile('stall'); }, condition: { duration: 1, onStart(target) { this.add('-singleturn', target, 'move: Protect'); }, onTryHitPriority: 3, onTryHit(target, source, move) { if (!move.flags['protect'] || move.category === 'Status') { if (move.isZ || move.isMax) target.getMoveHitData(move).zBrokeProtect = true; return; } this.add('-activate', target, 'move: Protect'); const lockedmove = source.getVolatile('lockedmove'); if (lockedmove) { // Outrage counter is reset if (source.volatiles['lockedmove'].duration === 2) { delete source.volatiles['lockedmove']; } } this.add('-anim', target, "Scary Face", source); this.add('-anim', target, "Roar", source); source.forceSwitchFlag = true; this.add('-message', `${source.name} was scared off!`); return null; }, }, secondary: null, target: "self", type: "Fire", }, // Used for Andrew's ability lavaterrain: { accuracy: true, basePower: 0, category: "Status", desc: "For 5 turns, the terrain becomes Lava Terrain. During the effect, the power of Fire-type attacks made by Pokemon is multiplied by 1.5 and the power of Water-type attacks made by Pokemon is halved. Quilava's defense is doubled under Lava Terrain. Fire-type Pokemon have 1/16 of their maximum HP restored at the end of each turn, and all other Pokemon lose 1/16 of their maximum HP at the end of each turn.", shortDesc: "Damages non-Fire-types. +Fire, -Water power.", name: "Lava Terrain", isNonstandard: "Custom", pp: 10, priority: 0, flags: {}, terrain: 'lavaterrain', condition: { duration: 5, durationCallback(source, effect) { if (source?.hasItem('terrainextender')) { return 8; } return 5; }, onModifyDefPriority: 1, onModifyDef(def, pokemon) { if (pokemon.baseSpecies.baseSpecies === 'Quilava') { return this.chainModify(2); } }, onBasePower(basePower, attacker, defender, move) { if (move.type === 'Fire') { return this.chainModify(1.5); } else if (move.type === 'Water') { return this.chainModify(0.5); } }, onStart(battle, source, effect) { if (effect && effect.effectType === 'Ability') { this.add('-fieldstart', 'move: Lava Terrain', '[from] ability: ' + effect, '[of] ' + source); } else { this.add('-fieldstart', 'move: Lava Terrain'); } this.add('-message', 'The battlefield was covered in Lava!'); }, onResidualOrder: 21, onResidualSubOrder: 2, onResidual() { this.eachEvent('Terrain'); }, onTerrain(pokemon) { if (pokemon.hasType('Fire')) { this.heal(pokemon.baseMaxhp / 16); this.add('-message', `${pokemon.illusion ? pokemon.illusion.name : pokemon.name} was healed by the Lava Terrain!`); } else { this.damage(pokemon.baseMaxhp / 16); this.add('-message', `${pokemon.illusion ? pokemon.illusion.name : pokemon.name} was hurt by Lava Terrain!`); } }, onEnd() { this.add('-fieldend', 'move: Lava Terrain'); this.add('-message', 'The battlefield is no longer covered in Lava.'); }, }, secondary: null, target: "all", type: "Fire", }, // Anubis hereticsmark: { accuracy: true, basePower: 0, category: "Status", desc: "The target is replaced with a new randomly generated Super Staff Bros Brawl set. The new Pokemon retains the old pokemon's HP percentage, power point percentages, and status condition.", shortDesc: "Target is replaced with random SSBB set.", name: "Heretic's Mark", isNonstandard: "Custom", pp: 2, noPPBoosts: true, priority: -7, flags: {authentic: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Shadow Force', target); this.add('-anim', target, 'Dark Void', target); }, onHit(target, source, move) { const wouldMove = this.queue.cancelMove(target); // Generate a new team const team = this.teamGenerator.getTeam({name: target.side.name, inBattle: true}); let set = team.shift(); if (set.name === target.set.name) set = team.shift(); // Must be a new set const oldName = target.name; // Bit of a hack so client doesn't crash when formeChange is called for the new pokemon const effect = this.effect; this.effect = {id: ''} as Effect; const pokemon = new Pokemon(set, target.side); this.effect = effect; pokemon.hp = Math.floor(pokemon.maxhp * (target.hp / target.maxhp)) || 1; pokemon.status = target.status; delete target.volatiles[target.name]; if (target.statusData) pokemon.statusData = target.statusData; for (const [j, moveSlot] of pokemon.moveSlots.entries()) { moveSlot.pp = Math.floor( moveSlot.maxpp * (target.moveSlots[j] ? (target.moveSlots[j].pp / target.moveSlots[j].maxpp) : 1) ); } this.add('faint', target); pokemon.position = target.position; pokemon.isActive = true; target = pokemon; target.side.pokemon[0] = pokemon; target.side.active[0] = pokemon; this.add('replace', target, pokemon.getDetails, target.hp / target.maxhp); // name change target.setAbility(set.ability); const format = this.format; if (format.exists && format.onSwitchIn) format.onSwitchIn.call(this, target); this.add('-message', `${oldName} was sent to the Distortion World and replaced with somebody else!`); let stat: BoostName; for (stat in target.boosts) { // Iterate through stat changes to update client if (target.boosts[stat] !== 0) { // Iterate through stat changes to update client this.add('-setboost', target, stat, target.boosts[stat], '[silent]'); } } if (wouldMove) this.hint(`${oldName}'s move was aborted because its moves changed.`); }, target: "normal", type: "Ghost", }, // Used for Anubis's ability distortionworld: { accuracy: true, basePower: 0, category: "Status", desc: "Sets Distortion World for 5 turns. The power of Ghost type moves is boosted by 1.5x, and all Pokemon on the field have an effective Speed of 0. This terrain affects floating Pokemon.", shortDesc: "5 turns: +Ghost power, all Pokemon Speed tie.", name: "Distortion World", isNonstandard: "Custom", pp: 5, priority: 0, flags: {nosky: true}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Dark Void', source); this.add('-anim', target, 'Dark Void', target); }, pseudoWeather: 'distortionworld', condition: { duration: 5, onBasePower(basePower, attacker, defender, move) { if (move.type === 'Ghost') { this.debug('distortion world boost'); return this.chainModify(1.5); } }, onStart(battle, source, effect) { if (effect && effect.effectType === 'Ability') { this.add('-fieldstart', 'move: Distortion World', '[from] ability: ' + effect, '[of] ' + source); } else { this.add('-fieldstart', 'move: Distortion World'); } this.add('-message', 'Distortion World has caused all speed to become the same!'); }, onEnd() { this.add('-fieldend', 'move: Distortion World'); this.add('-message', 'Speeds have returned to normal.'); }, }, target: "all", type: "Ghost", }, // A Quag to The Past murkyambush: { accuracy: true, basePower: 150, category: "Physical", desc: "Fails unless the user is hit by a physical move from an opponent this turn before it can execute the move. The foe's move has its secondary effects suppressed and damage halved. If the user was hit and has not fainted, it attacks and the effect ends. This move can affect Flying-type Pokemon.", shortDesc: "Prepares for foe's attack, then retaliates.", name: "Murky Ambush", isNonstandard: "Custom", pp: 10, priority: -3, flags: {contact: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { if (source.volatiles['murkyambush'] && source.volatiles['murkyambush'].gotHit) { this.add('-anim', source, "Dig", target); } }, beforeTurnCallback(pokemon) { pokemon.addVolatile('murkyambush'); this.add('-message', `${pokemon.name} anticipates the opposing Pokémon's next move!`); this.attrLastMove('[still]'); this.add('-anim', pokemon, "Work Up", pokemon); }, beforeMoveCallback(pokemon) { if (pokemon.volatiles['murkyambush'] && !pokemon.volatiles['murkyambush'].gotHit) { this.add('cant', pokemon, 'Murky Ambush', 'Murky Ambush'); this.add('-message', `${pokemon.name} eases up.`); return true; } this.add('-message', `${pokemon.side.foe.active[0].name} was caught in the ambush!`); this.add(`c|+A Quag to The Past|GOTCHA BITCH`); }, condition: { duration: 1, onStart(pokemon) { this.add('-singleturn', pokemon, 'move: Murky Ambush'); }, onSourceBasePowerPriority: 7, onSourceBasePower(basePower, attacker, defender, move) { this.debug('Murky Ambush weaken'); if (move.category === 'Physical') { return this.chainModify(0.5); } }, onFoeTryMove(target, source, move) { if (move.secondaries && move.category !== 'Status') { this.debug('Murky Ambush secondary effects suppression'); delete move.secondaries; } }, onHit(pokemon, source, move) { if (pokemon.side !== source.side && move.category === 'Physical') { pokemon.volatiles['murkyambush'].gotHit = true; } }, }, ignoreImmunity: {Ground: true}, target: "normal", type: "Ground", }, // a random duck flock: { basePower: 100, accuracy: 100, category: "Special", desc: "This move suppresses the foe's ability and has a 70% chance to boost the user's Special Attack and Speed by one stage.", shortDesc: "70% SpA & Spe +1. Suppresses foe's ability.", name: "Flock", isNonstandard: "Custom", pp: 10, priority: 0, flags: {mirror: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Cosmic Power', source); this.add('-anim', source, 'Brave Bird', target); this.add('-anim', source, 'Judgment', target); }, onHit(target, source) { target.addVolatile('gastroacid', source); }, secondary: { chance: 70, self: { boosts: { spa: 1, spe: 1, }, }, }, target: "normal", type: "Flying", }, // Arcticblast trashalanche: { basePower: 80, basePowerCallback(pokemon, target, move) { let noitem = 0; for (const foes of target.side.pokemon) { if (!foes.item) noitem += 20; } return move.basePower + noitem; }, accuracy: 100, category: "Physical", desc: "This move's Base Power increases by 20 for every foe that is not holding an item.", shortDesc: "+20 Base Power for each itemless foe.", name: "Trashalanche", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Gunk Shot", target); }, secondary: null, target: "normal", type: "Poison", }, // Arsenal comeonyougunners: { accuracy: 100, basePower: 100, category: "Special", desc: "This move's type depends on the user's held Plate. If the target has the same type as this move, its Base Power is boosted by 1.5x.", shortDesc: "Type = Plate. 1.5x power for same-type targets.", name: "Come on you Gunners", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source, move) { this.add('-anim', source, 'Judgment', target); this.add('-anim', target, 'Extreme Evoboost', target); // Modifying BP here so it happens AFTER ModifyMove if (target.types.includes(move.type)) { this.debug('Come on you Gunners BP boost'); move.basePower = move.basePower * 1.5; } }, onModifyMove(move, pokemon) { const item = pokemon.getItem(); if (item.id && item.onPlate && !item.zMove) { this.debug(`Come on you Gunners type changed to: ${item.onPlate}`); move.type = item.onPlate; } }, secondary: null, target: "normal", type: "Normal", }, // Averardo dragonsmash: { accuracy: 90, basePower: 150, category: "Physical", desc: "This Pokemon takes 50% of the damage it deals as recoil.", shortDesc: "50% recoil.", name: "Dragon Smash", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Head Smash', target); this.add('-anim', target, 'Blue Flare', target); }, recoil: [1, 2], secondary: null, target: "normal", type: "Dragon", }, // Beowulf buzzingoftheswarm: { accuracy: 100, basePower: 95, category: "Physical", desc: "Has a 20% chance to cause the target to flinch.", shortDesc: "20% chance to flinch.", name: "Buzzing of the Swarm", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Bug Buzz', source); }, secondary: { chance: 20, volatileStatus: 'flinch', }, target: "normal", type: "Bug", }, // biggie foodrush: { accuracy: 100, basePower: 100, category: "Physical", desc: "If both the user and the target have not fainted, the target is forced to switch out to a random non-fainted ally. This effect fails if the target used Ingrain previously, has the Suction Cups ability, or is behind a Substitute.", shortDesc: "Forces the target to switch to a random ally.", name: "Food Rush", isNonstandard: "Custom", pp: 10, priority: -6, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Stockpile', source); this.add('-anim', source, 'Spit Up', target); }, forceSwitch: true, secondary: null, target: "normal", type: "Normal", }, // Birdy~! justdance: { accuracy: true, basePower: 0, category: "Status", desc: "Uses a random dance move other than Lunar Dance twice in a row and then restores 1/3 of its max HP.", shortDesc: "Uses random dance move twice; heals 1/3 HP.", name: "Just Dance", isNonstandard: "Custom", pp: 5, priority: 0, flags: {dance: 1, heal: 1}, onTryMove(pokemon) { this.attrLastMove('[still]'); }, onHit(target, source, effect) { this.heal(source.baseMaxhp / 3, source); const dancemoves = [ 'dragondance', 'featherdance', 'fierydance', 'petaldance', 'quiverdance', 'revelationdance', 'swordsdance', 'teeterdance', ]; const randomMove = dancemoves[this.random(dancemoves.length)]; this.useMove(randomMove, target); this.useMove(randomMove, target); // Kill getting locked into petal dance if (source.getVolatile('lockedmove')) { source.removeVolatile('lockedmove'); } }, secondary: null, target: "self", type: "Normal", }, // bobochan thousandcircuitoverload: { accuracy: 100, basePower: 90, category: "Physical", desc: "If the target is a Ground-type and is immune to Electric due to its typing, this move deals neutral damage regardless of other types, and the target loses its type-based immunity to Electric.", shortDesc: "First hit neutral on Ground; removes its immunity.", name: "Thousand Circuit Overload", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Plasma Fists', target); }, onEffectiveness(typeMod, target, type, move) { if (move.type !== 'Electric') return; if (!target) return; // avoid crashing when called from a chat plugin if (!target.runImmunity('Electric')) { if (target.hasType('Ground')) return 0; } }, volatileStatus: 'thousandcircuitoverload', condition: { noCopy: true, onStart(pokemon) { this.add('-start', pokemon, 'Thousand Circuit Overload'); }, onNegateImmunity(pokemon, type) { if (pokemon.hasType('Ground') && type === 'Electric') return false; }, }, ignoreImmunity: {Electric: true}, secondary: null, target: "normal", type: "Electric", }, // Brandon blusterywinds: { accuracy: 100, basePower: 70, category: "Special", desc: "Removes Reflect, Light Screen, Aurora Veil, Safeguard, Mist, Spikes, Toxic Spikes, Stealth Rock, and Sticky Web from both sides, and it removes any active weather condition or terrain.", shortDesc: "Removes all field conditions and hazards.", name: "Blustery Winds", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, authentic: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Defog", target); }, onHit(target, source, move) { const removeAll = [ 'reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist', 'spikes', 'toxicspikes', 'stealthrock', 'stickyweb', ]; const silentRemove = ['reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist']; for (const sideCondition of removeAll) { if (target.side.removeSideCondition(sideCondition)) { if (!(silentRemove.includes(sideCondition))) { this.add('-sideend', target.side, this.dex.getEffect(sideCondition).name, '[from] move: Blustery Winds', '[of] ' + source); } } if (source.side.removeSideCondition(sideCondition)) { if (!(silentRemove.includes(sideCondition))) { this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Blustery Winds', '[of] ' + source); } } } this.field.clearWeather(); this.field.clearTerrain(); }, secondary: null, target: "normal", type: "Flying", }, // Cake sparcedance: { accuracy: true, basePower: 0, category: "Status", desc: "Boosts the user's Attack, Defense, and Speed by one stage.", shortDesc: "+1 Atk, Def, and Spe.", name: "Sparce Dance", isNonstandard: "Custom", pp: 15, priority: 0, flags: {snatch: 1, mirror: 1, dance: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Quiver Dance", source); }, boosts: {atk: 1, def: 1, spe: 1}, secondary: null, target: "self", type: "Normal", }, // c.kilgannon insidiousassault: { accuracy: 100, basePower: 70, category: "Special", desc: "This move's category becomes physical if the opponent's Defense stat is lower than its Special Defense stat. This move's Base Power is 1.5x if this move is physical.", shortDesc: "Physical and power x1.5 if foe's Def < SpD.", name: "Insidious Assault", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Black Hole Eclipse', target); }, onModifyMove(move, pokemon, target) { if (!target) return; if (target.getStat('def', false, true) < target.getStat('spd', false, true)) move.category = 'Physical'; }, onBasePower(basePower, source, target, move) { if (move.category === 'Physical') { return this.chainModify(1.5); } }, target: "normal", type: "Dark", }, // cant say aesthetislash: { accuracy: 100, basePower: 100, category: "Physical", desc: "Summons Grassy Terrain. If the user is an Aegislash, it changes to Blade forme, attacks, then goes back to Shield forme.", shortDesc: "Summons Grassy Terrain. Aegislash transforms.", name: "a e s t h e t i s l a s h", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Geomancy', source); this.add('-anim', source, 'Swords Dance', source); this.add('-anim', source, 'Bloom Doom', target); }, onAfterMoveSecondarySelf() { this.field.setTerrain('grassyterrain'); }, onAfterMove(pokemon) { if (pokemon.species.baseSpecies !== 'Aegislash' || pokemon.transformed) return; if (pokemon.species.name !== 'Aegislash') pokemon.formeChange('Aegislash'); }, target: "normal", type: "Steel", }, // Catalystic birbtotherescue: { accuracy: true, basePower: 0, category: "Status", desc: "Resets the stat stages of all active Pokemon to 0, then lowers target's evasion by one stage and removes hazards.", shortDesc: "Resets stats; target's evasion -1; clears hazards.", name: "Birb to the Rescue", pp: 15, priority: 1, flags: {protect: 1, reflectable: 1, mirror: 1, authentic: 1}, onHit(target, source, move) { this.add('-clearallboost'); for (const pokemon of this.getAllActive()) { pokemon.clearBoosts(); } let success = false; if (!target.volatiles['substitute'] || move.infiltrates) success = !!this.boost({evasion: -1}); const removeTarget = [ 'reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist', 'spikes', 'toxicspikes', 'stealthrock', 'stickyweb', ]; const removeAll = ['spikes', 'toxicspikes', 'stealthrock', 'stickyweb']; for (const targetCondition of removeTarget) { if (target.side.removeSideCondition(targetCondition)) { if (!removeAll.includes(targetCondition)) continue; this.add('-sideend', target.side, this.dex.getEffect(targetCondition).name, '[from] move: Defog', '[of] ' + source); success = true; } } for (const sideCondition of removeAll) { if (source.side.removeSideCondition(sideCondition)) { this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Defog', '[of] ' + source); success = true; } } return success; }, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Haze", target); this.add('-anim', source, "Defog", target); }, secondary: null, target: "normal", type: "Ice", }, // Ceteris bringerofdarkness: { accuracy: true, basePower: 0, category: "Status", desc: "Has a 50% chance to cause the target to fall asleep. Sets one layer of Spikes on the opponent's side of the field and randomly boosts the user's Speed or Special Attack by one stage.", shortDesc: "50% sleep; sets Spikes; Spe or SpA +1.", name: "Bringer of Darkness", isNonstandard: "Custom", pp: 5, priority: 0, flags: {reflectable: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Dark Void", target); }, onHit(target, source, move) { this.add('-anim', source, "Spikes", target); target.side.addSideCondition('spikes'); if (this.random(2) === 0) { this.boost({spa: 1}, source, source); } else { this.boost({spe: 1}, source, source); } if (this.random(2) === 0) target.trySetStatus('slp', source); }, secondary: null, target: "normal", type: "Dark", }, // chaos forcewin: { accuracy: 100, basePower: 0, category: "Status", desc: "Confuses the target and subjects it to the effects of Taunt, Torment, Heal Block, and Embargo.", shortDesc: "Ensures domination of the opponent.", name: "Forcewin", isNonstandard: "Custom", pp: 15, priority: 0, flags: {protect: 1, reflectable: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Entrainment", target); this.add('-anim', source, "Lock On", target); }, onHit(target, source) { target.addVolatile('taunt', source); target.addVolatile('embargo', source); target.addVolatile('torment', source); target.addVolatile('confusion', source); target.addVolatile('healblock', source); this.add(`c|~chaos|/forcewin chaos`); if (this.random(1000) === 420) { // Should almost never happen, but will be hilarious when it does. // Basically, roll a 1000 sided die, if it lands on 420 forcibly give the user's trainer the win this.add(`c|~chaos|Actually`); this.add(`c|~chaos|/forcewin ${source.side.name}`); this.win(source.side); } }, secondary: null, target: "normal", type: "???", }, // Chloe beskyttelsesnet: { accuracy: true, basePower: 0, category: "Status", desc: "The user faints, sets Reflect, Light Screen, and Safeguard, and lowers the target's Attack and Special Attack by 2 stages.", shortDesc: "Faint; +Screens & Safeguard; foe -2 Atk & SpA.", name: "beskyttelsesnet", isNonstandard: "Custom", pp: 10, priority: 0, flags: {mirror: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Geomancy', source); this.add('-anim', source, 'Memento', target); }, onHit(target, source) { this.boost({atk: -2, spa: -2}, target, source); source.side.addSideCondition('lightscreen', source); source.side.addSideCondition('reflect', source); source.side.addSideCondition('safeguard', source); }, selfdestruct: "ifHit", secondary: null, target: "normal", type: "Dark", }, // Darth leechswap: { accuracy: 85, basePower: 0, category: "Status", desc: "Applies Leech Seed to the foe, then switches out", shortDesc: "Leech Seeds foe, then switches out.", name: "Leech Swap", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, reflectable: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Leech Seed", target); }, onHit(target, source) { if (target.hasType('Grass') || target.volatiles['leechseed']) { this.add('-fail', source); return false; } else { target.addVolatile('leechseed'); } }, selfSwitch: true, secondary: null, target: "normal", type: "Grass", }, // DaWoblefet superegoinflation: { accuracy: true, basePower: 0, category: "Status", desc: "User heals 25% HP. The target's Attack and Special Attack increase by two stages, and the target becomes affected by Taunt.", shortDesc: "User heals 25% HP; target Atk & SpA +2; Taunt.", name: "Super Ego Inflation", isNonstandard: "Custom", pp: 5, priority: -7, flags: {mirror: 1, authentic: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Follow Me', source); this.add('-anim', target, 'Swords Dance', target); this.add('-anim', target, 'Nasty Plot', target); }, onHit(target, source, move) { this.heal(source.baseMaxhp / 4, source, source, this.dex.getActiveMove('Super Ego Inflation')); this.boost({atk: 2, spa: 2}, target, source, this.dex.getActiveMove('Super Ego Inflation')); target.addVolatile('taunt', source, this.dex.getActiveMove('Super Ego Inflation')); }, secondary: null, target: "normal", type: "Normal", }, // Decem hitandrun: { accuracy: 100, basePower: 70, category: "Special", desc: "If this move hits, the Pokemon that was hit is affected with the Gooey status. Gooey causes the affected Pokemon to lose 1/6 of its max HP until it switches out. The user switches out.", shortDesc: "Target loses 1/6 of HP per turn, user switches.", name: "Hit and Run", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Outrage', target); }, onHit(target, source, move) { target.addVolatile('Gooey', source, move); }, selfSwitch: true, secondary: null, target: "normal", type: "Dragon", }, // deetah galvanizedstrike: { accuracy: 100, basePower: 70, category: "Physical", desc: "Power doubles if the user is burned, paralyzed, or poisoned. The physical damage halving effect from the user's burn is ignored. Has a 30% chance to paralyze the target.", shortDesc: "Power x2 if burn/poison/paralyze; 30% paralyze.", name: "Galvanized Strike", isNonstandard: "Custom", pp: 20, priority: 0, flags: {contact: 1, protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Wild Charge', target); this.add('-anim', source, 'Bolt Strike', target); }, onBasePower(basePower, pokemon) { if (pokemon.status && pokemon.status !== 'slp') { return this.chainModify(2); } }, secondary: { chance: 30, status: 'par', }, target: "normal", type: "Electric", }, // Dragontite hyperforcestrike: { accuracy: 100, basePower: 90, category: "Physical", desc: "Damages the target and restores user's HP by 15% of its total health.", shortDesc: "Damages the target and heals 15% total HP.", name: "Hyperforce Strike", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, heal: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Draco Meteor", target); }, onAfterMoveSecondarySelf(pokemon, target, move) { this.heal(pokemon.maxhp * 0.15, pokemon, pokemon, move); // 15% health recovered }, secondary: null, target: "normal", type: "Flying", }, // DragonWhale earthsblessing: { accuracy: true, basePower: 0, category: "Status", desc: "Sets Gravity, raises the user's Attack by 2 stages, and cures the user's burn, paralysis, or poison. Fails if Gravity is already in effect.", shortDesc: "Sets Gravity, raises Attack by 2, cures status.", name: "Earth's Blessing", isNonstandard: "Custom", pp: 5, priority: 0, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Swords Dance', source); this.add('-anim', source, 'Wood Hammer', source); }, onHit(pokemon, move) { if (this.field.pseudoWeather.gravity) return false; this.boost({atk: 2}, pokemon, pokemon, this.dex.getActiveMove('EarthsBlessing')); this.field.addPseudoWeather('gravity'); if (['', 'slp', 'frz'].includes(pokemon.status)) return; pokemon.cureStatus(); }, flags: {mirror: 1, snatch: 1}, secondary: null, target: "self", type: "Ground", zMove: {effect: 'healhalf'}, }, // E4 Flint fangofthefireking: { accuracy: 90, basePower: 0, damage: 111, category: "Physical", desc: "Deals 111 HP of damage and burns the target. If the target already has a status ailment, it is replaced with a burn. Fails if the target is a Fire-type or if the user is not a Fire-type.", shortDesc: "111 damage & target burned; fails on Fire-type.", name: "Fang of the Fire King", isNonstandard: "Custom", pp: 10, priority: 0, flags: {mirror: 1, protect: 1, bite: 1}, onTryMove(pokemon, target, move) { this.attrLastMove('[still]'); if (!pokemon.hasType('Fire') || target.hasType('Fire')) { this.add('-fail', pokemon, 'move: Fang of the Fire King'); return null; } }, onPrepareHit(target, source) { this.add('-anim', source, 'Crunch', target); this.add('-anim', target, 'Searing Shot', target); }, onHit(target, source) { target.setStatus('brn', source, null, true); // Cringy message if (this.random(5) === 1) this.add(`c|@E4 Flint|here's a __taste__ of my __firepower__ XD`); }, secondary: null, target: "normal", type: "Fire", }, // Eien ancestralpower: { accuracy: true, basePower: 0, category: "Status", desc: "The user's Attack and Special Attack are raised by one stage, it transforms into a different Pokemon, and it uses two moves dependent on the Pokemon; Celebi (Future Sight and Recover), Jirachi (Doom Desire and Wish), Manaphy (Tail Glow and Surf), Shaymin (Seed Flare and Leech Seed), or Victini (V-create and Blue Flare). Reverts to Mew and loses the initial raises of one stage to Attack and Special Attack at the end of the turn.", shortDesc: "For turn: transforms, boosts, uses linked moves.", name: "Ancestral Power", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, authentic: 1}, onTryMove() { this.attrLastMove('[still]'); }, onHit(target, source, move) { const baseForme = source.species.id; const formes: {[forme: string]: string[]} = { celebi: ['Future Sight', 'Recover'], jirachi: ['Doom Desire', 'Wish'], manaphy: ['Tail Glow', 'Surf'], shaymin: ['Seed Flare', 'Leech Seed'], victini: ['V-create', 'Blue Flare'], }; const forme = Object.keys(formes)[this.random(5)]; // Suppress Ability now to prevent starting new abilities when transforming source.addVolatile('gastroacid', source); source.formeChange(forme, this.dex.getAbility('psychicsurge'), true); this.boost({atk: 1, spa: 1}, source, source, move); this.useMove(formes[forme][0], source, target); this.useMove(formes[forme][1], source, target); this.boost({atk: -1, spa: -1}, source, source, move); source.formeChange(baseForme, this.dex.getAbility('psychicsurge'), true); }, secondary: null, target: "normal", type: "Psychic", }, // Elgino roughsnuggle: { accuracy: 100, basePower: 90, category: "Physical", desc: "Power doubles if the target is not fully evolved.", shortDesc: "Power doubles if the target is NFE.", name: "Rough Snuggle", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Let\'s Snuggle Forever', target); }, onBasePower(basePower, pokemon, target) { if (target.species.evos.length) { return this.chainModify(2); } }, secondary: null, target: "normal", type: "Fighting", zMove: {basePower: 175}, }, // eternally quack: { accuracy: true, basePower: 0, category: "Status", desc: "Boosts the user's Special Attack and accuracy by one stage.", shortDesc: "Raises the user's SpA and accuracy by 1.", name: "Quack", isNonstandard: "Custom", pp: 5, priority: 0, flags: {mirror: 1, snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Feather Dance', source); this.add('-anim', source, 'Aqua Ring', source); }, boosts: {spa: 1, accuracy: 1}, secondary: null, target: "self", type: "Flying", }, // explodingdaisies doom: { basePower: 100, accuracy: 100, category: "Special", desc: "Summons Sunny Day after doing damage.", shortDesc: "Summons Sunny Day after doing damage.", name: "DOOM!", isNonstandard: "Custom", pp: 5, priority: 0, flags: {mirror: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Eruption', target); this.add('-anim', source, 'Sunny Day', source); }, onAfterMoveSecondarySelf() { this.field.setWeather('sunnyday'); }, secondary: null, target: "normal", type: "Fire", }, // False frck: { accuracy: true, basePower: 0, category: "Physical", desc: "Does not check accuracy. KOes the foe. User faints afterwards if move hits.", shortDesc: "KOes foe. Always hits. User faints on success.", name: "fr*ck", isNonstandard: "Custom", pp: 6, noPPBoosts: true, priority: 0, flags: {protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-activate', source, 'move: Celebrate'); this.add('-anim', source, 'Searing Sunraze Smash', target); this.add('-anim', source, 'Explosion', target); }, onHit(target, source) { target.faint(); source.faint(); }, secondary: null, target: "normal", type: "???", }, // fart soupstealing7starstrike: { accuracy: 100, basePower: 90, category: "Physical", desc: "This move is either a Water-, Fire-, or Grass-type move. The selected type is added to the user of this move.", shortDesc: "Changes user/move type to Fire, Water, or Grass.", name: "Soup-Stealing 7-Star Strike", isNonstandard: "Custom", pp: 15, priority: 0, flags: {protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Conversion", source); }, onModifyMove(move, pokemon) { const types = ['Fire', 'Water', 'Grass']; const randomType = this.sample(types); move.type = randomType; pokemon.addType(randomType); this.add('-start', pokemon, 'typeadd', randomType); }, onHit(target, source) { this.add('-anim', source, 'Spectral Thief', target); if (Math.round(this.random())) { this.add(`c|%fart|I hl on soup`); } else { this.add(`c|%fart|did someone say soup?`); } }, secondary: null, target: "normal", type: "Normal", }, // Felucia quickreload: { accuracy: true, basePower: 0, category: "Physical", desc: "Uses Defog and then attempts to use U-Turn.", shortDesc: "Uses Defog, then U-Turn.", name: "Quick Reload", isNonstandard: "Custom", pp: 15, priority: 0, flags: {mirror: 1, protect: 1, authentic: 1}, onTryMove() { this.attrLastMove('[still]'); }, onHit(target, source) { this.useMove('Defog', source, target); const move = this.dex.getActiveMove('uturn'); move.basePower = 90; this.useMove(move, source, target); }, secondary: null, target: "normal", type: "Bug", }, // FOMG rickrollout: { accuracy: true, basePower: 140, category: "Physical", desc: "Raises the user's Speed by two stages and has a 30% chance to confuse the target.", shortDesc: "Speed +2; 30% chance to confuse target.", name: "Rickrollout", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Rock Polish', source); this.add('-anim', source, 'Let\'s Snuggle Forever', target); }, onHit() { const messages = ["SPL players don't want you to know about this secret", "North American player reveals the concerning secret how to make money with Pokemon that will crack you up", "10 amazing facts about Zarel you have never heard of", "Veteran player shared his best team with a beginner - here's what happened after", "Use these 3 simple methods to gain 200+ rating in 10 minutes"][this.random(5)]; this.add(`raw|${messages}`); }, self: { boosts: { spe: 2, }, }, secondary: { chance: 30, volatileStatus: 'confusion', }, isZ: "astleyiumz", target: "normal", type: "Rock", }, // Gallant Spear stormassaultogs: { accuracy: 90, basePower: 25, multihit: 3, category: "Physical", desc: "Hits three times. Each hit has a 10% chance to drop the target's Defense and a 10% chance to burn. Each hit is always a critical hit. If one of the hits breaks the target's Substitute, it will take damage for the remaining hits.", shortDesc: "Hits thrice; 10% Def -1; 10% burn; always crits.", isNonstandard: "Custom", name: "Storm Assault OGs", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, willCrit: true, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Bullet Seed', target); this.add('-anim', source, 'Magma Storm', target); }, secondaries: [ { chance: 10, status: 'brn', }, { chance: 10, boosts: { def: -1, }, }, ], target: "normal", type: "Fire", }, // Gimm1ck slavsquat: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Attack, Defense, and Special Defense by one stage. Weather becomes Hail.", shortDesc: "Atk, Def, and SpD +1; weather becomes Hail.", name: "Slav Squat", isNonstandard: "Custom", pp: 10, priority: 0, flags: {snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Automotize', source); this.add('-anim', source, 'Hail', source); this.add('-anim', source, 'Gravity', source); }, boosts: { atk: 1, def: 1, spd: 1, }, weather: 'hail', secondary: null, target: "self", type: "Ice", }, // GMars tastetherainbow: { accuracy: true, basePower: 0, category: "Status", desc: "Increases this Pokemon's Attack, Special Attack, and Speed by two stages while also decreasing this Pokemon's Defense and Special Defense by one stage. If this Pokemon is a Minior in its Meteor forme, it will permanently transform into one of the Minior colors and have a special effect based on that color. Red burns the foe, orange confuses it, yellow paralyzes it, green applies Leech Seed, blue gives the user Aqua Ring status, indigo poisons the foe, and violet badly poisons it.", shortDesc: "+2 Atk, SpA, Spe. -1 Def, SpD. Meteor -> Core.", name: "Taste the Rainbow", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Extreme Evoboost', source); }, onHit(target, source, move) { // Set target to the foe, this is a self targeting move so it works even if the foe has a subsitute target = source.side.foe.active[0]; this.boost({atk: 2, spa: 2, spe: 2, def: -1, spd: -1}, source); if (source.species.id !== 'miniormeteor' || source.transformed) return; const rainbow = ['', '-Orange', '-Yellow', '-Green', '-Blue', '-Indigo', '-Violet']; const color = rainbow[this.random(rainbow.length)]; source.formeChange(`Minior${color}`, move, true); // Display correct color on client if (color) { this.add('-formechange', source, `Minior${color}`); source.m.miniorColor = color; } if (target.volatiles['substitute'] && color !== '-Blue') { this.add('-fail', source); return; } switch (color) { case '': if (!target.trySetStatus('brn', source)) this.add('-fail', target); break; case '-Orange': if (!target.addVolatile('confusion', source)) this.add('-fail', target); break; case '-Yellow': if (!target.trySetStatus('par', source)) this.add('-fail', target); break; case '-Green': if (!target.hasType('Grass')) { this.add('-anim', source, 'Leech Seed', target); target.addVolatile('leechseed'); } else { this.add('-immune', target); } break; case '-Blue': if (!source.addVolatile('aquaring', source)) this.add('-fail', source); break; case '-Indigo': if (!target.trySetStatus('psn', source)) this.add('-fail', target); break; case '-Violet': if (!target.trySetStatus('tox', source)) this.add('-fail', target); break; default: throw new Error(`Invalid color for Taste the Rainbow selected: ${color}`); } }, target: "self", type: "Normal", }, // grimAuxiliatrix paintrain: { accuracy: 100, basePower: 0, basePowerCallback(pokemon, target) { const targetWeight = target.getWeight(); const pokemonWeight = pokemon.getWeight(); if (pokemonWeight > targetWeight * 5) { return 120; } if (pokemonWeight > targetWeight * 4) { return 100; } if (pokemonWeight > targetWeight * 3) { return 80; } if (pokemonWeight > targetWeight * 2) { return 60; } return 40; }, category: "Physical", desc: "The power of this move depends on (user's weight / target's weight), rounded down. Power is equal to 120 if the result is 5 or more, 100 if 4, 80 if 3, 60 if 2, and 40 if 1 or less. The user recovers 1/2 the HP lost by the target, rounded half up. If Big Root is held by the user, the HP recovered is 1.3x normal, rounded half down.", shortDesc: "Stronger if user is heavier. Heals 50% of damage.", name: "Pain Train", isNonstandard: "Custom", pp: 10, priority: 0, flags: {contact: 1, protect: 1, mirror: 1, heal: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Meteor Mash', target); }, drain: [1, 2], secondary: null, target: "normal", type: "Steel", }, // guishark dadjoke: { accuracy: 100, basePower: 90, category: "Physical", desc: "50% chance to confuse the foe.", shortDesc: "50% chance to confuse the foe.", name: "Dad Joke", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Boomburst", target); }, secondary: { chance: 50, volatileStatus: "confusion", }, target: "normal", type: "Dark", }, // Hippopotas hazardpass: { accuracy: 100, basePower: 0, category: "Status", pp: 20, priority: 0, desc: "The user sets two of Stealth Rock, Spikes (1 layer), Toxic Spikes (1 layer), and Sticky Web on the foe's side of the field and then switches out.", shortDesc: "Sets 2 random hazards, then switches out.", name: "Hazard Pass", isNonstandard: "Custom", flags: {reflectable: 1, mirror: 1, authentic: 1}, onTryMove() { this.attrLastMove('[still]'); }, onHitSide(target, source) { // All possible hazards, and their maximum possible layer count const hazards: {[k: string]: number} = {stealthrock: 1, spikes: 3, toxicspikes: 2, stickyweb: 1}; // Check how many layers of each hazard can still be added to the foe's side if (target.getSideCondition('stealthrock')) delete hazards.stealthrock; if (target.getSideCondition('spikes')) { hazards.spikes -= target.sideConditions['spikes'].layers; if (!hazards.spikes) delete hazards.spikes; } if (target.getSideCondition('toxicspikes')) { hazards.toxicspikes -= target.sideConditions['toxicspikes'].layers; if (!hazards.toxicspikes) delete hazards.toxicspikes; } if (target.getSideCondition('stickyweb')) delete hazards.stickyweb; // Create a list of hazards not yet at their maximum layer count const hazardTypes = Object.keys(hazards); // If there are no possible hazards, don't do anything if (!hazardTypes.length) return false; // Pick a random hazard, and set it const hazard1 = this.sample(hazardTypes); // Theoretically, this should always work this.add('-anim', source, this.dex.getMove(hazard1).name, target); target.addSideCondition(hazard1, source, this.effect); // If that was the last possible layer of that hazard, remove it from our list of possible hazards if (hazards[hazard1] === 1) { hazardTypes.splice(hazardTypes.indexOf(hazard1), 1); // If there are no more hazards we can set, end early on a success if (!hazardTypes.length) return true; } // Set the last hazard and animate the switch const hazard2 = this.sample(hazardTypes); this.add('-anim', source, this.dex.getMove(hazard2).name, target); target.addSideCondition(hazard2, source, this.effect); this.add('-anim', source, "Baton Pass", target); }, selfSwitch: true, secondary: null, target: "foeSide", type: "Normal", zMove: {boost: {def: 1}}, }, // HoeenHero scriptedterrain: { accuracy: 100, basePower: 0, category: "Status", desc: "Sets Scripted Terrain for 5 turns. The power of Bug-type moves is boosted by 1.5, and there is a 5% chance for every move used to become Glitch Out instead. At the end of a turn, every Pokemon has a 5% chance to transform into a MissingNo. with 3 random moves and Glitch Out. Switching out will restore the Pokemon to its normal state. This terrain affects floating Pokemon.", shortDesc: "5 turns: +Bug power, glitchy effects.", name: "Scripted Terrain", isNonstandard: "Custom", pp: 5, priority: 0, flags: {nonsky: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Calm Mind', source); this.add('-anim', source, 'Geomancy', source); }, terrain: 'scriptedterrain', condition: { duration: 5, durationCallback(source, effect) { if (source?.hasItem('terrainextender')) { return 8; } return 5; }, onBasePower(basePower, attacker, defender, move) { if (move.type === 'Bug') { this.debug('scripted terrain boost'); return this.chainModify(1.5); } }, onTryHitPriority: 4, onTryHit(target, source, effect) { if (!effect || effect.id === 'glitchout' || source.volatiles['glitchout']) return; if (this.random(20) === 1) { this.add('message', `${source.illusion ? source.illusion.name : source.name}'s move was glitched by the Scripted Terrain!`); this.useMove('Glitch Out', source, source.side.foe.active[0]); return null; } }, onStart(battle, source, effect) { if (effect && effect.effectType === 'Ability') { this.add('-fieldstart', 'move: Scripted Terrain', '[from] ability: ' + effect, '[of] ' + source); } else { this.add('-fieldstart', 'move: Scripted Terrain'); } this.add('-message', 'The battlefield got Technical!'); }, onResidualOrder: 21, onResidualSubOrder: 2, onResidual() { this.eachEvent('Terrain'); }, onTerrain(pokemon) { if (pokemon.species.id === 'missingno') return; if (pokemon.fainted || !pokemon.hp) return; if (this.random(20) === 1) { this.debug('Scripted terrain corrupt'); this.add('message', `${pokemon.name} was corrupted by a bug in the Scripted Terrain!`); // generate a movepool const moves = []; const pool = Object.keys(this.dex.data.Moves); this.prng.shuffle(pool); const metronome = this.dex.getMove('metronome'); for (const id of pool) { const move = this.dex.getMove(id); if (move.realMove) continue; if (move.isZ || move.isNonstandard) continue; if (metronome.noMetronome && metronome.noMetronome.includes(move.name)) continue; if (this.dex.getMove(id).gen > this.gen) continue; moves.push(move); if (moves.length >= 3) break; } moves.push('glitchout'); if (this.toID(pokemon.ability).includes('illusion') && pokemon.illusion) { this.singleEvent('End', this.dex.getAbility('Illusion'), pokemon.abilityData, pokemon, pokemon); } pokemon.formeChange('missingno'); pokemon.moveSlots = []; for (const moveid of moves) { const move = this.dex.getMove(moveid); if (!move.id) continue; pokemon.moveSlots.push({ move: move.name, id: move.id, pp: 5, maxpp: 5, target: move.target, disabled: false, used: false, virtual: true, }); } } }, onEnd() { this.add('-fieldend', 'move: Scripted Terrain'); this.add('-message', 'The battlefield is no longer Technical.'); }, }, secondary: null, target: "all", type: "Psychic", }, // Used by HoeenHero's terrain glitchout: { accuracy: true, basePower: 0, category: "Status", desc: "A random move is selected for use, other than After You, Assist, Baneful Bunker, Beak Blast, Belch, Bestow, Celebrate, Chatter, Copycat, Counter, Covet, Crafty Shield, Destiny Bond, Detect, Diamond Storm, Endure, Feint, Fleur Cannon, Focus Punch, Follow Me, Freeze Shock, Helping Hand, Hold Hands, Hyperspace Hole, Ice Burn, Instruct, King's Shield, Light of Ruin, Mat Block, Me First, Metronome, Mimic, Mind Blown, Mirror Coat, Mirror Move, Nature Power, Photon Geyser, Plasma Fists, Protect, Quash, Quick Guard, Rage Powder, Relic Song, Secret Sword, Shell Trap, Sketch, Sleep Talk, Snarl, Snatch, Snore, Spectral Thief, Spiky Shield, Spotlight, Steam Eruption, Struggle, Switcheroo, Techno Blast, Thief, Thousand Arrows, Thousand Waves, Transform, Trick, Trump Card, V-create, or Wide Guard. The selected move's Base Power is increased by 20.", shortDesc: "Uses a random move with Base Power +20.", name: "Glitch Out", isNonstandard: "Custom", pp: 10, priority: 0, flags: {}, noMetronome: [ "After You", "Assist", "Baneful Bunker", "Beak Blast", "Belch", "Bestow", "Celebrate", "Chatter", "Copycat", "Counter", "Covet", "Crafty Shield", "Destiny Bond", "Detect", "Diamond Storm", "Dragon Ascent", "Endure", "Feint", "Fleur Cannon", "Focus Punch", "Follow Me", "Freeze Shock", "Helping Hand", "Hold Hands", "Hyperspace Fury", "Hyperspace Hole", "Ice Burn", "Instruct", "King's Shield", "Light of Ruin", "Mat Block", "Me First", "Metronome", "Mimic", "Mind Blown", "Mirror Coat", "Mirror Move", "Nature Power", "Origin Pulse", "Photon Geyser", "Plasma Fists", "Precipice Blades", "Protect", "Quash", "Quick Guard", "Rage Powder", "Relic Song", "Secret Sword", "Shell Trap", "Sketch", "Sleep Talk", "Snarl", "Snatch", "Snore", "Spectral Thief", "Spiky Shield", "Spotlight", "Steam Eruption", "Struggle", "Switcheroo", "Techno Blast", "Thief", "Thousand Arrows", "Thousand Waves", "Transform", "Trick", "Trump Card", "V-create", "Wide Guard", ], onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Bug Buzz', source); this.add('-anim', source, 'Metronome', source); source.addVolatile('glitchout'); }, onHit(target, source, effect) { const moves = []; for (const id in this.dex.data.Moves) { const move = this.dex.data.Moves[id]; if (move.realMove) continue; if (move.isZ || move.isNonstandard) continue; if (effect.noMetronome && effect.noMetronome.includes(move.name)) continue; if (this.dex.getMove(id).gen > this.gen) continue; moves.push(move); } let randomMove = ''; if (moves.length) { moves.sort((a, b) => (a.num || 0) - (b.num || 0)); randomMove = this.sample(moves).name; } if (!randomMove) { return false; } this.useMove(randomMove, target); }, secondary: null, target: "self", type: "Bug", }, // Hubriz flowertornado: { accuracy: 90, basePower: 95, category: "Special", desc: "Has a 20% chance to either poison the target or cause it to fall asleep.", shortDesc: "20% chance to either poison or sleep target.", name: "Flower Tornado", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Petal Blizzard", target); this.add('-anim', source, "Leaf Tornado", target); }, secondary: { chance: 20, onHit(target, source) { const result = this.random(2); if (result === 0) { target.trySetStatus('psn', source); } else { target.trySetStatus('slp', source); } }, }, target: "normal", type: "Grass", }, // inactive petrifyinggaze: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Attack by two stages. Traps and paralyzes the foe.", shortDesc: "Raises user's Atk by 2; traps and paralyzes foe.", name: "Petrifying Gaze", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Mean Look", target); }, onHit(target, source, move) { this.boost({atk: 2}, source, source); target.trySetStatus('par', source); return target.addVolatile('trapped', source, move, 'trapper'); }, isZ: "dusknoiriumz", secondary: null, target: "normal", type: "Ghost", }, // irritated pureskill: { accuracy: 100, basePower: 80, category: "Physical", desc: "Has a 30% chance to paralyze the target and a 10% chance to confuse it.", shortDesc: "30% chance to paralyze. 10% chance to confuse.", name: "Pure Skill", isNonstandard: "Custom", pp: 10, priority: 0, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Heart Stamp', target); }, flags: {protect: 1, mirror: 1}, secondaries: [ { chance: 30, status: 'par', }, { chance: 10, volatileStatus: 'confusion', }, ], target: "normal", type: "Psychic", }, // Iyarito rosarosa: { accuracy: true, basePower: 0, category: "Status", desc: "Cures the user's party of all status conditions, then poisons the user.", shortDesc: "Cures party's statuses, then poisons self.", name: "Rosa Rosa", isNonstandard: "Custom", pp: 5, priority: 0, flags: {mirror: 1, snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Acid Armor', source); }, onHit(pokemon, source, move) { // this.add('-activate', source, 'move: Víbora'); let success = false; for (const ally of pokemon.side.pokemon) { if (ally.cureStatus()) success = true; } if (pokemon.trySetStatus('psn', pokemon)) success = true; return success; }, secondary: null, target: "allyTeam", type: "Poison", }, // Kaiju Bunny bestialstrike: { accuracy: 100, basePower: 150, basePowerCallback(pokemon, target, move) { return move.basePower * pokemon.hp / pokemon.maxhp; }, category: "Physical", desc: "Power is equal to (user's current HP * 150 / user's maximum HP), rounded down, but not less than 1.", shortDesc: "Less power as user's HP decreases.", name: "Bestial Strike", isNonstandard: "Custom", onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Outrage', target); }, pp: 5, priority: 0, flags: {protect: 1, mirror: 1, contact: 1}, secondary: null, target: "normal", type: "Flying", }, // kalalokki maelstrm: { accuracy: 85, basePower: 100, category: "Special", desc: "Prevents the target from switching for four or five turns (seven turns if the user is holding Grip Claw). Causes damage to the target equal to 1/8 of its maximum HP (1/6 if the user is holding Binding Band), rounded down, at the end of each turn during effect. Both of these effects persist for their normal duration even if the user switches out or faints. The target can still switch out if it is holding Shed Shell or uses Baton Pass, Parting Shot, U-turn, or Volt Switch. The effect ends if the target leaves the field or uses Rapid Spin or Substitute successfully. This effect is not stackable or reset by using this or another binding move.", shortDesc: "Traps/damages 4-5 turns, even if user switches.", name: "Maelström", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, volatileStatus: 'maelstrm', onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Dark Void', target); this.add('-anim', source, 'Surf', target); }, condition: { duration: 5, durationCallback(target, source) { if (source.hasItem('gripclaw')) { this.debug('maelstrm grip claw duration boost'); return 8; } return this.random(5, 7); }, onStart() { this.add('-message', 'It became trapped in an enormous maelström!'); }, onResidualOrder: 11, onResidual(pokemon) { if (this.effectData.source.hasItem('bindingband')) { this.debug('maelstrm binding band damage boost'); this.damage(pokemon.baseMaxhp / 6); } else { this.damage(pokemon.baseMaxhp / 8); } }, onEnd() { this.add('-message', 'The maelström dissipated.'); }, onTrapPokemon(pokemon) { pokemon.tryTrap(); }, }, secondary: null, target: "normal", type: "Water", }, // kaori w: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Special Attack, Special Defense, and Speed by one stage. Summons Sunny Day.", shortDesc: "User's SpA, SpD, Spe +1. Sets Sunny Day.", name: ">w<", isNonstandard: "Custom", pp: 5, priority: 0, flags: {snatch: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Petal Dance', source); }, onHit(target, source) { this.field.setWeather('sunnyday', source); }, boosts: { spa: 1, spd: 1, spe: 1, }, secondary: null, target: "self", type: "Grass", }, // Kay inkzooka: { accuracy: 100, basePower: 80, category: "Physical", desc: "Lowers the user's Defense, Special Defense, and Speed by one stage.", shortDesc: "Lowers the user's Def, Sp. Def, and Spe by 1.", name: "Inkzooka", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Never Ending Nightmare', target); }, self: { boosts: { def: -1, spd: -1, spe: -1, }, }, secondary: null, target: "normal", type: "Psychic", }, // Kie chaotic: { accuracy: 100, basePower: 70, category: "Physical", desc: "Before the user attacks, its Attack is increased by one stage. After the user attacks, one of its stats other than accuracy and evasion is boosted by one stage. This move has a 50% chance to confuse the target.", shortDesc: "Atk +1, attacks. Random stat +1. 50% confuse.", name: "Chaotic", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.boost({atk: 1}, source); this.add('-anim', source, "Dragon Dance", source); this.add('-anim', source, "Liquidation", target); }, onAfterHit(target, source) { const boost: SparseBoostsTable = {}; const stats: BoostName[] = ['atk', 'def', 'spa', 'spd', 'spe']; const stat: BoostName = stats[this.random(5)]; boost[stat] = 1; this.boost(boost, source); }, secondary: { chance: 50, volatileStatus: "confusion", }, target: "normal", type: "Water", }, // KingSwordYT dragonwarriortouch: { accuracy: 100, basePower: 70, category: "Physical", desc: "The user recovers 1/2 the HP lost by the target, rounded half up. Raises the user's Attack by one stage.", shortDesc: "User recovers 50% of the damage dealt; Atk +1.", name: "Dragon Warrior Touch", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1, punch: 1, contact: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Outrage', target); this.add('-anim', source, 'Drain Punch', target); }, self: { boosts: { atk: 1, }, }, drain: [1, 2], target: "normal", type: "Fighting", }, // Kipkluif salutethecolonel: { accuracy: true, basePower: 0, category: "Status", desc: "The user is protected from most attacks made by other Pokemon during this turn, and Pokemon trying to make contact with the user have their Attack lowered by 2 stages. Non-damaging moves go through this protection. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. The user also swaps its Defense and Special Defense stat stage changes with the target. Fails if the user moves last this turn.", shortDesc: "Blocks attacks; contact: Atk -2; Guard Swap.", isNonstandard: "Custom", name: "Salute the Colonel", pp: 15, priority: 4, flags: {}, stallingMove: true, volatileStatus: 'kingsshield', onTryMove() { this.attrLastMove('[still]'); }, onTryHit(pokemon) { return !!this.queue.willAct() && this.runEvent('StallMove', pokemon); }, onPrepareHit(target, source) { this.add('-anim', source, "King's Shield", source); this.add('-anim', source, "Guard Swap", target); }, onHit(pokemon) { pokemon.addVolatile('stall'); this.add(`c|+Kipkluif|o7`); const target = pokemon.side.foe.active[0]; if (!target) return; const targetBoosts: SparseBoostsTable = {}; const sourceBoosts: SparseBoostsTable = {}; const defSpd: BoostName[] = ['def', 'spd']; let stat: BoostName; for (stat of defSpd) { targetBoosts[stat] = target.boosts[stat]; sourceBoosts[stat] = pokemon.boosts[stat]; } pokemon.setBoost(targetBoosts); target.setBoost(sourceBoosts); this.add('-swapboost', pokemon, target, 'def, spd', '[from] move: Guard Swap'); }, secondary: null, target: "self", type: "Fighting", }, // Kris ectoplasm: { accuracy: 100, basePower: 95, category: "Special", desc: "This move's type is equal to the user's secondary type. Has a 10% chance to lower the user's Special Defense by 1.", shortDesc: "Attack is user's 2nd type. 10% SpD -1.", isNonstandard: "Custom", name: "Ectoplasm", pp: 15, priority: 0, flags: {protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onTry(pokemon, target) { if (pokemon.types[1] === undefined) { this.add('-fail', pokemon); return null; } }, onModifyMove(move, pokemon) { move.type = pokemon.types[1]; }, onPrepareHit(target, source) { let move = 'Tri Attack'; switch (source.types[1]) { case 'Ghost': move = 'Moongeist Beam'; break; case 'Flying': move = 'Hurricane'; break; case 'Fire': move = 'Blast Burn'; break; case 'Water': move = 'Hydro Cannon'; break; case 'Grass': move = 'Frenzy Plant'; break; case 'Ice': move = 'Sheer Cold'; break; } this.add('-anim', source, move, target); }, secondary: { chance: 10, boosts: { spd: -1, }, }, target: "normal", type: "Normal", }, // Level 51 nextlevelstrats: { accuracy: true, basePower: 0, category: "Status", desc: "The user gains 5 levels upon using this move, which persist upon switching out.", shortDesc: "User gains 5 levels.", name: "Next Level Strats", isNonstandard: "Custom", pp: 5, priority: 0, flags: {snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Nasty Plot", target); }, onHit(pokemon) { const species = pokemon.species; const level = pokemon.level + 5; (pokemon as any).level = level; pokemon.set.level = level; pokemon.formeChange(species); pokemon.details = species.name + (level === 100 ? '' : ', L' + level) + (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); this.add('detailschange', pokemon, pokemon.details); const newHP = Math.floor(Math.floor( 2 * species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100 ) * level / 100 + 10); pokemon.hp = newHP - (pokemon.maxhp - pokemon.hp); pokemon.maxhp = newHP; this.add('-heal', pokemon, pokemon.getHealth, '[silent]'); this.add('-message', `${pokemon.name} advanced 5 levels! It is now level ${level}!`); }, secondary: null, target: "self", type: "Normal", }, // LifeisDANK barfight: { accuracy: 100, basePower: 10, category: "Physical", desc: "Raises both the user's and the target's Attack by three stages, lowers the Defense of both by three stages, confuses both Pokemon, and has a 100% chance to cause the target to flinch. Only works on the user's first turn on the field.", shortDesc: "First turn: +3 Atk, -3 Def, flinch, both confused.", name: "Bar Fight", isNonstandard: "Custom", pp: 10, priority: 3, flags: {protect: 1, mirror: 1, contact: 1}, onTry(pokemon, target) { if (pokemon.activeMoveActions > 1) { this.attrLastMove('[still]'); this.add('-fail', pokemon); this.hint("Bar Fight only works on your first turn out."); return null; } }, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Fake Out", target); this.add('-anim', source, "Feather Dance", target); }, onHit(target, source) { this.boost({atk: 3, def: -3}, target); this.boost({atk: 3, def: -3}, source); target.addVolatile('confusion'); source.addVolatile('confusion'); target.addVolatile('flinch'); }, secondary: null, target: "normal", type: "Flying", }, // Lost Seso shuffleramendance: { accuracy: 100, basePower: 80, category: "Special", desc: "This move's type effectiveness is inverted, meaning that it's super effective on Water-types but not very effective on Grass-types, and so forth. 20% chance to paralyze the target.", shortDesc: "Type effectiveness is inverted; 20% paralyze.", name: "Shuffle Ramen Dance", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, dance: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Outrage', target); }, onEffectiveness(typeMod, target) { return -typeMod; }, secondary: { status: 'par', chance: 20, }, target: "normal", type: "Fire", zMove: {basePower: 160}, }, // MacChaeger naptime: { accuracy: true, basePower: 0, category: "Status", desc: "The user falls asleep for the next turn, restoring 50% of its HP and curing itself of any major status condition. If the user falls asleep in this way, all other active Pokemon that are not asleep or frozen also try to use Nap Time. Fails if the user has full HP, if the user is already asleep, or if another effect is preventing sleep.", shortDesc: "Active Pokemon sleep 1 turn, restoring HP/status.", name: "Nap Time", isNonstandard: "Custom", pp: 5, priority: 0, flags: {snatch: 1, heal: 1}, onTryMove(pokemon) { this.attrLastMove('[still]'); if (pokemon.hp < pokemon.maxhp && pokemon.status !== 'slp' && !pokemon.hasAbility('comatose')) return; this.add('-fail', pokemon); this.hint("Nap Time fails if the user has full health, is already asleep, or has Comatose."); return null; }, onPrepareHit(target, source) { this.add('-anim', source, "Rest", target); this.add('-anim', source, "Aromatic Mist", target); }, onHit(target, source, move) { const napWeather = this.field.pseudoWeather['naptime']; // Trigger sleep clause if not the original user if (target !== napWeather.source) { for (const ally of target.side.pokemon) { if (ally.status === 'slp') { if (!(ally.statusData.source && ally.statusData.source.side === ally.side)) return false; } } } if (!target.setStatus('slp', napWeather.source, move)) return false; target.statusData.time = 2; target.statusData.startTime = 2; this.heal(target.baseMaxhp / 2); // Aesthetic only as the healing happens after you fall asleep in-game if (napWeather.source === target) { for (const curMon of this.getAllActive()) { if (curMon === source) continue; if (curMon.status !== 'slp' && curMon.status !== 'frz' && !curMon.hasAbility('comatose')) { this.add('-anim', source, "Yawn", curMon); this.useMove(move, curMon, curMon, move); } } } this.field.removePseudoWeather('naptime'); }, pseudoWeather: 'naptime', condition: { duration: 1, }, target: "self", type: "Fairy", zMove: {effect: 'clearnegativeboosts'}, }, // Mad Monty ¾° llamacide: { accuracy: 100, basePower: 80, category: "Physical", desc: "Has a 40% chance to lower target's Defense by one stage and a 10% chance to freeze it.", shortDesc: "40% target's Def -1. 10% chance of freeze.", name: "Llamacide", pp: 10, priority: 0, flags: {protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Nasty Plot", source); this.add('-anim', source, "Plasma Fists", target); this.add('-anim', source, "Sheer Cold", target); }, secondaries: [ { status: "frz", chance: 10, }, { chance: 40, boosts: { def: -1, }, }, ], target: "normal", type: "Ice", }, // MajorBowman blazeofglory: { accuracy: true, basePower: 0, damageCallback(pokemon, target) { const damage = pokemon.hp; pokemon.faint(); if ( target.volatiles['banefulbunker'] || target.volatiles['kingsshield'] || target.side.sideConditions['matblock'] || target.volatiles['protect'] || target.volatiles['spikyshield'] || target.volatiles['lilypadshield'] || target.volatiles['backoffgrrr'] ) { this.add('-zbroken', target); return Math.floor(damage / 4); } return damage; }, category: "Physical", desc: "The user's HP is restored to maximum, and the user then faints. The target then takes damage equal to the amount of HP the user lost. This move does not check accuracy.", shortDesc: "Does damage equal to user's max HP. User faints.", name: "Blaze of Glory", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Recover", source); this.heal(source.maxhp, source, source, this.dex.getActiveMove('Blaze of Glory')); this.add('-anim', source, "Final Gambit", target); }, selfdestruct: "ifHit", isZ: "victiniumz", secondary: null, target: "normal", type: "Fire", }, // Marshmallon weatherforecast: { accuracy: true, basePower: 0, category: "Status", desc: "The user heals 1/4 of their HP rounded down, is protected from most attacks made by other Pokemon during this turn, and changes the weather. The selected weather depends on the current weather. Rain: Hail, Sun: Rain, Hail: Sun, Other: Randomly pick one of Rain, Sun, and Hail. This move has a 1/X chance of being successful, where X starts at 1 and triples each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, or Wide Guard, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.", shortDesc: "Protect + Heal 1/4 + change weather.", name: "Weather Forecast", isNonstandard: "Custom", pp: 10, priority: 2, flags: {heal: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Protect", source); this.add('-anim', source, "Quiver Dance", source); const result = !!this.queue.willAct() && this.runEvent('StallMove', source); return result; }, onHit(target, source) { let didSomething = false; switch (this.field.weather) { case 'raindance': if (this.field.setWeather('hail', source)) didSomething = true; break; case 'sunnyday': if (this.field.setWeather('raindance', source)) didSomething = true; break; case 'hail': if (this.field.setWeather('sunnyday', source)) didSomething = true; break; default: if (this.field.setWeather(['raindance', 'sunnyday', 'hail'][this.random(3)], source)) didSomething = true; } if (this.heal(source.baseMaxhp / 4, source)) didSomething = true; if (source.addVolatile('stall')) didSomething = true; if (source.addVolatile('protect')) didSomething = true; return didSomething; }, secondary: null, target: "self", type: "Normal", }, // martha crystalboost: { accuracy: 90, basePower: 75, category: "Special", desc: "Has a 50% chance to raise the user's Special Attack by one stage.", shortDesc: "50% chance to raise the user's SpA by 1.", name: "Crystal Boost", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Power Gem", target); }, secondary: { chance: 50, self: { boosts: { spa: 1, }, }, }, target: "normal", type: "Rock", }, // Marty typeanalysis: { accuracy: true, basePower: 0, category: "Status", desc: "If the user is a Silvally, its item becomes a random Memory whose type matches one of the target's weaknesses, it changes forme, and it uses Multi-Attack. This move and its effects ignore the abilities of other Pokemon. Fails if the target has no weaknesses or if the user's species is not Silvally.", shortDesc: "Changes user/move type to target's weakness.", name: "Type Analysis", isNonstandard: "Custom", pp: 10, priority: 0, flags: {authentic: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Conversion", source); }, onHit(target, source) { if (source.baseSpecies.baseSpecies !== 'Silvally') return false; let targetTypes = target.getTypes(true).filter(type => type !== '???'); if (!targetTypes.length) { if (target.addedType) { targetTypes = ['Normal']; } else { return false; } } const weaknesses = []; for (const type in this.dex.data.TypeChart) { const typeMod = this.dex.getEffectiveness(type, targetTypes); if (typeMod > 0 && this.dex.getImmunity(type, target)) weaknesses.push(type); } if (!weaknesses.length) { return false; } const randomType = this.sample(weaknesses); source.setItem(randomType + 'memory'); this.add('-item', source, source.getItem(), '[from] move: Type Analysis'); const species = this.dex.getSpecies('Silvally-' + randomType); source.formeChange(species, this.dex.getAbility('rkssystem'), true); const move = this.dex.getActiveMove('multiattack'); move.basePower = 80; this.useMove(move, source, target); }, secondary: null, target: "normal", type: "Normal", zMove: {effect: 'heal'}, }, // Meicoo scavengesu: { accuracy: true, basePower: 0, category: "Status", desc: "Lowers the user's Attack and Special Attack by two stages and then swaps all of its stat changes with the target.", shortDesc: "Atk/SpA -2, then swaps all stats with foe.", name: "/scavenges u", isNonstandard: "Custom", pp: 5, priority: 0, flags: {mirror: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Imprison", source); this.add('-anim', source, "Miracle Eye", target); }, onHit(target, source) { this.boost({atk: -2, spa: -2}, source, source, this.dex.getActiveMove('/scavenges u')); const targetBoosts: SparseBoostsTable = {}; const sourceBoosts: SparseBoostsTable = {}; let i: BoostName; for (i in target.boosts) { targetBoosts[i] = target.boosts[i]; sourceBoosts[i] = source.boosts[i]; } target.setBoost(sourceBoosts); source.setBoost(targetBoosts); this.add(`c|%Meicoo|cool quiz`); this.add('-swapboost', source, target, '[from] move: /scavenges u'); }, secondary: null, target: "normal", type: "Psychic", }, // Megazard tippingover: { accuracy: 100, basePower: 20, basePowerCallback(pokemon, target, move) { return move.basePower + 20 * pokemon.positiveBoosts(); }, category: "Physical", desc: "Base Power rises by 20 for each of the user's positive stat stage changes. The user loses any defensive boosts not from Stockpile.", shortDesc: "+20 BP per boost. Lose non-Stockpile +Def/SpD.", name: "Tipping Over", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, contact: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Dragon Hammer", target); this.add('-anim', target, "Earthquake", target); }, onAfterMoveSecondarySelf(pokemon) { let stockpileLayers = 0; if (pokemon.volatiles['stockpile']) stockpileLayers = pokemon.volatiles['stockpile'].layers; const boosts: SparseBoostsTable = {}; if (pokemon.boosts.def > stockpileLayers) boosts.def = stockpileLayers - pokemon.boosts.def; if (pokemon.boosts.spd > stockpileLayers) boosts.spd = stockpileLayers - pokemon.boosts.spd; if (boosts.def || boosts.spd) this.boost(boosts, pokemon, pokemon); }, secondary: null, target: "normal", type: "???", }, // Mitsuki pythonivy: { accuracy: 95, basePower: 110, category: "Special", desc: "Lowers the user's Special Attack, Special Defense, and Speed by one stage.", shortDesc: "Lowers the user's SpA, SpD, and Spe by 1.", name: "Python Ivy", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Leaf Tornado", target); this.add('-anim', source, "Leaf Storm", target); }, self: { boosts: { spa: -1, spd: -1, spe: -1, }, }, secondary: null, target: "normal", type: "Grass", }, // Morfent e: { accuracy: true, basePower: 0, category: "Status", desc: "If Trick Room is not already in play, sets Trick Room for 5 turns and raises the user's Attack by one stage.", shortDesc: "User Attack +1; sets Trick Room.", name: "E", isNonstandard: "Custom", pp: 5, priority: -6, onModifyMove(move) { if (!this.field.pseudoWeather.trickroom) { move.pseudoWeather = 'trickroom'; } }, flags: {snatch: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Recover", source); this.add('-anim', source, "Nasty Plot", source); }, boosts: { atk: 1, }, secondary: null, target: "self", type: "Ghost", }, // Used for nui's ability prismaticterrain: { accuracy: true, basePower: 0, category: "Status", desc: "For 5 turns, the terrain becomes Prismatic Terrain. During the effect, the power of Ice-type attacks is multiplied by 0.5, even if the user is not grounded. Hazards and screens are removed and cannot be set while Prismatic Terrain is active. Fails if the current terrain is Prismatic Terrain.", shortDesc: "5 turns. No hazards, -Ice power even if floating.", name: "Prismatic Terrain", isNonstandard: "Custom", pp: 10, priority: 0, flags: {}, terrain: 'prismaticterrain', condition: { duration: 5, durationCallback(source, effect) { if (source?.hasItem('terrainextender')) { return 8; } return 5; }, onBasePower(basePower, attacker, defender, move) { if (move.type === 'Ice') { this.debug('prismatic terrain weaken'); return this.chainModify(0.5); } }, onStart(battle, source, effect) { if (effect && effect.effectType === 'Ability') { this.add('-fieldstart', 'move: Prismatic Terrain', '[from] ability: ' + effect, '[of] ' + source); } else { this.add('-fieldstart', 'move: Prismatic Terrain'); } this.add('-message', 'The battlefield suddenly got a refractive high poly count!'); const removeAll = [ 'reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist', 'spikes', 'toxicspikes', 'stealthrock', 'stickyweb', ]; for (const sideCondition of removeAll) { if (source.side.foe.removeSideCondition(sideCondition)) { this.add('-sideend', source.side.foe, this.dex.getEffect(sideCondition).name, '[from] move: Prismatic Terrain', '[of] ' + source); } if (source.side.removeSideCondition(sideCondition)) { this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Prismatic Terrain', '[of] ' + source); } } }, onResidualOrder: 21, onResidualSubOrder: 2, onEnd() { this.add('-fieldend', 'move: Prismatic Terrain'); this.add('-message', 'The battlefield no longer has a refractive high poly count!'); }, }, secondary: null, target: "all", type: "Fairy", }, // nui pyramidingsong: { accuracy: 100, basePower: 0, category: "Status", desc: "If the target has not fainted, both the user and the target are forced to switch out and be replaced with a chosen unfainted ally. The target's replacement has its Speed lowered by 1 stage. Fails if either Pokemon is under the effect of Ingrain or Suction Cups.", shortDesc: "Both Pokemon switch. Opp. replacement: Spe -1.", name: "Pyramiding Song", isNonstandard: "Custom", pp: 20, priority: -6, flags: {mirror: 1, protect: 1, authentic: 1, sound: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Freeze Dry", target); this.add('-anim', source, "Mist", target); }, onTryHit(target, source, move) { target.side.addSlotCondition(target, 'pyramidingsong'); }, onHit(target, source, move) { if (this.runEvent('DragOut', source, target, move)) { source.forceSwitchFlag = true; } }, condition: { duration: 1, onSwitchIn(pokemon) { this.boost({spe: -1}, pokemon, pokemon.side.foe.active[0], this.dex.getActiveMove('pyramidingsong')); }, }, forceSwitch: true, secondary: null, target: "normal", type: "Water", zMove: {effect: "boostreplacement"}, }, // OM omboom: { accuracy: 95, basePower: 110, category: "Physical", desc: "Has a 50% chance to raise the user's Speed by two stages and a 5% chance to raise the user's Attack by one stage. Only one will ever activate on a single use", shortDesc: "50% chance of Spe +2 or 5% chance of Atk +1.", name: "OM Boom", isNonstandard: "Custom", pp: 15, priority: 0, flags: {mirror: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Fire Lash", target); this.add('-anim', source, "Heat Crash", target); }, onHit() { this.add(`c|@OM|Bang Bang`); }, secondary: { chance: 100, onHit(target, source) { if (this.random(2) === 0) { this.boost({spe: 2}, source); } else if (this.random(20) === 0) { this.boost({atk: 1}, source); } }, }, target: "normal", type: "Fire", }, // Overneat ultimateslash: { accuracy: 100, basePower: 80, category: "Physical", desc: "If this attack does not miss, the effects of Reflect, Light Screen, and Aurora Veil end for the target's side of the field before damage is calculated. If the user has not fainted, the target loses its held item.", shortDesc: "Destroys screens. Removes foe's item.", name: "Ultimate Slash", isNonstandard: "Custom", pp: 5, priority: 0, flags: {contact: 1, protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Night Slash", target); }, onTryHit(pokemon) { // will shatter screens through sub, before you hit if (pokemon.runImmunity('Dark')) { pokemon.side.removeSideCondition('reflect'); pokemon.side.removeSideCondition('lightscreen'); pokemon.side.removeSideCondition('auroraveil'); } }, onAfterHit(target, source) { if (source.hp) { const item = target.takeItem(); if (item) { this.add('-enditem', target, item.name, '[from] move: Ultimate Slash', '[of] ' + source); } } }, secondary: null, target: "normal", type: "Dark", }, // Pablo jailshell: { accuracy: 90, basePower: 90, category: "Special", desc: "This move has a 50% change to paralyze the target and prevents the target from switching out or using any moves that the user also knows while the user is active.", shortDesc: "50% chance to paralyze. Traps and imprisons.", name: "Jail Shell", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Anchor Shot", target); }, onHit(target, source, move) { if (source.isActive) target.addVolatile('trapped', source, move, 'trapper'); source.addVolatile('imprison', source, move); }, secondary: { chance: 50, status: 'par', }, target: "normal", type: "Normal", }, // Paradise corrosivetoxic: { accuracy: true, basePower: 0, category: "Status", desc: "Badly poisons the target, even if they are Poison-type or Steel-type. This move does not check accuracy.", shortDesc: "Badly poisons the target, regardless of type.", name: "Corrosive Toxic", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, reflectable: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Toxic", target); }, // Innate corrosive implemented in Scripts#setStatus status: 'tox', secondary: null, target: "normal", type: "Poison", }, // Pirate Princess teabreak: { accuracy: 100, basePower: 0, category: "Status", desc: "The user attempts to use Toxic followed by Venoshock, then Rest and Sleep Talk.", shortDesc: "Toxic -> Venoshock -> Rest -> Sleep Talk.", name: "Tea Break", pp: 5, priority: 0, flags: {protect: 1, authentic: 1}, sleepUsable: true, onTryMove(pokemon) { this.attrLastMove('[still]'); }, onHit(target, source) { this.useMove('Toxic', source, target); this.useMove('Venoshock', source, target); if (source.hp !== source.maxhp) this.useMove('Rest', source, source); if (source.status === 'slp' || source.hasAbility('comatose')) this.useMove('Sleep Talk', source, target); }, secondary: null, target: "normal", type: "Fairy", }, // Used for PiratePrincess's ability acidrain: { accuracy: true, basePower: 0, category: "Status", desc: "For 5 turns, the weather becomes Acid Rain. Pokemon that are not Poison-type take damage every turn. Special Defense of Poison-type pokemon is multiplied by 1.5.", shortDesc: "5 turns: +Poison SpD, corrosive damage.", name: "Acid Rain", isNonstandard: "Custom", pp: 5, priority: 0, flags: {}, weather: 'acidrain', onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Rain Dance', source); }, secondary: null, target: "all", type: "Poison", }, // pluviometer grammarhammer: { accuracy: 100, basePower: 90, category: "Special", desc: "100% chance to burn the target.", shortDesc: "100% chance to burn the target.", name: "Grammar Hammer", isNonstandard: "Custom", pp: 10, priority: 0, flags: {contact: 1, protect: 1, mirror: 1, punch: 1}, onPrepareHit(target, source) { this.attrLastMove('[still]'); this.add('-anim', source, "Hammer Arm", target); }, onHit(target, source) { if (target.name === 'HoeenHero') { this.add(`c|@pluviometer|HoennHero*`); this.add(`c|~HoeenHero|I can speel`); } }, secondary: { chance: 100, status: 'brn', }, target: "normal", type: "Ghost", }, // Pohjis greateqake: { accuracy: true, basePower: 200, category: "Physical", desc: "No additional effect.", shortDesc: "No additional effect.", name: "Great Eqake", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Tectonic Rage", target); }, isZ: "marowakiumz", secondary: null, target: "normal", type: "Ground", }, // pre refactor: { accuracy: true, basePower: 0, category: "Status", desc: "The user swaps all its stat stage changes with the target, then takes 1/4 of its maximum HP, rounded down, and puts it into a substitute to take its place in battle.", shortDesc: "Swaps all stat changes with target + Substitute.", name: "Refactor", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, authentic: 1, mystery: 1, snatch: 1, nonsky: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Skill Swap', target); }, onTryHit(target, source) { if (source.volatiles['substitute']) { this.add('-fail', source, 'move: Refactor'); return null; } if (source.hp <= source.maxhp / 4) { this.add('-fail', source, 'move: Refactor', '[weak]'); return null; } }, onHit(target, source) { const targetBoosts: SparseBoostsTable = {}; const sourceBoosts: SparseBoostsTable = {}; let i: BoostName; for (i in target.boosts) { targetBoosts[i] = target.boosts[i]; sourceBoosts[i] = source.boosts[i]; } target.setBoost(sourceBoosts); source.setBoost(targetBoosts); this.add('-swapboost', source, target, '[from] move: Refactor'); this.directDamage(source.maxhp / 4, source); }, self: { volatileStatus: 'substitute', }, secondary: null, target: "normal", type: "Psychic", }, // ptoad lilypadshield: { accuracy: true, basePower: 0, category: "Status", desc: "The user is protected from most moves made by other Pokemon during this turn, and if a Pokemon makes contact with the user, the user restores 1/4 of its maximum HP, rounded half up. This move has a 1/X chance of being successful, where X starts at 1 and doubles each time this move is successfully used. X resets to 1 if this move fails, if the user's last move used is not Baneful Bunker, Detect, Endure, King's Shield, Protect, Quick Guard, Spiky Shield, Wide Guard, or this move, or if it was one of those moves and the user's protection was broken. Fails if the user moves last this turn.", shortDesc: "Protects from moves. Contact: restores 25% HP.", name: "Lilypad Shield", isNonstandard: "Custom", pp: 10, priority: 4, flags: {heal: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Spiky Shield", source); }, stallingMove: true, volatileStatus: 'lilypadshield', onTryHit(target, source, move) { return !!this.queue.willAct() && this.runEvent('StallMove', target); }, onHit(pokemon) { pokemon.addVolatile('stall'); }, condition: { duration: 1, onStart(target) { this.add('-singleturn', target, 'move: Protect'); }, onTryHitPriority: 3, onTryHit(target, source, move) { if (!move.flags['protect']) { if (move.isZ || move.isMax) target.getMoveHitData(move).zBrokeProtect = true; return; } this.add('-activate', target, 'move: Protect'); const lockedmove = source.getVolatile('lockedmove'); if (lockedmove) { // Outrage counter is reset if (source.volatiles['lockedmove'].duration === 2) { delete source.volatiles['lockedmove']; } } if (move.flags['contact']) { this.heal(target.baseMaxhp / 4, target, target); } return null; }, onHit(target, source, move) { if (move.isZOrMaxPowered && move.flags['contact']) { this.heal(target.baseMaxhp / 4, target, target); } }, }, secondary: null, target: "self", type: "Grass", }, // Psynergy resolve: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Speed by one stage. Gives Focus Energy.", shortDesc: "Raises user's Speed by 1; Focus Energy.", name: "Resolve", isNonstandard: "Custom", pp: 10, priority: 0, flags: {snatch: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Acupressure", source); this.add('-anim', source, "Flare Blitz", source); }, onHit(target, source) { source.addVolatile('focusenergy', source); }, boosts: { spe: 1, }, target: "self", type: "Fighting", }, // Quite Quiet literallycheating: { accuracy: true, basePower: 0, category: "Status", desc: "For seven turns, any Pokemon that has one of their stats boosted through any manner loses all PP on the last move they used.", shortDesc: "7 turns: boosting stat: lose all PP from last move.", name: "Literally Cheating", isNonstandard: "Custom", pp: 5, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Genesis Supernova", source); }, pseudoWeather: 'literallycheating', condition: { duration: 7, onBoost(boost, target, source, effect) { let positiveBoost = false; const values = Object.values(boost); for (const i of values) { if (i !== undefined && i > 0) { positiveBoost = true; break; } } if (!positiveBoost || !target.lastMove) return; for (const moveSlot of target.moveSlots) { if (moveSlot.id === target.lastMove.id) { target.deductPP(moveSlot.id, moveSlot.pp); } } this.add('-activate', target, 'move: Literally Cheating', target.lastMove.name, target.lastMove.pp); this.add('-message', `${target.name} lost all PP for the move ${target.lastMove.name}!`); }, onStart(battle, source, effect) { this.add('-fieldstart', 'move: Literally Cheating'); }, onResidualOrder: 21, onResidualSubOrder: 2, onEnd() { this.add('-fieldend', 'move: Literally Cheating'); }, }, secondary: null, target: "all", type: "Ghost", }, // Rach stunner: { accuracy: 85, basePower: 95, category: "Physical", desc: "Has a 50% chance to raise the user's Attack by one stage and a 20% chance to paralyze the foe or cause them to flinch.", shortDesc: "50% user's Atk +1. 20% flinch or paralyze foe.", name: "Stunner", pp: 10, priority: 0, isNonstandard: "Custom", onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Zen Headbutt", target); }, flags: {protect: 1, mirror: 1, contact: 1}, secondaries: [ { chance: 50, self: { boosts: {atk: 1}, }, }, { chance: 20, onHit(target, source) { const result = this.random(2); if (result === 0) { target.trySetStatus('par', source); } else { target.addVolatile('flinch', source); } }, }, ], target: "normal", type: "Electric", }, // Rage rageeeee: { accuracy: 100, basePower: 40, category: "Physical", desc: "The user becomes affected with the effects of Rage and Endure. The opponent's next attack will hit 2 to 5 times with a Base Power of 25.", shortDesc: "Rage + Endure. Foe: next move 2-5 hits at 25 BP.", name: "Rageeeee", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, contact: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Rage", target); }, onHit(target, source) { source.addVolatile('rage', source); if (this.queue.willAct() && this.runEvent('StallMove', source)) { this.debug('Rageeeee endure'); source.addVolatile('endure', source); source.addVolatile('stall'); } target.addVolatile('enrageeeeed', source); }, secondary: null, target: "normal", type: "Flying", }, // Ransei mashupmotive: { accuracy: 100, basePower: 80, category: "Physical", desc: "Raises the user's accuracy by one stage. 50% chance to raise Attack by one stage.", shortDesc: "Accuracy +1. 50% chance to raise Atk by 1.", name: "Mashup Motive", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Revelation Dance", target); }, secondaries: [ { chance: 50, self: { boosts: {atk: 1}, }, }, { chance: 100, self: { boosts: {accuracy: 1}, }, }, ], target: "normal", type: "Normal", }, // Rory Mercury switchoff: { accuracy: 100, basePower: 60, category: "Physical", desc: "Before doing damage, the target's stat boosts are inverted. The user switches out after damaging the target.", shortDesc: "Inverts target's boosts, then switches.", name: "Switch Off", isNonstandard: "Custom", pp: 10, priority: 0, flags: {mirror: 1, protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Topsy-Turvy", target); this.add('-anim', source, "Zing Zap", target); }, onTryHit(target, source, move) { let success = false; let i: BoostName; for (i in target.boosts) { if (target.boosts[i] === 0) continue; target.boosts[i] = -target.boosts[i]; success = true; } if (!success) return; this.add('-invertboost', target, '[from] move: Switch Off'); }, selfSwitch: true, secondary: null, target: "normal", type: "Electric", }, // SamJo thicc: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Attack and accuracy by one stage.", shortDesc: "Raises the user's Attack and accuracy by 1.", name: "Thicc", isNonstandard: "Custom", pp: 15, priority: 0, flags: {snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Hone Claws", source); }, boosts: { atk: 1, accuracy: 1, }, secondary: null, target: "self", type: "Ice", }, // SamJo Z-Move extrathicc: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Attack and accuracy by one stage. Summons Hail and Aurora Veil.", shortDesc: "User's Atk and acc +1. Sets Hail and Aurora Veil.", name: "Extra T h i c c", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Hone Claws", source); this.add('-anim', source, "Extreme Evoboost", source); this.add('-anim', source, "Blizzard", source); }, onHit(target, source) { this.field.setWeather('hail'); if (this.field.isWeather('hail')) source.side.addSideCondition('auroraveil', source); this.add('-message', source.name + ' became extra thicc!'); }, boosts: { atk: 1, accuracy: 1, }, isZ: "thicciniumz", secondary: null, target: "self", type: "Ice", }, // Salamander expressyourself: { accuracy: true, basePower: 0, category: "Status", isNonstandard: "Custom", desc: "The user is healed for 50% of its HP. All Pokemon in the team's party get healed by 12.5% of their maximum HP.", shortDesc: "User heals 50% HP. User's team heals 12.5% HP.", name: "Express Yourself", pp: 5, priority: 0, flags: {snatch: 1, heal: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Tail Glow', source); this.add('-anim', source, 'Discharge', source); }, onHit(target, source) { this.heal(source.baseMaxhp / 2, source); if (!this.canSwitch(source.side)) return; for (const ally of source.side.pokemon) { if (ally === source) continue; if (ally.fainted || !ally.hp) continue; ally.heal(ally.baseMaxhp / 8, ally); } this.add('-message', `${source.name} restored everyone's HP.`); }, secondary: null, target: "self", type: "Fairy", }, // Schiavetto plurshift: { accuracy: 100, basePower: 120, category: "Physical", desc: "Has a 10% chance, calculated separately per effect, to apply any of Taunt, confusion, flinch, Heal Block, or Focus Energy to the target. Afterwards, the user is switched out for another Pokemon in its party. The selected Pokemon has the user's stat stage changes, confusion, and certain move effects transferred to it. ", shortDesc: "Multiple status effects, then uses Baton Pass.", name: "Plurshift", isNonstandard: "Custom", pp: 1, priority: 0, flags: {contact: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "First Impression", target); this.add('-anim', target, "Infestation", target); }, onHit(target, source) { source.addVolatile('batonpasshelper'); }, secondaries: [ { volatileStatus: "taunt", chance: 10, }, { volatileStatus: "confusion", chance: 10, }, { volatileStatus: "flinch", chance: 10, }, { volatileStatus: "healblock", chance: 10, }, { volatileStatus: "focusenergy", chance: 10, }, ], selfSwitch: 'copyvolatile', isZ: "mariahcariumz", target: "normal", type: "Poison", }, // Scotteh geomagneticstorm: { accuracy: 100, basePower: 140, category: "Special", desc: "No additional effect.", shortDesc: "No additional effect.", name: "Geomagnetic Storm", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Discharge", target); }, secondary: null, target: "allAdjacent", type: "Electric", }, // Shiba goinda: { accuracy: true, basePower: 0, category: "Status", desc: "Raises the user's Attack by two stages and Speed by one stage.", shortDesc: "Raises the user's Attack by 2 and Speed by 1.", name: "GO INDA", isNonstandard: "Custom", pp: 5, priority: 0, flags: {snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Swords Dance", source); this.add('-anim', source, "Sacred Fire", source); }, boosts: { atk: 2, spe: 1, }, target: "self", type: "Flying", }, // Slowbroth alienwave: { accuracy: true, basePower: 0, category: "Status", desc: "For 5 turns, slower Pokemon move first. Psychic-type attacks can hit if the target is a Dark-type.", shortDesc: "5 turns: Trick Room; Psychic hits Dark.", name: "Alien Wave", isNonstandard: "Custom", pp: 10, priority: -7, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Telekinesis", source); this.add('-anim', source, "Trick Room", source); }, pseudoWeather: 'alienwave', condition: { duration: 5, onStart(target, source) { this.add('-fieldstart', 'move: Alien Wave'); this.add('-message', `Psychic-type attacks can hit Dark-type Pokemon!`); }, onNegateImmunity(pokemon, type) { if (pokemon.hasType('Dark') && type === 'Psychic') return false; }, // Speed modification is changed in Pokemon.getActionSpeed() in mods/seasonal/scripts.js onResidualOrder: 23, onEnd() { this.add('-fieldend', 'move: Alien Wave'); this.add('-message', `Psychic-type attacks can no longer hit Dark-type Pokemon.`); }, }, secondary: null, target: "all", type: "Normal", }, // Snaquaza fakeclaim: { accuracy: true, category: "Physical", basePower: 1, desc: "The user creates a substitute to take its place in battle. This substitute is a Pokemon selected from a broad set of Random Battle-eligible Pokemon able to learn the move chosen as this move's base move. Upon the substitute's creation, this Pokemon's ability is suppressed until it switches out. The substitute Pokemon is generated with a Random Battle moveset with maximum PP that is added (except for duplicates) to the user's moveset; these additions are removed when this substitute is no longer active. The substitute uses its species's base stats, types, Ability, and weight but retains the user's max HP, stat stages, gender, level, status conditions, trapping, binding, and pseudo-statuses such as confusion. Its HP is 100% of the user's maximum HP. When this substitute falls to zero HP, it breaks, and the user reverts to the state in which it used this move. This substitute absorbs indirect damage and authentic moves but does not reset the counter of Toxic poison when broken and cannot be transferred through Baton Pass. Transforming into this substitute will not fail. If the user switches out while the substitute is up, the substitute will be removed and the user will revert to the state in which it used this move. This move's properties are based on the move Fake Claim is inheriting from.", shortDesc: "Uses a Random Battle Pokemon as a Substitute.", name: "Fake Claim", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onModifyMove(move) { move.type = move.baseMove ? this.dex.getMove(move.baseMove).type : move.type; // Hack for Snaquaza's Z move move.basePower = move.baseMove ? this.dex.getMove(move.baseMove).basePower : move.basePower; // Hack for Snaquaza's Z move move.category = move.baseMove ? this.dex.getMove(move.baseMove).category : move.category; // @ts-ignore Hack for Snaquaza's Z move this.claimMove = move.baseMove ? this.dex.getMove(move.baseMove) : this.dex.getMove('bravebird'); }, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source, move) { const zmove = this.dex.getMove(this.zMoveTable[move.type]); this.add('-anim', source, zmove.name, target); this.add('-anim', source, "Transform", source); }, onAfterMoveSecondarySelf(pokemon, move) { const claims: {[move: string]: string[]} = { bravebird: [ 'Braviary', 'Crobat', 'Decidueye', 'Dodrio', 'Farfetch\u2019d', 'Golbat', 'Mandibuzz', 'Pidgeot', 'Skarmory', 'Staraptor', 'Swanna', 'Swellow', 'Talonflame', 'Tapu Koko', 'Toucannon', ], superpower: [ 'Absol', 'Aggron', 'Armaldo', 'Avalugg', 'Azumarill', 'Barbaracle', 'Basculin', 'Beartic', 'Bewear', 'Bibarel', 'Bouffalant', 'Braviary', 'Breloom', 'Buzzwole', 'Cacturne', 'Carracosta', 'Celesteela', 'Chesnaught', 'Cobalion', 'Conkeldurr', 'Crabominable', 'Crawdaunt', 'Darmanitan', 'Diggersby', 'Donphan', 'Dragonite', 'Drampa', 'Druddigon', 'Durant', 'Eelektross', 'Emboar', 'Exeggutor-Alola', 'Feraligatr', 'Flareon', 'Flygon', 'Gigalith', 'Gogoat', 'Golem', 'Golurk', 'Goodra', 'Granbull', 'Gurdurr', 'Hariyama', 'Hawlucha', 'Haxorus', 'Heatmor', 'Hippowdon', 'Hitmonlee', 'Hydreigon', 'Incineroar', 'Kabutops', 'Keldeo', 'Kingler', 'Komala', 'Kommo-o', 'Krookodile', 'Landorus-Therian', 'Lurantis', 'Luxray', 'Machamp', 'Malamar', 'Mamoswine', 'Mew', 'Mudsdale', 'Nidoking', 'Nidoqueen', 'Pangoro', 'Passimian', 'Piloswine', 'Pinsir', 'Rampardos', 'Regice', 'Regigigas', 'Regirock', 'Registeel', 'Reuniclus', 'Rhydon', 'Rhyperior', 'Samurott', 'Sawk', 'Scizor', 'Scolipede', 'Simipour', 'Simisage', 'Simisear', 'Smeargle', 'Snorlax', 'Spinda', 'Stakataka', 'Stoutland', 'Swampert', 'Tapu Bulu', 'Terrakion', 'Throh', 'Thundurus', 'Torkoal', 'Tornadus', 'Torterra', 'Tyranitar', 'Tyrantrum', 'Ursaring', 'Virizion', 'Zeraora', ], suckerpunch: [ 'Absol', 'Arbok', 'Ariados', 'Banette', 'Bisharp', 'Cacturne', 'Celebi', 'Corsola', 'Decidueye', 'Delcatty', 'Drifblim', 'Druddigon', 'Dugtrio', 'Dusknoir', 'Electrode', 'Emboar', 'Froslass', 'Furfrou', 'Furret', 'Galvantula', 'Gengar', 'Girafarig', 'Golem', 'Golisopod', 'Heatmor', 'Hitmonlee', 'Hitmontop', 'Houndoom', 'Huntail', 'Kangaskhan', 'Kecleon', 'Komala', 'Lanturn', 'Latias', 'Liepard', 'Lycanroc', 'Maractus', 'Mawile', 'Meowstic', 'Mew', 'Mightyena', 'Mismagius', 'Nidoking', 'Nidoqueen', 'Purugly', 'Raticate', 'Rotom', 'Sableye', 'Seviper', 'Shiftry', 'Skuntank', 'Slaking', 'Smeargle', 'Spinda', 'Spiritomb', 'Stantler', 'Sudowoodo', 'Toxicroak', 'Umbreon', 'Victreebel', 'Wormadam', 'Xatu', ], flamethrower: [ 'Absol', 'Aerodactyl', 'Aggron', 'Altaria', 'Arcanine', 'Audino', 'Azelf', 'Bastiodon', 'Blacephalon', 'Blissey', 'Camerupt', 'Castform', 'Celesteela', 'Chandelure', 'Chansey', 'Charizard', 'Clefable', 'Clefairy', 'Darmanitan', 'Delphox', 'Dragonite', 'Drampa', 'Druddigon', 'Dunsparce', 'Eelektross', 'Electivire', 'Emboar', 'Entei', 'Exeggutor-Alola', 'Exploud', 'Flareon', 'Flygon', 'Furret', 'Garchomp', 'Golem', 'Goodra', 'Gourgeist', 'Granbull', 'Guzzlord', 'Gyarados', 'Heatmor', 'Heatran', 'Houndoom', 'Hydreigon', 'Incineroar', 'Infernape', 'Kangaskhan', 'Kecleon', 'Kommo-o', 'Lickilicky', 'Machamp', 'Magcargo', 'Magmortar', 'Malamar', 'Manectric', 'Marowak', 'Mawile', 'Mew', 'Moltres', 'Muk', 'Nidoking', 'Nidoqueen', 'Ninetales', 'Noivern', 'Octillery', 'Pyroar', 'Rampardos', 'Rapidash', 'Rhydon', 'Rhyperior', 'Salamence', 'Salazzle', 'Seviper', 'Silvally', 'Simisear', 'Skuntank', 'Slaking', 'Slowbro', 'Slowking', 'Slurpuff', 'Smeargle', 'Snorlax', 'Solrock', 'Talonflame', 'Tauros', 'Togekiss', 'Torkoal', 'Turtonator', 'Typhlosion', 'Tyranitar', 'Watchog', 'Weezing', 'Wigglytuff', 'Zangoose', ], thunderbolt: [ 'Absol', 'Aggron', 'Ambipom', 'Ampharos', 'Aromatisse', 'Audino', 'Aurorus', 'Azelf', 'Banette', 'Bastiodon', 'Beheeyem', 'Bibarel', 'Blissey', 'Castform', 'Chansey', 'Cinccino', 'Clefable', 'Clefairy', 'Dedenne', 'Delcatty', 'Dragalge', 'Dragonite', 'Drampa', 'Drifblim', 'Dunsparce', 'Eelektross', 'Electivire', 'Electrode', 'Emolga', 'Ferroseed', 'Ferrothorn', 'Froslass', 'Furret', 'Gallade', 'Galvantula', 'Garbodor', 'Gardevoir', 'Gengar', 'Girafarig', 'Golem-Alola', 'Golurk', 'Goodra', 'Gothitelle', 'Granbull', 'Gyarados', 'Heliolisk', 'Illumise', 'Jirachi', 'Jolteon', 'Kangaskhan', 'Kecleon', 'Klinklang', 'Lanturn', 'Lapras', 'Latias', 'Latios', 'Lickilicky', 'Linoone', 'Lopunny', 'Luxray', 'Magearna', 'Magmortar', 'Magneton', 'Magnezone', 'Malamar', 'Manectric', 'Marowak-Alola', 'Marowak-Alola-Totem', 'Meloetta', 'Meowstic', 'Mesprit', 'Mew', 'Miltank', 'Mimikyu', 'Minun', 'Mismagius', 'Mr. Mime', 'Muk', 'Nidoking', 'Nidoqueen', 'Nihilego', 'Oranguru', 'Pachirisu', 'Persian', 'Plusle', 'Porygon-Z', 'Porygon2', 'Primeape', 'Probopass', 'Purugly', 'Raichu', 'Raikou', 'Rampardos', 'Raticate', 'Regice', 'Regigigas', 'Regirock', 'Registeel', 'Rhydon', 'Rhyperior', 'Rotom', 'Silvally', 'Slaking', 'Slurpuff', 'Smeargle', 'Snorlax', 'Stantler', 'Starmie', 'Stoutland', 'Stunfisk', 'Tapu Koko', 'Tapu Lele', 'Tauros', 'Thundurus', 'Togedemaru', 'Tyranitar', 'Uxie', 'Vikavolt', 'Volbeat', 'Watchog', 'Weezing', 'Wigglytuff', 'Xurkitree', 'Zangoose', 'Zapdos', 'Zebstrika', 'Zeraora', ], icebeam: [ 'Abomasnow', 'Absol', 'Aggron', 'Alomomola', 'Altaria', 'Araquanid', 'Articuno', 'Audino', 'Aurorus', 'Avalugg', 'Azumarill', 'Barbaracle', 'Basculin', 'Bastiodon', 'Beartic', 'Bibarel', 'Blastoise', 'Blissey', 'Bruxish', 'Carracosta', 'Castform', 'Chansey', 'Clawitzer', 'Claydol', 'Clefable', 'Clefairy', 'Cloyster', 'Corsola', 'Crabominable', 'Crawdaunt', 'Cresselia', 'Cryogonal', 'Delcatty', 'Delibird', 'Dewgong', 'Dragonite', 'Drampa', 'Dunsparce', 'Dusknoir', 'Empoleon', 'Exploud', 'Feraligatr', 'Floatzel', 'Froslass', 'Furret', 'Gastrodon', 'Glaceon', 'Glalie', 'Golduck', 'Golisopod', 'Golurk', 'Goodra', 'Gorebyss', 'Greninja', 'Gyarados', 'Huntail', 'Jellicent', 'Jynx', 'Kabutops', 'Kangaskhan', 'Kecleon', 'Kingdra', 'Kingler', 'Kyurem', 'Lanturn', 'Lapras', 'Latias', 'Latios', 'Lickilicky', 'Linoone', 'Lopunny', 'Ludicolo', 'Lumineon', 'Lunatone', 'Luvdisc', 'Magearna', 'Mamoswine', 'Manaphy', 'Mantine', 'Marowak', 'Masquerain', 'Mawile', 'Mesprit', 'Mew', 'Milotic', 'Miltank', 'Nidoking', 'Nidoqueen', 'Ninetales-Alola', 'Octillery', 'Omastar', 'Pelipper', 'Phione', 'Piloswine', 'Politoed', 'Poliwrath', 'Porygon-Z', 'Porygon2', 'Primarina', 'Quagsire', 'Qwilfish', 'Rampardos', 'Raticate', 'Regice', 'Relicanth', 'Rhydon', 'Rhyperior', 'Samurott', 'Seaking', 'Sharpedo', 'Sigilyph', 'Silvally', 'Simipour', 'Slaking', 'Slowbro', 'Slowking', 'Smeargle', 'Sneasel', 'Snorlax', 'Starmie', 'Suicune', 'Swalot', 'Swampert', 'Swanna', 'Tapu Fini', 'Tauros', 'Tentacruel', 'Toxapex', 'Tyranitar', 'Vanilluxe', 'Vaporeon', 'Wailord', 'Walrein', 'Weavile', 'Whiscash', 'Wigglytuff', 'Wishiwashi', 'Zangoose', ], }; // @ts-ignore Hack for Snaquaza's Z move const baseMove = this.claimMove.id; const pool = claims[baseMove]; if (!pool) { // Should never happen throw new Error(`SSB: Unable to find fake claim movepool for the move: "${baseMove}".`); } const claim = claims[baseMove][this.random(pool.length)]; // Generate new set const generator = new RandomStaffBrosTeams('gen7randombattle', this.prng); const set = generator.randomSet(claim); // Suppress Ability now to prevent starting new abilities when transforming pokemon.addVolatile('gastroacid', pokemon); // Tranform into it pokemon.formeChange(set.species); for (const newMove of set.moves) { const moveSpecies = this.dex.getMove(newMove); if (pokemon.moves.includes(moveSpecies.id)) continue; pokemon.moveSlots.push({ move: moveSpecies.name, id: moveSpecies.id, pp: ((moveSpecies.noPPBoosts || moveSpecies.isZ) ? moveSpecies.pp : moveSpecies.pp * 8 / 5), maxpp: ((moveSpecies.noPPBoosts || moveSpecies.isZ) ? moveSpecies.pp : moveSpecies.pp * 8 / 5), target: moveSpecies.target, disabled: false, disabledSource: '', used: false, }); } // Update HP // Hack for Snaquaza's Z Move pokemon.m.claimHP = pokemon.hp; pokemon.heal(pokemon.maxhp - pokemon.hp, pokemon); this.add('-heal', pokemon, pokemon.getHealth, '[silent]'); this.add('message', `${pokemon.name} claims to be a ${set.species}!`); }, isZ: "fakeclaimiumz", secondary: null, target: "normal", type: "Dark", }, // sparksblade kratosmana: { accuracy: 100, basePower: 250, category: "Physical", desc: "The user faints after using this move, even if this move fails for having no target. Has a 10% chance to paralyze the target.", shortDesc: "The user faints. 10% chance to paralyze target.", name: "Kratosmana", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Explosion", target); this.add('-anim', source, "Searing Shot", target); this.add('-anim', target, "Poison Gas", target); }, selfdestruct: "always", secondary: { chance: 10, status: 'par', }, target: "normal", type: "Fire", }, // Sundar leafblaster: { accuracy: 100, basePower: 90, category: "Special", desc: "Lowers the user's accuracy by 2 stages.", shortDesc: "Lowers the user's accuracy by 2.", name: "Leaf Blaster", isNonstandard: "Custom", pp: 15, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Leaf Storm", target); }, self: { boosts: { accuracy: -2, }, }, secondary: null, target: "normal", type: "Grass", }, // Teclis absoluteconfiguration: { accuracy: true, basePower: 0, category: "Status", desc: "Puts the foe to sleep. Summons a Nightmare Field with the effects of Nightmare for 4 turns.", shortDesc: "Puts foe to sleep. Nightmare for 4 turns.", name: "Absolute Configuration", isNonstandard: "Custom", pp: 1, priority: 0, flags: {reflectable: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Dark Pulse', target); this.add('-anim', source, 'Dark Void', target); }, onHit(source) { this.field.addPseudoWeather('nightmarefield', source); }, status: 'slp', isZ: "darkrainiumz", target: "normal", type: "Dark", }, // Used for Teclis's z-move nightmarefield: { accuracy: true, basePower: 0, category: "Status", desc: "For 4 turns, Nightmare Field is active. During the effect, sleeping Pokemon suffer from the effects of Nightmare.", shortDesc: "4 turns. Sleeping Pokemon suffer Nightmare.", name: "Nightmare Field", isNonstandard: "Custom", pp: 10, priority: 0, flags: {}, pseudoWeather: 'nightmarefield', condition: { duration: 4, onStart(battle, source, effect) { if (effect && effect.effectType === 'Ability') { this.add('-fieldstart', 'move: Nightmare Field', '[from] ability: ' + effect, '[of] ' + source); } else { this.add('-fieldstart', 'move: Nightmare Field'); } }, onResidualOrder: 21, onResidualSubOrder: 2, onResidual() { for (const curMon of this.getAllActive()) { if (curMon.status === 'slp' || curMon.hasAbility('comatose')) { this.damage(curMon.baseMaxhp / 4, curMon); } } }, onEnd() { this.add('-fieldend', 'move: Nightmare Field'); }, }, secondary: null, target: "self", type: "Dark", }, // tennisace groundsurge: { accuracy: 100, basePower: 95, category: "Special", desc: "This move's type effectiveness against Ground is changed to be super effective no matter what this move's type is.", shortDesc: "Super effective on Ground.", name: "Ground Surge", isNonstandard: "Custom", pp: 15, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Thunder", target); this.add('-anim', source, "Fissure", target); }, ignoreImmunity: {Electric: true}, onEffectiveness(typeMod, target, type) { if (type === 'Ground') return 1; }, secondary: null, target: "normal", type: "Electric", }, // Teremiare rotate: { accuracy: 100, basePower: 0, category: "Status", desc: "The user's replacement will switch out at the end of next turn if the replacement's move is successful.", shortDesc: "User's replacement switches after using its move.", name: "Rotate", isNonstandard: "Custom", pp: 10, priority: 0, flags: {snatch: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Celebrate", target); }, sideCondition: "rotate", condition: { duration: 2, onStart(source) { this.add('-message', `${source.active[0].name}'s replacement is going to switch out next turn!`); }, onBeforeTurn(pokemon) { this.queue.insertChoice({choice: 'event', event: 'SSBRotate', pokemon: pokemon, priority: -69}); }, // @ts-ignore unsupported custom event onSSBRotate(pokemon: Pokemon) { // @ts-ignore Unsupported custom event, this is refering to a battle this.add('-message', `${pokemon.illusion ? pokemon.illusion.name : pokemon.name} is preparing to switch out!`); pokemon.switchFlag = true; }, }, selfSwitch: true, secondary: null, target: "self", type: "Normal", }, // The Immortal ultrasucc: { accuracy: true, basePower: 140, category: "Physical", desc: "Has a 100% chance to raise the user's Speed by one stage.", shortDesc: "100% chance to raise the user's Speed by 1.", name: "Ultra Succ", isNonstandard: "Custom", pp: 1, priority: 0, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Dragon Ascent", target); }, secondary: { chance: 100, self: { boosts: { spe: 1, }, }, }, isZ: "buzzniumz", target: "normal", type: "Fighting", }, // The Leprechaun gyroballin: { accuracy: 100, basePower: 0, basePowerCallback(pokemon, target) { let power = (Math.floor(25 * target.getStat('spe') / pokemon.getStat('spe')) || 1); if (power > 150) power = 150; this.debug('' + power + ' bp'); return power; }, category: "Physical", desc: "Base Power is equal to (25 * target's current Speed / user's current Speed) + 1, rounded down, but not more than 150. If the user's current Speed is 0, this move's power is 1. Summons Trick Room unless Trick Room is already active.", shortDesc: "More power if slower; sets Trick Room.", name: "Gyro Ballin'", isNonstandard: "Custom", pp: 5, priority: 0, flags: {bullet: 1, contact: 1, protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Gyro Ball", target); }, onAfterMoveSecondarySelf(pokemon) { if (!this.field.pseudoWeather.trickroom) { this.field.addPseudoWeather('trickroom', pokemon); } this.add('-fieldactivate', 'move: Pay Day'); // Coins are scattered on the ground }, secondary: null, target: "normal", type: "Steel", zMove: {basePower: 160}, contestType: "Cool", }, // Tony greed: { accuracy: true, basePower: 0, category: "Status", desc: "If there is no Stealth Rock on the foe's side of the field, sets Stealth Rock and one layer of Spikes. Otherwise, it sets two layers of Spikes.", shortDesc: "SR present: Spikes x2; otherwise: SR + Spikes.", name: "Greed", isNonstandard: "Custom", pp: 10, priority: 0, flags: {reflectable: 1, nosky: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { if (!target.side.sideConditions['stealthrock']) { this.add('-anim', source, "Stealth Rock", target); } else { this.add('-anim', source, "Spikes", target); } this.add('-anim', source, "Spikes", target); }, onHitSide(target, source) { if (!target.sideConditions['stealthrock']) { target.addSideCondition('stealthrock', source); } else { target.addSideCondition('spikes', source); } target.addSideCondition('spikes', source); }, secondary: null, target: "foeSide", type: "Ground", }, // torkool smokebomb: { accuracy: true, basePower: 0, category: "Status", desc: "Moves all hazards that are on the user's side of the field to the foe's side of the field. Sets Stealth Rock on the foe's side, after which the user switches out.", shortDesc: "Hazards -> foe side. Set SR. User switches out.", name: "Smoke Bomb", isNonstandard: "Custom", pp: 10, priority: 0, flags: {snatch: 1, mirror: 1, reflectable: 1, authentic: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Smokescreen", target); this.add('-anim', source, "Parting Shot", target); }, onHit(target, source) { const sideConditions = {spikes: 1, toxicspikes: 1, stealthrock: 1, stickyweb: 1}; for (const i in sideConditions) { let layers = source.side.sideConditions[i] ? (source.side.sideConditions[i].layers || 1) : 1; if (source.side.removeSideCondition(i)) { this.add('-sideend', source.side, this.dex.getEffect(i).name, '[from] move: Smoke Bomb', '[of] ' + source); for (layers; layers > 0; layers--) target.side.addSideCondition(i, source); } } target.side.addSideCondition('stealthrock'); }, selfSwitch: true, secondary: null, target: "normal", type: "Fire", }, // Trickster minisingularity: { accuracy: 55, basePower: 0, basePowerCallback(pokemon, target) { const targetWeight = target.getWeight(); if (targetWeight >= 2000) { this.debug('120 bp'); return 120; } if (targetWeight >= 1000) { this.debug('100 bp'); return 100; } if (targetWeight >= 500) { this.debug('80 bp'); return 80; } if (targetWeight >= 250) { this.debug('60 bp'); return 60; } if (targetWeight >= 100) { this.debug('40 bp'); return 40; } this.debug('20 bp'); return 20; }, category: "Special", desc: "This move's Base Power is 20 if the target weighs less than 10 kg, 40 if its weight is less than 25 kg, 60 if its weight is less than 50 kg, 80 if its weight is less than 100 kg, 100 if its weight is less than 200 kg, and 120 if its weight is greater than or equal to 200 kg. Before doing damage, the target's item is replaced with an Iron Ball, and the target's weight is doubled.", shortDesc: "BP:weight; +foe weight; foe item = Iron Ball.", name: "Mini Singularity", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Spacial Rend", target); this.add('-anim', source, "Flash", target); // Really feel like this could be done better (blocked by protect and alike moves.) if (!( target.volatiles['banefulbunker'] || target.volatiles['kingsshield'] || target.side.sideConditions['matblock'] || target.volatiles['protect'] || target.volatiles['spikyshield'] || target.volatiles['lilypadshield'] || target.volatiles['backoffgrrr'] )) { target.addVolatile('weightdoubler', source); const item = target.takeItem(); if (!target.item) { if (item) this.add('-enditem', target, item.name, '[from] move: Mini Singularity', '[of] ' + source); target.setItem('ironball'); this.add('-message', target.name + ' obtained an Iron Ball.'); } } }, secondary: null, target: "normal", type: "Psychic", }, // vivalospride ceilingsabsent: { accuracy: true, basePower: 0, category: "Status", desc: "Before the turn starts, this Pokemon uses Taunt against the foe. When this move hits, the user is healed by 50% of its max HP.", shortDesc: "Foe is Taunted; user heals 50% of Max HP.", name: "CEILINGS ABSENT", isNonstandard: "Custom", pp: 10, priority: 0, flags: {snatch: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Recover", source); }, beforeTurnCallback(pokemon) { if (pokemon.status === 'slp' || pokemon.status === 'frz') return; this.useMove("taunt", pokemon); }, onHit(source) { this.heal(source.baseMaxhp / 2, source); }, secondary: null, target: "self", type: "Normal", }, // Volco explosivedrain: { basePower: 90, accuracy: 100, category: "Special", desc: "The user recovers half the HP lost by the target, rounded half up. If Big Root is held, the user recovers 1.3x the normal amount of HP, rounded half down.", shortDesc: "User recovers 50% of the damage dealt.", name: "Explosive Drain", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, heal: 1}, drain: [1, 2], onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Fire Blast", target); this.add('-anim', source, "Giga Drain", target); }, secondary: null, target: "normal", type: "Fire", }, // Xayah feathersnare: { accuracy: 100, basePower: 95, category: "Special", desc: "Has a 20% chance to make the target flinch and a 50% chance to paralyze the target.", shortDesc: "20% to flinch; 50% to paralyze.", name: "Feather Snare", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Revelation Dance", source); this.add('-anim', source, "Air Slash", target); this.add('-anim', source, "Air Slash", target); }, secondaries: [ { chance: 20, volatileStatus: 'flinch', }, { chance: 50, status: 'par', }, ], zMove: {basePower: 175}, target: "normal", type: "Flying", }, // xfix glitzerpopping: { accuracy: true, basePower: 0, category: "Status", desc: "Uses 2-5 random moves. Does not include Z-Moves that have 1 Base Power or Glitzer Popping.", shortDesc: "Uses 2-5 random moves; avoids 1 BP Z-Moves.", name: "glitzer popping", isNonstandard: "Custom", pp: 3.14, noPPBoosts: true, priority: 0, flags: {}, onTryMove(pokemon) { this.attrLastMove('[still]'); const moveData = pokemon.getMoveData('glitzerpopping'); if (!moveData) return; // Lost 1 PP due to move usage, restore 0.9 PP to make it so that only 0.1 PP // would be used. moveData.pp = (Math.round(moveData.pp * 100) + 90) / 100; }, onPrepareHit(target, source) { this.add('-anim', source, "Metronome", source); }, onHit(target, source, effect) { const moves = []; for (const id in this.dex.data.Moves) { const move = this.dex.getMove(id); if (move.realMove || move.id === 'glitzerpopping') continue; // Calling 1 BP move is somewhat lame and disappointing. However, // signature Z moves are fine, as they actually have a base power. if (move.isZ && move.basePower === 1) continue; if (move.gen > this.gen) continue; moves.push(move.name); } if (!moves.length) return false; const randomMove = this.sample(moves); this.useMove(randomMove, target); }, multihit: [2, 5], secondary: null, target: "self", type: "???", }, // xJoelituh lavabone: { accuracy: 100, basePower: 130, category: "Physical", desc: "Has a 35% chance to burn the target.", shortDesc: "35% chance to burn the target.", name: "Lava Bone", isNonstandard: "Custom", pp: 5, priority: 0, flags: {protect: 1, mirror: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Shadow Bone", target); this.add('-anim', target, "Fire Blast", target); }, secondary: { chance: 35, status: 'brn', }, target: "normal", type: "Fire", }, // XpRienzo ☑◡☑ blehflame: { accuracy: 100, basePower: 130, category: "Special", desc: "No additional effect.", shortDesc: "Usually goes first.", name: "Bleh Flame", isNonstandard: "Custom", pp: 1, priority: 1, flags: {}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Focus Energy", source); this.add('-anim', source, "Fusion Flare", target); }, secondary: null, isZ: "charcoal", target: "normal", type: "Fire", }, // Yuki cutieescape: { accuracy: true, category: "Status", basePower: 0, desc: "The user is replaced with another Pokemon in its party. The foe is confused, trapped, and infatuated regardless of the replacement's gender. This move fails unless the user already took damage this turn.", shortDesc: "If hit; switches out + confuses, traps, infatuates.", name: "Cutie Escape", isNonstandard: "Custom", pp: 10, priority: -6, flags: {mirror: 1}, beforeTurnCallback(pokemon) { pokemon.addVolatile('cutieescape'); this.add('-message', `${pokemon.name} is preparing to flee!`); }, beforeMoveCallback(pokemon) { if (!pokemon.volatiles['cutieescape'] || !pokemon.volatiles['cutieescape'].tookDamage) { this.add('-fail', pokemon, 'move: Cutie Escape'); this.add('-hint', 'Cutie Escape only works when Yuki is hit in the same turn the move is used.'); return true; } }, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, "Baton Pass", source); }, onHit(target, source) { target.addVolatile('confusion'); target.addVolatile('cutietrap'); }, condition: { duration: 1, onStart(pokemon) { this.add('-singleturn', pokemon, 'move: Cutie Escape'); }, onHit(pokemon, source, move) { if (move.category !== 'Status') { pokemon.volatiles['cutieescape'].tookDamage = true; } }, }, secondary: null, selfSwitch: true, target: "normal", type: "Fairy", }, // Zalm twinweedle: { accuracy: 100, basePower: 40, multihit: 2, category: "Physical", desc: "Hits twice. Each hit has a 20% chance to poison the target and heals the user for 30% damage dealt. If one of the hits breaks the target's Substitute, it will take damage for the remaining hits.", shortDesc: "2 hits, 20% poison each, heals 30% of damage.", isNonstandard: "Custom", name: "TwinWeedle", pp: 25, noPPBoosts: true, priority: 0, flags: {protect: 1, mirror: 1, heal: 1}, onTryMove() { this.attrLastMove('[still]'); }, onPrepareHit(target, source) { this.add('-anim', source, 'Poison Sting', target); }, drain: [3, 10], secondary: { chance: 20, status: 'psn', }, target: "normal", type: "Poison", }, // Zarel relicsongdance: { accuracy: 100, basePower: 60, multihit: 2, category: "Special", desc: "Hits twice and ignores type immunities. Before the second hit, the user switches to its Pirouette forme, and this move's second hit deals physical Fighting-type damage. After the second hit, the user reverts to its Aria forme. Fails unless the user is Meloetta.", shortDesc: "Attacks in Aria forme, then in Pirouette forme.", name: "Relic Song Dance", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1, mirror: 1, sound: 1, authentic: 1}, ignoreImmunity: true, onTryMove() { this.attrLastMove('[still]'); }, onTryHit(target, pokemon) { if (pokemon.name !== 'Zarel') { this.add('-fail', pokemon); this.hint("Only Zarel can use Relic Song Dance."); return null; } this.attrLastMove('[still]'); const move = pokemon.species.id === 'meloettapirouette' ? 'Brick Break' : 'Relic Song'; this.add('-anim', pokemon, move, target); }, onHit(target, pokemon, move) { if (pokemon.species.id === 'meloettapirouette') { pokemon.formeChange('Meloetta'); } else if (pokemon.formeChange('Meloetta-Pirouette')) { move.category = 'Physical'; move.type = 'Fighting'; } }, onAfterMove(pokemon) { // Ensure Meloetta goes back to standard form after using the move if (pokemon.species.id === 'meloettapirouette') { pokemon.formeChange('Meloetta'); } this.hint("Zarel still has the Serene Grace ability."); }, condition: { duration: 1, onAfterMoveSecondarySelf(pokemon, target, move) { if (pokemon.species.id === 'meloettapirouette') { pokemon.formeChange('Meloetta'); } else { pokemon.formeChange('Meloetta-Pirouette'); } pokemon.removeVolatile('relicsong'); }, }, secondary: null, target: "allAdjacentFoes", type: "Psychic", }, // Zyg thelifeofzyg: { accuracy: 100, basePower: 0, category: "Status", desc: "Both the user and target are badly poisoned.", shortDesc: "Badly poisons the user and target.", name: "The Life of Zyg", isNonstandard: "Custom", pp: 10, priority: 0, flags: {protect: 1}, onTryMove() { this.attrLastMove('[still]'); }, onTryHit(target, source) { this.add('-anim', source, "Toxic", source); this.add('-anim', source, "Toxic", target); }, onHit(target, source) { source.trySetStatus('tox'); target.trySetStatus('tox'); }, secondary: null, target: "normal", type: "Poison", }, // Modded Sleep Talk for pirate princess sleeptalk: { inherit: true, onHit(pokemon) { const moves = []; for (const moveSlot of pokemon.moveSlots) { const move = this.dex.getMove(moveSlot.id); const noSleepTalk = [ 'assist', 'beakblast', 'belch', 'bide', 'celebrate', 'chatter', 'copycat', 'focuspunch', 'mefirst', 'metronome', 'mimic', 'mirrormove', 'naturepower', 'shelltrap', 'sketch', 'sleeptalk', 'uproar', 'teabreak', 'glitzerpopping', // Modded banlist ]; if (noSleepTalk.includes(move.id) || move.flags['charge'] || (move.isZ && move.basePower !== 1)) { continue; } moves.push(move.id); } let randomMove = ''; if (moves.length) randomMove = this.sample(moves); if (!randomMove) { return false; } this.useMove(randomMove, pokemon); }, }, };