LTDV10/packet/showdown/data/mods/vaporemons/moves.js
2026-04-14 18:20:56 +08:00

3188 lines
91 KiB
JavaScript

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var moves_exports = {};
__export(moves_exports, {
Moves: () => Moves
});
module.exports = __toCommonJS(moves_exports);
const Moves = {
direclaw: {
shortDesc: "Sets a layer of Toxic Spikes.",
num: -1005,
accuracy: 100,
basePower: 65,
category: "Physical",
name: "Dire Claw",
desc: "Sets a layer of Toxic Spikes on the opponent's side of the field.",
pp: 15,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
onAfterHit(target, source, move) {
if (!move.hasSheerForce && source.hp && !target.hasItem("covertcloak")) {
for (const side of source.side.foeSidesWithConditions()) {
side.addSideCondition("toxicspikes");
}
}
},
onAfterSubDamage(damage, target, source, move) {
if (!move.hasSheerForce && source.hp && !target.hasItem("covertcloak")) {
for (const side of source.side.foeSidesWithConditions()) {
side.addSideCondition("toxicspikes");
}
}
},
secondary: {},
target: "normal",
type: "Poison",
contestType: "Clever"
},
ceaselessedge: {
num: 845,
accuracy: 100,
basePower: 65,
category: "Physical",
shortDesc: "Sets a layer of Spikes on the opposing side.",
name: "Ceaseless Edge",
pp: 15,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, slicing: 1 },
onAfterHit(target, source, move) {
if (!move.hasSheerForce && source.hp && !target.hasItem("covertcloak")) {
for (const side of source.side.foeSidesWithConditions()) {
side.addSideCondition("spikes");
}
}
},
onAfterSubDamage(damage, target, source, move) {
if (!move.hasSheerForce && source.hp && !target.hasItem("covertcloak")) {
for (const side of source.side.foeSidesWithConditions()) {
side.addSideCondition("spikes");
}
}
},
secondary: {},
target: "normal",
type: "Dark"
},
stoneaxe: {
num: 830,
accuracy: 100,
basePower: 65,
category: "Physical",
name: "Stone Axe",
desc: "If this move is successful, it sets up a hazard on the opposing side of the field, damaging each opposing Pokemon that switches in. Foes lose 1/32, 1/16, 1/8, 1/4, or 1/2 of their maximum HP, rounded down, based on their weakness to the Rock type; 0.25x, 0.5x, neutral, 2x, or 4x, respectively. Can be removed from the opposing side if any opposing Pokemon uses Rapid Spin or Defog successfully, or is hit by Defog.",
shortDesc: "Sets Stealth Rock on the target's side.",
pp: 15,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, slicing: 1 },
secondary: {
chance: 100,
sideCondition: "stealthrock"
},
target: "adjacentFoe",
type: "Rock",
contestType: "Tough"
},
electroweb: {
num: 527,
accuracy: 95,
basePower: 65,
category: "Special",
shortDesc: "Sets Sticky Web on the target's side.",
name: "Electroweb",
pp: 15,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
secondary: {
chance: 100,
sideCondition: "stickyweb"
},
target: "allAdjacentFoes",
type: "Electric",
contestType: "Beautiful"
},
skullbash: {
num: 130,
accuracy: 90,
basePower: 120,
category: "Physical",
shortDesc: "Raises user's Atk by 1 on turn 1. Hits turn 2.",
isNonstandard: null,
name: "Skull Bash",
pp: 10,
priority: 0,
flags: { contact: 1, charge: 1, protect: 1, mirror: 1, metronome: 1 },
onTryMove(attacker, defender, move) {
if (attacker.removeVolatile(move.id)) {
return;
}
this.add("-prepare", attacker, move.name);
this.boost({ atk: 1 }, attacker, attacker, move);
if (!this.runEvent("ChargeMove", attacker, defender, move)) {
return;
}
attacker.addVolatile("twoturnmove", defender);
return null;
},
secondary: null,
target: "normal",
type: "Steel",
contestType: "Tough"
},
shelter: {
num: 842,
accuracy: true,
basePower: 0,
category: "Status",
shortDesc: "Removes Spikes and Stealth Rock from the field. +1 Def for every type of hazard cleared.",
name: "Shelter",
pp: 10,
priority: 0,
flags: { snatch: 1, metronome: 1 },
onHit(pokemon) {
const somesideConditions = ["spikes", "stealthrock"];
const sides = [pokemon.side];
for (const side of sides) {
for (const sideCondition of somesideConditions) {
if (sideCondition) {
this.add("-message", `This sides Stealth Rock and Spikes will be removed!`);
}
if (side.removeSideCondition("spikes")) {
this.add("-sideend", side, this.dex.conditions.get("spikes"));
this.boost({ def: 1 }, pokemon);
}
if (side.removeSideCondition("stealthrock")) {
this.add("-sideend", side, this.dex.conditions.get("stealthrock"));
this.boost({ def: 1 }, pokemon);
}
}
}
},
secondary: null,
target: "self",
type: "Steel"
},
healingstones: {
num: -191,
accuracy: true,
basePower: 0,
category: "Status",
desc: "Sets healing stones on the user's side, healing Pokemon that switch in for 1/8th of their max HP.",
shortDesc: "Heals allies on switch-in.",
name: "Healing Stones",
pp: 20,
priority: 0,
flags: { snatch: 1, heal: 1, nonsky: 1, metronome: 1 },
sideCondition: "healingstones",
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Stealth Rock", target);
},
condition: {
onSideStart(side) {
this.add("-sidestart", side, "Healing Stones");
this.effectState.layers = 1;
},
onSideRestart(side) {
if (this.effectState.layers >= 1)
return false;
this.add("-sidestart", side, "Healing Stones");
this.effectState.layers++;
},
onEntryHazard(pokemon) {
if (pokemon.hasItem("heavydutyboots") || pokemon.hasAbility("overcoat") || pokemon.hasItem("mantisclaw"))
return;
const healAmounts = [0, 3];
this.heal(healAmounts[this.effectState.layers] * pokemon.maxhp / 24);
}
},
secondary: null,
target: "allySide",
type: "Fairy",
contestType: "Clever"
},
junglehealing: {
num: 816,
accuracy: true,
basePower: 0,
category: "Status",
shortDesc: "User and allies: healed 1/3 max HP, status cured.",
name: "Jungle Healing",
pp: 10,
priority: 0,
flags: { heal: 1, bypasssub: 1, allyanim: 1 },
onHit(pokemon) {
const success = !!this.heal(this.modify(pokemon.maxhp, 0.33));
return pokemon.cureStatus() || success;
},
secondary: null,
target: "allies",
type: "Grass"
},
lifedew: {
num: 791,
accuracy: true,
basePower: 0,
category: "Status",
shortDesc: "User: healed 1/3 max HP. Next switch-in: healed 1/4 max HP.",
name: "Life Dew",
pp: 10,
priority: 0,
flags: { snatch: 1, heal: 1, bypasssub: 1 },
heal: [1, 3],
slotCondition: "lifedew",
condition: {
onSwap(target) {
if (!target.fainted) {
const source = this.effectState.source;
const damage = this.heal(target.baseMaxhp / 4, target, target);
if (damage)
this.add("-heal", target, target.getHealth, "[from] move: Life Dew", "[of] " + source);
target.side.removeSlotCondition(target, "lifedew");
}
}
},
secondary: null,
target: "self",
type: "Water"
},
shrapnelshot: {
accuracy: 90,
basePower: 15,
category: "Physical",
shortDesc: "Hits 2-5 times. First hit lowers the foe's Defense by 1 stage.",
name: "Shrapnel Shot",
pp: 20,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1, bullet: 1 },
multihit: [2, 5],
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Spikes", target);
},
secondary: {
chance: 100,
onHit(target, source, move) {
if (move.hit < 2) {
this.boost({ def: -1 }, target);
}
return false;
}
},
target: "normal",
type: "Steel",
zMove: { basePower: 140 },
maxMove: { basePower: 130 },
contestType: "Cool"
},
stormthrow: {
num: 480,
accuracy: true,
basePower: 70,
category: "Physical",
isNonstandard: null,
name: "Storm Throw",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
willCrit: true,
secondary: null,
target: "normal",
type: "Fighting",
contestType: "Cool"
},
frostbreath: {
num: 524,
accuracy: true,
basePower: 70,
category: "Special",
name: "Frost Breath",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
willCrit: true,
secondary: null,
target: "normal",
type: "Ice",
contestType: "Beautiful"
},
snipeshot: {
num: 745,
accuracy: true,
basePower: 70,
category: "Special",
shortDesc: "Always critically hits.",
name: "Snipe Shot",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1, pulse: 1 },
willCrit: true,
tracksTarget: true,
secondary: null,
target: "normal",
type: "Water"
},
falsesurrender: {
num: 793,
accuracy: true,
basePower: 70,
category: "Physical",
shortDesc: "Always critically hits.",
name: "False Surrender",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1 },
willCrit: true,
secondary: null,
target: "normal",
type: "Dark"
},
choke: {
accuracy: 100,
basePower: 80,
category: "Physical",
shortDesc: "Inflicts the Heal Block effect.",
name: "Choke",
pp: 15,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Sky Uppercut", target);
this.add("-anim", source, "Hex", target);
},
secondary: {
chance: 100,
onHit(target) {
target.addVolatile("healblock");
}
},
target: "normal",
type: "Ghost",
contestType: "Clever"
},
cuttingremark: {
accuracy: 100,
basePower: 40,
category: "Physical",
overrideDefensiveStat: "spd",
shortDesc: "Usually goes first. Targets the foe's Special Defense.",
name: "Cutting Remark",
pp: 25,
priority: 1,
flags: { protect: 1, mirror: 1, sound: 1, bypasssub: 1, metronome: 1, slicing: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Psycho Cut", target);
},
self: {
sideCondition: "echochamber"
},
secondary: null,
target: "normal",
type: "Psychic",
contestType: "Cool"
},
chainlightning: {
accuracy: 100,
basePower: 15,
category: "Physical",
shortDesc: "Usually goes first. Hits 2-5 times.",
name: "Chain Lightning",
pp: 20,
priority: 1,
flags: { protect: 1, mirror: 1, metronome: 1 },
multihit: [2, 5],
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Thunder Shock", target);
},
secondary: null,
target: "normal",
type: "Electric",
contestType: "Cool"
},
pluck: {
num: 365,
accuracy: 100,
basePower: 70,
category: "Physical",
shortDesc: "Heals the user by 75% of the damage dealt.",
name: "Pluck",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, heal: 1, metronome: 1 },
drain: [3, 4],
secondary: null,
target: "normal",
type: "Flying",
contestType: "Cute"
},
throatchop: {
num: 675,
accuracy: 100,
basePower: 85,
category: "Physical",
shortDesc: "Foe can't use Sound moves or Yawn for 3 turns.",
name: "Throat Chop",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
condition: {
duration: 3,
onStart(target) {
this.add("-start", target, "Throat Chop", "[silent]");
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.dex.moves.get(moveSlot.id).flags["sound"]) {
pokemon.disableMove(moveSlot.id);
}
}
},
onBeforeMovePriority: 6,
onBeforeMove(pokemon, target, move) {
if (!move.isZ && !move.isMax && (move.flags["sound"] || move.id === "yawn")) {
this.add("cant", pokemon, "move: Throat Chop");
return false;
}
},
onResidualOrder: 22,
onEnd(target) {
this.add("-end", target, "Throat Chop", "[silent]");
}
},
secondary: {
chance: 100,
onHit(target) {
target.addVolatile("throatchop");
}
},
target: "normal",
type: "Dark",
contestType: "Clever"
},
windbreaker: {
accuracy: 100,
basePower: 85,
category: "Special",
shortDesc: "Foe can't use Wind moves for 3 turns.",
name: "Wind Breaker",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1, wind: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Gust", target);
},
condition: {
duration: 3,
onStart(target) {
this.add("-start", target, "Wind Breaker", "[silent]");
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.dex.moves.get(moveSlot.id).flags["wind"]) {
pokemon.disableMove(moveSlot.id);
}
}
},
onBeforeMovePriority: 6,
onBeforeMove(pokemon, target, move) {
if (!move.isZ && !move.isMax && move.flags["wind"]) {
this.add("cant", pokemon, "move: Wind Breaker");
return false;
}
},
onResidualOrder: 22,
onEnd(target) {
this.add("-end", target, "Wind Breaker", "[silent]");
}
},
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
},
secondary: {
chance: 100,
onHit(target) {
target.addVolatile("windbreaker");
}
},
target: "normal",
type: "Flying",
contestType: "Clever"
},
hazardouswaste: {
accuracy: 100,
basePower: 50,
basePowerCallback(pokemon, target, move) {
const yourSide = pokemon.side;
const targetSide = target.side;
let allLayers = 0;
if (yourSide.getSideCondition("stealthrock"))
allLayers++;
if (yourSide.getSideCondition("healingstones"))
allLayers++;
if (yourSide.getSideCondition("stickyweb"))
allLayers++;
if (yourSide.sideConditions["spikes"]) {
allLayers += yourSide.sideConditions["spikes"].layers;
}
if (yourSide.sideConditions["toxicspikes"]) {
allLayers += yourSide.sideConditions["toxicspikes"].layers;
}
if (targetSide.getSideCondition("stealthrock"))
allLayers++;
if (targetSide.getSideCondition("healingstones"))
allLayers++;
if (targetSide.getSideCondition("stickyweb"))
allLayers++;
if (targetSide.sideConditions["spikes"]) {
allLayers += targetSide.sideConditions["spikes"].layers;
}
if (targetSide.sideConditions["toxicspikes"]) {
allLayers += targetSide.sideConditions["toxicspikes"].layers;
}
this.debug("Hazardous Waste damage boost");
return Math.min(400, 50 + 50 * allLayers);
},
category: "Physical",
shortDesc: "+50 power for each hazard layer on the field. Caps at 400.",
name: "Hazardous Waste",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Acid Downpour", target);
},
onHit(target, source, move) {
const yourSide = source.side;
const targetSide = target.side;
let allLayers = 0;
if (yourSide.getSideCondition("stealthrock"))
allLayers++;
if (yourSide.getSideCondition("healingstones"))
allLayers++;
if (yourSide.getSideCondition("stickyweb"))
allLayers++;
if (yourSide.sideConditions["spikes"]) {
allLayers += yourSide.sideConditions["spikes"].layers;
}
if (yourSide.sideConditions["toxicspikes"]) {
allLayers += yourSide.sideConditions["toxicspikes"].layers;
}
if (targetSide.getSideCondition("stealthrock"))
allLayers++;
if (targetSide.getSideCondition("healingstones"))
allLayers++;
if (targetSide.getSideCondition("stickyweb"))
allLayers++;
if (targetSide.sideConditions["spikes"]) {
allLayers += targetSide.sideConditions["spikes"].layers;
}
if (targetSide.sideConditions["toxicspikes"]) {
allLayers += targetSide.sideConditions["toxicspikes"].layers;
}
const bp = Math.min(400, 50 + 50 * allLayers);
this.add("-message", `Hazardous Waste currently has a BP of ${bp}!`);
},
secondary: null,
target: "normal",
type: "Poison",
contestType: "Tough"
},
chisel: {
accuracy: 100,
basePower: 45,
category: "Physical",
shortDesc: "Gives the foe a Substitute, then hits 4 times.",
name: "Chisel",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
multihit: 4,
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Salt Cure", target);
target.addVolatile("substitute");
this.add("-anim", source, "Stone Axe", target);
},
secondary: null,
target: "normal",
type: "Rock",
contestType: "Cool"
},
peekaboo: {
accuracy: 100,
basePower: 140,
category: "Physical",
shortDesc: "Deal halved damage if the user takes damage before it hits.",
name: "Peekaboo",
pp: 20,
priority: -3,
flags: {
contact: 1,
protect: 1,
metronome: 1,
failmefirst: 1,
nosleeptalk: 1,
noassist: 1,
failcopycat: 1,
failinstruct: 1
},
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Heart Stamp", target);
},
priorityChargeCallback(pokemon) {
pokemon.addVolatile("peekaboo");
},
condition: {
duration: 1,
onStart(pokemon) {
this.add("-singleturn", pokemon, "move: Peekaboo");
},
onHit(pokemon, source, move) {
if (move.category !== "Status") {
this.effectState.lostSurprise = true;
}
},
onBasePower(basePower, pokemon) {
if (pokemon.volatiles["peekaboo"]?.lostSurprise) {
this.debug("halved power");
return this.chainModify(0.5);
}
}
},
secondary: null,
target: "normal",
type: "Fairy",
contestType: "Tough"
},
psychoboost: {
num: 354,
accuracy: 100,
basePower: 120,
shortDesc: "Lowers the user's Sp. Atk by 1. Hits foe(s).",
category: "Special",
isNonstandard: null,
name: "Psycho Boost",
pp: 5,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
self: {
boosts: {
spa: -1
}
},
secondary: null,
target: "allAdjacentFoes",
type: "Psychic",
contestType: "Clever"
},
ragefist: {
num: 889,
accuracy: 100,
basePower: 50,
basePowerCallback(pokemon) {
return Math.min(200, 50 + 50 * pokemon.timesAttacked);
},
shortDesc: "+50 power for each time user was hit. Max 3 hits.",
category: "Physical",
name: "Rage Fist",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, punch: 1 },
onHit(target, source, move) {
const bp = Math.min(200, 50 + 50 * source.timesAttacked);
this.add("-message", `Rage Fist currently has a BP of ${bp}!`);
},
secondary: null,
target: "normal",
type: "Ghost"
},
ragingfury: {
num: 833,
accuracy: 100,
basePower: 50,
basePowerCallback(pokemon) {
return Math.min(200, 50 + 50 * pokemon.timesAttacked);
},
shortDesc: "+50 power for each time user was hit. Max 3 hits.",
category: "Physical",
name: "Raging Fury",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1 },
onHit(target, source, move) {
const bp = Math.min(200, 50 + 50 * source.timesAttacked);
this.add("-message", `Raging Fury currently has a BP of ${bp}!`);
},
secondary: null,
target: "normal",
type: "Fire"
},
parry: {
accuracy: 100,
basePower: 80,
category: "Physical",
shortDesc: "If the foe used a priority move, this move hits before that move and flinches the foe.",
name: "Parry",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Mach Punch", target);
},
priorityChargeCallback(pokemon) {
this.add("-anim", pokemon, "Imprison", pokemon);
this.add("-message", `${pokemon.name} is attempting to parry!`);
pokemon.addVolatile("parry");
},
secondary: {},
// sheer force boosted
condition: {
duration: 1,
onStart(target, source) {
this.add("-singleturn", source, "Parry");
},
onFoeTryMove(target, source, move) {
const targetAllExceptions = ["perishsong", "flowershield", "rototiller"];
if (move.target === "foeSide" || move.target === "all" && !targetAllExceptions.includes(move.id)) {
return;
}
const parryHolder = this.effectState.target;
if ((source.isAlly(parryHolder) || move.target === "all") && (!source.hasAbility("innerfocus") || !source.hasAbility("shielddust") || !source.hasAbility("steadfast") || !source.hasItem("covertcloak") || !source.hasAbility("sandveil") && !this.field.isWeather("sandstorm") || !source.hasAbility("sunblock") && !this.field.isWeather("sunnyday") || !source.hasAbility("snowcloak") && !this.field.isWeather("snow")) && move.priority > 0.1) {
this.attrLastMove("[still]");
this.add("cant", parryHolder, "move: Parry", move, "[of] " + target);
return false;
}
}
},
target: "normal",
type: "Fighting",
contestType: "Clever"
},
rollout: {
num: 205,
accuracy: 100,
basePower: 50,
basePowerCallback(pokemon, target, move) {
if (pokemon.volatiles["defensecurl"]) {
this.debug("BP doubled");
return move.basePower * 2;
}
return move.basePower;
},
category: "Physical",
shortDesc: "Switches the user out. 2x power if Rollout or Defense Curl was used last turn.",
name: "Rollout",
pp: 15,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, failinstruct: 1, noparentalbond: 1 },
self: {
sideCondition: "rollout"
},
selfSwitch: true,
condition: {
duration: 2,
onBasePowerPriority: 1,
onBasePower(basePower, attacker, defender, move) {
if (move.id === "rollout" && !attacker.volatiles["defensecurl"]) {
return this.chainModify(2);
}
}
},
secondary: null,
target: "normal",
type: "Rock",
contestType: "Cute"
},
round: {
num: 496,
accuracy: 100,
basePower: 50,
category: "Special",
shortDesc: "Switches the user out. 2x power if Round was used last turn.",
name: "Round",
pp: 15,
priority: 0,
flags: { protect: 1, mirror: 1, sound: 1, bypasssub: 1, metronome: 1 },
self: {
sideCondition: "round"
},
selfSwitch: true,
condition: {
duration: 2,
onBasePowerPriority: 1,
onBasePower(basePower, attacker, defender, move) {
if (move.id === "round" || move.id === "echochamber") {
return this.chainModify(2);
}
}
},
secondary: null,
target: "normal",
type: "Normal",
contestType: "Beautiful"
},
rekindleheal: {
accuracy: true,
basePower: 0,
category: "Status",
shortDesc: "Healing from Rekindle.",
name: "Rekindle Heal",
pp: 5,
priority: 0,
flags: { metronome: 1 },
volatileStatus: "rekindleheal",
condition: {
onStart(pokemon) {
this.add("-start", pokemon, "Rekindle");
},
onResidualOrder: 6,
onResidual(pokemon) {
this.heal(pokemon.baseMaxhp / 8);
}
},
secondary: null,
target: "self",
type: "Fire"
},
rekindle: {
accuracy: true,
basePower: 0,
category: "Status",
shortDesc: "Heals 33% then 12.5% every turn. Burns foes that make contact.",
name: "Rekindle",
pp: 10,
priority: 0,
flags: { snatch: 1, heal: 1, metronome: 1 },
heal: [1, 3],
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Morning Sun", target);
},
self: {
onHit(pokemon, source, move) {
pokemon.addVolatile("rekindleheal");
pokemon.addVolatile("rekindle");
this.add("-message", `${pokemon.name}'s flames burn brightly!`);
}
},
condition: {
duration: 1,
onDamagingHit(damage, target, source, move) {
if (this.checkMoveMakesContact(move, source, target)) {
source.trySetStatus("brn", target);
this.add("-message", `${target.name}'s flames burnt its attacker!`);
target.removeVolatile("rekindleheal");
this.add("-message", `${target.name}'s flames were put out!`);
}
}
},
secondary: null,
target: "all",
type: "Fire",
contestType: "Clever"
},
meteorbeam: {
num: 800,
accuracy: 90,
basePower: 120,
category: "Special",
shortDesc: "Raises user's Sp. Atk by 1 on turn 1. Hits turn 2. Hits in 1 turn in Sand.",
name: "Meteor Beam",
pp: 10,
priority: 0,
flags: { charge: 1, protect: 1, mirror: 1, metronome: 1 },
onTryMove(attacker, defender, move) {
if (attacker.removeVolatile(move.id)) {
return;
}
this.add("-prepare", attacker, move.name);
this.boost({ spa: 1 }, attacker, attacker, move);
if (this.field.isWeather("sandstorm")) {
this.attrLastMove("[still]");
this.addMove("-anim", attacker, move.name, defender);
return;
}
if (!this.runEvent("ChargeMove", attacker, defender, move)) {
return;
}
attacker.addVolatile("twoturnmove", defender);
return null;
},
secondary: null,
target: "normal",
type: "Rock"
},
rebuild: {
accuracy: true,
basePower: 0,
category: "Status",
shortDesc: "Restores HP equal to the user's level \xD7 1.25.",
name: "Rebuild",
pp: 10,
priority: 0,
flags: { snatch: 1, heal: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Iron Defense", target);
},
onHit(pokemon) {
this.heal(pokemon.level * 1.25);
},
secondary: null,
target: "self",
type: "Steel",
contestType: "Clever"
},
washaway: {
accuracy: 100,
basePower: 80,
category: "Special",
shortDesc: "Removes hazards and terrains, then forces out target.",
name: "Wash Away",
pp: 10,
priority: -6,
flags: { protect: 1, mirror: 1, metronome: 1, noassist: 1, failcopycat: 1 },
forceSwitch: true,
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Surf", target);
},
onHit(target, source, move) {
let success = false;
const removeTarget = [
"spikes",
"toxicspikes",
"stealthrock",
"stickyweb",
"gmaxsteelsurge",
"healingstones"
];
const removeAll = [
"spikes",
"toxicspikes",
"stealthrock",
"stickyweb",
"gmaxsteelsurge",
"healingstones"
];
for (const targetCondition of removeTarget) {
if (target.side.removeSideCondition(targetCondition)) {
if (!removeAll.includes(targetCondition))
continue;
this.add("-sideend", target.side, this.dex.conditions.get(targetCondition).name, "[from] move: Wash Away", "[of] " + source);
success = true;
}
}
for (const sideCondition of removeAll) {
if (source.side.removeSideCondition(sideCondition)) {
this.add("-sideend", source.side, this.dex.conditions.get(sideCondition).name, "[from] move: Wash Away", "[of] " + source);
success = true;
}
}
this.field.clearTerrain();
return success;
},
target: "normal",
type: "Water",
contestType: "Tough"
},
echochamber: {
accuracy: 100,
basePower: 90,
category: "Special",
shortDesc: "1.5x power if a sound move was used last turn.",
name: "Echo Chamber",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, sound: 1, bypasssub: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Hyper Voice", target);
},
self: {
sideCondition: "echochamber"
},
condition: {
duration: 2,
onBasePowerPriority: 1,
onBasePower(basePower, attacker, defender, move) {
if (move.id === "echochamber") {
return this.chainModify(1.5);
}
}
},
secondary: null,
target: "normal",
type: "Steel",
contestType: "Cool"
},
brickbreak: {
inherit: true,
basePower: 90
},
psychicfangs: {
inherit: true,
basePower: 90,
flags: { protect: 1, mirror: 1, metronome: 1, bite: 1 }
},
sledgehammerblow: {
accuracy: 100,
basePower: 90,
category: "Physical",
shortDesc: "Destroys screens, unless the target is immune.",
name: "Sledgehammer Blow",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Gigaton Hammer", target);
},
onTryHit(pokemon) {
pokemon.side.removeSideCondition("reflect");
pokemon.side.removeSideCondition("lightscreen");
pokemon.side.removeSideCondition("auroraveil");
},
secondary: null,
target: "normal",
type: "Steel",
contestType: "Clever"
},
desertstorm: {
accuracy: 100,
basePower: 90,
category: "Physical",
shortDesc: "(Partially functional placeholder) Hits two turns after being used. Sets sands when it hits, even if the target is immune.",
name: "Desert Storm",
pp: 15,
priority: 0,
flags: { allyanim: 1, metronome: 1, futuremove: 1 },
ignoreImmunity: true,
onTry(source, target) {
if (!target.side.addSlotCondition(target, "futuremove"))
return false;
Object.assign(target.side.slotConditions[target.position]["futuremove"], {
duration: 3,
move: "desertstorm",
source,
moveData: {
id: "desertstorm",
name: "Desert Storm",
accuracy: 100,
basePower: 90,
category: "Physical",
priority: 0,
flags: { allyanim: 1, futuremove: 1 },
ignoreImmunity: false,
self: {
sideCondition: "desertstorm"
},
effectType: "Move",
type: "Ground"
}
});
this.add("-start", source, "move: Desert Storm");
return this.NOT_FAIL;
},
condition: {
duration: 1,
onStart(source) {
this.field.setWeather("sandstorm");
}
},
secondary: null,
target: "normal",
type: "Ground",
contestType: "Clever"
},
dragonrage: {
num: 82,
accuracy: 100,
basePower: 85,
category: "Special",
shortDesc: "If the user is hit this turn, +1 SpA.",
isNonstandard: null,
name: "Dragon Rage",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
priorityChargeCallback(pokemon) {
pokemon.addVolatile("dragonrage");
},
condition: {
duration: 1,
onStart(pokemon) {
this.add("-singleturn", pokemon, "move: Dragon Rage");
},
onHit(target, source, move) {
if (target !== source && move.category !== "Status") {
this.boost({ spa: 1 });
}
}
},
secondary: null,
target: "normal",
type: "Dragon",
contestType: "Cool"
},
rage: {
num: 99,
accuracy: 100,
basePower: 85,
category: "Physical",
shortDesc: "If the user is hit this turn, +1 Atk.",
isNonstandard: null,
name: "Rage",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
priorityChargeCallback(pokemon) {
pokemon.addVolatile("rage");
},
condition: {
duration: 1,
onStart(pokemon) {
this.add("-singleturn", pokemon, "move: Rage");
},
onHit(target, source, move) {
if (target !== source && move.category !== "Status") {
this.boost({ atk: 1 });
}
}
},
secondary: null,
target: "normal",
type: "Normal",
contestType: "Tough"
},
latentvenom: {
accuracy: 100,
basePower: 0,
category: "Status",
shortDesc: "Hits two turns after being used. Foe: badly poisoned and -1 Def & SpD.",
name: "Latent Venom",
pp: 5,
priority: 0,
flags: { snatch: 1, allyanim: 1, metronome: 1, futuremove: 1 },
ignoreImmunity: true,
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Acid Spray", target);
},
onTry(source, target) {
if (!target.side.addSlotCondition(target, "futuremove"))
return false;
Object.assign(target.side.slotConditions[target.position]["futuremove"], {
duration: 3,
move: "latentvenom",
source,
moveData: {
id: "latentvenom",
name: "Latent Venom",
accuracy: 100,
basePower: 0,
category: "Status",
priority: 0,
flags: { allyanim: 1, futuremove: 1 },
ignoreImmunity: false,
status: "tox",
boosts: {
def: -1,
spd: -1
},
effectType: "Move",
type: "Poison"
}
});
this.add("-start", source, "move: Latent Venom");
return this.NOT_FAIL;
},
secondary: null,
target: "normal",
type: "Poison",
contestType: "Cool"
},
pivotfail: {
accuracy: true,
basePower: 0,
category: "Status",
shortDesc: "Prevents pivoting moves from being used for the rest of the turn.",
name: "Pivot Fail",
pp: 5,
priority: 0,
flags: { metronome: 1 },
volatileStatus: "pivotfail",
condition: {
duration: 1,
onStart(pokemon) {
this.add("-message", `${pokemon.name}'s pivoting moves will fail for the rest of the turn!`);
},
onBeforeMovePriority: 6,
onBeforeMove(pokemon, target, move) {
if (!move.isZ && !move.isMax && move.selfSwitch) {
this.add("cant", pokemon, "move: Smack Down");
return false;
}
},
onModifyMove(move, pokemon, target) {
if (!move.isZ && !move.isMax && move.selfSwitch) {
this.add("cant", pokemon, "move: Smack Down");
return false;
}
}
},
secondary: null,
target: "self",
type: "Rock"
},
smackdown: {
num: 479,
accuracy: 100,
basePower: 65,
category: "Physical",
shortDesc: "Removes the target's Ground immunity and causes pivoting moves to fail.",
name: "Smack Down",
pp: 15,
priority: 0,
flags: { protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
volatileStatus: "smackdown",
onHit(target) {
target.addVolatile("pivotfail");
},
condition: {
noCopy: true,
onStart(pokemon) {
let applies = false;
if (pokemon.hasType("Flying") || pokemon.hasAbility("levitate"))
applies = true;
if (pokemon.hasItem("ironball") || pokemon.volatiles["ingrain"] || this.field.getPseudoWeather("gravity"))
applies = false;
if (pokemon.removeVolatile("fly") || pokemon.removeVolatile("bounce")) {
applies = true;
this.queue.cancelMove(pokemon);
pokemon.removeVolatile("twoturnmove");
}
if (pokemon.volatiles["magnetrise"]) {
applies = true;
delete pokemon.volatiles["magnetrise"];
}
if (pokemon.volatiles["telekinesis"]) {
applies = true;
delete pokemon.volatiles["telekinesis"];
}
if (!applies)
return false;
this.add("-start", pokemon, "Smack Down");
},
onRestart(pokemon) {
if (pokemon.removeVolatile("fly") || pokemon.removeVolatile("bounce")) {
this.queue.cancelMove(pokemon);
pokemon.removeVolatile("twoturnmove");
this.add("-start", pokemon, "Smack Down");
}
}
// groundedness implemented in battle.engine.js:BattlePokemon#isGrounded
},
secondary: null,
target: "normal",
type: "Rock",
contestType: "Tough"
},
rootpull: {
accuracy: 100,
basePower: 90,
category: "Physical",
shortDesc: "100% chance to lower the target's Speed by 1 (2 if Flying-type).",
name: "Root Pull",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Trailblaze", target);
},
onHit(target) {
if (target.hasType("Flying") && !target.hasItem("covertcloak") && !target.hasAbility("shielddust")) {
this.boost({ spe: -1 }, target);
}
},
secondary: {
chance: 100,
boosts: {
spe: -1
}
},
target: "normal",
type: "Grass"
},
snatch: {
num: 289,
accuracy: 100,
basePower: 30,
category: "Physical",
isNonstandard: null,
name: "Snatch",
pp: 10,
priority: 2,
flags: { protect: 1, mirror: 1, bypasssub: 1, mustpressure: 1, noassist: 1, failcopycat: 1 },
self: {
onHit(pokemon, source, move) {
pokemon.addVolatile("snatch");
}
},
condition: {
duration: 1,
onStart(pokemon) {
this.add("-singleturn", pokemon, "Snatch");
},
onAnyPrepareHitPriority: -1,
onAnyPrepareHit(source, target, move) {
const snatchUser = this.effectState.source;
if (snatchUser.isSkyDropped())
return;
if (!move || move.isZ || move.isMax || !move.flags["snatch"] || move.sourceEffect === "snatch") {
return;
}
snatchUser.removeVolatile("snatch");
this.add("-activate", snatchUser, "move: Snatch", "[of] " + source);
this.actions.useMove(move.id, snatchUser);
return null;
}
},
secondary: null,
target: "normal",
type: "Dark",
contestType: "Clever"
},
tailslap: {
inherit: true,
accuracy: 100
},
pinmissile: {
inherit: true,
accuracy: 100
},
rockblast: {
inherit: true,
accuracy: 100
},
signalbeam: {
num: 324,
accuracy: 100,
basePower: 75,
category: "Special",
shortDesc: "Nullifies the target's Ability.",
isNonstandard: null,
name: "Signal Beam",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
onHit(target) {
if (target.getAbility().flags["cantsuppress"])
return;
target.addVolatile("gastroacid");
},
onAfterSubDamage(damage, target) {
if (target.getAbility().flags["cantsuppress"])
return;
target.addVolatile("gastroacid");
},
secondary: null,
target: "normal",
type: "Bug",
contestType: "Beautiful"
},
flyingpress: {
num: 560,
accuracy: 95,
basePower: 100,
category: "Physical",
shortDesc: "Either Fighting or Flying-type, whichever is more effective.",
name: "Flying Press",
pp: 10,
flags: { contact: 1, protect: 1, mirror: 1, gravity: 1, distance: 1, nonsky: 1, metronome: 1 },
onModifyType(move, pokemon) {
for (const target of pokemon.side.foe.active) {
const type1 = "Fighting";
const type2 = "Flying";
if (this.dex.getEffectiveness(type1, target) < this.dex.getEffectiveness(type2, target)) {
move.type = "Flying";
} else if (target.hasType("Ghost") && !pokemon.hasAbility("scrappy") && !pokemon.hasAbility("mindseye") && !target.hasItem("ringtarget")) {
move.type = "Flying";
} else if (this.dex.getEffectiveness(type1, target) === this.dex.getEffectiveness(type2, target)) {
if (pokemon.hasType("Flying") && !pokemon.hasType("Fighting")) {
move.type = "Flying";
}
}
}
},
onHit(target, source, move) {
this.add("-message", `Flying Press dealt ${move.type}-type damage!`);
},
priority: 0,
secondary: null,
target: "any",
type: "Fighting",
zMove: { basePower: 170 },
contestType: "Tough"
},
softwarecrash: {
num: 560,
accuracy: 95,
basePower: 100,
category: "Special",
shortDesc: "Either Bug or Electric-type, whichever is more effective.",
name: "Software Crash",
pp: 10,
flags: { protect: 1, mirror: 1, metronome: 1 },
onPrepareHit(target, source, move) {
this.attrLastMove("[still]");
this.add("-anim", source, "Hyper Beam", target);
},
onModifyType(move, pokemon) {
for (const target of pokemon.side.foe.active) {
const type1 = "Bug";
const type2 = "Electric";
if (this.dex.getEffectiveness(type1, target) < this.dex.getEffectiveness(type2, target)) {
if (!target.hasType("Ground") && !target.hasItem("ringtarget")) {
move.type = "Electric";
}
} else if (this.dex.getEffectiveness(type1, target) === this.dex.getEffectiveness(type2, target)) {
if (pokemon.hasType("Electric") && !pokemon.hasType("Bug")) {
move.type = "Electric";
}
}
}
},
onHit(target, source, move) {
this.add("-message", `Software Crash dealt ${move.type}-type damage!`);
},
priority: 0,
secondary: null,
target: "any",
type: "Bug",
zMove: { basePower: 170 },
contestType: "Tough"
},
lashout: {
num: 808,
accuracy: 100,
basePower: 70,
category: "Physical",
shortDesc: "2x power if the user has negative stat changes or a status.",
name: "Lash Out",
pp: 10,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
onBasePower(basePower, pokemon) {
const negativeVolatiles = [
"confusion",
"taunt",
"torment",
"trapped",
"partiallytrapped",
"leechseed",
"sandspit",
"attract",
"curse",
"disable",
"electrify",
"embargo",
"encore",
"foresight",
"gastroacid",
"foresight",
"miracleeye",
"glaiverush",
"healblock",
"throatchop",
"windbreaker",
"nightmare",
"octolock",
"powder",
"saltcure",
"smackdown",
"syrupbomb",
"tarshot",
"telekinesis",
"yawn"
];
let i;
for (i in pokemon.boosts) {
for (const volatile of negativeVolatiles) {
if (pokemon.status && pokemon.status !== "brn" || pokemon.volatiles[volatile] || pokemon.boosts[i] < 0) {
return this.chainModify(2);
} else if (pokemon.status === "brn") {
return this.chainModify(4);
}
}
}
},
secondary: null,
target: "normal",
type: "Dark"
},
naturalgift: {
num: 363,
accuracy: 100,
basePower: 0,
category: "Physical",
shortDesc: "Type and power based on user's berry.",
isNonstandard: null,
name: "Natural Gift",
pp: 15,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1 },
onModifyType(move, pokemon) {
if (pokemon.ignoringItem())
return;
const item = pokemon.getItem();
if (!item.naturalGift)
return;
move.type = item.naturalGift.type;
},
onPrepareHit(target, pokemon, move) {
if (pokemon.ignoringItem())
return false;
const item = pokemon.getItem();
if (!item.naturalGift)
return false;
move.basePower = item.naturalGift.basePower;
this.debug("BP: " + move.basePower);
},
onBasePower(basePower, pokemon) {
if (pokemon.hasAbility("ripen") || pokemon.hasAbility("harvest")) {
return this.chainModify(2);
}
},
secondary: null,
target: "normal",
type: "Normal",
zMove: { basePower: 160 },
maxMove: { basePower: 130 },
contestType: "Clever"
},
// all edited unchanged moves
stealthrock: {
num: 446,
accuracy: true,
basePower: 0,
category: "Status",
name: "Stealth Rock",
pp: 20,
priority: 0,
flags: { reflectable: 1, snatch: 1, metronome: 1 },
sideCondition: "stealthrock",
condition: {
// this is a side condition
onSideStart(side) {
this.add("-sidestart", side, "move: Stealth Rock");
},
onEntryHazard(pokemon) {
if (pokemon.hasItem("heavydutyboots") || pokemon.hasAbility("overcoat") || pokemon.hasItem("mantisclaw"))
return;
const typeMod = this.clampIntRange(pokemon.runEffectiveness(this.dex.getActiveMove("stealthrock")), -6, 6);
if (pokemon.hasAbility("smelt")) {
const fireHazard = this.dex.getActiveMove("Stealth Rock");
fireHazard.type = "Fire";
const smeltMod = this.clampIntRange(pokemon.runEffectiveness(fireHazard), -6, 6);
this.damage(pokemon.maxhp * Math.pow(2, smeltMod) / 8);
} else {
this.damage(pokemon.maxhp * Math.pow(2, typeMod) / 8);
}
}
},
secondary: null,
target: "foeSide",
type: "Rock",
zMove: { boost: { def: 1 } },
contestType: "Cool"
},
spikes: {
num: 191,
accuracy: true,
basePower: 0,
category: "Status",
name: "Spikes",
pp: 20,
priority: 0,
flags: { reflectable: 1, snatch: 1, nonsky: 1, metronome: 1, mustpressure: 1 },
sideCondition: "spikes",
condition: {
// this is a side condition
onSideStart(side) {
this.add("-sidestart", side, "Spikes");
this.effectState.layers = 1;
},
onSideRestart(side) {
if (this.effectState.layers >= 3)
return false;
this.add("-sidestart", side, "Spikes");
this.effectState.layers++;
},
onEntryHazard(pokemon) {
if (!pokemon.isGrounded())
return;
if (pokemon.hasItem("heavydutyboots") || pokemon.hasAbility("overcoat") || pokemon.hasItem("mantisclaw"))
return;
const damageAmounts = [0, 3, 4, 6];
this.damage(damageAmounts[this.effectState.layers] * pokemon.maxhp / 24);
}
},
secondary: null,
target: "foeSide",
type: "Ground",
zMove: { boost: { def: 1 } },
contestType: "Clever"
},
toxicspikes: {
num: 390,
accuracy: true,
basePower: 0,
category: "Status",
name: "Toxic Spikes",
pp: 20,
priority: 0,
flags: { reflectable: 1, snatch: 1, nonsky: 1, metronome: 1, mustpressure: 1 },
sideCondition: "toxicspikes",
condition: {
// this is a side condition
onSideStart(side) {
this.add("-sidestart", side, "move: Toxic Spikes");
this.effectState.layers = 1;
},
onSideRestart(side) {
if (this.effectState.layers >= 2)
return false;
this.add("-sidestart", side, "move: Toxic Spikes");
this.effectState.layers++;
},
onEntryHazard(pokemon) {
if (!pokemon.isGrounded())
return;
if (pokemon.hasType("Poison")) {
this.add("-sideend", pokemon.side, "move: Toxic Spikes", "[of] " + pokemon);
pokemon.side.removeSideCondition("toxicspikes");
} else if (pokemon.hasType("Steel") || pokemon.hasItem("heavydutyboots") || pokemon.hasAbility("overcoat") || pokemon.hasItem("mantisclaw")) {
return;
} else if (this.effectState.layers >= 2) {
pokemon.trySetStatus("tox", pokemon.side.foe.active[0]);
} else {
pokemon.trySetStatus("psn", pokemon.side.foe.active[0]);
}
}
},
secondary: null,
target: "foeSide",
type: "Poison",
zMove: { boost: { def: 1 } },
contestType: "Clever"
},
stickyweb: {
num: 564,
accuracy: true,
basePower: 0,
category: "Status",
name: "Sticky Web",
pp: 20,
priority: 0,
flags: { reflectable: 1, snatch: 1, metronome: 1 },
sideCondition: "stickyweb",
condition: {
onSideStart(side) {
this.add("-sidestart", side, "move: Sticky Web");
},
onEntryHazard(pokemon) {
if (!pokemon.isGrounded() || pokemon.hasItem("heavydutyboots") || pokemon.hasAbility("overcoat") || pokemon.hasItem("mantisclaw"))
return;
this.add("-activate", pokemon, "move: Sticky Web");
this.boost({ spe: -1 }, pokemon, this.effectState.source, this.dex.getActiveMove("stickyweb"));
}
},
secondary: null,
target: "foeSide",
type: "Bug",
zMove: { boost: { spe: 1 } },
contestType: "Tough"
},
defog: {
num: 432,
accuracy: true,
basePower: 0,
category: "Status",
name: "Defog",
pp: 15,
priority: 0,
flags: { protect: 1, reflectable: 1, mirror: 1, bypasssub: 1, metronome: 1, wind: 1 },
onHit(target, source, move) {
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",
"gmaxsteelsurge",
"healingstones"
];
const removeAll = [
"spikes",
"toxicspikes",
"stealthrock",
"stickyweb",
"gmaxsteelsurge",
"healingstones"
];
for (const targetCondition of removeTarget) {
if (target.side.removeSideCondition(targetCondition)) {
if (!removeAll.includes(targetCondition))
continue;
this.add("-sideend", target.side, this.dex.conditions.get(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.conditions.get(sideCondition).name, "[from] move: Defog", "[of] " + source);
success = true;
}
}
this.field.clearTerrain();
return success;
},
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
},
secondary: null,
target: "normal",
type: "Flying",
zMove: { boost: { accuracy: 1 } },
contestType: "Cool"
},
blazingtorque: {
inherit: true,
isNonstandard: null
},
wickedtorque: {
inherit: true,
isNonstandard: null
},
noxioustorque: {
inherit: true,
isNonstandard: null
},
combattorque: {
inherit: true,
isNonstandard: null
},
magicaltorque: {
inherit: true,
isNonstandard: null
},
rapidspin: {
num: 229,
accuracy: 100,
basePower: 50,
category: "Physical",
name: "Rapid Spin",
pp: 40,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
onAfterHit(target, pokemon, move) {
if (!move.hasSheerForce) {
if (pokemon.hp && pokemon.removeVolatile("leechseed")) {
this.add("-end", pokemon, "Leech Seed", "[from] move: Rapid Spin", "[of] " + pokemon);
}
const sideConditions = ["spikes", "toxicspikes", "stealthrock", "stickyweb", "gmaxsteelsurge", "healingstones"];
for (const condition of sideConditions) {
if (pokemon.hp && pokemon.side.removeSideCondition(condition)) {
this.add("-sideend", pokemon.side, this.dex.conditions.get(condition).name, "[from] move: Rapid Spin", "[of] " + pokemon);
}
}
if (pokemon.hp && pokemon.volatiles["partiallytrapped"]) {
pokemon.removeVolatile("partiallytrapped");
}
}
},
onAfterSubDamage(damage, target, pokemon, move) {
if (!move.hasSheerForce) {
if (pokemon.hp && pokemon.removeVolatile("leechseed")) {
this.add("-end", pokemon, "Leech Seed", "[from] move: Rapid Spin", "[of] " + pokemon);
}
const sideConditions = ["spikes", "toxicspikes", "stealthrock", "stickyweb", "gmaxsteelsurge", "healingstones"];
for (const condition of sideConditions) {
if (pokemon.hp && pokemon.side.removeSideCondition(condition)) {
this.add("-sideend", pokemon.side, this.dex.conditions.get(condition).name, "[from] move: Rapid Spin", "[of] " + pokemon);
}
}
if (pokemon.hp && pokemon.volatiles["partiallytrapped"]) {
pokemon.removeVolatile("partiallytrapped");
}
}
},
secondary: {
chance: 100,
self: {
boosts: {
spe: 1
}
}
},
target: "normal",
type: "Normal",
contestType: "Cool"
},
mortalspin: {
num: 866,
accuracy: 100,
basePower: 30,
category: "Physical",
name: "Mortal Spin",
pp: 15,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
onAfterHit(target, pokemon, move) {
if (!move.hasSheerForce) {
if (pokemon.hp && pokemon.removeVolatile("leechseed")) {
this.add("-end", pokemon, "Leech Seed", "[from] move: Mortal Spin", "[of] " + pokemon);
}
const sideConditions = ["spikes", "toxicspikes", "stealthrock", "stickyweb", "gmaxsteelsurge", "healingstones"];
for (const condition of sideConditions) {
if (pokemon.hp && pokemon.side.removeSideCondition(condition)) {
this.add("-sideend", pokemon.side, this.dex.conditions.get(condition).name, "[from] move: Mortal Spin", "[of] " + pokemon);
}
}
if (pokemon.hp && pokemon.volatiles["partiallytrapped"]) {
pokemon.removeVolatile("partiallytrapped");
}
}
},
onAfterSubDamage(damage, target, pokemon, move) {
if (!move.hasSheerForce) {
if (pokemon.hp && pokemon.removeVolatile("leechseed")) {
this.add("-end", pokemon, "Leech Seed", "[from] move: Mortal Spin", "[of] " + pokemon);
}
const sideConditions = ["spikes", "toxicspikes", "stealthrock", "stickyweb", "gmaxsteelsurge", "healingstones"];
for (const condition of sideConditions) {
if (pokemon.hp && pokemon.side.removeSideCondition(condition)) {
this.add("-sideend", pokemon.side, this.dex.conditions.get(condition).name, "[from] move: Mortal Spin", "[of] " + pokemon);
}
}
if (pokemon.hp && pokemon.volatiles["partiallytrapped"]) {
pokemon.removeVolatile("partiallytrapped");
}
}
},
secondary: {
chance: 100,
status: "psn"
},
target: "allAdjacentFoes",
type: "Poison"
},
tidyup: {
num: 882,
accuracy: true,
basePower: 0,
category: "Status",
name: "Tidy Up",
pp: 10,
priority: 0,
flags: {},
onHit(pokemon) {
let success = false;
for (const active of this.getAllActive()) {
if (active.removeVolatile("substitute"))
success = true;
}
const removeAll = ["spikes", "toxicspikes", "stealthrock", "stickyweb", "gmaxsteelsurge", "healingstones"];
const sides = [pokemon.side, ...pokemon.side.foeSidesWithConditions()];
for (const side of sides) {
for (const sideCondition of removeAll) {
if (side.removeSideCondition(sideCondition)) {
this.add("-sideend", side, this.dex.conditions.get(sideCondition).name);
success = true;
}
}
}
if (success)
this.add("-activate", pokemon, "move: Tidy Up");
return !!this.boost({ atk: 1, spe: 1 }, pokemon, pokemon, null, false, true) || success;
},
secondary: null,
target: "self",
type: "Normal"
},
courtchange: {
num: 756,
accuracy: 100,
basePower: 0,
category: "Status",
name: "Court Change",
pp: 10,
priority: 0,
flags: { mirror: 1, metronome: 1 },
onHitField(target, source) {
const sideConditions = [
"mist",
"lightscreen",
"reflect",
"spikes",
"safeguard",
"tailwind",
"toxicspikes",
"stealthrock",
"waterpledge",
"firepledge",
"grasspledge",
"stickyweb",
"auroraveil",
"gmaxsteelsurge",
"gmaxcannonade",
"gmaxvinelash",
"gmaxwildfire",
"healingstones"
];
let success = false;
if (this.gameType === "freeforall") {
const offset = this.random(3) + 1;
const sides = [this.sides[0], this.sides[2], this.sides[1], this.sides[3]];
const temp = { 0: {}, 1: {}, 2: {}, 3: {} };
for (const side of sides) {
for (const id in side.sideConditions) {
if (!sideConditions.includes(id))
continue;
temp[side.n][id] = side.sideConditions[id];
delete side.sideConditions[id];
const effectName = this.dex.conditions.get(id).name;
this.add("-sideend", side, effectName, "[silent]");
success = true;
}
}
for (let i = 0; i < 4; i++) {
const sourceSideConditions = temp[sides[i].n];
const targetSide = sides[(i + offset) % 4];
for (const id in sourceSideConditions) {
targetSide.sideConditions[id] = sourceSideConditions[id];
const effectName = this.dex.conditions.get(id).name;
let layers = sourceSideConditions[id].layers || 1;
for (; layers > 0; layers--)
this.add("-sidestart", targetSide, effectName, "[silent]");
}
}
} else {
const sourceSideConditions = source.side.sideConditions;
const targetSideConditions = source.side.foe.sideConditions;
const sourceTemp = {};
const targetTemp = {};
for (const id in sourceSideConditions) {
if (!sideConditions.includes(id))
continue;
sourceTemp[id] = sourceSideConditions[id];
delete sourceSideConditions[id];
success = true;
}
for (const id in targetSideConditions) {
if (!sideConditions.includes(id))
continue;
targetTemp[id] = targetSideConditions[id];
delete targetSideConditions[id];
success = true;
}
for (const id in sourceTemp) {
targetSideConditions[id] = sourceTemp[id];
}
for (const id in targetTemp) {
sourceSideConditions[id] = targetTemp[id];
}
this.add("-swapsideconditions");
}
if (!success)
return false;
this.add("-activate", source, "move: Court Change");
},
secondary: null,
target: "all",
type: "Normal"
},
healblock: {
num: 377,
accuracy: 100,
basePower: 0,
category: "Status",
isNonstandard: "Past",
name: "Heal Block",
pp: 15,
priority: 0,
flags: { protect: 1, reflectable: 1, mirror: 1, metronome: 1 },
volatileStatus: "healblock",
condition: {
duration: 5,
durationCallback(target, source, effect) {
if (source?.hasAbility("persistent")) {
this.add("-activate", source, "ability: Persistent", "[move] Heal Block");
return 7;
}
if (effect && effect.id === "deathaura") {
return 0;
}
return 5;
},
onStart(pokemon, source) {
this.add("-start", pokemon, "move: Heal Block");
source.moveThisTurnResult = true;
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.dex.moves.get(moveSlot.id).flags["heal"]) {
pokemon.disableMove(moveSlot.id);
}
}
},
onBeforeMovePriority: 6,
onBeforeMove(pokemon, target, move) {
if ((move.flags["heal"] || move.id === "bitterblade") && !move.isZ && !move.isMax) {
this.add("cant", pokemon, "move: Heal Block", move);
return false;
}
},
onModifyMove(move, pokemon, target) {
if ((move.flags["heal"] || move.id === "bitterblade") && !move.isZ && !move.isMax) {
this.add("cant", pokemon, "move: Heal Block", move);
return false;
}
},
onResidualOrder: 20,
onEnd(pokemon) {
this.add("-end", pokemon, "move: Heal Block");
},
onTryHeal(damage, target, source, effect) {
if (effect?.id === "zpower" || this.effectState.isZ)
return damage;
return false;
},
onRestart(target, source) {
this.add("-fail", target, "move: Heal Block");
if (!source.moveThisTurnResult) {
source.moveThisTurnResult = false;
}
}
},
secondary: null,
target: "allAdjacentFoes",
type: "Psychic",
zMove: { boost: { spa: 2 } },
contestType: "Clever"
},
electricterrain: {
num: 604,
accuracy: true,
basePower: 0,
category: "Status",
name: "Electric Terrain",
pp: 10,
priority: 0,
flags: { nonsky: 1, metronome: 1 },
terrain: "electricterrain",
condition: {
duration: 5,
durationCallback(source, effect) {
if (source?.hasItem("terrainextender")) {
return 8;
}
return 5;
},
onSetStatus(status, target, source, effect) {
if (status.id === "slp" && target.isGrounded() && !target.isSemiInvulnerable()) {
if (effect.id === "yawn" || effect.effectType === "Move" && !effect.secondaries) {
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
return;
}
}
this.add("-activate", target, "move: Electric Terrain");
}
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
return;
}
}
return false;
}
},
onTryAddVolatile(status, target) {
if (!target.isGrounded() || target.isSemiInvulnerable())
return;
if (status.id === "yawn") {
this.add("-activate", target, "move: Electric Terrain");
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
return;
}
}
return null;
}
},
onBasePowerPriority: 6,
onBasePower(basePower, attacker, defender, move) {
if (move.type === "Electric" && attacker.isGrounded() && !attacker.isSemiInvulnerable()) {
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
return;
}
}
this.debug("electric terrain boost");
return this.chainModify([5325, 4096]);
}
},
onFieldStart(field, source, effect) {
if (effect?.effectType === "Ability") {
this.add("-fieldstart", "move: Electric Terrain", "[from] ability: " + effect.name, "[of] " + source);
} else {
this.add("-fieldstart", "move: Electric Terrain");
}
},
onFieldResidualOrder: 27,
onFieldResidualSubOrder: 7,
onFieldEnd() {
this.add("-fieldend", "move: Electric Terrain");
}
},
secondary: null,
target: "all",
type: "Electric",
zMove: { boost: { spe: 1 } },
contestType: "Clever"
},
psychicterrain: {
num: 678,
accuracy: true,
basePower: 0,
category: "Status",
name: "Psychic Terrain",
pp: 10,
priority: 0,
flags: { nonsky: 1, metronome: 1 },
terrain: "psychicterrain",
condition: {
duration: 5,
durationCallback(source, effect) {
if (source?.hasItem("terrainextender")) {
return 8;
}
return 5;
},
onTryHitPriority: 4,
onTryHit(target, source, effect) {
if (effect && (effect.priority <= 0.1 || effect.target === "self")) {
return;
}
if (target.isSemiInvulnerable() || target.isAlly(source))
return;
if (!target.isGrounded()) {
const baseMove = this.dex.moves.get(effect.id);
if (baseMove.priority > 0) {
this.hint("Psychic Terrain doesn't affect Pok\xE9mon immune to Ground.");
}
return;
}
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
return;
}
}
this.add("-activate", target, "move: Psychic Terrain");
return null;
},
onBasePowerPriority: 6,
onBasePower(basePower, attacker, defender, move) {
if (move.type === "Psychic" && attacker.isGrounded() && !attacker.isSemiInvulnerable()) {
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
return;
}
}
this.debug("psychic terrain boost");
return this.chainModify([5325, 4096]);
}
},
onFieldStart(field, source, effect) {
if (effect?.effectType === "Ability") {
this.add("-fieldstart", "move: Psychic Terrain", "[from] ability: " + effect.name, "[of] " + source);
} else {
this.add("-fieldstart", "move: Psychic Terrain");
}
},
onFieldResidualOrder: 27,
onFieldResidualSubOrder: 7,
onFieldEnd() {
this.add("-fieldend", "move: Psychic Terrain");
}
},
secondary: null,
target: "all",
type: "Psychic",
zMove: { boost: { spa: 1 } },
contestType: "Clever"
},
grassyterrain: {
num: 580,
accuracy: true,
basePower: 0,
category: "Status",
name: "Grassy Terrain",
pp: 10,
priority: 0,
flags: { nonsky: 1, metronome: 1 },
terrain: "grassyterrain",
condition: {
duration: 5,
durationCallback(source, effect) {
if (source?.hasItem("terrainextender")) {
return 8;
}
return 5;
},
onBasePowerPriority: 6,
onBasePower(basePower, attacker, defender, move) {
const weakenedMoves = ["earthquake", "bulldoze", "magnitude"];
if (weakenedMoves.includes(move.id) && defender.isGrounded() && !defender.isSemiInvulnerable()) {
for (const target of this.getAllActive()) {
if (target.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return;
}
}
this.debug("move weakened by grassy terrain");
return this.chainModify(0.5);
}
if (move.type === "Grass" && attacker.isGrounded()) {
for (const target of this.getAllActive()) {
if (target.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return;
}
}
this.debug("grassy terrain boost");
return this.chainModify([5325, 4096]);
}
},
onFieldStart(field, source, effect) {
if (effect?.effectType === "Ability") {
this.add("-fieldstart", "move: Grassy Terrain", "[from] ability: " + effect.name, "[of] " + source);
} else {
this.add("-fieldstart", "move: Grassy Terrain");
}
},
onResidualOrder: 5,
onResidualSubOrder: 2,
onResidual(pokemon) {
for (const target of this.getAllActive()) {
if (target.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return;
}
}
if (pokemon.isGrounded() && !pokemon.isSemiInvulnerable()) {
this.heal(pokemon.baseMaxhp / 16, pokemon, pokemon);
} else {
this.debug(`Pokemon semi-invuln or not grounded; Grassy Terrain skipped`);
}
},
onFieldResidualOrder: 27,
onFieldResidualSubOrder: 7,
onFieldEnd() {
this.add("-fieldend", "move: Grassy Terrain");
}
},
secondary: null,
target: "all",
type: "Grass",
zMove: { boost: { def: 1 } },
contestType: "Beautiful"
},
mistyterrain: {
num: 581,
accuracy: true,
basePower: 0,
category: "Status",
name: "Misty Terrain",
pp: 10,
priority: 0,
flags: { nonsky: 1, metronome: 1 },
terrain: "mistyterrain",
condition: {
duration: 5,
durationCallback(source, effect) {
if (source?.hasItem("terrainextender")) {
return 8;
}
return 5;
},
onSetStatus(status, target, source, effect) {
if (!target.isGrounded() || target.isSemiInvulnerable())
return;
if (effect && (effect.status || effect.id === "yawn")) {
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
return;
}
}
this.add("-activate", target, "move: Misty Terrain");
}
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
return;
}
}
return false;
},
onTryAddVolatile(status, target, source, effect) {
if (!target.isGrounded() || target.isSemiInvulnerable())
return;
if (status.id === "confusion") {
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
return;
}
}
if (effect.effectType === "Move" && !effect.secondaries)
this.add("-activate", target, "move: Misty Terrain");
return null;
}
},
onBasePowerPriority: 6,
onBasePower(basePower, attacker, defender, move) {
if (move.type === "Dragon" && defender.isGrounded() && !defender.isSemiInvulnerable()) {
for (const target of this.getAllActive()) {
if (target.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return;
}
}
this.debug("misty terrain weaken");
return this.chainModify(0.5);
}
},
onFieldStart(field, source, effect) {
if (effect?.effectType === "Ability") {
this.add("-fieldstart", "move: Misty Terrain", "[from] ability: " + effect.name, "[of] " + source);
} else {
this.add("-fieldstart", "move: Misty Terrain");
}
},
onFieldResidualOrder: 27,
onFieldResidualSubOrder: 7,
onFieldEnd() {
this.add("-fieldend", "Misty Terrain");
}
},
secondary: null,
target: "all",
type: "Fairy",
zMove: { boost: { spd: 1 } },
contestType: "Beautiful"
},
camouflage: {
inherit: true,
onHit(target) {
let newType = "Normal";
if (this.field.isTerrain("electricterrain")) {
newType = "Electric";
} else if (this.field.isTerrain("grassyterrain")) {
newType = "Grass";
} else if (this.field.isTerrain("mistyterrain")) {
newType = "Fairy";
} else if (this.field.isTerrain("psychicterrain")) {
newType = "Psychic";
}
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
newType = "Normal";
}
}
if (target.getTypes().join() === newType || !target.setType(newType))
return false;
this.add("-start", target, "typechange", newType);
}
},
expandingforce: {
inherit: true,
onBasePower(basePower, source) {
if (this.getAllActive().some((x) => x.hasAbility("cloudnine")))
return;
if (this.field.isTerrain("psychicterrain") && source.isGrounded()) {
this.debug("terrain buff");
return this.chainModify(1.5);
}
},
onModifyMove(move, source, target) {
if (this.getAllActive().some((x) => x.hasAbility("cloudnine")))
return;
if (this.field.isTerrain("psychicterrain") && source.isGrounded()) {
move.target = "allAdjacentFoes";
}
}
},
floralhealing: {
inherit: true,
onHit(target, source) {
let success = false;
if (this.field.isTerrain("grassyterrain")) {
if (this.getAllActive().some((x) => x.hasAbility("cloudnine"))) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return success;
}
success = !!this.heal(this.modify(target.baseMaxhp, 0.667));
} else {
success = !!this.heal(Math.ceil(target.baseMaxhp * 0.5));
}
if (success && target.side !== source.side) {
target.staleness = "external";
}
return success;
}
},
grassyglide: {
inherit: true,
onModifyPriority(priority, source, target, move) {
if (this.getAllActive().some((x) => x.hasAbility("cloudnine")))
return priority;
if (this.field.isTerrain("grassyterrain") && source.isGrounded()) {
return priority + 1;
}
}
},
mistyexplosion: {
inherit: true,
onBasePower(basePower, source) {
if (this.getAllActive().some((x) => x.hasAbility("cloudnine")))
return;
if (this.field.isTerrain("mistyterrain") && source.isGrounded()) {
this.debug("misty terrain boost");
return this.chainModify(1.5);
}
}
},
naturepower: {
inherit: true,
onTryHit(target, pokemon) {
let move = "triattack";
if (this.field.isTerrain("electricterrain")) {
move = "thunderbolt";
} else if (this.field.isTerrain("grassyterrain")) {
move = "energyball";
} else if (this.field.isTerrain("mistyterrain")) {
move = "moonblast";
} else if (this.field.isTerrain("psychicterrain")) {
move = "psychic";
}
for (const active of this.getAllActive()) {
if (active.hasAbility("cloudnine")) {
this.add("-message", `${active.name} suppresses the effects of the terrain!`);
move = "triattack";
}
}
this.actions.useMove(move, pokemon, target);
return null;
}
},
risingvoltage: {
inherit: true,
onBasePower(basePower, pokemon, target) {
if (this.getAllActive().some((x) => x.hasAbility("cloudnine")))
return;
if (this.field.isTerrain("electricterrain") && target.isGrounded()) {
this.debug("terrain buff");
return this.chainModify(2);
}
}
},
secretpower: {
inherit: true,
onModifyMove(move, pokemon) {
if (this.field.isTerrain(""))
return;
for (const target of this.getAllActive()) {
if (target.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return;
}
}
move.secondaries = [];
if (this.field.isTerrain("electricterrain")) {
move.secondaries.push({
chance: 30,
status: "par"
});
} else if (this.field.isTerrain("grassyterrain")) {
move.secondaries.push({
chance: 30,
status: "slp"
});
} else if (this.field.isTerrain("mistyterrain")) {
move.secondaries.push({
chance: 30,
boosts: {
spa: -1
}
});
} else if (this.field.isTerrain("psychicterrain")) {
move.secondaries.push({
chance: 30,
boosts: {
spe: -1
}
});
}
}
},
steelroller: {
inherit: true,
onTryHit() {
if (this.field.isTerrain(""))
return false;
for (const target of this.getAllActive()) {
if (target.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return false;
}
}
}
},
terrainpulse: {
inherit: true,
onModifyType(move, pokemon) {
if (!pokemon.isGrounded())
return;
if (this.getAllActive().some((x) => x.hasAbility("cloudnine")))
return;
switch (this.field.terrain) {
case "electricterrain":
move.type = "Electric";
break;
case "grassyterrain":
move.type = "Grass";
break;
case "mistyterrain":
move.type = "Fairy";
break;
case "psychicterrain":
move.type = "Psychic";
break;
}
},
onModifyMove(move, pokemon) {
if (this.field.terrain && pokemon.isGrounded()) {
for (const target of this.getAllActive()) {
if (target.hasAbility("cloudnine")) {
this.add("-message", `${target.name} suppresses the effects of the terrain!`);
return;
}
}
move.basePower *= 2;
}
}
},
bleakwindstorm: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
sandsearstorm: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
springtidestorm: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
wildboltstorm: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
aircutter: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
fairywind: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
gust: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
heatwave: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
hurricane: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
icywind: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
petalblizzard: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
sandstorm: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
tailwind: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
twister: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
whirlwind: {
inherit: true,
self: {
onHit(pokemon, source, move) {
if (source.hasItem("airfreshener")) {
this.add("-activate", source, "move: Aromatherapy");
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles["substitute"] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
}
}
}
},
boomburst: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
bugbuzz: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
clangingscales: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
clangoroussoul: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
confide: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
disarmingvoice: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
echoedvoice: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
eeriespell: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
growl: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
healbell: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
hypervoice: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
metalsound: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
howl: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
nobleroar: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
overdrive: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
partingshot: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
perishsong: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
relicsong: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
roar: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
screech: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
sing: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
snarl: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
snore: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
sparklingaria: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
chatter: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
supersonic: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
torchsong: {
inherit: true,
self: {
sideCondition: "echochamber"
}
},
uproar: {
inherit: true,
self: {
sideCondition: "echochamber",
volatileStatus: "uproar"
}
},
revivalblessing: {
inherit: true,
flags: { snatch: 1 }
},
shedtail: {
inherit: true,
flags: { snatch: 1 }
},
aromaticmist: {
inherit: true,
flags: { snatch: 1, bypasssub: 1, metronome: 1 }
},
terablast: {
num: 851,
accuracy: 100,
basePower: 80,
category: "Special",
name: "Tera Blast",
pp: 10,
priority: 0,
flags: { protect: 1, mirror: 1, metronome: 1, mustpressure: 1 },
onPrepareHit(target, source, move) {
if (source.terastallized) {
this.attrLastMove("[anim] Tera Blast " + source.teraType);
}
},
onModifyType(move, pokemon, target) {
if (pokemon.terastallized) {
move.type = pokemon.teraType;
}
},
onModifyMove(move, pokemon) {
if ((pokemon.terastallized || pokemon.hasItem("terashard")) && pokemon.getStat("atk", false, true) > pokemon.getStat("spa", false, true)) {
move.category = "Physical";
}
},
secondary: null,
target: "normal",
type: "Normal"
},
doubleshock: {
num: 892,
accuracy: 100,
basePower: 120,
category: "Physical",
name: "Double Shock",
pp: 5,
priority: 0,
flags: { contact: 1, protect: 1, mirror: 1 },
onTryMove(pokemon, target, move) {
if (pokemon.hasType("Electric"))
return;
this.add("-fail", pokemon, "move: Double Shock");
this.attrLastMove("[still]");
return null;
},
self: {
onHit(pokemon) {
if (pokemon.hasItem("terashard") && pokemon.teraType === "Electric")
return;
pokemon.setType(pokemon.getTypes(true).map((type) => type === "Electric" ? "???" : type));
this.add("-start", pokemon, "typechange", pokemon.getTypes().join("/"), "[from] move: Double Shock");
}
},
secondary: null,
target: "normal",
type: "Electric",
contestType: "Clever"
},
burnup: {
num: 682,
accuracy: 100,
basePower: 130,
category: "Special",
name: "Burn Up",
pp: 5,
priority: 0,
flags: { protect: 1, mirror: 1, defrost: 1, metronome: 1 },
onTryMove(pokemon, target, move) {
if (pokemon.hasType("Fire"))
return;
this.add("-fail", pokemon, "move: Burn Up");
this.attrLastMove("[still]");
return null;
},
self: {
onHit(pokemon) {
if (pokemon.hasItem("terashard") && pokemon.teraType === "Fire")
return;
pokemon.setType(pokemon.getTypes(true).map((type) => type === "Fire" ? "???" : type));
this.add("-start", pokemon, "typechange", pokemon.getTypes().join("/"), "[from] move: Burn Up");
}
},
secondary: null,
target: "normal",
type: "Fire",
contestType: "Clever"
},
roost: {
num: 355,
accuracy: true,
basePower: 0,
category: "Status",
name: "Roost",
pp: 5,
priority: 0,
flags: { snatch: 1, heal: 1, metronome: 1 },
heal: [1, 2],
self: {
volatileStatus: "roost"
},
condition: {
duration: 1,
onResidualOrder: 25,
onStart(target) {
if (!target.terastallized && !target.hasItem("terashard")) {
this.add("-singleturn", target, "move: Roost");
} else if (target.terastallized === "Flying" || target.hasItem("terashard")) {
this.add("-hint", "If a Flying Terastallized Pokemon uses Roost, it remains Flying-type.");
}
},
onTypePriority: -1,
onType(types, pokemon) {
this.effectState.typeWas = types;
return types.filter((type) => type !== "Flying");
}
},
secondary: null,
target: "self",
type: "Flying",
zMove: { effect: "clearnegativeboost" },
contestType: "Clever"
}
};
//# sourceMappingURL=moves.js.map