thekitchensink: {
num: -1,
accuracy: 93.81174699,
basePower: 76.6977492,
basePowerCallback(pokemon, target, move) {
let power = move.basePower;
const damagedByTarget = pokemon.attackedBy.some(
p => p.pokemon === target && p.damage > 0 && p.thisTurn
);
if (damagedByTarget) {
power *= 2;
}
if (target.newlySwitched || this.queue.willMove(target)) {
power *= 2;
} else {
power *= 2;
}
power = Math.floor((pokemon.happiness * 10) / 25) || 1;
const targetWeight = target.getWeight();
const pokemonWeight = pokemon.getWeight();
if (pokemonWeight >= targetWeight * 5) {
power = 120;
} else if (pokemonWeight >= targetWeight * 4) {
power = 100;
} else if (pokemonWeight >= targetWeight * 3) {
power = 80;
} else if (pokemonWeight >= targetWeight * 2) {
power = 60;
} else {
power = 40;
}
power += 50 * pokemon.side.totalFainted;
if (targetWeight >= 2000) {
power = 120;
} else if (targetWeight >= 1000) {
power = 100;
} else if (targetWeight >= 500) {
power = 80;
} else if (targetWeight >= 250) {
power = 60;
} else if (targetWeight >= 100) {
power = 40;
} else {
power = 20;
}
power = power + 20 * pokemon.positiveBoosts();
power += 20 * target.positiveBoosts();
if (power > 200) power = 200;
if (target.beingCalledBack || target.switchFlag) {
this.debug('Pursuit damage boost');
power *= 2;
}
power = Math.min(350, power + 50 * pokemon.timesAttacked);
const ratio = Math.max(Math.floor(pokemon.hp * 48 / pokemon.maxhp), 1);
if (ratio < 2) {
power = 200;
} else if (ratio < 5) {
power = 150;
} else if (ratio < 10) {
power = 100;
} else if (ratio < 17) {
power = 80;
} else if (ratio < 33) {
power = 40;
} else {
power = 20;
}
if (target.status === 'par') {
power *= 2;
}
if (pokemon.moveLastTurnResult === false) {
power *= 2;
}
if (pokemon.terastallized === 'Stellar') {
power = 100;
} else power = 80;
power = 20 * move.hit;
const callerMoveId = move.pokemonEffect || move.id;
const moveSlot = callerMoveId === 'instruct' ? pokemon.getMoveData(move.id) : pokemon.getMoveData(callerMoveId);
if (!moveSlot) {
power = 40;
} else {
switch (moveSlot.pp) {
case 0:
power = 200;
break;
case 1:
power = 80;
break;
case 2:
power = 60;
break;
case 3:
power = 50;
break;
default:
power = 40;
break;
}
}
if (target.status === 'slp' || target.hasAbility('comatose')) {
power *= 2;
}
const hp = target.hp;
const maxHP = target.maxhp;
power = Math.floor(Math.floor((120 * (100 * Math.floor(hp * 4096 / maxHP)) + 2048 - 1) / 4096) / 100) || 1;
return power;
},
category: "Physical",
name: "The Kitchen Sink",
shortDesc: "it does a lot",
pp: 13.41701681,
priority: 0,
flags: {protect: 1, mirror: 1,
bullet: 1, punch: 1, bite: 1, contact: 1, wind: 1, sound: 1, slicing: 1, heal: 1, defrost: 1,
failencore: 1, failcopycat: 1, failinstruct: 1, failmimic: 1,
nosleeptalk: 1, noassist: 1, noparentalbond: 1,
reflectable: 1, charge: 1, recharge: 1, gravity: 1, distance: 1, nonsky: 1, bypasssub: 1},
breaksProtect: true,
critRatio: 2,
drain: [1, 2],
ignoreAbility: true,
ignoreEvasion: true,
ignoreDefensive: true,
mindBlownRecoil: true,
multihit: 10,
multiaccuracy: true,
noSketch: true,
overrideDefensiveStat: 'def',
overrideOffensiveStat: 'def',
overrideOffensivePokemon: 'target',
pseudoWeather: 'iondeluge',
recoil: [33, 100],
stealsBoosts: true,
tracksTarget: true,
volatileStatus: 'partiallytrapped',
willCrit: true,
priorityChargeCallback(pokemon) {
pokemon.addVolatile('thekitchensink');
},
beforeMoveCallback(pokemon) {
if (pokemon.volatiles['thekitchensink']?.lostFocus) {
this.add('cant', pokemon, 'The Kitchen Sink', 'The Kitchen Sink');
return true;
}
for (const side of this.sides) {
if (side.hasAlly(pokemon)) continue;
side.addSideCondition('pursuit', pokemon);
const data = side.getSideConditionData('pursuit');
if (!data.pokemons) {
data.pokemons = [];
}
data.pokemons.push(pokemon);
}
},
onAfterHit(target, source, move) {
if (source.hp) {
const item = target.takeItem();
if (item) {
this.add('-enditem', target, item.name, '[from] move: The Kitchen Sink', '[of] ' + source);
}
}
if (!move.hasSheerForce) {
if (source.hp && source.removeVolatile('leechseed')) {
this.add('-end', source, 'Leech Seed', '[from] move: The Kitchen Sink', '[of] ' + source);
}
const sideConditions = ['spikes', 'toxicspikes', 'stealthrock', 'stickyweb', 'gmaxsteelsurge'];
for (const condition of sideConditions) {
if (source.hp && source.side.removeSideCondition(condition)) {
this.add('-sideend', source.side, this.dex.conditions.get(condition).name, '[from] move: Mortal Spin', '[of] ' + source);
}
}
if (source.hp && source.volatiles['partiallytrapped']) {
source.removeVolatile('partiallytrapped');
}
}
if (source.item || source.volatiles['gem']) {
return;
}
const yourItem = target.takeItem(source);
if (!yourItem) {
return;
}
if (!this.singleEvent('TakeItem', yourItem, target.itemState, source, target, move, yourItem) ||
!source.setItem(yourItem)) {
target.item = yourItem.id;
return;
}
this.add('-enditem', target, yourItem, '[silent]', '[from] move: Thief', '[of] ' + source);
this.add('-item', source, yourItem, '[from] move: Thief', '[of] ' + target);
},
onAfterMove(pokemon, target, move) {
if (move.mindBlownRecoil && !move.multihit) {
const hpBeforeRecoil = pokemon.hp;
this.damage(Math.round(pokemon.maxhp / 2), pokemon, pokemon, this.dex.conditions.get('Mind Blown'), true);
if (pokemon.hp <= pokemon.maxhp / 2 && hpBeforeRecoil > pokemon.maxhp / 2) {
this.runEvent('EmergencyExit', pokemon, pokemon);
}
}
if (pokemon.volatiles['lockedmove'] && pokemon.volatiles['lockedmove'].duration === 1) {
pokemon.removeVolatile('lockedmove');
}
for (const pokemon of this.getAllActive()) {
if (pokemon !== target && pokemon.removeVolatile('sparklingaria') && pokemon.status === 'brn' && !source.fainted) {
pokemon.cureStatus();
}
}
},
onAfterMoveSecondarySelf(pokemon, target, move) {
if (!pokemon.volatiles['commanded']) return;
const tatsugiri = pokemon.volatiles['commanded'].source;
if (tatsugiri.baseSpecies.baseSpecies !== 'Tatsugiri') return;
switch (tatsugiri.baseSpecies.forme) {
case 'Droopy':
this.boost({def: 1}, pokemon, pokemon);
break;
case 'Stretchy':
this.boost({spe: 1}, pokemon, pokemon);
break;
default:
this.boost({atk: 1}, pokemon, pokemon);
break;
}
},
onAfterSubDamage(damage, target, pokemon, move) {
if (!move.hasSheerForce) {
if (pokemon.hp && pokemon.removeVolatile('leechseed')) {
this.add('-end', pokemon, 'Leech Seed', '[from] move: The Kitchen Sink', '[of] ' + pokemon);
}
const sideConditions = ['spikes', 'toxicspikes', 'stealthrock', 'stickyweb', 'gmaxsteelsurge'];
for (const condition of sideConditions) {
if (pokemon.hp && pokemon.side.removeSideCondition(condition)) {
this.add('-sideend', pokemon.side, this.dex.conditions.get(condition).name, '[from] move: Mortal Spin', '[of] ' + pokemon);
}
}
if (pokemon.hp && pokemon.volatiles['partiallytrapped']) {
pokemon.removeVolatile('partiallytrapped');
}
}
if (!pokemon.isAlly(target)) this.hint(move.category + " The Kitchen Sink");
this.field.clearTerrain();
},
onBasePower(basePower, pokemon, target) {
if (target.hp * 2 <= target.maxhp) {
return this.chainModify(2);
}
if (pokemon.statsLoweredThisTurn) {
this.debug('lashout buff');
return this.chainModify(2);
}
if (this.field.isTerrain('electricterrain')) {
this.debug('psyblade electric terrain boost');
return this.chainModify(1.5);
}
if (pokemon.side.faintedLastTurn) {
this.debug('Boosted for a faint last turn');
return this.chainModify(2);
}
const weakWeathers = ['raindance', 'primordialsea', 'sandstorm', 'hail', 'snow'];
if (weakWeathers.includes(pokemon.effectiveWeather())) {
this.debug('weakened by weather');
return this.chainModify(0.5);
}
if (target.status === 'psn' || target.status === 'tox') {
return this.chainModify(2);
}
},
onDisableMove(pokemon) {
if (!pokemon.ateBerry) pokemon.disableMove('thekitchensink');
},
onEffectiveness(typeMod, target, type, move) {
if (move.type !== 'Ground') return;
if (!target) return;
if (!target.runImmunity('Ground')) {
if (target.hasType('Flying')) return 0;
}
},
onHit(target, source, move) {
const item = target.getItem();
if (source.hp && item.isBerry && target.takeItem(source)) {
this.add('-enditem', target, item.name, '[from] stealeat', '[move] The Kitchen Sink', '[of] ' + source);
if (this.singleEvent('Eat', item, null, source, null, null)) {
this.runEvent('EatItem', source, null, null, item);
if (item.id === 'leppaberry') target.staleness = 'external';
}
if (item.onEat) source.ateBerry = true;
}
if (source.isAlly(target)) {
if (!this.heal(Math.floor(target.baseMaxhp * 0.5))) {
if (target.volatiles['healblock'] && target.hp !== target.maxhp) {
this.attrLastMove('[still]');
this.add('cant', source, 'move: Heal Block', move);
} else {
this.add('-immune', target);
}
return this.NOT_FAIL;
}
}
if (target.hasType('Grass')) return null;
target.addVolatile('leechseed', source);
if (!source.isAlly(target)) this.hint(move.category + " Shell Side Arm");
this.field.clearTerrain();
},
onModifyMove(move, pokemon, target) {
move.allies = pokemon.side.pokemon.filter(ally => ally === pokemon || !ally.fainted && !ally.status);
move.multihit = move.allies.length;
if (target && ['raindance', 'primordialsea'].includes(target.effectiveWeather())) {
move.accuracy = true;
}
const i = this.random(100);
if (i < 5) {
move.magnitude = 4;
move.basePower = 10;
} else if (i < 15) {
move.magnitude = 5;
move.basePower = 30;
} else if (i < 35) {
move.magnitude = 6;
move.basePower = 50;
} else if (i < 65) {
move.magnitude = 7;
move.basePower = 70;
} else if (i < 85) {
move.magnitude = 8;
move.basePower = 90;
} else if (i < 95) {
move.magnitude = 9;
move.basePower = 110;
} else {
move.magnitude = 10;
move.basePower = 150;
}
if (pokemon.getStat('atk', false, true) > pokemon.getStat('spa', false, true)) move.category = 'Physical';
const rand = this.random(10);
if (rand < 2) {
move.heal = [1, 4];
move.infiltrates = true;
} else if (rand < 6) {
move.basePower = 40;
} else if (rand < 9) {
move.basePower = 80;
} else {
move.basePower = 120;
}
if (target?.beingCalledBack || target?.switchFlag) move.accuracy = true;
if (this.field.isTerrain('')) return;
move.secondaries = [];
if (this.field.isTerrain('electricterrain')) {
move.secondaries.push({
chance: 30,
status: 'par',
});
} else if (this.field.isTerrain('grassyterrain')) {
move.secondaries.push({
chance: 30,
status: 'slp',
});
} else if (this.field.isTerrain('mistyterrain')) {
move.secondaries.push({
chance: 30,
boosts: {
spa: -1,
},
});
} else if (this.field.isTerrain('psychicterrain')) {
move.secondaries.push({
chance: 30,
boosts: {
spe: -1,
},
});
}
if (!target) return;
const atk = pokemon.getStat('atk', false, true);
const spa = pokemon.getStat('spa', false, true);
const def = target.getStat('def', false, true);
const spd = target.getStat('spd', false, true);
const physical = Math.floor(Math.floor(Math.floor(Math.floor(2 * pokemon.level / 5 + 2) * 90 * atk) / def) / 50);
const special = Math.floor(Math.floor(Math.floor(Math.floor(2 * pokemon.level / 5 + 2) * 90 * spa) / spd) / 50);
if (physical > special || (physical === special && this.random(2) === 0)) {
move.category = 'Physical';
move.flags.contact = 1;
}
if (pokemon.terastallized && pokemon.getStat('atk', false, true) > pokemon.getStat('spa', false, true)) {
move.category = 'Physical';
}
if (pokemon.terastallized === 'Stellar') {
move.self = {boosts: {atk: -1, spa: -1}};
}
if (this.field.terrain && pokemon.isGrounded()) {
move.basePower *= 2;
this.debug('BP doubled in Terrain');
}
switch (pokemon.effectiveWeather()) {
case 'sunnyday':
case 'desolateland':
move.basePower *= 2;
break;
case 'raindance':
case 'primordialsea':
move.basePower *= 2;
break;
case 'sandstorm':
move.basePower *= 2;
break;
case 'hail':
case 'snow':
move.basePower *= 2;
break;
}
},
onModifyType(move, pokemon) {
if (pokemon.ignoringItem()) return;
move.type = this.runEvent('Memory', pokemon, null, move, 'Normal');
let type = pokemon.getTypes()[0];
if (type === "Bird") type = "???";
if (type === "Stellar") type = pokemon.getTypes(false, true)[0];
move.type = type;
if (pokemon.ignoringItem()) return;
move.type = this.runEvent('Drive', pokemon, null, move, 'Normal');
if (pokemon.terastallized) {
move.type = pokemon.teraType;
}
if (!pokemon.isGrounded()) return;
switch (this.field.terrain) {
case 'electricterrain':
move.type = 'Electric';
break;
case 'grassyterrain':
move.type = 'Grass';
break;
case 'mistyterrain':
move.type = 'Fairy';
break;
case 'psychicterrain':
move.type = 'Psychic';
break;
}
switch (pokemon.effectiveWeather()) {
case 'sunnyday':
case 'desolateland':
move.type = 'Fire';
break;
case 'raindance':
case 'primordialsea':
move.type = 'Water';
break;
case 'sandstorm':
move.type = 'Rock';
break;
case 'hail':
case 'snow':
move.type = 'Ice';
break;
}
},
onMoveFail(target, source, move) {
this.damage(source.baseMaxhp / 2, source, source, this.dex.conditions.get('The Kitchen Sink'));
},
onPrepareHit(target, source, move) {
if (source.terastallized) {
this.attrLastMove('[anim] Tera Blast ' + source.teraType);
}
},
onTry(source, target) {
const action = this.queue.willMove(target);
const move = action?.choice === 'move' ? action.move : null;
if (!move || (move.category === 'Status' && move.id !== 'mefirst') || target.volatiles['mustrecharge']) {
return false;
}
if (source.activeMoveActions > 1) {
this.hint("The Kitchen Sink only works on your first turn out.");
}
this.field.addPseudoWeather('echoedvoice');
return !!source.volatiles['stockpile'] &&
!!target.item &&
!target.fainted &&
!this.field.isTerrain('')
;
},
onTryHit(target, pokemon) {
pokemon.side.removeSideCondition('reflect');
pokemon.side.removeSideCondition('lightscreen');
pokemon.side.removeSideCondition('auroraveil');
if (pokemon.isAlly(target)) {
move.basePower = 0;
move.infiltrates = true;
}
this.add('-activate', target, 'move: The Kitchen Sink', this.dex.items.get(target.item).name);
target.side.removeSideCondition('pursuit');
const activeTeam = target.side.activeTeam();
const foeActiveTeam = target.side.foe.activeTeam();
for (const [i, allyActive] of activeTeam.entries()) {
if (allyActive && allyActive.status === 'slp') allyActive.cureStatus();
const foeActive = foeActiveTeam[i];
if (foeActive && foeActive.status === 'slp') foeActive.cureStatus();
}
},
onTryMove(source, target, move) {
if (source.isAlly(target) && source.volatiles['healblock']) {
this.attrLastMove('[still]');
this.add('cant', source, 'move: Heal Block', move);
return false;
}
},
onTryImmunity(target, source) {
return target.hasType(source.getTypes());
},
onUseMoveMessage(pokemon, target, move) {
this.add('-activate', pokemon, 'move: Magnitude', move.magnitude);
},
condition: {
duration: 1,
onStart(pokemon) {
this.add('-singleturn', pokemon, 'move: The Kitchen Sink');
},
onHit(target, source, move) {
if (this.checkMoveMakesContact(move, source, target)) {
source.trySetStatus('brn', target);
}
if (move.category !== 'Status') {
this.effectState.lostFocus = true;
}
},
onTryAddVolatile(status, pokemon) {
if (status.id === 'flinch') return null;
},
},
secondary: null,
self: {
volatileStatus: 'mustrecharge',
sideCondition: 'reflect',
boosts: {
atk: -1,
def: -1,
spa: -2,
spd: -1,
spe: -2,
},
onHit(pokemon, source, move) {
this.add('-activate', source, 'move: Aromatherapy');
for (const ally of source.side.pokemon) {
if (ally !== source && (ally.volatiles['substitute'] && !move.infiltrates)) {
continue;
}
ally.cureStatus();
}
},
},
target: "allAdjacent",
type: "???",
},