3188 lines
91 KiB
JavaScript
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
|