Support inheritance of ability, item, and move conditions (#11754)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run

This commit is contained in:
André Bastos Dias 2026-03-19 10:44:48 +00:00 committed by GitHub
parent 2dfe57c13a
commit 815b5f260a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 278 additions and 1409 deletions

View File

@ -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,

View File

@ -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: {

View File

@ -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",

View File

@ -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: {

View File

@ -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,

View File

@ -82,6 +82,7 @@ export const Items: import('../../../sim/dex-items').ModdedItemDataTable = {
num: 208,
gen: 3,
isNonstandard: "Unobtainable",
// No competitive use
},
fastball: {
inherit: true,

View File

@ -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);
},
},
},

View File

@ -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",

View File

@ -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,

View File

@ -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');

View File

@ -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);
},
},
},
};

View File

@ -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: {

View File

@ -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 (

View File

@ -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,

View File

@ -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: {

View File

@ -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,

View File

@ -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');

View File

@ -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);

View File

@ -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'));

View File

@ -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 }

View File

@ -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 }

View File

@ -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 }

View File

@ -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] };
}