"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 = { aeroblast: { inherit: true, critRatio: 3 }, beatup: { inherit: true, onModifyMove(move, pokemon) { move.type = "???"; move.category = "Special"; move.allies = pokemon.side.pokemon.filter((ally) => !ally.fainted && !ally.status); move.multihit = move.allies.length; } }, bellydrum: { inherit: true, onHit(target) { if (target.boosts.atk >= 6) { return false; } if (target.hp <= target.maxhp / 2) { this.boost({ atk: 2 }, null, null, this.dex.conditions.get("bellydrum2")); return false; } this.directDamage(target.maxhp / 2); const originalStage = target.boosts.atk; let currentStage = originalStage; let boosts = 0; let loopStage = 0; while (currentStage < 6) { loopStage = currentStage; currentStage++; if (currentStage < 6) currentStage++; target.boosts.atk = loopStage; if (target.getStat("atk", false, true) < 999) { target.boosts.atk = currentStage; continue; } target.boosts.atk = currentStage - 1; break; } boosts = target.boosts.atk - originalStage; target.boosts.atk = originalStage; this.boost({ atk: boosts }); } }, bide: { inherit: true, condition: { duration: 3, durationCallback(target, source, effect) { return this.random(3, 5); }, onLockMove: "bide", onStart(pokemon) { this.effectState.totalDamage = 0; this.add("-start", pokemon, "move: Bide"); }, onDamagePriority: -101, onDamage(damage, target, source, move) { if (!move || move.effectType !== "Move" || !source) return; this.effectState.totalDamage += damage; this.effectState.lastDamageSource = source; }, onBeforeMove(pokemon, target, move) { if (this.effectState.duration === 1) { this.add("-end", pokemon, "move: Bide"); if (!this.effectState.totalDamage) { this.add("-fail", pokemon); return false; } target = this.effectState.lastDamageSource; if (!target) { this.add("-fail", pokemon); return false; } if (!target.isActive) { const possibleTarget = this.getRandomTarget(pokemon, this.dex.moves.get("pound")); if (!possibleTarget) { this.add("-miss", pokemon); return false; } target = possibleTarget; } const moveData = { id: "bide", name: "Bide", accuracy: 100, damage: this.effectState.totalDamage * 2, category: "Physical", priority: 0, flags: { contact: 1, protect: 1 }, effectType: "Move", type: "Normal" }; this.actions.tryMoveHit(target, pokemon, moveData); pokemon.removeVolatile("bide"); return false; } this.add("-activate", pokemon, "move: Bide"); }, onMoveAborted(pokemon) { pokemon.removeVolatile("bide"); }, onEnd(pokemon) { this.add("-end", pokemon, "move: Bide", "[silent]"); } } }, counter: { inherit: true, damageCallback(pokemon, target) { const lastAttackedBy = pokemon.getLastAttackedBy(); if (!lastAttackedBy?.move || !lastAttackedBy.thisTurn) return false; if (this.getCategory(lastAttackedBy.move) === "Physical" && target.lastMove?.id !== "sleeptalk") { return 2 * lastAttackedBy.damage; } return false; }, beforeTurnCallback() { }, onTry() { }, condition: {}, priority: -1 }, crabhammer: { inherit: true, critRatio: 3 }, crosschop: { inherit: true, critRatio: 3 }, curse: { inherit: true, condition: { onStart(pokemon, source) { this.add("-start", pokemon, "Curse", "[of] " + source); }, onAfterMoveSelf(pokemon) { this.damage(pokemon.baseMaxhp / 4); } } }, detect: { inherit: true, priority: 2 }, dig: { inherit: true, onPrepareHit(target, source) { return source.status !== "slp"; }, condition: { duration: 2, onImmunity(type, pokemon) { if (type === "sandstorm") return false; }, onInvulnerability(target, source, move) { if (move.id === "earthquake" || move.id === "magnitude" || move.id === "fissure") { return; } if (["attract", "curse", "foresight", "meanlook", "mimic", "nightmare", "spiderweb", "transform"].includes(move.id)) { return false; } if (source.volatiles["lockon"] && target === source.volatiles["lockon"].source) return; return false; }, onSourceBasePower(basePower, target, source, move) { if (move.id === "earthquake" || move.id === "magnitude") { return this.chainModify(2); } } } }, doubleedge: { inherit: true, recoil: [25, 100] }, encore: { inherit: true, condition: { durationCallback() { return this.random(3, 7); }, onStart(target) { const lockedMove = target.lastMoveEncore?.id || ""; const moveIndex = lockedMove ? target.moves.indexOf(lockedMove) : -1; if (moveIndex < 0 || target.lastMoveEncore?.flags["failencore"] || target.moveSlots[moveIndex].pp <= 0) { return false; } this.effectState.move = lockedMove; this.add("-start", target, "Encore"); }, onOverrideAction(pokemon) { return this.effectState.move; }, onResidualOrder: 13, onResidual(target) { const lockedMoveIndex = target.moves.indexOf(this.effectState.move); if (lockedMoveIndex >= 0 && target.moveSlots[lockedMoveIndex].pp <= 0) { target.removeVolatile("encore"); } }, onEnd(target) { this.add("-end", target, "Encore"); }, onDisableMove(pokemon) { if (!this.effectState.move || !pokemon.hasMove(this.effectState.move)) { return; } for (const moveSlot of pokemon.moveSlots) { if (moveSlot.id !== this.effectState.move) { pokemon.disableMove(moveSlot.id); } } } } }, endure: { inherit: true, priority: 2 }, explosion: { inherit: true, noSketch: true }, flail: { inherit: true, noDamageVariance: true, willCrit: false }, fly: { inherit: true, onPrepareHit(target, source) { return source.status !== "slp"; }, condition: { duration: 2, onInvulnerability(target, source, move) { if (move.id === "gust" || move.id === "twister" || move.id === "thunder" || move.id === "whirlwind") { return; } if (move.id === "earthquake" || move.id === "magnitude" || move.id === "fissure") { return false; } if (["attract", "curse", "foresight", "meanlook", "mimic", "nightmare", "spiderweb", "transform"].includes(move.id)) { return false; } if (source.volatiles["lockon"] && target === source.volatiles["lockon"].source) return; return false; }, onSourceBasePower(basePower, target, source, move) { if (move.id === "gust" || move.id === "twister") { return this.chainModify(2); } } } }, focusenergy: { inherit: true, condition: { onStart(pokemon) { this.add("-start", pokemon, "move: Focus Energy"); }, onModifyCritRatio(critRatio) { return critRatio + 1; } } }, foresight: { inherit: true, onTryHit(target) { if (target.volatiles["foresight"]) return false; }, condition: { onStart(pokemon) { this.add("-start", pokemon, "Foresight"); }, onNegateImmunity(pokemon, type) { if (pokemon.hasType("Ghost") && ["Normal", "Fighting"].includes(type)) return false; }, onModifyBoost(boosts) { if (boosts.evasion && boosts.evasion > 0) { boosts.evasion = 0; } } } }, frustration: { inherit: true, basePowerCallback(pokemon) { return Math.floor((255 - pokemon.happiness) * 10 / 25) || null; } }, healbell: { inherit: true, onHit(target, source) { this.add("-cureteam", source, "[from] move: Heal Bell"); for (const pokemon of target.side.pokemon) { pokemon.clearStatus(); } } }, highjumpkick: { inherit: true, onMoveFail(target, source, move) { if (target.runImmunity("Fighting")) { const damage = this.actions.getDamage(source, target, move, true); if (typeof damage !== "number") throw new Error("Couldn't get High Jump Kick recoil"); this.damage(this.clampIntRange(damage / 8, 1), source, source, move); } } }, jumpkick: { inherit: true, onMoveFail(target, source, move) { if (target.runImmunity("Fighting")) { const damage = this.actions.getDamage(source, target, move, true); if (typeof damage !== "number") throw new Error("Couldn't get Jump Kick recoil"); this.damage(this.clampIntRange(damage / 8, 1), source, source, move); } } }, karatechop: { inherit: true, critRatio: 3 }, leechseed: { inherit: true, onHit() { }, condition: { onStart(target) { this.add("-start", target, "move: Leech Seed"); }, onAfterMoveSelfPriority: 2, onAfterMoveSelf(pokemon) { if (!pokemon.hp) return; const leecher = this.getAtSlot(pokemon.volatiles["leechseed"].sourceSlot); if (!leecher || leecher.fainted || leecher.hp <= 0) { return; } const toLeech = this.clampIntRange(pokemon.maxhp / 8, 1); const damage = this.damage(toLeech, pokemon, leecher); if (damage) { this.heal(damage, leecher, pokemon); } } } }, lightscreen: { inherit: true, condition: { duration: 5, // Sp. Def boost applied directly in stat calculation onSideStart(side) { this.add("-sidestart", side, "move: Light Screen"); }, onSideResidualOrder: 9, onSideEnd(side) { this.add("-sideend", side, "move: Light Screen"); } } }, lockon: { inherit: true, onTryHit(target) { if (target.volatiles["foresight"] || target.volatiles["lockon"]) return false; }, condition: { duration: 2, onSourceAccuracy(accuracy, target, source, move) { if (move && source === this.effectState.target && target === this.effectState.source) return true; } } }, lowkick: { inherit: true, accuracy: 90, basePower: 50, basePowerCallback() { return 50; }, secondary: { chance: 30, volatileStatus: "flinch" } }, meanlook: { inherit: true, flags: { reflectable: 1, mirror: 1 } }, metronome: { inherit: true, flags: { failencore: 1 }, noMetronome: [ "Counter", "Destiny Bond", "Detect", "Endure", "Metronome", "Mimic", "Mirror Coat", "Protect", "Sketch", "Sleep Talk", "Struggle", "Thief" ], noSketch: true }, mimic: { inherit: true, accuracy: 100, noSketch: true, flags: { protect: 1, bypasssub: 1, allyanim: 1, failencore: 1, noassist: 1 } }, mindreader: { inherit: true, onTryHit(target) { if (target.volatiles["foresight"] || target.volatiles["lockon"]) return false; } }, mirrorcoat: { inherit: true, damageCallback(pokemon, target) { const lastAttackedBy = pokemon.getLastAttackedBy(); if (!lastAttackedBy?.move || !lastAttackedBy.thisTurn) return false; if (this.getCategory(lastAttackedBy.move) === "Special" && target.lastMove?.id !== "sleeptalk") { return 2 * lastAttackedBy.damage; } return false; }, beforeTurnCallback() { }, onTry() { }, condition: {}, priority: -1 }, mirrormove: { inherit: true, flags: { failencore: 1 }, onHit(pokemon) { const noMirror = ["metronome", "mimic", "mirrormove", "sketch", "sleeptalk", "transform"]; const target = pokemon.side.foe.active[0]; const lastMove = target?.lastMove && target?.lastMove.id; if (!lastMove || !pokemon.activeTurns && !target.moveThisTurn) { return false; } if (noMirror.includes(lastMove) || pokemon.moves.includes(lastMove)) { return false; } this.actions.useMove(lastMove, pokemon); }, noSketch: true }, mist: { num: 54, accuracy: true, basePower: 0, category: "Status", name: "Mist", pp: 30, priority: 0, flags: {}, volatileStatus: "mist", condition: { onStart(pokemon) { this.add("-start", pokemon, "Mist"); }, onTryBoost(boost, target, source, effect) { if (source && target !== source) { let showMsg = false; let i; for (i in boost) { if (boost[i] < 0) { delete boost[i]; showMsg = true; } } if (showMsg && !effect.secondaries) { this.add("-activate", target, "move: Mist"); } } } }, secondary: null, target: "self", type: "Ice" }, moonlight: { inherit: true, onHit(pokemon) { if (this.field.isWeather(["sunnyday", "desolateland"])) { this.heal(pokemon.maxhp); } else if (this.field.isWeather(["raindance", "primordialsea", "sandstorm", "hail"])) { this.heal(pokemon.baseMaxhp / 4); } else { this.heal(pokemon.baseMaxhp / 2); } } }, morningsun: { inherit: true, onHit(pokemon) { if (this.field.isWeather(["sunnyday", "desolateland"])) { this.heal(pokemon.maxhp); } else if (this.field.isWeather(["raindance", "primordialsea", "sandstorm", "hail"])) { this.heal(pokemon.baseMaxhp / 4); } else { this.heal(pokemon.baseMaxhp / 2); } } }, nightmare: { inherit: true, condition: { noCopy: true, onStart(pokemon) { if (pokemon.status !== "slp") { return false; } this.add("-start", pokemon, "Nightmare"); }, onAfterMoveSelfPriority: 1, onAfterMoveSelf(pokemon) { if (pokemon.status === "slp") this.damage(pokemon.baseMaxhp / 4); } } }, outrage: { inherit: true, onMoveFail(target, source, move) { source.addVolatile("lockedmove"); }, onAfterMove(pokemon) { if (pokemon.volatiles["lockedmove"] && pokemon.volatiles["lockedmove"].duration === 1) { pokemon.removeVolatile("lockedmove"); } } }, painsplit: { inherit: true, accuracy: 100 }, perishsong: { inherit: true, condition: { duration: 4, onEnd(target) { this.add("-start", target, "perish0"); target.faint(); }, onResidualOrder: 4, onResidual(pokemon) { const duration = pokemon.volatiles["perishsong"].duration; this.add("-start", pokemon, "perish" + duration); } } }, petaldance: { inherit: true, onMoveFail(target, source, move) { source.addVolatile("lockedmove"); }, onAfterMove(pokemon) { if (pokemon.volatiles["lockedmove"] && pokemon.volatiles["lockedmove"].duration === 1) { pokemon.removeVolatile("lockedmove"); } } }, poisongas: { inherit: true, ignoreImmunity: false }, poisonpowder: { inherit: true, ignoreImmunity: false }, protect: { inherit: true, priority: 2 }, psywave: { inherit: true, damageCallback(pokemon) { return this.random(1, pokemon.level + Math.floor(pokemon.level / 2)); } }, pursuit: { inherit: true, onModifyMove() { }, condition: { duration: 1, onBeforeSwitchOut(pokemon) { this.debug("Pursuit start"); let alreadyAdded = false; for (const source of this.effectState.sources) { if (source.speed < pokemon.speed || source.speed === pokemon.speed && this.random(2) === 0) { pokemon.removeVolatile("destinybond"); } if (!this.queue.cancelMove(source) || !source.hp) continue; if (!alreadyAdded) { this.add("-activate", pokemon, "move: Pursuit"); alreadyAdded = true; } if (source.canMegaEvo || source.canUltraBurst) { for (const [actionIndex, action] of this.queue.entries()) { if (action.pokemon === source && action.choice === "megaEvo") { this.actions.runMegaEvo(source); this.queue.list.splice(actionIndex, 1); break; } } } this.actions.runMove("pursuit", source, source.getLocOf(pokemon)); } } } }, razorleaf: { inherit: true, critRatio: 3 }, razorwind: { inherit: true, accuracy: 75, critRatio: 3, onPrepareHit(target, source) { return source.status !== "slp"; } }, reflect: { inherit: true, condition: { duration: 5, // Defense boost applied directly in stat calculation onSideStart(side) { this.add("-sidestart", side, "Reflect"); }, onSideResidualOrder: 9, onSideEnd(side) { this.add("-sideend", side, "Reflect"); } } }, rest: { inherit: true, onTry(pokemon) { if (pokemon.hp < pokemon.maxhp) return; this.add("-fail", pokemon); return null; }, onHit(target, source, move) { if (target.status !== "slp") { if (!target.setStatus("slp", source, move)) return; } else { this.add("-status", target, "slp", "[from] move: Rest"); } target.statusState.time = 3; target.statusState.startTime = 3; target.statusState.source = target; this.heal(target.maxhp); }, secondary: null }, return: { inherit: true, basePowerCallback(pokemon) { return Math.floor(pokemon.happiness * 10 / 25) || null; } }, reversal: { inherit: true, noDamageVariance: true, willCrit: false }, roar: { inherit: true, onTryHit() { for (const action of this.queue) { if (action.choice === "move" || action.choice === "switch") return false; } }, priority: -1 }, safeguard: { inherit: true, condition: { duration: 5, durationCallback(target, source, effect) { if (source?.hasAbility("persistent")) { this.add("-activate", source, "ability: Persistent", effect); return 7; } return 5; }, onSetStatus(status, target, source, effect) { if (!effect || !source) return; if (effect.id === "yawn") return; if (effect.effectType === "Move" && effect.infiltrates && !target.isAlly(source)) return; if (target !== source) { this.debug("interrupting setStatus"); if (effect.id === "synchronize" || effect.effectType === "Move" && !effect.secondaries) { this.add("-activate", target, "move: Safeguard"); } return null; } }, onTryAddVolatile(status, target, source, effect) { if (!effect || !source) return; if (effect.effectType === "Move" && effect.infiltrates && !target.isAlly(source)) return; if ((status.id === "confusion" || status.id === "yawn") && target !== source) { if (effect.effectType === "Move" && !effect.secondaries) this.add("-activate", target, "move: Safeguard"); return null; } }, onSideStart(side) { this.add("-sidestart", side, "Safeguard"); }, onSideResidualOrder: 8, onSideEnd(side) { this.add("-sideend", side, "Safeguard"); } } }, selfdestruct: { inherit: true, noSketch: true }, sketch: { inherit: true, flags: { bypasssub: 1, failencore: 1, noassist: 1 }, onHit() { this.add("-nothing"); } }, skullbash: { inherit: true, onPrepareHit(target, source) { return source.status !== "slp"; } }, skyattack: { inherit: true, critRatio: 1, onPrepareHit(target, source) { return source.status !== "slp"; }, secondary: null }, slash: { inherit: true, critRatio: 3 }, sleeptalk: { inherit: true, flags: { failencore: 1, nosleeptalk: 1 }, onHit(pokemon) { const moves = []; for (const moveSlot of pokemon.moveSlots) { const moveid = moveSlot.id; const move = this.dex.moves.get(moveid); if (moveid && !move.flags["nosleeptalk"] && !move.flags["charge"]) { moves.push(moveid); } } let randomMove = ""; if (moves.length) randomMove = this.sample(moves); if (!randomMove) return false; this.actions.useMove(randomMove, pokemon); }, noSketch: true }, solarbeam: { inherit: true, onPrepareHit(target, source) { return source.status !== "slp"; }, // Rain weakening done directly in the damage formula onBasePower() { } }, spiderweb: { inherit: true, flags: { reflectable: 1, mirror: 1 } }, spikes: { inherit: true, condition: { // this is a side condition onSideStart(side) { if (!this.effectState.layers || this.effectState.layers === 0) { this.add("-sidestart", side, "Spikes"); this.effectState.layers = 1; } else { return false; } }, onSwitchIn(pokemon) { if (!pokemon.runImmunity("Ground")) return; const damageAmounts = [0, 3]; this.damage(damageAmounts[this.effectState.layers] * pokemon.maxhp / 24); } } }, substitute: { inherit: true, condition: { onStart(target) { this.add("-start", target, "Substitute"); this.effectState.hp = Math.floor(target.maxhp / 4); delete target.volatiles["partiallytrapped"]; }, onTryPrimaryHitPriority: -1, onTryPrimaryHit(target, source, move) { if (move.stallingMove) { this.add("-fail", source); return null; } if (target === source) { this.debug("sub bypass: self hit"); return; } if (move.id === "twineedle") { move.secondaries = move.secondaries.filter((p) => !p.kingsrock); } if (move.drain) { this.add("-miss", source); this.hint("In Gen 2, draining moves always miss against Substitute."); return null; } if (move.category === "Status") { const SubBlocked = ["leechseed", "lockon", "mindreader", "nightmare", "painsplit", "sketch"]; if (move.id === "swagger") { delete move.volatileStatus; } if (move.status || move.boosts && move.id !== "swagger" || move.volatileStatus === "confusion" || SubBlocked.includes(move.id)) { this.add("-activate", target, "Substitute", "[block] " + move.name); return null; } return; } let damage = this.actions.getDamage(source, target, move); if (!damage) { return null; } damage = this.runEvent("SubDamage", target, source, move, damage); if (!damage) { return damage; } if (damage > target.volatiles["substitute"].hp) { damage = target.volatiles["substitute"].hp; } target.volatiles["substitute"].hp -= damage; source.lastDamage = damage; if (target.volatiles["substitute"].hp <= 0) { target.removeVolatile("substitute"); } else { this.add("-activate", target, "Substitute", "[damage]"); } if (move.recoil) { this.damage(1, source, target, "recoil"); } this.runEvent("AfterSubDamage", target, source, move, damage); return this.HIT_SUBSTITUTE; }, onEnd(target) { this.add("-end", target, "Substitute"); } } }, swagger: { inherit: true, onTryHit(target, pokemon) { if (target.boosts.atk >= 6 || target.getStat("atk", false, true) === 999) { this.add("-miss", pokemon); return null; } } }, synthesis: { inherit: true, onHit(pokemon) { if (this.field.isWeather(["sunnyday", "desolateland"])) { this.heal(pokemon.maxhp); } else if (this.field.isWeather(["raindance", "primordialsea", "sandstorm", "hail"])) { this.heal(pokemon.baseMaxhp / 4); } else { this.heal(pokemon.baseMaxhp / 2); } } }, thief: { inherit: true, onAfterHit() { }, secondary: { chance: 100, onHit(target, source) { if (source.item || source.volatiles["gem"]) { return; } const yourItem = target.takeItem(source); if (!yourItem) { return; } if (!source.setItem(yourItem)) { target.item = yourItem.id; return; } this.add("-item", source, yourItem, "[from] move: Thief", "[of] " + target); } } }, thrash: { inherit: true, onMoveFail(target, source, move) { source.addVolatile("lockedmove"); }, onAfterMove(pokemon) { if (pokemon.volatiles["lockedmove"] && pokemon.volatiles["lockedmove"].duration === 1) { pokemon.removeVolatile("lockedmove"); } } }, toxic: { inherit: true, ignoreImmunity: false }, transform: { inherit: true, noSketch: true }, triattack: { inherit: true, onHit(target, source, move) { move.statusRoll = ["par", "frz", "brn"][this.random(3)]; }, secondary: { chance: 20, onHit(target, source, move) { if (move.statusRoll) { target.trySetStatus(move.statusRoll, source); } } } }, triplekick: { inherit: true, multiaccuracy: false, multihit: [1, 3] }, whirlwind: { inherit: true, onTryHit() { for (const action of this.queue) { if (action.choice === "move" || action.choice === "switch") return false; } }, priority: -1 } }; //# sourceMappingURL=moves.js.map