mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-21 17:25:10 -05:00
Support inheritance of ability, item, and move conditions (#11754)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run
This commit is contained in:
parent
2dfe57c13a
commit
815b5f260a
|
|
@ -211,22 +211,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
disable: {
|
||||
num: 50,
|
||||
accuracy: 55,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Disable",
|
||||
pp: 20,
|
||||
priority: 0,
|
||||
flags: { protect: 1, mirror: 1, bypasssub: 1, metronome: 1 },
|
||||
volatileStatus: 'disable',
|
||||
inherit: true,
|
||||
onTryHit(target) {
|
||||
// This function should not return if the checks are met. Adding && undefined ensures this happens.
|
||||
return target.moveSlots.some(ms => ms.pp > 0) &&
|
||||
!('disable' in target.volatiles) &&
|
||||
undefined;
|
||||
return target.moveSlots.some(ms => ms.pp > 0);
|
||||
},
|
||||
condition: {
|
||||
inherit: true,
|
||||
durationCallback: undefined,
|
||||
onStart(pokemon) {
|
||||
// disable can only select moves that have pp > 0, hence the onTryHit modification
|
||||
const moveSlot = this.sample(pokemon.moveSlots.filter(ms => ms.pp > 0));
|
||||
|
|
@ -235,9 +226,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
// 1-8 turns (which will in effect translate to 0-7 missed turns for the target)
|
||||
this.effectState.time = this.random(1, 9);
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'Disable');
|
||||
},
|
||||
onBeforeMovePriority: 6,
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
pokemon.volatiles['disable'].time--;
|
||||
|
|
@ -252,17 +240,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id === this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
type: "Normal",
|
||||
},
|
||||
dizzypunch: {
|
||||
inherit: true,
|
||||
|
|
@ -319,11 +297,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
focusenergy: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Focus Energy');
|
||||
},
|
||||
inherit: true,
|
||||
// This does nothing as it's dealt with on critical hit calculation.
|
||||
onModifyMove() {},
|
||||
onModifyCritRatio() {},
|
||||
},
|
||||
},
|
||||
glare: {
|
||||
|
|
@ -408,9 +384,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
onHit() {},
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: Leech Seed');
|
||||
},
|
||||
inherit: true,
|
||||
onAfterMoveSelfPriority: 1,
|
||||
onAfterMoveSelf(pokemon) {
|
||||
const leecher = this.getAtSlot(pokemon.volatiles['leechseed'].sourceSlot);
|
||||
|
|
@ -436,15 +410,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
lightscreen: {
|
||||
num: 113,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Light Screen",
|
||||
pp: 30,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
inherit: true,
|
||||
volatileStatus: 'lightscreen',
|
||||
sideCondition: undefined,
|
||||
onTryHit(pokemon) {
|
||||
if (pokemon.volatiles['lightscreen']) {
|
||||
return false;
|
||||
|
|
@ -456,7 +424,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
target: "self",
|
||||
type: "Psychic",
|
||||
},
|
||||
metronome: {
|
||||
inherit: true,
|
||||
|
|
@ -497,6 +464,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-start', source, 'Mimic', move.name);
|
||||
},
|
||||
},
|
||||
minimize: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
onSourceModifyDamage() {},
|
||||
},
|
||||
},
|
||||
mirrormove: {
|
||||
inherit: true,
|
||||
onHit(pokemon) {
|
||||
|
|
@ -511,9 +485,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mist: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'Mist');
|
||||
},
|
||||
inherit: true,
|
||||
onTryBoost(boost, target, source, effect) {
|
||||
if (effect.effectType === 'Move' && effect.category !== 'Status') return;
|
||||
if (source && target !== source) {
|
||||
|
|
@ -629,15 +601,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
reflect: {
|
||||
num: 115,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Reflect",
|
||||
pp: 20,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
inherit: true,
|
||||
volatileStatus: 'reflect',
|
||||
sideCondition: undefined,
|
||||
onTryHit(pokemon) {
|
||||
if (pokemon.volatiles['reflect']) {
|
||||
return false;
|
||||
|
|
@ -648,9 +614,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.add('-start', pokemon, 'Reflect');
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Psychic",
|
||||
},
|
||||
rest: {
|
||||
inherit: true,
|
||||
|
|
@ -782,15 +746,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
onModifyMove() {},
|
||||
},
|
||||
substitute: {
|
||||
num: 164,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Substitute",
|
||||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
volatileStatus: 'substitute',
|
||||
inherit: true,
|
||||
onTryHit(target) {
|
||||
if (target.volatiles['substitute']) {
|
||||
this.add('-fail', target, 'move: Substitute');
|
||||
|
|
@ -810,11 +766,16 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
inherit: true,
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4) + 1;
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
if (target.volatiles['partiallytrapped']) {
|
||||
this.add('-end', target, target.volatiles['partiallytrapped'].sourceEffect, '[partiallytrapped]', '[silent]');
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
}
|
||||
},
|
||||
onTryPrimaryHit() {},
|
||||
onTryHitPriority: -1,
|
||||
onTryHit(target, source, move) {
|
||||
if (move.category === 'Status') {
|
||||
|
|
@ -878,13 +839,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return 0;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Normal",
|
||||
},
|
||||
superfang: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -13,12 +13,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
substitute: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4) + 1;
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
},
|
||||
onTryHitPriority: -1,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (move.drain) {
|
||||
this.add('-miss', source);
|
||||
|
|
@ -76,9 +71,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return accuracy;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
},
|
||||
swift: {
|
||||
|
|
|
|||
|
|
@ -160,11 +160,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
volatileStatus: 'rage',
|
||||
},
|
||||
condition: {
|
||||
inherit: true,
|
||||
// Rage lock
|
||||
onStart(target, source, effect) {
|
||||
this.effectState.move = 'rage';
|
||||
},
|
||||
onLockMove: 'rage',
|
||||
onHit(target, source, move) {
|
||||
if (target.boosts.atk < 6 && (move.category !== 'Status' || move.id === 'disable')) {
|
||||
this.boost({ atk: 1 });
|
||||
|
|
@ -220,12 +220,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Substitute');
|
||||
this.effectState.hp = Math.floor(target.maxhp / 4);
|
||||
delete target.volatiles['partiallytrapped'];
|
||||
},
|
||||
onTryHitPriority: -1,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (target === source) {
|
||||
this.debug('sub bypass: self hit');
|
||||
|
|
@ -275,9 +270,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return 0;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
|
|
|
|||
|
|
@ -51,64 +51,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
bide: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 3,
|
||||
inherit: true,
|
||||
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',
|
||||
} as unknown as ActiveMove;
|
||||
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: {
|
||||
|
|
@ -139,12 +85,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
curse: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon, source) {
|
||||
this.add('-start', pokemon, 'Curse', `[of] ${source}`);
|
||||
},
|
||||
inherit: true,
|
||||
onAfterMoveSelfPriority: 0, // explicit
|
||||
onAfterMoveSelf(pokemon) {
|
||||
this.damage(pokemon.baseMaxhp / 4);
|
||||
},
|
||||
onResidual() {},
|
||||
},
|
||||
},
|
||||
detect: {
|
||||
|
|
@ -157,10 +103,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return source.status !== 'slp';
|
||||
},
|
||||
condition: {
|
||||
duration: 2,
|
||||
onImmunity(type, pokemon) {
|
||||
if (type === 'sandstorm') return false;
|
||||
},
|
||||
inherit: true,
|
||||
onInvulnerability(target, source, move) {
|
||||
if (move.id === 'earthquake' || move.id === 'magnitude' || move.id === 'fissure') {
|
||||
return;
|
||||
|
|
@ -172,6 +115,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
if (source.volatiles['lockon'] && target === source.volatiles['lockon'].source) return;
|
||||
return false;
|
||||
},
|
||||
onSourceModifyDamage() {},
|
||||
onSourceBasePower(basePower, target, source, move) {
|
||||
if (move.id === 'earthquake' || move.id === 'magnitude') {
|
||||
return this.chainModify(2);
|
||||
|
|
@ -186,9 +130,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
encore: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
durationCallback() {
|
||||
return this.random(3, 7);
|
||||
},
|
||||
inherit: true,
|
||||
onStart(target) {
|
||||
const lockedMove = target.lastMoveEncore?.id || '';
|
||||
const moveSlot = lockedMove ? target.getMoveData(lockedMove) : null;
|
||||
|
|
@ -199,30 +141,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.effectState.move = lockedMove;
|
||||
this.add('-start', target, 'Encore');
|
||||
},
|
||||
onOverrideAction(pokemon) {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onResidualOrder: 13,
|
||||
onResidual(target) {
|
||||
const lockedMoveSlot = target.getMoveData(this.effectState.move);
|
||||
if (lockedMoveSlot && lockedMoveSlot.pp <= 0) {
|
||||
// early termination if you run out of PP
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
onResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
endure: {
|
||||
|
|
@ -244,7 +164,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return source.status !== 'slp';
|
||||
},
|
||||
condition: {
|
||||
duration: 2,
|
||||
inherit: true,
|
||||
onInvulnerability(target, source, move) {
|
||||
if (move.id === 'gust' || move.id === 'twister' || move.id === 'thunder' || move.id === 'whirlwind') {
|
||||
return;
|
||||
|
|
@ -260,6 +180,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
if (source.volatiles['lockon'] && target === source.volatiles['lockon'].source) return;
|
||||
return false;
|
||||
},
|
||||
onSourceModifyDamage() {},
|
||||
onSourceBasePower(basePower, target, source, move) {
|
||||
if (move.id === 'gust' || move.id === 'twister') {
|
||||
return this.chainModify(2);
|
||||
|
|
@ -270,9 +191,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
focusenergy: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Focus Energy');
|
||||
},
|
||||
inherit: true,
|
||||
onModifyCritRatio(critRatio) {
|
||||
return critRatio + 1;
|
||||
},
|
||||
|
|
@ -284,17 +203,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
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;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
noCopy: false,
|
||||
},
|
||||
},
|
||||
frustration: {
|
||||
|
|
@ -340,9 +250,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
onHit() {},
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: Leech Seed');
|
||||
},
|
||||
inherit: true,
|
||||
onResidual() {},
|
||||
onAfterMoveSelfPriority: 2,
|
||||
onAfterMoveSelf(pokemon) {
|
||||
if (!pokemon.hp) return;
|
||||
|
|
@ -378,10 +287,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
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;
|
||||
},
|
||||
inherit: true,
|
||||
onSourceInvulnerability() {},
|
||||
},
|
||||
},
|
||||
lowkick: {
|
||||
|
|
@ -449,15 +356,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
mist: {
|
||||
num: 54,
|
||||
accuracy: true,
|
||||
basePower: 0,
|
||||
category: "Status",
|
||||
name: "Mist",
|
||||
pp: 30,
|
||||
priority: 0,
|
||||
flags: { metronome: 1 },
|
||||
inherit: true,
|
||||
volatileStatus: 'mist',
|
||||
sideCondition: undefined,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'Mist');
|
||||
|
|
@ -478,9 +379,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
},
|
||||
secondary: null,
|
||||
target: "self",
|
||||
type: "Ice",
|
||||
},
|
||||
moonlight: {
|
||||
inherit: true,
|
||||
|
|
@ -509,13 +408,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
nightmare: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onStart(pokemon) {
|
||||
if (pokemon.status !== 'slp') {
|
||||
return false;
|
||||
}
|
||||
this.add('-start', pokemon, 'Nightmare');
|
||||
},
|
||||
inherit: true,
|
||||
onResidual() {},
|
||||
onAfterMoveSelfPriority: 1,
|
||||
onAfterMoveSelf(pokemon) {
|
||||
if (pokemon.status === 'slp') this.damage(pokemon.baseMaxhp / 4);
|
||||
|
|
@ -535,16 +429,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
perishsong: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 4,
|
||||
onEnd(target) {
|
||||
this.add('-start', target, 'perish0');
|
||||
target.faint();
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 4,
|
||||
onResidual(pokemon) {
|
||||
const duration = pokemon.volatiles['perishsong'].duration;
|
||||
this.add('-start', pokemon, `perish${duration}`);
|
||||
},
|
||||
},
|
||||
},
|
||||
petaldance: {
|
||||
|
|
@ -584,7 +470,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
onModifyMove() {},
|
||||
condition: {
|
||||
duration: 1,
|
||||
inherit: true,
|
||||
onBeforeSwitchOut(pokemon) {
|
||||
this.debug('Pursuit start');
|
||||
let alreadyAdded = false;
|
||||
|
|
@ -684,41 +570,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
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');
|
||||
},
|
||||
inherit: true,
|
||||
onSideResidualOrder: 8,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Safeguard');
|
||||
},
|
||||
},
|
||||
},
|
||||
selfdestruct: {
|
||||
|
|
@ -784,31 +637,14 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
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);
|
||||
},
|
||||
inherit: true,
|
||||
onSideRestart: undefined,
|
||||
},
|
||||
},
|
||||
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,
|
||||
inherit: true,
|
||||
onTryPrimaryHit(target, source, move) {
|
||||
if (move.stallingMove) {
|
||||
this.add('-fail', source);
|
||||
|
|
@ -861,9 +697,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.runEvent('AfterSubDamage', target, source, move, damage);
|
||||
return this.HIT_SUBSTITUTE;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
},
|
||||
swagger: {
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
lightningrod: {
|
||||
inherit: true,
|
||||
onAnyRedirectTarget() {},
|
||||
onFoeRedirectTarget(target, source, source2, move) {
|
||||
// don't count Hidden Power as Electric-type
|
||||
if (this.dex.moves.get(move.id).type !== 'Electric') return;
|
||||
|
|
@ -98,10 +100,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.effectState.target;
|
||||
}
|
||||
},
|
||||
flags: { breakable: 1 },
|
||||
name: "Lightning Rod",
|
||||
rating: 0,
|
||||
num: 32,
|
||||
},
|
||||
magnetpull: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
num: 208,
|
||||
gen: 3,
|
||||
isNonstandard: "Unobtainable",
|
||||
// No competitive use
|
||||
},
|
||||
fastball: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
astonish: {
|
||||
inherit: true,
|
||||
basePowerCallback(pokemon, target) {
|
||||
if (target.volatiles['minimize']) return 60;
|
||||
return 30;
|
||||
},
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
},
|
||||
beatup: {
|
||||
inherit: true,
|
||||
|
|
@ -63,18 +60,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
accuracy: 100,
|
||||
priority: 0,
|
||||
condition: {
|
||||
duration: 3,
|
||||
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;
|
||||
},
|
||||
inherit: true,
|
||||
onAfterSetStatus() {},
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
if (this.effectState.duration === 1) {
|
||||
this.add('-end', pokemon, 'move: Bide');
|
||||
|
|
@ -112,12 +99,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
this.add('-activate', pokemon, 'move: Bide');
|
||||
},
|
||||
onMoveAborted(pokemon) {
|
||||
pokemon.removeVolatile('bide');
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Bide', '[silent]');
|
||||
},
|
||||
},
|
||||
},
|
||||
blizzard: {
|
||||
|
|
@ -183,17 +164,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
counter: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
noCopy: true,
|
||||
onStart(target, source, move) {
|
||||
this.effectState.slot = null;
|
||||
this.effectState.damage = 0;
|
||||
},
|
||||
onRedirectTargetPriority: -1,
|
||||
inherit: true,
|
||||
onRedirectTarget(target, source, source2) {
|
||||
if (source !== this.effectState.target || !this.effectState.slot) return;
|
||||
return this.getAtSlot(this.effectState.slot);
|
||||
},
|
||||
onDamagingHit() {},
|
||||
onDamagePriority: -101,
|
||||
onDamage(damage, target, source, effect) {
|
||||
if (
|
||||
|
|
@ -227,48 +203,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
accuracy: 55,
|
||||
flags: { protect: 1, mirror: 1, bypasssub: 1, metronome: 1 },
|
||||
volatileStatus: 'disable',
|
||||
condition: {
|
||||
inherit: true,
|
||||
durationCallback() {
|
||||
return this.random(2, 6);
|
||||
},
|
||||
noCopy: true,
|
||||
onStart(pokemon) {
|
||||
if (!this.queue.willMove(pokemon)) {
|
||||
this.effectState.duration!++;
|
||||
}
|
||||
if (!pokemon.lastMove) {
|
||||
return false;
|
||||
}
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id === pokemon.lastMove.id) {
|
||||
if (!moveSlot.pp) {
|
||||
return false;
|
||||
} else {
|
||||
this.add('-start', pokemon, 'Disable', moveSlot.move);
|
||||
this.effectState.move = pokemon.lastMove.id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Disable');
|
||||
},
|
||||
onBeforeMove(attacker, defender, move) {
|
||||
if (move.id === this.effectState.move) {
|
||||
this.add('cant', attacker, 'Disable', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id === this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
"onResidualOrder": undefined,
|
||||
"onResidualSubOrder": undefined,
|
||||
},
|
||||
},
|
||||
dive: {
|
||||
|
|
@ -312,51 +253,15 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
volatileStatus: 'encore',
|
||||
condition: {
|
||||
inherit: true,
|
||||
durationCallback() {
|
||||
return this.random(3, 7);
|
||||
},
|
||||
onStart(target, source) {
|
||||
const moveSlot = target.lastMove ? target.getMoveData(target.lastMove.id) : null;
|
||||
if (!target.lastMove || target.lastMove.flags['failencore'] || !moveSlot || moveSlot.pp <= 0) {
|
||||
// it failed
|
||||
return false;
|
||||
}
|
||||
this.effectState.move = target.lastMove.id;
|
||||
this.add('-start', target, 'Encore');
|
||||
},
|
||||
onOverrideAction(pokemon) {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 14,
|
||||
onResidual(target) {
|
||||
const moveSlot = target.getMoveData(this.effectState.move);
|
||||
if (moveSlot && moveSlot.pp <= 0) {
|
||||
// early termination if you run out of PP
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
extrasensory: {
|
||||
inherit: true,
|
||||
basePowerCallback(pokemon, target) {
|
||||
if (target.volatiles['minimize']) return 160;
|
||||
return 80;
|
||||
},
|
||||
flags: { protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
},
|
||||
fakeout: {
|
||||
inherit: true,
|
||||
|
|
@ -401,12 +306,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
volatileStatus: undefined,
|
||||
slotCondition: 'followme',
|
||||
condition: {
|
||||
duration: 1,
|
||||
inherit: true,
|
||||
onStart(target, source, effect) {
|
||||
this.add('-singleturn', target, 'move: Follow Me');
|
||||
this.effectState.slot = target.getSlot();
|
||||
},
|
||||
onFoeRedirectTargetPriority: 1,
|
||||
onFoeRedirectTarget(target, source, source2, move) {
|
||||
const userSlot = this.getAtSlot(this.effectState.slot);
|
||||
if (this.validTarget(userSlot, source, move.target)) {
|
||||
|
|
@ -504,17 +408,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mirrorcoat: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
noCopy: true,
|
||||
onStart(target, source, move) {
|
||||
this.effectState.slot = null;
|
||||
this.effectState.damage = 0;
|
||||
},
|
||||
onRedirectTargetPriority: -1,
|
||||
inherit: true,
|
||||
onRedirectTarget(target, source, source2) {
|
||||
if (source !== this.effectState.target || !this.effectState.slot) return;
|
||||
return this.getAtSlot(this.effectState.slot);
|
||||
},
|
||||
onDamagingHit() {},
|
||||
onDamagePriority: -101,
|
||||
onDamage(damage, target, source, effect) {
|
||||
if (
|
||||
|
|
@ -555,10 +454,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
needlearm: {
|
||||
inherit: true,
|
||||
basePowerCallback(pokemon, target) {
|
||||
if (target.volatiles['minimize']) return 120;
|
||||
return 60;
|
||||
},
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
},
|
||||
nightmare: {
|
||||
inherit: true,
|
||||
|
|
@ -697,28 +593,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, bypasssub: 1, metronome: 1 },
|
||||
condition: {
|
||||
inherit: true,
|
||||
duration: 2,
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: Taunt');
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 15,
|
||||
durationCallback: undefined,
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'move: Taunt', '[silent]');
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (this.dex.moves.get(moveSlot.move).category === 'Status') {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
onBeforeMove(attacker, defender, move) {
|
||||
if (move.category === 'Status') {
|
||||
this.add('cant', attacker, 'move: Taunt', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onBeforeMovePriority: undefined,
|
||||
},
|
||||
},
|
||||
teeterdance: {
|
||||
|
|
@ -732,37 +613,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
uproar: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Uproar');
|
||||
// 2-5 turns
|
||||
this.effectState.duration = this.random(2, 6);
|
||||
},
|
||||
onResidual(target) {
|
||||
if (target.volatiles['throatchop']) {
|
||||
target.removeVolatile('uproar');
|
||||
return;
|
||||
}
|
||||
if (target.lastMove && target.lastMove.id === 'struggle') {
|
||||
// don't lock
|
||||
delete target.volatiles['uproar'];
|
||||
}
|
||||
this.add('-start', target, 'Uproar', '[upkeep]');
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 11,
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Uproar');
|
||||
},
|
||||
onLockMove: 'uproar',
|
||||
onAnySetStatus(status, pokemon) {
|
||||
if (status.id === 'slp') {
|
||||
if (pokemon === this.effectState.target) {
|
||||
this.add('-fail', pokemon, 'slp', '[from] Uproar', '[msg]');
|
||||
} else {
|
||||
this.add('-fail', pokemon, 'slp', '[from] Uproar');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
inherit: true,
|
||||
durationCallback() {
|
||||
return this.random(2, 6);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
enigmaberry: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
},
|
||||
fastball: {
|
||||
inherit: true,
|
||||
isNonstandard: "Unobtainable",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onResidualSubOrder: 10,
|
||||
},
|
||||
blaze: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifySpA() {},
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Fire' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -30,9 +33,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Blaze",
|
||||
rating: 2,
|
||||
num: 66,
|
||||
},
|
||||
cloudnine: {
|
||||
inherit: true,
|
||||
|
|
@ -58,7 +58,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onSourceModifyAccuracy(accuracy) {
|
||||
if (typeof accuracy !== 'number') return;
|
||||
this.debug('compoundeyes - enhancing accuracy');
|
||||
return accuracy * 1.3;
|
||||
return this.chainModify(1.3);
|
||||
},
|
||||
inherit: true,
|
||||
},
|
||||
|
|
@ -128,19 +128,15 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
noCopy: true, // doesn't get copied by Baton Pass
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'ability: Flash Fire');
|
||||
},
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifySpA() {},
|
||||
onModifyDamagePhase1(atk, attacker, defender, move) {
|
||||
if (move.type === 'Fire') {
|
||||
this.debug('Flash Fire boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'ability: Flash Fire', '[silent]');
|
||||
},
|
||||
},
|
||||
},
|
||||
flowergift: {
|
||||
|
|
@ -200,20 +196,19 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onSourceModifyAccuracyPriority: 7,
|
||||
onSourceModifyAccuracy(accuracy, target, source, move) {
|
||||
if (move.category === 'Physical' && typeof accuracy === 'number') {
|
||||
return accuracy * 0.8;
|
||||
return this.chainModify(0.8);
|
||||
}
|
||||
},
|
||||
},
|
||||
hydration: {
|
||||
inherit: true,
|
||||
onResidual() {},
|
||||
onWeather(target, source, effect) {
|
||||
if (effect.id === 'raindance' && target.status) {
|
||||
this.add('-activate', target, 'ability: Hydration');
|
||||
target.cureStatus();
|
||||
}
|
||||
},
|
||||
name: "Hydration",
|
||||
rating: 1.5,
|
||||
num: 93,
|
||||
},
|
||||
insomnia: {
|
||||
inherit: true,
|
||||
|
|
@ -270,31 +265,24 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
magicguard: {
|
||||
onDamage(damage, target, source, effect) {
|
||||
if (effect.effectType !== 'Move') {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onSetStatus(status, target, source, effect) {
|
||||
if (effect && effect.id === 'toxicspikes') {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
name: "Magic Guard",
|
||||
rating: 4.5,
|
||||
num: 98,
|
||||
},
|
||||
minus: {
|
||||
inherit: true,
|
||||
onModifySpAPriority: undefined,
|
||||
onModifySpA(spa, pokemon) {
|
||||
for (const ally of pokemon.allies()) {
|
||||
if (ally.ability === 'plus') {
|
||||
return spa * 1.5;
|
||||
for (const allyActive of pokemon.allies()) {
|
||||
if (allyActive.hasAbility('plus')) {
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
}
|
||||
},
|
||||
name: "Minus",
|
||||
rating: 0,
|
||||
num: 58,
|
||||
},
|
||||
naturalcure: {
|
||||
inherit: true,
|
||||
|
|
@ -318,6 +306,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
overgrow: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifySpA() {},
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Grass' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -325,26 +316,23 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Overgrow",
|
||||
rating: 2,
|
||||
num: 65,
|
||||
},
|
||||
pickup: {
|
||||
name: "Pickup",
|
||||
inherit: true,
|
||||
onResidual() {},
|
||||
rating: 0,
|
||||
num: 53,
|
||||
// No competitive use
|
||||
},
|
||||
plus: {
|
||||
inherit: true,
|
||||
onModifySpAPriority: undefined,
|
||||
onModifySpA(spa, pokemon) {
|
||||
for (const ally of pokemon.allies()) {
|
||||
if (ally.ability === 'minus') {
|
||||
return spa * 1.5;
|
||||
for (const allyActive of pokemon.allies()) {
|
||||
if (allyActive.hasAbility('minus')) {
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
}
|
||||
},
|
||||
name: "Plus",
|
||||
rating: 0,
|
||||
num: 57,
|
||||
},
|
||||
poisonpoint: {
|
||||
inherit: true,
|
||||
|
|
@ -357,16 +345,12 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
pressure: {
|
||||
onStart(pokemon) {
|
||||
this.add('-ability', pokemon, 'Pressure');
|
||||
},
|
||||
inherit: true,
|
||||
onDeductPP(target, source) {
|
||||
if (target === source) return;
|
||||
return 1;
|
||||
},
|
||||
name: "Pressure",
|
||||
rating: 1.5,
|
||||
num: 46,
|
||||
},
|
||||
roughskin: {
|
||||
inherit: true,
|
||||
|
|
@ -383,7 +367,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
if (typeof accuracy !== 'number') return;
|
||||
if (this.field.isWeather('sandstorm')) {
|
||||
this.debug('Sand Veil - decreasing accuracy');
|
||||
return accuracy * 0.8;
|
||||
return this.chainModify(0.8);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -404,16 +388,14 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onResidualSubOrder: 3,
|
||||
},
|
||||
simple: {
|
||||
inherit: true,
|
||||
onChangeBoost() {},
|
||||
onModifyBoost(boosts) {
|
||||
let key: BoostID;
|
||||
for (key in boosts) {
|
||||
boosts[key]! *= 2;
|
||||
}
|
||||
},
|
||||
flags: { breakable: 1 },
|
||||
name: "Simple",
|
||||
rating: 4,
|
||||
num: 86,
|
||||
},
|
||||
snowcloak: {
|
||||
inherit: true,
|
||||
|
|
@ -422,7 +404,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
if (typeof accuracy !== 'number') return;
|
||||
if (this.field.isWeather('hail')) {
|
||||
this.debug('Snow Cloak - decreasing accuracy');
|
||||
return accuracy * 0.8;
|
||||
return this.chainModify(0.8);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -442,9 +424,10 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
},
|
||||
},
|
||||
stench: {
|
||||
name: "Stench",
|
||||
inherit: true,
|
||||
onModifyMove() {},
|
||||
rating: 0,
|
||||
num: 1,
|
||||
// No competitive use
|
||||
},
|
||||
stickyhold: {
|
||||
inherit: true,
|
||||
|
|
@ -466,6 +449,9 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
rating: 0,
|
||||
},
|
||||
swarm: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifySpA() {},
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Bug' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -473,9 +459,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Swarm",
|
||||
rating: 2,
|
||||
num: 68,
|
||||
},
|
||||
synchronize: {
|
||||
inherit: true,
|
||||
|
|
@ -495,23 +478,25 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
if (typeof accuracy !== 'number') return;
|
||||
if (target?.volatiles['confusion']) {
|
||||
this.debug('Tangled Feet - decreasing accuracy');
|
||||
return accuracy * 0.5;
|
||||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
},
|
||||
thickfat: {
|
||||
inherit: true,
|
||||
onSourceModifyAtk() {},
|
||||
onSourceModifySpA() {},
|
||||
onSourceBasePowerPriority: 1,
|
||||
onSourceBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Ice' || move.type === 'Fire') {
|
||||
return this.chainModify(0.5);
|
||||
}
|
||||
},
|
||||
flags: { breakable: 1 },
|
||||
name: "Thick Fat",
|
||||
rating: 3.5,
|
||||
num: 47,
|
||||
},
|
||||
torrent: {
|
||||
inherit: true,
|
||||
onModifyAtk() {},
|
||||
onModifySpA() {},
|
||||
onBasePowerPriority: 2,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Water' && attacker.hp <= attacker.maxhp / 3) {
|
||||
|
|
@ -519,9 +504,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
name: "Torrent",
|
||||
rating: 2,
|
||||
num: 67,
|
||||
},
|
||||
trace: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
},
|
||||
focussash: {
|
||||
inherit: true,
|
||||
onDamage() { },
|
||||
onDamage() {},
|
||||
onTryHit(target, source, move) {
|
||||
if (target !== source && target.hp === target.maxhp) {
|
||||
target.addVolatile('focussash');
|
||||
|
|
@ -306,11 +306,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
metronome: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.effectState.numConsecutive = 0;
|
||||
this.effectState.lastMove = '';
|
||||
},
|
||||
onTryMovePriority: -2,
|
||||
inherit: true,
|
||||
onTryMove(pokemon, target, move) {
|
||||
if (!pokemon.hasItem('metronome')) {
|
||||
pokemon.removeVolatile('metronome');
|
||||
|
|
@ -323,6 +319,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
}
|
||||
this.effectState.lastMove = move.id;
|
||||
},
|
||||
onModifyDamage() {},
|
||||
onModifyDamagePhase2(damage, source, target, move) {
|
||||
return damage * (1 + (this.effectState.numConsecutive / 10));
|
||||
},
|
||||
|
|
@ -331,7 +328,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
|
|||
micleberry: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 2,
|
||||
inherit: true,
|
||||
onSourceModifyAccuracyPriority: 3,
|
||||
onSourceModifyAccuracy(accuracy, target, source) {
|
||||
this.add('-enditem', source, 'Micle Berry');
|
||||
|
|
|
|||
|
|
@ -37,14 +37,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { metronome: 1 },
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'Aqua Ring');
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 2,
|
||||
onResidual(pokemon) {
|
||||
this.heal(pokemon.baseMaxhp / 16);
|
||||
},
|
||||
},
|
||||
},
|
||||
assist: {
|
||||
|
|
@ -109,18 +104,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
bide: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 3,
|
||||
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;
|
||||
},
|
||||
inherit: true,
|
||||
onAfterSetStatus(status, pokemon) {
|
||||
if (status.id === 'slp' || status.id === 'frz') {
|
||||
pokemon.removeVolatile('bide');
|
||||
|
|
@ -164,12 +148,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
this.add('-activate', pokemon, 'move: Bide');
|
||||
},
|
||||
onMoveAborted(pokemon) {
|
||||
pokemon.removeVolatile('bide');
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Bide', '[silent]');
|
||||
},
|
||||
},
|
||||
},
|
||||
bind: {
|
||||
|
|
@ -303,14 +281,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
onStart(pokemon, source) {
|
||||
this.add('-start', pokemon, 'Curse', `[of] ${source}`);
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 8,
|
||||
onResidual(pokemon) {
|
||||
this.damage(pokemon.baseMaxhp / 4);
|
||||
},
|
||||
},
|
||||
type: "???",
|
||||
},
|
||||
|
|
@ -321,36 +294,17 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
detect: {
|
||||
inherit: true,
|
||||
priority: 3,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target) {
|
||||
this.add('-singleturn', target, 'Protect');
|
||||
},
|
||||
onTryHitPriority: 3,
|
||||
onTryHit(target, source, move) {
|
||||
if (!move.flags['protect']) return;
|
||||
this.add('-activate', target, 'Protect');
|
||||
const lockedmove = source.getVolatile('lockedmove');
|
||||
if (lockedmove) {
|
||||
// Outrage counter is NOT reset
|
||||
if (source.volatiles['lockedmove'].trueDuration >= 2) {
|
||||
source.volatiles['lockedmove'].duration = 2;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
},
|
||||
},
|
||||
disable: {
|
||||
inherit: true,
|
||||
accuracy: 80,
|
||||
flags: { protect: 1, mirror: 1, bypasssub: 1, metronome: 1 },
|
||||
volatileStatus: 'disable',
|
||||
condition: {
|
||||
inherit: true,
|
||||
duration: undefined,
|
||||
durationCallback() {
|
||||
return this.random(4, 8);
|
||||
},
|
||||
noCopy: true,
|
||||
onStart(pokemon) {
|
||||
if (!this.queue.willMove(pokemon)) {
|
||||
this.effectState.duration!++;
|
||||
|
|
@ -373,23 +327,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 13,
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Disable');
|
||||
},
|
||||
onBeforeMovePriority: 7,
|
||||
onBeforeMove(attacker, defender, move) {
|
||||
if (move.id === this.effectState.move) {
|
||||
this.add('cant', attacker, 'Disable', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id === this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
doomdesire: {
|
||||
|
|
@ -451,16 +388,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
duration: 5,
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'Embargo');
|
||||
},
|
||||
// Item suppression implemented in Pokemon.ignoringItem() within sim/pokemon.js
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 18,
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'Embargo');
|
||||
},
|
||||
},
|
||||
},
|
||||
encore: {
|
||||
|
|
@ -468,43 +398,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
flags: { protect: 1, mirror: 1, bypasssub: 1, metronome: 1, failencore: 1 },
|
||||
volatileStatus: 'encore',
|
||||
condition: {
|
||||
inherit: true,
|
||||
duration: undefined,
|
||||
durationCallback() {
|
||||
return this.random(4, 9);
|
||||
},
|
||||
onStart(target, source) {
|
||||
const moveSlot = target.lastMove ? target.getMoveData(target.lastMove.id) : null;
|
||||
if (!target.lastMove || target.lastMove.flags['failencore'] || !moveSlot || moveSlot.pp <= 0) {
|
||||
// it failed
|
||||
return false;
|
||||
}
|
||||
this.effectState.move = target.lastMove.id;
|
||||
this.add('-start', target, 'Encore');
|
||||
},
|
||||
onOverrideAction(pokemon) {
|
||||
return this.effectState.move;
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 14,
|
||||
onResidual(target) {
|
||||
const moveSlot = target.getMoveData(this.effectState.move);
|
||||
if (moveSlot && moveSlot.pp <= 0) {
|
||||
// early termination if you run out of PP
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
endeavor: {
|
||||
|
|
@ -619,10 +519,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
basePower: 10,
|
||||
condition: {
|
||||
duration: 2,
|
||||
onStart() {
|
||||
this.effectState.multiplier = 1;
|
||||
},
|
||||
inherit: true,
|
||||
onRestart() {
|
||||
if (this.effectState.multiplier < 16) {
|
||||
this.effectState.multiplier <<= 1;
|
||||
|
|
@ -678,77 +575,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
gravity: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(source, effect) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-activate', source, 'ability: Persistent', '[move] Gravity');
|
||||
return 7;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
onFieldStart(target, source) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-fieldstart', 'move: Gravity', '[persistent]');
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Gravity');
|
||||
}
|
||||
for (const pokemon of this.getAllActive()) {
|
||||
let applies = false;
|
||||
if (pokemon.removeVolatile('bounce') || pokemon.removeVolatile('fly')) {
|
||||
applies = true;
|
||||
this.queue.cancelMove(pokemon);
|
||||
pokemon.removeVolatile('twoturnmove');
|
||||
}
|
||||
if (pokemon.volatiles['skydrop']) {
|
||||
applies = true;
|
||||
this.queue.cancelMove(pokemon);
|
||||
|
||||
if (pokemon.volatiles['skydrop'].source) {
|
||||
this.add('-end', pokemon.volatiles['twoturnmove'].source, 'Sky Drop', '[interrupt]');
|
||||
}
|
||||
pokemon.removeVolatile('skydrop');
|
||||
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) this.add('-activate', pokemon, 'move: Gravity');
|
||||
}
|
||||
},
|
||||
onModifyAccuracy(accuracy) {
|
||||
if (typeof accuracy !== 'number') return;
|
||||
return this.chainModify([6840, 4096]);
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (this.dex.moves.get(moveSlot.id).flags['gravity']) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
// groundedness implemented in battle.engine.js:BattlePokemon#isGrounded
|
||||
onBeforeMovePriority: 6,
|
||||
onBeforeMove(pokemon, target, move) {
|
||||
if (move.flags['gravity'] && !move.isZ) {
|
||||
this.add('cant', pokemon, 'move: Gravity', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onModifyMove(move, pokemon, target) {
|
||||
if (move.flags['gravity'] && !move.isZ) {
|
||||
this.add('cant', pokemon, 'move: Gravity', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onFieldResidualOrder: 9,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'move: Gravity');
|
||||
},
|
||||
onFieldResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
growth: {
|
||||
|
|
@ -786,36 +615,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-activate', source, 'ability: Persistent', '[move] Heal Block');
|
||||
return 7;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Heal Block');
|
||||
},
|
||||
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']) {
|
||||
this.add('cant', pokemon, 'move: Heal Block', move);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 17,
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'move: Heal Block');
|
||||
},
|
||||
onTryHeal(damage, pokemon, source, effect) {
|
||||
if (effect && (effect.id === 'drain' || effect.id === 'leechseed' || effect.id === 'wish')) {
|
||||
return false;
|
||||
|
|
@ -875,22 +677,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
ingrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Ingrain');
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 1,
|
||||
onResidual(pokemon) {
|
||||
this.heal(pokemon.baseMaxhp / 16);
|
||||
},
|
||||
onTrapPokemon(pokemon) {
|
||||
pokemon.tryTrap();
|
||||
},
|
||||
// groundedness implemented in battle.engine.js:BattlePokemon#isGrounded
|
||||
onDragOut(pokemon) {
|
||||
this.add('-activate', pokemon, 'move: Ingrain');
|
||||
return null;
|
||||
},
|
||||
},
|
||||
},
|
||||
jumpkick: {
|
||||
|
|
@ -925,34 +714,16 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
leechseed: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'move: Leech Seed');
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 5,
|
||||
onResidual(pokemon) {
|
||||
const target = this.getAtSlot(pokemon.volatiles['leechseed'].sourceSlot);
|
||||
if (!target || target.fainted || target.hp <= 0) {
|
||||
this.debug('Nothing to leech into');
|
||||
return;
|
||||
}
|
||||
const damage = this.damage(pokemon.baseMaxhp / 8, pokemon, target);
|
||||
if (damage) {
|
||||
this.heal(damage, target, pokemon);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
lightscreen: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasItem('lightclay')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onAnyModifyDamage() {},
|
||||
onAnyModifyDamagePhase1(damage, source, target, move) {
|
||||
if (target !== source && this.effectState.target.hasAlly(target) && this.getCategory(move) === 'Special') {
|
||||
if (!target.getMoveHitData(move).crit && !move.infiltrates) {
|
||||
|
|
@ -962,41 +733,24 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'Light Screen');
|
||||
},
|
||||
onSideResidualOrder: 2,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Light Screen');
|
||||
},
|
||||
onSideResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
lockon: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 2,
|
||||
onSourceInvulnerabilityPriority: 1,
|
||||
onSourceInvulnerability(target, source, move) {
|
||||
if (move && source === this.effectState.target && target === this.effectState.source) return 0;
|
||||
},
|
||||
onSourceAccuracy(accuracy, target, source, move) {
|
||||
if (move && source === this.effectState.target && target === this.effectState.source) return true;
|
||||
},
|
||||
inherit: true,
|
||||
noCopy: false,
|
||||
},
|
||||
},
|
||||
luckychant: {
|
||||
inherit: true,
|
||||
flags: { metronome: 1 },
|
||||
condition: {
|
||||
duration: 5,
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'move: Lucky Chant');
|
||||
},
|
||||
onCriticalHit: false,
|
||||
inherit: true,
|
||||
onSideResidualOrder: 6,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'move: Lucky Chant');
|
||||
},
|
||||
onSideResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
lunardance: {
|
||||
|
|
@ -1033,8 +787,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
magiccoat: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onTryHitPriority: 2,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (target === source || move.hasBounced || !move.flags['reflectable']) {
|
||||
return;
|
||||
|
|
@ -1045,6 +798,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.actions.useMove(newMove, target, { target: source });
|
||||
return null;
|
||||
},
|
||||
onAllyTryHitSide() {},
|
||||
},
|
||||
},
|
||||
magmastorm: {
|
||||
|
|
@ -1056,25 +810,20 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
flags: { gravity: 1, metronome: 1 },
|
||||
volatileStatus: 'magnetrise',
|
||||
condition: {
|
||||
duration: 5,
|
||||
inherit: true,
|
||||
onStart(target) {
|
||||
if (target.volatiles['ingrain'] || target.ability === 'levitate') return false;
|
||||
this.add('-start', target, 'Magnet Rise');
|
||||
},
|
||||
onImmunity(type) {
|
||||
if (type === 'Ground') return false;
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 16,
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Magnet Rise');
|
||||
},
|
||||
},
|
||||
},
|
||||
mefirst: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
inherit: true,
|
||||
onBasePower() {},
|
||||
onModifyDamagePhase2(damage) {
|
||||
return damage * 1.5;
|
||||
},
|
||||
|
|
@ -1162,30 +911,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mist: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
onTryBoost(boost, target, source, effect) {
|
||||
if (effect.effectType === 'Move' && effect.infiltrates && !target.isAlly(source)) return;
|
||||
if (source && target !== source) {
|
||||
let showMsg = false;
|
||||
let i: BoostID;
|
||||
for (i in boost) {
|
||||
if (boost[i]! < 0) {
|
||||
delete boost[i];
|
||||
showMsg = true;
|
||||
}
|
||||
}
|
||||
if (showMsg && !(effect as ActiveMove).secondaries) {
|
||||
this.add('-activate', target, 'move: Mist');
|
||||
}
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'Mist');
|
||||
},
|
||||
inherit: true,
|
||||
onSideResidualOrder: 3,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Mist');
|
||||
},
|
||||
onSideResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
moonlight: {
|
||||
|
|
@ -1215,9 +943,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mudsport: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Mud Sport');
|
||||
},
|
||||
inherit: true,
|
||||
noCopy: false,
|
||||
onAnyBasePowerPriority: 3,
|
||||
onAnyBasePower(basePower, user, target, move) {
|
||||
if (move.type === 'Electric') {
|
||||
|
|
@ -1237,18 +964,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
nightmare: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onStart(pokemon) {
|
||||
if (pokemon.status !== 'slp' && !pokemon.hasAbility('comatose')) {
|
||||
return false;
|
||||
}
|
||||
this.add('-start', pokemon, 'Nightmare');
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 7,
|
||||
onResidual(pokemon) {
|
||||
this.damage(pokemon.baseMaxhp / 4);
|
||||
},
|
||||
},
|
||||
},
|
||||
odorsleuth: {
|
||||
|
|
@ -1278,16 +996,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
perishsong: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 4,
|
||||
onEnd(target) {
|
||||
this.add('-start', target, 'perish0');
|
||||
target.faint();
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 12,
|
||||
onResidual(pokemon) {
|
||||
const duration = pokemon.volatiles['perishsong'].duration;
|
||||
this.add('-start', pokemon, `perish${duration}`);
|
||||
},
|
||||
},
|
||||
},
|
||||
petaldance: {
|
||||
|
|
@ -1308,11 +1018,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
priority: 3,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target) {
|
||||
this.add('-singleturn', target, 'Protect');
|
||||
},
|
||||
onTryHitPriority: 3,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (!move.flags['protect']) return;
|
||||
this.add('-activate', target, 'Protect');
|
||||
|
|
@ -1346,7 +1052,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
duration: 1,
|
||||
inherit: true,
|
||||
onBeforeSwitchOut(pokemon) {
|
||||
this.debug('Pursuit start');
|
||||
let alreadyAdded = false;
|
||||
|
|
@ -1403,13 +1109,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
reflect: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasItem('lightclay')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onAnyModifyDamage() {},
|
||||
onAnyModifyDamagePhase1(damage, source, target, move) {
|
||||
if (target !== source && this.effectState.target.hasAlly(target) && this.getCategory(move) === 'Physical') {
|
||||
if (!target.getMoveHitData(move).crit && !move.infiltrates) {
|
||||
|
|
@ -1419,13 +1120,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'Reflect');
|
||||
},
|
||||
onSideResidualOrder: 1,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Reflect');
|
||||
},
|
||||
onSideResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
reversal: {
|
||||
|
|
@ -1470,45 +1166,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
safeguard: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-activate', source, 'ability: Persistent', '[move] Safeguard');
|
||||
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, source) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-sidestart', side, 'Safeguard', '[persistent]');
|
||||
} else {
|
||||
this.add('-sidestart', side, 'Safeguard');
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onSideResidualOrder: 4,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Safeguard');
|
||||
},
|
||||
onSideResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
sandtomb: {
|
||||
|
|
@ -1566,11 +1226,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { bypasssub: 1, noassist: 1, failcopycat: 1 },
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(pokemon) {
|
||||
this.add('-singleturn', pokemon, 'Snatch');
|
||||
},
|
||||
onAnyPrepareHitPriority: -1,
|
||||
inherit: true,
|
||||
onAnyPrepareHit(source, target, move) {
|
||||
const snatchUser = this.effectState.source;
|
||||
if (snatchUser.isSkyDropped()) return;
|
||||
|
|
@ -1594,16 +1250,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { metronome: 1, mustpressure: 1 },
|
||||
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++;
|
||||
},
|
||||
inherit: true,
|
||||
onSwitchIn() {},
|
||||
onEntryHazard(pokemon) {
|
||||
if (!pokemon.isGrounded() || pokemon.hasItem('heavydutyboots')) return;
|
||||
const damageAmounts = [0, 3, 4, 6]; // 1/8, 1/6, 1/4
|
||||
|
|
@ -1619,10 +1267,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { metronome: 1, mustpressure: 1 },
|
||||
condition: {
|
||||
// this is a side condition
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'move: Stealth Rock');
|
||||
},
|
||||
inherit: true,
|
||||
onSwitchIn() {},
|
||||
onEntryHazard(pokemon) {
|
||||
if (pokemon.hasItem('heavydutyboots')) return;
|
||||
const typeMod = this.clampIntRange(pokemon.runEffectiveness(this.dex.getActiveMove('stealthrock')), -6, 6);
|
||||
|
|
@ -1643,12 +1289,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
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,
|
||||
inherit: true,
|
||||
onTryPrimaryHit(target, source, move) {
|
||||
if (target === source || move.flags['bypasssub']) {
|
||||
return;
|
||||
|
|
@ -1681,9 +1322,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.runEvent('AfterSubDamage', target, source, move, damage);
|
||||
return this.HIT_SUBSTITUTE;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
},
|
||||
suckerpunch: {
|
||||
|
|
@ -1735,6 +1373,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
tailwind: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
inherit: true,
|
||||
duration: 3,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
|
|
@ -1743,26 +1382,19 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
return 3;
|
||||
},
|
||||
onSideStart(side, source) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-sidestart', side, 'move: Tailwind', '[persistent]');
|
||||
} else {
|
||||
this.add('-sidestart', side, 'move: Tailwind');
|
||||
}
|
||||
},
|
||||
onModifySpe(spe) {
|
||||
return spe * 2;
|
||||
},
|
||||
onSideResidualOrder: 5,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'move: Tailwind');
|
||||
},
|
||||
onSideResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
taunt: {
|
||||
inherit: true,
|
||||
flags: { protect: 1, mirror: 1, bypasssub: 1, metronome: 1 },
|
||||
condition: {
|
||||
inherit: true,
|
||||
duration: undefined,
|
||||
durationCallback() {
|
||||
return this.random(3, 6);
|
||||
},
|
||||
|
|
@ -1771,9 +1403,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 15,
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'move: Taunt');
|
||||
},
|
||||
onDisableMove(pokemon) {
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (this.dex.moves.get(moveSlot.id).category === 'Status') {
|
||||
|
|
@ -1807,16 +1436,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { metronome: 1, mustpressure: 1 },
|
||||
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++;
|
||||
},
|
||||
inherit: true,
|
||||
onSwitchIn() {},
|
||||
onEntryHazard(pokemon) {
|
||||
if (!pokemon.isGrounded()) return;
|
||||
if (pokemon.hasType('Poison')) {
|
||||
|
|
@ -1846,67 +1467,22 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
trickroom: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(source, effect) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-activate', source, 'ability: Persistent', '[move] Trick Room');
|
||||
return 7;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
onFieldStart(target, source) {
|
||||
if (source?.hasAbility('persistent')) {
|
||||
this.add('-fieldstart', 'move: Trick Room', `[of] ${source}`, '[persistent]');
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Trick Room', `[of] ${source}`);
|
||||
}
|
||||
},
|
||||
onFieldRestart(target, source) {
|
||||
this.field.removePseudoWeather('trickroom');
|
||||
},
|
||||
// Speed modification is changed in Pokemon.getActionSpeed() in sim/pokemon.js
|
||||
inherit: true,
|
||||
onFieldResidualOrder: 13,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'move: Trick Room');
|
||||
},
|
||||
onFieldResidualSubOrder: undefined,
|
||||
},
|
||||
},
|
||||
uproar: {
|
||||
inherit: true,
|
||||
basePower: 50,
|
||||
condition: {
|
||||
onStart(target) {
|
||||
this.add('-start', target, 'Uproar');
|
||||
// 3-6 turns
|
||||
this.effectState.duration = this.random(3, 7);
|
||||
},
|
||||
onResidual(target) {
|
||||
if (target.volatiles['throatchop']) {
|
||||
target.removeVolatile('uproar');
|
||||
return;
|
||||
}
|
||||
if (target.lastMove && target.lastMove.id === 'struggle') {
|
||||
// don't lock
|
||||
delete target.volatiles['uproar'];
|
||||
}
|
||||
this.add('-start', target, 'Uproar', '[upkeep]');
|
||||
inherit: true,
|
||||
duration: undefined,
|
||||
durationCallback() {
|
||||
return this.random(3, 7);
|
||||
},
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 11,
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Uproar');
|
||||
},
|
||||
onLockMove: 'uproar',
|
||||
onAnySetStatus(status, pokemon) {
|
||||
if (status.id === 'slp') {
|
||||
if (pokemon === this.effectState.target) {
|
||||
this.add('-fail', pokemon, 'slp', '[from] Uproar', '[msg]');
|
||||
} else {
|
||||
this.add('-fail', pokemon, 'slp', '[from] Uproar');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
volttackle: {
|
||||
|
|
@ -1916,9 +1492,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
watersport: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon) {
|
||||
this.add('-start', pokemon, 'move: Water Sport');
|
||||
},
|
||||
inherit: true,
|
||||
noCopy: false,
|
||||
onAnyBasePowerPriority: 3,
|
||||
onAnyBasePower(basePower, user, target, move) {
|
||||
if (move.type === 'Fire') {
|
||||
|
|
@ -1981,17 +1556,9 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
yawn: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
noCopy: true, // doesn't get copied by Baton Pass
|
||||
duration: 2,
|
||||
onStart(target, source) {
|
||||
this.add('-start', target, 'move: Yawn', `[of] ${source}`);
|
||||
},
|
||||
inherit: true,
|
||||
onResidualOrder: 10,
|
||||
onResidualSubOrder: 19,
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'move: Yawn', '[silent]');
|
||||
target.trySetStatus('slp', this.effectState.source);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
autotomize: {
|
||||
inherit: true,
|
||||
volatileStatus: 'autotomize',
|
||||
onHit(pokemon) {
|
||||
},
|
||||
onHit() {},
|
||||
condition: {
|
||||
noCopy: true, // doesn't get copied by Baton Pass
|
||||
onStart(pokemon) {
|
||||
|
|
@ -78,6 +77,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, reflectable: 1, mirror: 1, metronome: 1 },
|
||||
},
|
||||
bodyslam: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
},
|
||||
bounce: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, charge: 1, protect: 1, mirror: 1, gravity: 1, distance: 1, metronome: 1, nosleeptalk: 1 },
|
||||
|
|
@ -192,6 +195,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, punch: 1, metronome: 1 },
|
||||
},
|
||||
dragonrush: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
},
|
||||
dreameater: {
|
||||
inherit: true,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
|
|
@ -260,10 +267,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
basePower: 20,
|
||||
condition: {
|
||||
duration: 2,
|
||||
onStart() {
|
||||
this.effectState.multiplier = 1;
|
||||
},
|
||||
inherit: true,
|
||||
onRestart() {
|
||||
if (this.effectState.multiplier < 8) {
|
||||
this.effectState.multiplier <<= 1;
|
||||
|
|
@ -363,6 +367,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return success;
|
||||
},
|
||||
},
|
||||
heatcrash: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
},
|
||||
heatwave: {
|
||||
inherit: true,
|
||||
basePower: 100,
|
||||
|
|
@ -494,13 +502,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
lightscreen: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasItem('lightclay')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onAnyModifyDamage(damage, source, target, move) {
|
||||
if (target !== source && this.effectState.target.hasAlly(target) && this.getCategory(move) === 'Special') {
|
||||
if (!target.getMoveHitData(move).crit && !move.infiltrates) {
|
||||
|
|
@ -510,14 +512,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'move: Light Screen');
|
||||
},
|
||||
onSideResidualOrder: 26,
|
||||
onSideResidualSubOrder: 2,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'move: Light Screen');
|
||||
},
|
||||
},
|
||||
},
|
||||
lowsweep: {
|
||||
|
|
@ -527,24 +521,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
magiccoat: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target, source, effect) {
|
||||
this.add('-singleturn', target, 'move: Magic Coat');
|
||||
if (effect?.effectType === 'Move') {
|
||||
this.effectState.pranksterBoosted = effect.pranksterBoosted;
|
||||
}
|
||||
},
|
||||
onTryHitPriority: 2,
|
||||
onTryHit(target, source, move) {
|
||||
if (target === source || move.hasBounced || !move.flags['reflectable'] || target.isSemiInvulnerable()) {
|
||||
return;
|
||||
}
|
||||
const newMove = this.dex.getActiveMove(move.id);
|
||||
newMove.hasBounced = true;
|
||||
newMove.pranksterBoosted = this.effectState.pranksterBoosted;
|
||||
this.actions.useMove(newMove, target, { target: source });
|
||||
return null;
|
||||
},
|
||||
inherit: true,
|
||||
onAllyTryHitSide(target, source, move) {
|
||||
if (target.isAlly(source) || move.hasBounced || !move.flags['reflectable']) {
|
||||
return;
|
||||
|
|
@ -587,12 +564,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
pp: 20,
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onSourceModifyDamage(damage, source, target, move) {
|
||||
if (['stomp', 'steamroller'].includes(move.id)) {
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onAccuracy() {},
|
||||
},
|
||||
},
|
||||
moonlight: {
|
||||
|
|
@ -689,11 +662,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
source.addVolatile('stall');
|
||||
},
|
||||
condition: {
|
||||
duration: 1,
|
||||
onSideStart(target, source) {
|
||||
this.add('-singleturn', source, 'Quick Guard');
|
||||
},
|
||||
onTryHitPriority: 4,
|
||||
inherit: true,
|
||||
onTryHit(target, source, effect) {
|
||||
// Quick Guard only blocks moves with a natural positive priority
|
||||
// (e.g. it doesn't block 0 priority moves boosted by Prankster)
|
||||
|
|
@ -720,13 +689,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
reflect: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 5,
|
||||
durationCallback(target, source, effect) {
|
||||
if (source?.hasItem('lightclay')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onAnyModifyDamage(damage, source, target, move) {
|
||||
if (target !== source && this.effectState.target.hasAlly(target) && this.getCategory(move) === 'Physical') {
|
||||
if (!target.getMoveHitData(move).crit && !move.infiltrates) {
|
||||
|
|
@ -736,14 +699,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
}
|
||||
}
|
||||
},
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'Reflect');
|
||||
},
|
||||
onSideResidualOrder: 26,
|
||||
onSideResidualSubOrder: 1,
|
||||
onSideEnd(side) {
|
||||
this.add('-sideend', side, 'Reflect');
|
||||
},
|
||||
},
|
||||
},
|
||||
relicsong: {
|
||||
|
|
@ -881,12 +836,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
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,
|
||||
inherit: true,
|
||||
onTryPrimaryHit(target, source, move) {
|
||||
if (target === source || move.flags['bypasssub']) {
|
||||
return;
|
||||
|
|
@ -918,9 +868,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.runEvent('AfterSubDamage', target, source, move, damage);
|
||||
return this.HIT_SUBSTITUTE;
|
||||
},
|
||||
onEnd(target) {
|
||||
this.add('-end', target, 'Substitute');
|
||||
},
|
||||
},
|
||||
},
|
||||
submission: {
|
||||
|
|
|
|||
|
|
@ -34,48 +34,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
},
|
||||
},
|
||||
},
|
||||
encore: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 3,
|
||||
onStart(target) {
|
||||
const moveSlot = target.lastMove ? target.getMoveData(target.lastMove.id) : null;
|
||||
if (!target.lastMove || target.lastMove.flags['failencore'] || !moveSlot || moveSlot.pp <= 0) {
|
||||
// it failed
|
||||
return false;
|
||||
}
|
||||
this.effectState.move = target.lastMove.id;
|
||||
this.add('-start', target, 'Encore');
|
||||
if (!this.queue.willMove(target)) {
|
||||
this.effectState.duration!++;
|
||||
}
|
||||
},
|
||||
onOverrideAction(pokemon, target, move) {
|
||||
if (move.id !== this.effectState.move) return this.effectState.move;
|
||||
},
|
||||
onResidualOrder: 16,
|
||||
onResidual(target) {
|
||||
const lockedMoveSlot = target.getMoveData(this.effectState.move);
|
||||
if (lockedMoveSlot && lockedMoveSlot.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.effectState.move || !pokemon.hasMove(this.effectState.move)) {
|
||||
return;
|
||||
}
|
||||
for (const moveSlot of pokemon.moveSlots) {
|
||||
if (moveSlot.id !== this.effectState.move) {
|
||||
pokemon.disableMove(moveSlot.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
fellstinger: {
|
||||
inherit: true,
|
||||
basePower: 30,
|
||||
|
|
@ -87,6 +45,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
basePower: 80,
|
||||
},
|
||||
heavyslam: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
},
|
||||
leechlife: {
|
||||
inherit: true,
|
||||
basePower: 20,
|
||||
|
|
@ -96,29 +58,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
inherit: true,
|
||||
flags: { protect: 1, bypasssub: 1, noassist: 1, failcopycat: 1, failmefirst: 1, nosleeptalk: 1 },
|
||||
},
|
||||
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;
|
||||
},
|
||||
},
|
||||
},
|
||||
metronome: {
|
||||
inherit: true,
|
||||
flags: { noassist: 1, failcopycat: 1, nosleeptalk: 1 },
|
||||
|
|
@ -126,39 +65,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
mistyterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
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);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect?.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Misty Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Misty Terrain');
|
||||
}
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'Misty Terrain');
|
||||
},
|
||||
inherit: true,
|
||||
onTryAddVolatile() {},
|
||||
},
|
||||
},
|
||||
mysticalfire: {
|
||||
|
|
@ -179,28 +87,25 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
this.boost({ atk: -1, spa: -1 }, target, source);
|
||||
},
|
||||
},
|
||||
phantomforce: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, charge: 1, mirror: 1, metronome: 1, nosleeptalk: 1, noassist: 1, failinstruct: 1, minimize: 1 },
|
||||
},
|
||||
powder: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target) {
|
||||
this.add('-singleturn', target, 'Powder');
|
||||
},
|
||||
inherit: true,
|
||||
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));
|
||||
this.attrLastMove('[still]');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
rockblast: {
|
||||
inherit: true,
|
||||
flags: { protect: 1, mirror: 1, metronome: 1 },
|
||||
},
|
||||
shadowforce: {
|
||||
inherit: true,
|
||||
flags: { contact: 1, charge: 1, mirror: 1, metronome: 1, nosleeptalk: 1, noassist: 1, failinstruct: 1, minimize: 1 },
|
||||
},
|
||||
sheercold: {
|
||||
inherit: true,
|
||||
ohko: true,
|
||||
|
|
@ -263,11 +168,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
wideguard: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onSideStart(target, source) {
|
||||
this.add('-singleturn', source, 'Wide Guard');
|
||||
},
|
||||
onTryHitPriority: 4,
|
||||
inherit: true,
|
||||
onTryHit(target, source, effect) {
|
||||
// Wide Guard blocks damaging spread moves
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -72,14 +72,8 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
onTryBoost() {},
|
||||
},
|
||||
rattled: {
|
||||
onDamagingHit(damage, target, source, move) {
|
||||
if (['Dark', 'Bug', 'Ghost'].includes(move.type)) {
|
||||
this.boost({ spe: 1 });
|
||||
}
|
||||
},
|
||||
name: "Rattled",
|
||||
rating: 1.5,
|
||||
num: 155,
|
||||
inherit: true,
|
||||
onAfterBoost() {},
|
||||
},
|
||||
scrappy: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -182,47 +182,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
electricterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
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)) {
|
||||
this.add('-activate', target, 'move: Electric Terrain');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
onTryAddVolatile(status, target) {
|
||||
if (!target.isGrounded() || target.isSemiInvulnerable()) return;
|
||||
if (status.id === 'yawn') {
|
||||
this.add('-activate', target, 'move: Electric Terrain');
|
||||
return null;
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Electric' && attacker.isGrounded() && !attacker.isSemiInvulnerable()) {
|
||||
this.debug('electric terrain boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect && effect.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Electric Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Electric Terrain');
|
||||
}
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'move: Electric Terrain');
|
||||
},
|
||||
},
|
||||
},
|
||||
embargo: {
|
||||
|
|
@ -316,14 +282,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
grassyterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
duration: 5,
|
||||
durationCallback(source, effect) {
|
||||
if (source?.hasItem('terrainextender')) {
|
||||
return 8;
|
||||
}
|
||||
return 5;
|
||||
},
|
||||
inherit: true,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
const weakenedMoves = ['earthquake', 'bulldoze', 'magnitude'];
|
||||
if (weakenedMoves.includes(move.id) && defender.isGrounded() && !defender.isSemiInvulnerable()) {
|
||||
|
|
@ -335,27 +294,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect && effect.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Grassy Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Grassy Terrain');
|
||||
}
|
||||
},
|
||||
onResidualOrder: 5,
|
||||
onResidualSubOrder: 2,
|
||||
onResidual(pokemon) {
|
||||
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');
|
||||
},
|
||||
},
|
||||
},
|
||||
guardianofalola: {
|
||||
|
|
@ -558,11 +496,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
kingsshield: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
duration: 1,
|
||||
onStart(target) {
|
||||
this.add('-singleturn', target, 'Protect');
|
||||
},
|
||||
onTryHitPriority: 3,
|
||||
inherit: true,
|
||||
onTryHit(target, source, move) {
|
||||
if (!move.flags['protect'] || move.category === 'Status') {
|
||||
if (move.isZ || move.isMax) target.getMoveHitData(move).zBrokeProtect = true;
|
||||
|
|
@ -780,48 +714,13 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
psychicterrain: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
effectType: 'Terrain',
|
||||
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émon immune to Ground.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.add('-activate', target, 'move: Psychic Terrain');
|
||||
return null;
|
||||
},
|
||||
inherit: true,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Psychic' && attacker.isGrounded() && !attacker.isSemiInvulnerable()) {
|
||||
this.debug('psychic terrain boost');
|
||||
return this.chainModify(1.5);
|
||||
}
|
||||
},
|
||||
onFieldStart(field, source, effect) {
|
||||
if (effect && effect.effectType === 'Ability') {
|
||||
this.add('-fieldstart', 'move: Psychic Terrain', `[from] ability: ${effect}`, `[of] ${source}`);
|
||||
} else {
|
||||
this.add('-fieldstart', 'move: Psychic Terrain');
|
||||
}
|
||||
},
|
||||
onFieldResidualOrder: 27,
|
||||
onFieldResidualSubOrder: 7,
|
||||
onFieldEnd() {
|
||||
this.add('-fieldend', 'move: Psychic Terrain');
|
||||
},
|
||||
},
|
||||
},
|
||||
psychoboost: {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
doubleironbash: {
|
||||
inherit: true,
|
||||
isNonstandard: null,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, punch: 1, minimize: 1 },
|
||||
},
|
||||
floatyfall: {
|
||||
inherit: true,
|
||||
|
|
|
|||
|
|
@ -59,19 +59,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
charge: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onStart(pokemon, source, effect) {
|
||||
this.add('-start', pokemon, 'Charge');
|
||||
},
|
||||
onRestart(pokemon, source, effect) {
|
||||
this.add('-start', pokemon, 'Charge');
|
||||
},
|
||||
onBasePowerPriority: 9,
|
||||
onBasePower(basePower, attacker, defender, move) {
|
||||
if (move.type === 'Electric') {
|
||||
this.debug('charge boost');
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
inherit: true,
|
||||
onMoveAborted(pokemon, target, move) {
|
||||
if (move.id !== 'charge') {
|
||||
pokemon.removeVolatile('charge');
|
||||
|
|
@ -82,9 +70,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
pokemon.removeVolatile('charge');
|
||||
}
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'Charge', '[silent]');
|
||||
},
|
||||
},
|
||||
},
|
||||
chatter: {
|
||||
|
|
@ -526,9 +511,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = {
|
|||
stickyweb: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
onSideStart(side) {
|
||||
this.add('-sidestart', side, 'move: Sticky Web');
|
||||
},
|
||||
inherit: true,
|
||||
onSwitchIn(pokemon) {
|
||||
if (!pokemon.isGrounded() || pokemon.hasItem('heavydutyboots')) return;
|
||||
this.add('-activate', pokemon, 'move: Sticky Web');
|
||||
|
|
|
|||
|
|
@ -19,91 +19,60 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
|
|||
}
|
||||
},
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onStart(pokemon, source, effect) {
|
||||
if (effect?.name === 'Booster Energy') {
|
||||
this.effectState.fromBooster = true;
|
||||
this.add('-activate', pokemon, 'ability: Protosynthesis', '[fromitem]');
|
||||
} else {
|
||||
this.add('-activate', pokemon, 'ability: Protosynthesis');
|
||||
}
|
||||
this.effectState.bestStat = pokemon.getBestStat(false, true);
|
||||
this.add('-start', pokemon, 'protosynthesis' + this.effectState.bestStat);
|
||||
},
|
||||
onModifyAtkPriority: 5,
|
||||
onModifyAtk(atk, pokemon) {
|
||||
inherit: true,
|
||||
onModifyAtk() {
|
||||
if (this.effectState.bestStat !== 'atk') return;
|
||||
this.debug('Protosynthesis atk boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifyDefPriority: 6,
|
||||
onModifyDef(def, pokemon) {
|
||||
onModifyDef() {
|
||||
if (this.effectState.bestStat !== 'def') return;
|
||||
this.debug('Protosynthesis def boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifySpAPriority: 5,
|
||||
onModifySpA(spa, pokemon) {
|
||||
onModifySpA() {
|
||||
if (this.effectState.bestStat !== 'spa') return;
|
||||
this.debug('Protosynthesis spa boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifySpDPriority: 6,
|
||||
onModifySpD(spd, pokemon) {
|
||||
onModifySpD() {
|
||||
if (this.effectState.bestStat !== 'spd') return;
|
||||
this.debug('Protosynthesis spd boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifySpe(spe, pokemon) {
|
||||
onModifySpe() {
|
||||
if (this.effectState.bestStat !== 'spe') return;
|
||||
this.debug('Protosynthesis spe boost');
|
||||
return this.chainModify(1.5);
|
||||
},
|
||||
onEnd(pokemon) {
|
||||
this.add('-end', pokemon, 'Protosynthesis');
|
||||
},
|
||||
},
|
||||
flags: { failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1, cantsuppress: 1 },
|
||||
},
|
||||
quarkdrive: {
|
||||
inherit: true,
|
||||
condition: {
|
||||
noCopy: true,
|
||||
onStart(pokemon, source, effect) {
|
||||
if (effect?.name === 'Booster Energy') {
|
||||
this.effectState.fromBooster = true;
|
||||
this.add('-activate', pokemon, 'ability: Quark Drive', '[fromitem]');
|
||||
} else {
|
||||
this.add('-activate', pokemon, 'ability: Quark Drive');
|
||||
}
|
||||
this.effectState.bestStat = pokemon.getBestStat(false, true);
|
||||
this.add('-start', pokemon, 'quarkdrive' + this.effectState.bestStat);
|
||||
},
|
||||
onModifyAtkPriority: 5,
|
||||
onModifyAtk(atk, pokemon) {
|
||||
inherit: true,
|
||||
onModifyAtk() {
|
||||
if (this.effectState.bestStat !== 'atk') return;
|
||||
this.debug('Quark Drive atk boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifyDefPriority: 6,
|
||||
onModifyDef(def, pokemon) {
|
||||
onModifyDef() {
|
||||
if (this.effectState.bestStat !== 'def') return;
|
||||
this.debug('Quark Drive def boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifySpAPriority: 5,
|
||||
onModifySpA(spa, pokemon) {
|
||||
onModifySpA() {
|
||||
if (this.effectState.bestStat !== 'spa') return;
|
||||
this.debug('Quark Drive spa boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifySpDPriority: 6,
|
||||
onModifySpD(spd, pokemon) {
|
||||
onModifySpD() {
|
||||
if (this.effectState.bestStat !== 'spd') return;
|
||||
this.debug('Quark Drive spd boost');
|
||||
return this.chainModify([5325, 4096]);
|
||||
},
|
||||
onModifySpe(spe, pokemon) {
|
||||
onModifySpe() {
|
||||
if (this.effectState.bestStat !== 'spe') return;
|
||||
this.debug('Quark Drive spe boost');
|
||||
return this.chainModify(1.5);
|
||||
|
|
|
|||
|
|
@ -1644,7 +1644,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Body Slam",
|
||||
pp: 15,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1, minimize: 1 },
|
||||
secondary: {
|
||||
chance: 30,
|
||||
status: 'par',
|
||||
|
|
@ -4349,7 +4349,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Dragon Rush",
|
||||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
secondary: {
|
||||
chance: 20,
|
||||
volatileStatus: 'flinch',
|
||||
|
|
@ -6149,7 +6149,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
category: "Physical",
|
||||
name: "Flying Press",
|
||||
pp: 10,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, gravity: 1, distance: 1, nonsky: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, gravity: 1, distance: 1, nonsky: 1, metronome: 1, minimize: 1 },
|
||||
onEffectiveness(typeMod, target, type, move) {
|
||||
return typeMod + this.dex.getEffectiveness('Flying', type);
|
||||
},
|
||||
|
|
@ -8608,7 +8608,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
onModifyMove(move, pokemon, target) {
|
||||
onModifyMove(move, pokemon) {
|
||||
if (move.flags['heal'] && !move.isZ && !move.isMax) {
|
||||
this.add('cant', pokemon, 'move: Heal Block', move);
|
||||
return false;
|
||||
|
|
@ -8801,7 +8801,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Heat Crash",
|
||||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1, minimize: 1 },
|
||||
onTryHit(target, pokemon, move) {
|
||||
if (target.volatiles['dynamax']) {
|
||||
this.add('-fail', pokemon, 'Dynamax');
|
||||
|
|
@ -8859,7 +8859,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Heavy Slam",
|
||||
pp: 10,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1, minimize: 1 },
|
||||
onTryHit(target, pokemon, move) {
|
||||
if (target.volatiles['dynamax']) {
|
||||
this.add('-fail', pokemon, 'Dynamax');
|
||||
|
|
@ -11364,7 +11364,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Malicious Moonsault",
|
||||
pp: 1,
|
||||
priority: 0,
|
||||
flags: { contact: 1 },
|
||||
flags: { contact: 1, minimize: 1 },
|
||||
isZ: "inciniumz",
|
||||
secondary: null,
|
||||
target: "normal",
|
||||
|
|
@ -12365,18 +12365,12 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
noCopy: true,
|
||||
onRestart: () => null,
|
||||
onSourceModifyDamage(damage, source, target, move) {
|
||||
const boostedMoves = [
|
||||
'stomp', 'steamroller', 'bodyslam', 'flyingpress', 'dragonrush', 'heatcrash', 'heavyslam', 'maliciousmoonsault', 'supercellslam',
|
||||
];
|
||||
if (boostedMoves.includes(move.id)) {
|
||||
if (move.flags['minimize']) {
|
||||
return this.chainModify(2);
|
||||
}
|
||||
},
|
||||
onAccuracy(accuracy, target, source, move) {
|
||||
const boostedMoves = [
|
||||
'stomp', 'steamroller', 'bodyslam', 'flyingpress', 'dragonrush', 'heatcrash', 'heavyslam', 'maliciousmoonsault', 'supercellslam',
|
||||
];
|
||||
if (boostedMoves.includes(move.id)) {
|
||||
if (move.flags['minimize']) {
|
||||
return true;
|
||||
}
|
||||
return accuracy;
|
||||
|
|
@ -16174,7 +16168,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
if (effect.effectType === 'Move' && effect.infiltrates && !target.isAlly(source)) return;
|
||||
if (target !== source) {
|
||||
this.debug('interrupting setStatus');
|
||||
if (effect.name === 'Synchronize' || (effect.effectType === 'Move' && !effect.secondaries)) {
|
||||
if (effect.id === 'synchronize' || (effect.effectType === 'Move' && !effect.secondaries)) {
|
||||
this.add('-activate', target, 'move: Safeguard');
|
||||
}
|
||||
return null;
|
||||
|
|
@ -18520,7 +18514,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Steamroller",
|
||||
pp: 20,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
secondary: {
|
||||
chance: 30,
|
||||
volatileStatus: 'flinch',
|
||||
|
|
@ -18702,7 +18696,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Stomp",
|
||||
pp: 20,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, nonsky: 1, metronome: 1, minimize: 1 },
|
||||
secondary: {
|
||||
chance: 30,
|
||||
volatileStatus: 'flinch',
|
||||
|
|
@ -19131,7 +19125,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
|
|||
name: "Supercell Slam",
|
||||
pp: 15,
|
||||
priority: 0,
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1 },
|
||||
flags: { contact: 1, protect: 1, mirror: 1, metronome: 1, minimize: 1 },
|
||||
hasCrashDamage: true,
|
||||
onMoveFail(target, source, move) {
|
||||
this.damage(source.baseMaxhp / 2, source, source, this.dex.conditions.get('Supercell Slam'));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { PokemonEventMethods, ConditionData } from './dex-conditions';
|
||||
import type { PokemonEventMethods, ConditionData, ModdedConditionData } from './dex-conditions';
|
||||
import { assignMissingFields, BasicEffect, toID } from './dex-data';
|
||||
import { Utils } from '../lib/utils';
|
||||
|
||||
|
|
@ -24,7 +24,10 @@ export interface AbilityData extends Partial<Ability>, AbilityEventMethods, Poke
|
|||
name: string;
|
||||
}
|
||||
|
||||
export type ModdedAbilityData = AbilityData | Partial<AbilityData> & { inherit: true };
|
||||
export type ModdedAbilityData = AbilityData | Partial<AbilityData> & {
|
||||
inherit: true,
|
||||
condition?: ModdedConditionData,
|
||||
};
|
||||
export interface AbilityDataTable { [abilityid: IDEntry]: AbilityData }
|
||||
export interface ModdedAbilityDataTable { [abilityid: IDEntry]: ModdedAbilityData }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { PokemonEventMethods, ConditionData } from './dex-conditions';
|
||||
import type { PokemonEventMethods, ConditionData, ModdedConditionData } from './dex-conditions';
|
||||
import { assignMissingFields, BasicEffect, toID } from './dex-data';
|
||||
import { Utils } from '../lib/utils';
|
||||
|
||||
|
|
@ -16,6 +16,7 @@ export interface ItemData extends Partial<Item>, PokemonEventMethods {
|
|||
export type ModdedItemData = ItemData | Partial<Omit<ItemData, 'name'>> & {
|
||||
inherit: true,
|
||||
onCustap?: (this: Battle, pokemon: Pokemon) => void,
|
||||
condition?: ModdedConditionData,
|
||||
};
|
||||
|
||||
export interface ItemDataTable { [itemid: IDEntry]: ItemData }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Utils } from '../lib/utils';
|
||||
import type { ConditionData } from './dex-conditions';
|
||||
import type { ConditionData, ModdedConditionData } from './dex-conditions';
|
||||
import { assignMissingFields, BasicEffect, toID } from './dex-data';
|
||||
|
||||
/**
|
||||
|
|
@ -45,6 +45,7 @@ interface MoveFlags {
|
|||
gravity?: 1; // Prevented from being executed or selected during Gravity's effect.
|
||||
heal?: 1; // Prevented from being executed or selected during Heal Block's effect.
|
||||
metronome?: 1; // Can be selected by Metronome.
|
||||
minimize?: 1; // Deals double damage if the user is minimized.
|
||||
mirror?: 1; // Can be copied by Mirror Move.
|
||||
mustpressure?: 1; // Additional PP is deducted due to Pressure when it ordinarily would not.
|
||||
noassist?: 1; // Cannot be selected by Assist.
|
||||
|
|
@ -278,6 +279,7 @@ export type ModdedMoveData = MoveData | Partial<Omit<MoveData, 'name'>> & {
|
|||
bodyofwaterBoosted?: boolean,
|
||||
longWhipBoost?: boolean,
|
||||
gen?: number,
|
||||
condition?: ModdedConditionData,
|
||||
};
|
||||
|
||||
export interface MoveDataTable { [moveid: IDEntry]: MoveData }
|
||||
|
|
|
|||
|
|
@ -651,6 +651,15 @@ export class ModdedDex {
|
|||
// instead of overwriting entirely
|
||||
delete childTypedData[entryId].inherit;
|
||||
|
||||
// {inherit: true} can also be used to inherit parts of conditions
|
||||
if (childTypedData[entryId].condition?.inherit) {
|
||||
delete childTypedData[entryId].condition.inherit;
|
||||
childTypedData[entryId].condition = {
|
||||
...parentTypedData[entryId].condition,
|
||||
...childTypedData[entryId].condition,
|
||||
};
|
||||
}
|
||||
|
||||
// Merge parent and child's entry, with child overwriting parent.
|
||||
childTypedData[entryId] = { ...parentTypedData[entryId], ...childTypedData[entryId] };
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user