mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-21 17:25:10 -05:00
This adds some new `data/text/` files, which are the new home for item/move/ability descriptions, as well as in-game messages, in one place for ease of translation.
305 lines
7.2 KiB
TypeScript
305 lines
7.2 KiB
TypeScript
export const Moves: {[k: string]: ModdedMoveData} = {
|
|
allyswitch: {
|
|
inherit: true,
|
|
priority: 1,
|
|
},
|
|
darkvoid: {
|
|
inherit: true,
|
|
accuracy: 80,
|
|
onTryMove() {},
|
|
},
|
|
destinybond: {
|
|
inherit: true,
|
|
onPrepareHit(pokemon) {
|
|
pokemon.removeVolatile('destinybond');
|
|
},
|
|
},
|
|
diamondstorm: {
|
|
inherit: true,
|
|
secondary: {
|
|
chance: 50,
|
|
self: {
|
|
boosts: {
|
|
def: 1,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
encore: {
|
|
inherit: true,
|
|
condition: {
|
|
duration: 3,
|
|
onStart(target) {
|
|
const noEncore = ['encore', 'mimic', 'mirrormove', 'sketch', 'struggle', 'transform'];
|
|
const moveIndex = target.lastMove ? target.moves.indexOf(target.lastMove.id) : -1;
|
|
if (
|
|
!target.lastMove || noEncore.includes(target.lastMove.id) ||
|
|
!target.moveSlots[moveIndex] || target.moveSlots[moveIndex].pp <= 0
|
|
) {
|
|
// it failed
|
|
return false;
|
|
}
|
|
this.effectData.move = target.lastMove.id;
|
|
this.add('-start', target, 'Encore');
|
|
if (!this.queue.willMove(target)) {
|
|
this.effectData.duration++;
|
|
}
|
|
},
|
|
onOverrideAction(pokemon, target, move) {
|
|
if (move.id !== this.effectData.move) return this.effectData.move;
|
|
},
|
|
onResidualOrder: 13,
|
|
onResidual(target) {
|
|
const lockedMoveIndex = target.moves.indexOf(this.effectData.move);
|
|
if (lockedMoveIndex >= 0 && target.moveSlots[lockedMoveIndex].pp <= 0) {
|
|
// Encore ends early if you run out of PP
|
|
target.removeVolatile('encore');
|
|
}
|
|
},
|
|
onEnd(target) {
|
|
this.add('-end', target, 'Encore');
|
|
},
|
|
onDisableMove(pokemon) {
|
|
if (!this.effectData.move || !pokemon.hasMove(this.effectData.move)) {
|
|
return;
|
|
}
|
|
for (const moveSlot of pokemon.moveSlots) {
|
|
if (moveSlot.id !== this.effectData.move) {
|
|
pokemon.disableMove(moveSlot.id);
|
|
}
|
|
}
|
|
},
|
|
},
|
|
},
|
|
fellstinger: {
|
|
inherit: true,
|
|
basePower: 30,
|
|
onAfterMoveSecondarySelf(pokemon, target, move) {
|
|
if (!target || target.fainted || target.hp <= 0) this.boost({atk: 2}, pokemon, pokemon, move);
|
|
},
|
|
},
|
|
flyingpress: {
|
|
inherit: true,
|
|
basePower: 80,
|
|
},
|
|
gastroacid: {
|
|
inherit: true,
|
|
onTryHit(pokemon) {
|
|
const bannedAbilities = ['multitype', 'stancechange'];
|
|
if (bannedAbilities.includes(pokemon.ability)) {
|
|
return false;
|
|
}
|
|
},
|
|
},
|
|
leechlife: {
|
|
inherit: true,
|
|
basePower: 20,
|
|
pp: 15,
|
|
},
|
|
minimize: {
|
|
inherit: true,
|
|
condition: {
|
|
noCopy: true,
|
|
onSourceModifyDamage(damage, source, target, move) {
|
|
const boostedMoves = [
|
|
'stomp', 'steamroller', 'bodyslam', 'flyingpress', 'dragonrush', 'phantomforce', 'heatcrash', 'shadowforce',
|
|
];
|
|
if (boostedMoves.includes(move.id)) {
|
|
return this.chainModify(2);
|
|
}
|
|
},
|
|
onAccuracy(accuracy, target, source, move) {
|
|
const boostedMoves = [
|
|
'stomp', 'steamroller', 'bodyslam', 'flyingpress', 'dragonrush', 'phantomforce', 'heatcrash', 'shadowforce',
|
|
];
|
|
if (boostedMoves.includes(move.id)) {
|
|
return true;
|
|
}
|
|
return accuracy;
|
|
},
|
|
},
|
|
},
|
|
mistyterrain: {
|
|
inherit: true,
|
|
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 as Move).status || effect.id === 'yawn')) {
|
|
this.add('-activate', target, 'move: Misty Terrain');
|
|
}
|
|
return false;
|
|
},
|
|
onBasePower(basePower, attacker, defender, move) {
|
|
if (move.type === 'Dragon' && defender.isGrounded() && !defender.isSemiInvulnerable()) {
|
|
this.debug('misty terrain weaken');
|
|
return this.chainModify(0.5);
|
|
}
|
|
},
|
|
onStart(battle, source, effect) {
|
|
if (effect?.effectType === 'Ability') {
|
|
this.add('-fieldstart', 'move: Misty Terrain', '[from] ability: ' + effect, '[of] ' + source);
|
|
} else {
|
|
this.add('-fieldstart', 'move: Misty Terrain');
|
|
}
|
|
},
|
|
onResidualOrder: 21,
|
|
onResidualSubOrder: 2,
|
|
onEnd(side) {
|
|
this.add('-fieldend', 'Misty Terrain');
|
|
},
|
|
},
|
|
},
|
|
mysticalfire: {
|
|
inherit: true,
|
|
basePower: 65,
|
|
},
|
|
paraboliccharge: {
|
|
inherit: true,
|
|
basePower: 50,
|
|
},
|
|
partingshot: {
|
|
inherit: true,
|
|
onHit(target, source) {
|
|
this.boost({atk: -1, spa: -1}, target, source);
|
|
},
|
|
},
|
|
powder: {
|
|
inherit: true,
|
|
condition: {
|
|
duration: 1,
|
|
onStart(target) {
|
|
this.add('-singleturn', target, 'Powder');
|
|
},
|
|
onTryMovePriority: 1,
|
|
onTryMove(pokemon, target, move) {
|
|
if (move.type === 'Fire') {
|
|
this.add('-activate', pokemon, 'move: Powder');
|
|
this.damage(this.clampIntRange(Math.round(pokemon.maxhp / 4), 1));
|
|
return false;
|
|
}
|
|
},
|
|
},
|
|
},
|
|
rockblast: {
|
|
inherit: true,
|
|
flags: {protect: 1, mirror: 1},
|
|
},
|
|
sheercold: {
|
|
inherit: true,
|
|
ohko: true,
|
|
},
|
|
simplebeam: {
|
|
inherit: true,
|
|
onTryHit(pokemon) {
|
|
const bannedAbilities = ['multitype', 'simple', 'stancechange', 'truant'];
|
|
if (bannedAbilities.includes(pokemon.ability)) {
|
|
return false;
|
|
}
|
|
},
|
|
},
|
|
skillswap: {
|
|
inherit: true,
|
|
onTryHit(target, source) {
|
|
const bannedAbilities = ['illusion', 'multitype', 'stancechange', 'wonderguard'];
|
|
if (bannedAbilities.includes(target.ability) || bannedAbilities.includes(source.ability)) {
|
|
return false;
|
|
}
|
|
},
|
|
},
|
|
stockpile: {
|
|
inherit: true,
|
|
condition: {
|
|
noCopy: true,
|
|
onStart(target) {
|
|
this.effectData.layers = 1;
|
|
this.add('-start', target, 'stockpile' + this.effectData.layers);
|
|
this.boost({def: 1, spd: 1}, target, target);
|
|
},
|
|
onRestart(target) {
|
|
if (this.effectData.layers >= 3) return false;
|
|
this.effectData.layers++;
|
|
this.add('-start', target, 'stockpile' + this.effectData.layers);
|
|
this.boost({def: 1, spd: 1}, target, target);
|
|
},
|
|
onEnd(target) {
|
|
const layers = this.effectData.layers * -1;
|
|
this.effectData.layers = 0;
|
|
this.boost({def: layers, spd: layers}, target, target);
|
|
this.add('-end', target, 'Stockpile');
|
|
},
|
|
},
|
|
},
|
|
suckerpunch: {
|
|
inherit: true,
|
|
basePower: 80,
|
|
},
|
|
swagger: {
|
|
inherit: true,
|
|
accuracy: 90,
|
|
},
|
|
tackle: {
|
|
inherit: true,
|
|
basePower: 50,
|
|
},
|
|
thousandarrows: {
|
|
inherit: true,
|
|
isNonstandard: "Unobtainable",
|
|
},
|
|
thousandwaves: {
|
|
inherit: true,
|
|
isNonstandard: "Unobtainable",
|
|
},
|
|
thunderwave: {
|
|
inherit: true,
|
|
accuracy: 100,
|
|
},
|
|
watershuriken: {
|
|
inherit: true,
|
|
category: "Physical",
|
|
},
|
|
wideguard: {
|
|
inherit: true,
|
|
condition: {
|
|
duration: 1,
|
|
onStart(target, source) {
|
|
this.add('-singleturn', source, 'Wide Guard');
|
|
},
|
|
onTryHitPriority: 4,
|
|
onTryHit(target, source, effect) {
|
|
// Wide Guard blocks damaging spread moves
|
|
if (
|
|
effect &&
|
|
(effect.category === 'Status' || (effect.target !== 'allAdjacent' && effect.target !== 'allAdjacentFoes'))
|
|
) {
|
|
return;
|
|
}
|
|
this.add('-activate', target, 'move: Wide Guard');
|
|
const lockedmove = source.getVolatile('lockedmove');
|
|
if (lockedmove) {
|
|
// Outrage counter is reset
|
|
if (source.volatiles['lockedmove'].duration === 2) {
|
|
delete source.volatiles['lockedmove'];
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
},
|
|
},
|
|
worryseed: {
|
|
inherit: true,
|
|
onTryHit(pokemon) {
|
|
const bannedAbilities = ['insomnia', 'multitype', 'stancechange', 'truant'];
|
|
if (bannedAbilities.includes(pokemon.ability)) {
|
|
return false;
|
|
}
|
|
},
|
|
},
|
|
};
|