Refactor battle.dex out of battle

In most other similar systems, like TeamValidator, we use `thing.dex`
instead of having it extend `ModdedDex`. Battle has always extended
`ModdedDex`, though. This changes Battle to match the others.

This should fix an issue with `Battle.data` not being cached.

This also frees up Battle to extend ObjectReadWriteStream<string> in
a future update.
This commit is contained in:
Guangcong Luo 2019-10-05 05:56:05 +10:00
parent 3cd04c349e
commit 2d3614f325
85 changed files with 734 additions and 731 deletions

View File

@ -239,7 +239,7 @@ let Formats = [
'Drought', 'Aurora Veil',
],
onValidateSet(set) {
let template = this.getTemplate(set.species || set.name);
let template = this.dex.getTemplate(set.species || set.name);
if (!template.nfe) {
return [set.species + " cannot evolve."];
}
@ -313,9 +313,9 @@ let Formats = [
'Spiritomb', 'Stantler', 'Starmie', 'Steelix', 'Stunfisk', 'Sudowoodo', 'Sunflora', 'Tauros', 'Throh', 'Togedemaru', 'Torkoal',
'Trevenant', 'Tropius', 'Turtonator', 'Vaporeon', 'Volbeat', 'Whimsicott', 'Wishiwashi', 'Wobbuffet', 'Zangoose',
];
let template = this.getTemplate(set.species || set.name);
let futureGenEvo = template.evos && this.getTemplate(template.evos[0]).gen > this.gen;
if ((template.prevo && this.getTemplate(template.prevo).gen <= this.gen || (!template.nfe || futureGenEvo)) && !allowedNonLittleCupMons.includes(template.baseSpecies) && template.speciesid !== 'sandslashalola') {
let template = this.dex.getTemplate(set.species || set.name);
let futureGenEvo = template.evos && this.dex.getTemplate(template.evos[0]).gen > this.gen;
if ((template.prevo && this.dex.getTemplate(template.prevo).gen <= this.gen || (!template.nfe || futureGenEvo)) && !allowedNonLittleCupMons.includes(template.baseSpecies) && template.speciesid !== 'sandslashalola') {
return [set.species + " isn't obtainable at Level 1."];
}
},
@ -414,12 +414,12 @@ let Formats = [
let n = 0;
let problems = [];
for (const set of team) {
const baseSpecies = this.getTemplate(set.species).baseSpecies;
const baseSpecies = this.dex.getTemplate(set.species).baseSpecies;
if (legends.includes(baseSpecies)) {
n++;
if (n === 3) problems.push(`You can only use up to two legendary Pok\u00E9mon.`);
}
const item = this.getItem(set.item);
const item = this.dex.getItem(set.item);
if (item.zMove || item.megaStone || ['redorb', 'blueorb'].includes(item.id)) problems.push(`${set.name || set.species}'s item ${item.name} is banned.`);
}
return problems;
@ -444,12 +444,12 @@ let Formats = [
let n = 0;
let problems = [];
for (const set of team) {
const baseSpecies = this.getTemplate(set.species).baseSpecies;
const baseSpecies = this.dex.getTemplate(set.species).baseSpecies;
if (legends.includes(baseSpecies)) {
n++;
if (n === 3) problems.push(`You can only use up to two legendary Pok\u00E9mon.`);
}
const item = this.getItem(set.item);
const item = this.dex.getItem(set.item);
if (item.megaStone || ['redorb', 'blueorb', 'ultranecroziumz'].includes(item.id)) problems.push(`${set.name || set.species}'s item ${item.name} is banned.`);
}
return problems;
@ -476,7 +476,7 @@ let Formats = [
const legends = ['Mewtwo', 'Lugia', 'Ho-Oh', 'Kyogre', 'Groudon', 'Rayquaza', 'Dialga', 'Palkia', 'Giratina', 'Reshiram', 'Zekrom', 'Kyurem', 'Xerneas', 'Yveltal', 'Zygarde', 'Cosmog', 'Cosmoem', 'Solgaleo', 'Lunala', 'Necrozma'];
let n = 0;
for (const set of team) {
const baseSpecies = this.getTemplate(set.species).baseSpecies;
const baseSpecies = this.dex.getTemplate(set.species).baseSpecies;
if (legends.includes(baseSpecies)) n++;
if (n > 2) return [`You can only use up to two legendary Pok\u00E9mon.`];
}
@ -590,7 +590,7 @@ let Formats = [
'Sitrus Berry', 'Wiki Berry', 'Harvest + Rowap Berry', 'Harvest + Jaboca Berry', 'Shedinja + Sturdy',
],
onValidateSet(set) {
let template = this.getTemplate(set.species);
let template = this.dex.getTemplate(set.species);
if (template.types.includes('Steel')) return [`${template.species} is a Steel-type, which is banned from Metronome Battle.`];
let bst = 0;
for (let stat in template.baseStats) {
@ -598,17 +598,17 @@ let Formats = [
bst += template.baseStats[stat];
}
if (bst > 625) return [`${template.species} is banned.`, `(Pok\u00e9mon with a BST higher than 625 are banned)`];
let item = this.getItem(set.item);
let item = this.dex.getItem(set.item);
if (set.item && item.megaStone) {
let bstMega = 0;
let megaTemplate = this.getTemplate(item.megaStone);
let megaTemplate = this.dex.getTemplate(item.megaStone);
for (let stat in megaTemplate.baseStats) {
// @ts-ignore
bstMega += megaTemplate.baseStats[stat];
}
if (template.baseSpecies === item.megaEvolves && bstMega > 625) return [`${set.name || set.species}'s item ${item.name} is banned.`, `(Pok\u00e9mon with a BST higher than 625 are banned)`];
}
if (set.moves.length !== 1 || this.getMove(set.moves[0]).id !== 'metronome') return [`${set.name || set.species} has illegal moves.`, `(Pok\u00e9mon can only have one Metronome in their moveset)`];
if (set.moves.length !== 1 || this.dex.getMove(set.moves[0]).id !== 'metronome') return [`${set.name || set.species} has illegal moves.`, `(Pok\u00e9mon can only have one Metronome in their moveset)`];
},
},
{
@ -743,7 +743,7 @@ let Formats = [
let [familyId] = evoFamilies;
if (!(familyId in requiredFamilies)) requiredFamilies[familyId] = 1;
requiredFamilies[familyId]++;
if (requiredFamilies[familyId] > 2) return [`You are limited to up to two inheritances from each evolution family by the Donor Clause.`, `(You inherit more than twice from ${this.getTemplate(familyId).species}).`];
if (requiredFamilies[familyId] > 2) return [`You are limited to up to two inheritances from each evolution family by the Donor Clause.`, `(You inherit more than twice from ${this.dex.getTemplate(familyId).species}).`];
}
},
onBegin() {
@ -762,7 +762,7 @@ let Formats = [
// @ts-ignore
if (!pokemon.donor) return;
// @ts-ignore
let donorTemplate = this.getTemplate(pokemon.donor);
let donorTemplate = this.dex.getTemplate(pokemon.donor);
if (!donorTemplate.exists) return;
// Place volatiles on the Pokémon to show the donor details.
this.add('-start', pokemon, donorTemplate.species, '[silent]');
@ -829,16 +829,16 @@ let Formats = [
/**@type {{[k: string]: true}} */
let itemTable = {};
for (const set of team) {
let item = this.getItem(set.item);
let item = this.dex.getItem(set.item);
if (!item) continue;
if (itemTable[item.id] && item.megaStone) return ["You are limited to one of each Mega Stone.", "(You have more than one " + this.getItem(item).name + ")"];
if (itemTable[item.id] && ['blueorb', 'redorb'].includes(item.id)) return ["You are limited to one of each Primal Orb.", "(You have more than one " + this.getItem(item).name + ")"];
if (itemTable[item.id] && item.megaStone) return ["You are limited to one of each Mega Stone.", "(You have more than one " + this.dex.getItem(item).name + ")"];
if (itemTable[item.id] && ['blueorb', 'redorb'].includes(item.id)) return ["You are limited to one of each Primal Orb.", "(You have more than one " + this.dex.getItem(item).name + ")"];
itemTable[item.id] = true;
}
},
onValidateSet(set, format) {
let template = this.getTemplate(set.species || set.name);
let item = this.getItem(set.item);
let template = this.dex.getTemplate(set.species || set.name);
let item = this.dex.getItem(set.item);
if (!item.megaEvolves && !['blueorb', 'redorb', 'ultranecroziumz'].includes(item.id)) return;
if (template.baseSpecies === item.megaEvolves || (template.baseSpecies === 'Groudon' && item.id === 'redorb') || (template.baseSpecies === 'Kyogre' && item.id === 'blueorb') || (template.species.substr(0, 9) === 'Necrozma-' && item.id === 'ultranecroziumz')) return;
let uberStones = format.restrictedStones || [];
@ -852,11 +852,11 @@ let Formats = [
},
onSwitchIn(pokemon) {
// @ts-ignore
let oMegaTemplate = this.getTemplate(pokemon.template.originalMega);
let oMegaTemplate = this.dex.getTemplate(pokemon.template.originalMega);
if (oMegaTemplate.exists && pokemon.m.originalSpecies !== oMegaTemplate.baseSpecies) {
// Place volatiles on the Pokémon to show its mega-evolved condition and details
this.add('-start', pokemon, oMegaTemplate.requiredItem || oMegaTemplate.requiredMove, '[silent]');
let oTemplate = this.getTemplate(pokemon.m.originalSpecies);
let oTemplate = this.dex.getTemplate(pokemon.m.originalSpecies);
if (oTemplate.types.length !== pokemon.template.types.length || oTemplate.types[1] !== pokemon.template.types[1]) {
this.add('-start', pokemon, 'typechange', pokemon.template.types.join('/'), '[silent]');
}
@ -864,7 +864,7 @@ let Formats = [
},
onSwitchOut(pokemon) {
// @ts-ignore
let oMegaTemplate = this.getTemplate(pokemon.template.originalMega);
let oMegaTemplate = this.dex.getTemplate(pokemon.template.originalMega);
if (oMegaTemplate.exists && pokemon.m.originalSpecies !== oMegaTemplate.baseSpecies) {
this.add('-end', pokemon, oMegaTemplate.requiredItem || oMegaTemplate.requiredMove, '[silent]');
}
@ -889,7 +889,7 @@ let Formats = [
onValidateSet(set, format) {
let restrictedAbilities = format.restrictedAbilities || [];
if (restrictedAbilities.includes(set.ability)) {
let template = this.getTemplate(set.species || set.name);
let template = this.dex.getTemplate(set.species || set.name);
let legalAbility = false;
for (let i in template.abilities) {
// @ts-ignore
@ -912,7 +912,7 @@ let Formats = [
onModifyTemplate(template, target, source, effect) {
if (!target) return; // Chat command
if (effect && ['imposter', 'transform'].includes(effect.id)) return;
let types = [...new Set(target.baseMoveSlots.slice(0, 2).map(move => this.getMove(move.id).type))];
let types = [...new Set(target.baseMoveSlots.slice(0, 2).map(move => this.dex.getMove(move.id).type))];
return Object.assign({}, template, {types: types});
},
onSwitchIn(pokemon) {
@ -964,20 +964,20 @@ let Formats = [
if (target && target.set.ability === 'Drizzle') return;
let tier = template.tier;
if (target && target.set.item) {
let item = this.getItem(target.set.item);
let item = this.dex.getItem(target.set.item);
if (item.name === 'Kommonium Z' || item.name === 'Mewnium Z') return;
if (item.megaEvolves === template.species) tier = this.getTemplate(item.megaStone).tier;
if (item.megaEvolves === template.species) tier = this.dex.getTemplate(item.megaStone).tier;
}
if (target && target.set.moves.includes('auroraveil')) tier = 'UU';
if (target && target.set.ability === 'Drought') tier = 'RU';
if (tier[0] === '(') tier = tier.slice(1, -1);
if (!(tier in boosts)) return;
let pokemon = this.deepClone(template);
let pokemon = this.dex.deepClone(template);
let boost = boosts[tier];
for (let statName in pokemon.baseStats) {
if (statName === 'hp') continue;
pokemon.baseStats[statName] = this.clampIntRange(pokemon.baseStats[statName] + boost, 1, 255);
pokemon.baseStats[statName] = this.dex.clampIntRange(pokemon.baseStats[statName] + boost, 1, 255);
}
return pokemon;
},
@ -1191,7 +1191,7 @@ let Formats = [
onSwitchInPriority: 100,
onSwitchIn(pokemon) {
let name = toID(pokemon.illusion ? pokemon.illusion.name : pokemon.name);
if (this.getTemplate(name).exists || name === 'rage') {
if (this.dex.getTemplate(name).exists || name === 'rage') {
// Certain pokemon have volatiles named after their speciesid
// To prevent overwriting those, and to prevent accidentaly leaking
// that a pokemon is on a team through the onStart even triggering
@ -1200,7 +1200,7 @@ let Formats = [
name = /** @type {ID} */(name + 'user');
}
// Add the mon's status effect to it as a volatile.
let status = this.getEffect(name);
let status = this.dex.getEffect(name);
if (status && status.exists) {
pokemon.addVolatile(name, pokemon);
}
@ -1632,7 +1632,7 @@ let Formats = [
const legends = ['Mewtwo', 'Lugia', 'Ho-Oh', 'Kyogre', 'Groudon', 'Rayquaza', 'Dialga', 'Palkia', 'Giratina', 'Reshiram', 'Zekrom', 'Kyurem', 'Xerneas', 'Yveltal', 'Zygarde'];
let n = 0;
for (const set of team) {
let baseSpecies = this.getTemplate(set.species).baseSpecies;
let baseSpecies = this.dex.getTemplate(set.species).baseSpecies;
if (legends.includes(baseSpecies)) n++;
if (n > 2) return ["You can only use up to two legendary Pok\u00E9mon."];
}

View File

@ -144,9 +144,9 @@ let BattleAbilities = {
for (const target of pokemon.side.foe.active) {
if (!target || target.fainted) continue;
for (const moveSlot of target.moveSlots) {
const move = this.getMove(moveSlot.move);
const move = this.dex.getMove(moveSlot.move);
const moveType = move.id === 'hiddenpower' ? target.hpType : move.type;
if (move.category !== 'Status' && (this.getImmunity(moveType, pokemon) && this.getEffectiveness(moveType, pokemon) > 0 || move.ohko)) {
if (move.category !== 'Status' && (this.dex.getImmunity(moveType, pokemon) && this.dex.getEffectiveness(moveType, pokemon) > 0 || move.ohko)) {
this.add('-ability', pokemon, 'Anticipation');
return;
}
@ -1111,7 +1111,7 @@ let BattleAbilities = {
for (const target of pokemon.side.foe.active) {
if (target.fainted) continue;
for (const moveSlot of target.moveSlots) {
let move = this.getMove(moveSlot.move);
let move = this.dex.getMove(moveSlot.move);
let bp = move.basePower;
if (move.ohko) bp = 150;
if (move.id === 'counter' || move.id === 'metalburst' || move.id === 'mirrorcoat') bp = 120;
@ -1290,7 +1290,7 @@ let BattleAbilities = {
onResidualSubOrder: 1,
onResidual(pokemon) {
if (this.field.isWeather(['sunnyday', 'desolateland']) || this.randomChance(1, 2)) {
if (pokemon.hp && !pokemon.item && this.getItem(pokemon.lastItem).isBerry) {
if (pokemon.hp && !pokemon.item && this.dex.getItem(pokemon.lastItem).isBerry) {
pokemon.setItem(pokemon.lastItem);
pokemon.lastItem = '';
this.add('-item', pokemon, pokemon.getItem(), '[from] ability: Harvest');
@ -1460,7 +1460,7 @@ let BattleAbilities = {
},
onAfterDamage(damage, target, source, effect) {
if (target.illusion && effect && effect.effectType === 'Move' && effect.id !== 'confused') {
this.singleEvent('End', this.getAbility('Illusion'), target.abilityData, target, source, effect);
this.singleEvent('End', this.dex.getAbility('Illusion'), target.abilityData, target, source, effect);
}
},
onEnd(pokemon) {
@ -1507,7 +1507,7 @@ let BattleAbilities = {
if (this.activeMove && this.activeMove.id === 'skillswap') return;
let target = pokemon.side.foe.active[pokemon.side.foe.active.length - 1 - pokemon.position];
if (target) {
pokemon.transformInto(target, this.getAbility('imposter'));
pokemon.transformInto(target, this.dex.getAbility('imposter'));
}
},
id: "imposter",
@ -1793,7 +1793,7 @@ let BattleAbilities = {
if (target === source || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.useMove(newMove, target, source);
@ -1803,7 +1803,7 @@ let BattleAbilities = {
if (target.side === source.side || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.useMove(newMove, this.effectData.target, source);
@ -2061,7 +2061,7 @@ let BattleAbilities = {
if (source && source !== target && move && move.flags['contact'] && source.ability !== 'mummy') {
let oldAbility = source.setAbility('mummy', target);
if (oldAbility) {
this.add('-activate', target, 'ability: Mummy', this.getAbility(oldAbility).name, '[of] ' + source);
this.add('-activate', target, 'ability: Mummy', this.dex.getAbility(oldAbility).name, '[of] ' + source);
}
}
},
@ -2094,7 +2094,7 @@ let BattleAbilities = {
// this.add('-message', "" + curPoke + " skipped: Natural Cure already known");
continue;
}
let template = this.getTemplate(curPoke.species);
let template = this.dex.getTemplate(curPoke.species);
// pokemon can't get Natural Cure
if (Object.values(template.abilities).indexOf('Natural Cure') < 0) {
// this.add('-message', "" + curPoke + " skipped: no Natural Cure");
@ -2235,7 +2235,7 @@ let BattleAbilities = {
},
onTryHitPriority: 1,
onTryHit(target, source, move) {
if (move.flags['powder'] && target !== source && this.getImmunity('powder', target)) {
if (move.flags['powder'] && target !== source && this.dex.getImmunity('powder', target)) {
this.add('-immune', target, '[from] ability: Overcoat');
return null;
}
@ -2354,7 +2354,7 @@ let BattleAbilities = {
let randomTarget = this.sample(pickupTargets);
let item = randomTarget.lastItem;
randomTarget.lastItem = '';
this.add('-item', pokemon, this.getItem(item), '[from] ability: Pickup');
this.add('-item', pokemon, this.dex.getItem(item), '[from] ability: Pickup');
pokemon.setItem(item);
},
id: "pickup",
@ -2440,7 +2440,7 @@ let BattleAbilities = {
move.secondaries.push({
chance: 30,
status: 'psn',
ability: this.getAbility('poisontouch'),
ability: this.dex.getAbility('poisontouch'),
});
},
id: "poisontouch",
@ -2472,7 +2472,7 @@ let BattleAbilities = {
shortDesc: "This Pokemon copies the Ability of an ally that faints.",
onAllyFaint(target) {
if (!this.effectData.target.hp) return;
let ability = this.getAbility(target.ability);
let ability = this.dex.getAbility(target.ability);
let bannedAbilities = ['battlebond', 'comatose', 'disguise', 'flowergift', 'forecast', 'illusion', 'imposter', 'multitype', 'powerconstruct', 'powerofalchemy', 'receiver', 'rkssystem', 'schooling', 'shieldsdown', 'stancechange', 'trace', 'wonderguard', 'zenmode'];
if (bannedAbilities.includes(target.ability)) return;
this.add('-ability', this.effectData.target, ability, '[from] ability: Power of Alchemy', '[of] ' + target);
@ -2647,7 +2647,7 @@ let BattleAbilities = {
shortDesc: "This Pokemon copies the Ability of an ally that faints.",
onAllyFaint(target) {
if (!this.effectData.target.hp) return;
let ability = this.getAbility(target.ability);
let ability = this.dex.getAbility(target.ability);
let bannedAbilities = ['battlebond', 'comatose', 'disguise', 'flowergift', 'forecast', 'illusion', 'imposter', 'multitype', 'powerconstruct', 'powerofalchemy', 'receiver', 'rkssystem', 'schooling', 'shieldsdown', 'stancechange', 'trace', 'wonderguard', 'zenmode'];
if (bannedAbilities.includes(target.ability)) return;
this.add('-ability', this.effectData.target, ability, '[from] ability: Receiver', '[of] ' + target);
@ -3735,7 +3735,7 @@ let BattleAbilities = {
let rand = 0;
if (possibleTargets.length > 1) rand = this.random(possibleTargets.length);
let target = possibleTargets[rand];
let ability = this.getAbility(target.ability);
let ability = this.dex.getAbility(target.ability);
let bannedAbilities = ['noability', 'battlebond', 'comatose', 'disguise', 'flowergift', 'forecast', 'illusion', 'imposter', 'multitype', 'powerconstruct', 'powerofalchemy', 'receiver', 'rkssystem', 'schooling', 'shieldsdown', 'stancechange', 'trace', 'zenmode'];
if (bannedAbilities.includes(target.ability)) {
possibleTargets.splice(rand, 1);
@ -4152,7 +4152,7 @@ let BattleAbilities = {
if (target === source || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
this.useMove(newMove, target, source);
return null;
@ -4163,7 +4163,7 @@ let BattleAbilities = {
if (target.side === source.side || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
this.useMove(newMove, this.effectData.target, source);
return null;

View File

@ -153,7 +153,7 @@ let BattleItems = {
this.add('-enditem', target, 'Air Balloon');
target.item = '';
target.itemData = {id: '', target};
this.runEvent('AfterUseItem', target, null, null, this.getItem('airballoon'));
this.runEvent('AfterUseItem', target, null, null, this.dex.getItem('airballoon'));
}
},
onAfterSubDamage(damage, target, source, effect) {
@ -162,7 +162,7 @@ let BattleItems = {
this.add('-enditem', target, 'Air Balloon');
target.item = '';
target.itemData = {id: '', target};
this.runEvent('AfterUseItem', target, null, null, this.getItem('airballoon'));
this.runEvent('AfterUseItem', target, null, null, this.dex.getItem('airballoon'));
}
},
num: 541,
@ -291,7 +291,7 @@ let BattleItems = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.move).category === 'Status') {
if (this.dex.getMove(moveSlot.move).category === 'Status') {
pokemon.disableMove(moveSlot.id);
}
}
@ -3001,7 +3001,7 @@ let BattleItems = {
},
onAfterMoveSecondarySelf(source, target, move) {
if (source && source !== target && move && move.category !== 'Status') {
this.damage(source.maxhp / 10, source, source, this.getItem('lifeorb'));
this.damage(source.maxhp / 10, source, source, this.dex.getItem('lifeorb'));
}
},
num: 270,
@ -4952,7 +4952,7 @@ let BattleItems = {
if (type === 'sandstorm' || type === 'hail' || type === 'powder') return false;
},
onTryHit(pokemon, source, move) {
if (move.flags['powder'] && pokemon !== source && this.getImmunity('powder', pokemon)) {
if (move.flags['powder'] && pokemon !== source && this.dex.getImmunity('powder', pokemon)) {
this.add('-activate', pokemon, 'item: Safety Goggles', move.name);
return null;
}

View File

@ -253,7 +253,7 @@ let BattleMovedex = {
// It will fail if the last move selected by the opponent has base power 0 or is not Normal or Fighting Type.
// If both are true, counter will deal twice the last damage dealt in battle, no matter what was the move.
// That means that, if opponent switches, counter will use last counter damage * 2.
let lastUsedMove = target.side.lastMove && this.getMove(target.side.lastMove.id);
let lastUsedMove = target.side.lastMove && this.dex.getMove(target.side.lastMove.id);
if (lastUsedMove && lastUsedMove.basePower > 0 && ['Normal', 'Fighting'].includes(lastUsedMove.type) && this.lastDamage > 0 && !this.willMove(target)) {
return 2 * this.lastDamage;
}
@ -306,7 +306,7 @@ let BattleMovedex = {
this.effectData.duration++;
}
let moves = pokemon.moves;
let move = this.getMove(this.sample(moves));
let move = this.dex.getMove(this.sample(moves));
this.add('-start', pokemon, 'Disable', move.name);
this.effectData.move = move.id;
return;
@ -558,7 +558,7 @@ let BattleMovedex = {
residualdmg.counter++;
toxicCounter = residualdmg.counter;
}
let toLeech = this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * toxicCounter;
let toLeech = this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * toxicCounter;
let damage = this.damage(toLeech, pokemon, leecher);
if (residualdmg) this.hint("In Gen 1, Leech Seed's damage is affected by Toxic's counter.", true);
if (!damage || toLeech > damage) {
@ -613,7 +613,7 @@ let BattleMovedex = {
let moves = target.moves;
let moveid = this.sample(moves);
if (!moveid) return false;
let move = this.getMove(moveid);
let move = this.dex.getMove(moveid);
source.moveSlots[moveslot] = {
move: move.name,
id: move.id,

View File

@ -22,9 +22,9 @@ class RandomGen1Teams extends RandomGen2Teams {
}
let formeCounter = 0;
for (let id in this.data.Pokedex) {
if (!(this.data.Pokedex[id].num in hasDexNumber)) continue;
let template = this.getTemplate(id);
for (let id in this.dex.data.Pokedex) {
if (!(this.dex.data.Pokedex[id].num in hasDexNumber)) continue;
let template = this.dex.getTemplate(id);
if (!template.learnset || template.forme) continue;
formes[hasDexNumber[template.num]].push(template.species);
if (++formeCounter >= 6) {
@ -36,7 +36,7 @@ class RandomGen1Teams extends RandomGen2Teams {
for (let i = 0; i < 6; i++) {
// Choose forme.
let poke = this.sample(formes[i]);
let template = this.getTemplate(poke);
let template = this.dex.getTemplate(poke);
// Level balance: calculate directly from stats rather than using some silly lookup table.
let mbstmin = 1307;
@ -90,7 +90,7 @@ class RandomGen1Teams extends RandomGen2Teams {
let pool = [];
if (template.learnset) {
for (let move in template.learnset) {
if (this.getMove(move).gen !== 1) continue;
if (this.dex.getMove(move).gen !== 1) continue;
if (template.learnset[move].some(learned => learned[0] === '1')) {
pool.push(move);
}
@ -132,8 +132,8 @@ class RandomGen1Teams extends RandomGen2Teams {
let uuTiers = ['NFE', 'UU', 'UUBL', 'NU'];
let pokemonPool = [];
for (let id in this.data.FormatsData) {
let template = this.getTemplate(id);
for (let id in this.dex.data.FormatsData) {
let template = this.dex.getTemplate(id);
if (!template.isNonstandard && template.randomBattleMoves) {
pokemonPool.push(id);
}
@ -149,7 +149,7 @@ class RandomGen1Teams extends RandomGen2Teams {
let hasShitmon = false;
while (pokemonPool.length && pokemonLeft < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
// Bias the tiers so you get less shitmons and only one of the two Ubers.
@ -189,7 +189,7 @@ class RandomGen1Teams extends RandomGen2Teams {
// Spammable attacks are: Thunderbolt, Psychic, Surf, Blizzard, Earthquake.
let pokemonWeaknesses = [];
for (let type in weaknessCount) {
let increaseCount = this.getImmunity(type, template) && this.getEffectiveness(type, template) > 0;
let increaseCount = this.dex.getImmunity(type, template) && this.dex.getEffectiveness(type, template) > 0;
if (!increaseCount) continue;
if (weaknessCount[type] >= 2) {
skip = true;
@ -241,8 +241,8 @@ class RandomGen1Teams extends RandomGen2Teams {
* @return {RandomTeamsTypes.RandomSet}
*/
randomSet(template) {
template = this.getTemplate(template);
if (!template.exists) template = this.getTemplate('pikachu'); // Because Gen 1.
template = this.dex.getTemplate(template);
if (!template.exists) template = this.dex.getTemplate('pikachu'); // Because Gen 1.
let movePool = template.randomBattleMoves ? template.randomBattleMoves.slice() : [];
/**@type {string[]} */
@ -292,7 +292,7 @@ class RandomGen1Teams extends RandomGen2Teams {
hasMove = {};
counter = {Physical: 0, Special: 0, Status: 0, physicalsetup: 0, specialsetup: 0};
for (const setMoveid of moves) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
let moveid = move.id;
hasMove[moveid] = true;
if (!move.damage && !move.damageCallback) {
@ -314,7 +314,7 @@ class RandomGen1Teams extends RandomGen2Teams {
for (const [i, moveid] of moves.entries()) {
if (moveid === template.essentialMove) continue;
let move = this.getMove(moveid);
let move = this.dex.getMove(moveid);
let rejected = false;
if (!template.essentialMove || moveid !== template.essentialMove) {
switch (moveid) {

View File

@ -11,7 +11,7 @@ let BattleScripts = {
inherit: 'gen2',
gen: 1,
debug(activity) {
if (this.getFormat().debug) {
if (this.format.debug) {
this.add('debug', activity);
}
},
@ -39,7 +39,7 @@ let BattleScripts = {
modifyStat(statName, modifier) {
if (!(statName in this.storedStats)) throw new Error("Invalid `statName` passed to `modifyStat`");
// @ts-ignore
this.modifiedStats[statName] = this.battle.clampIntRange(Math.floor(this.modifiedStats[statName] * modifier), 1, 999);
this.modifiedStats[statName] = this.battle.dex.clampIntRange(Math.floor(this.modifiedStats[statName] * modifier), 1, 999);
},
// In generation 1, boosting function increases the stored modified stat and checks for opponent's status.
boostBy(boost) {
@ -91,7 +91,7 @@ let BattleScripts = {
// It also deals with how PP reduction works on gen 1.
runMove(moveOrMoveName, pokemon, targetLoc, sourceEffect) {
let target = this.getTarget(pokemon, moveOrMoveName, targetLoc);
let move = this.getActiveMove(moveOrMoveName);
let move = this.dex.getActiveMove(moveOrMoveName);
if (target && target.subFainted) target.subFainted = null;
this.setActiveMove(move, pokemon, target);
@ -174,8 +174,8 @@ let BattleScripts = {
// @ts-ignore
useMove(moveOrMoveName, pokemon, target, sourceEffect) {
if (!sourceEffect && this.effect.id) sourceEffect = this.effect;
let baseMove = this.getMove(moveOrMoveName);
let move = this.getActiveMove(baseMove);
let baseMove = this.dex.getMove(moveOrMoveName);
let move = this.dex.getActiveMove(baseMove);
if (target === undefined) target = this.resolveTarget(pokemon, move);
if (move.target === 'self') {
target = pokemon;
@ -205,7 +205,7 @@ let BattleScripts = {
return false;
}
if (sourceEffect) attrs += '|[from]' + this.getEffect(sourceEffect);
if (sourceEffect) attrs += '|[from]' + this.dex.getEffect(sourceEffect);
this.addMove('move', pokemon, move.name, target + attrs);
if (!this.singleEvent('Try', move, null, pokemon, target, move)) {
@ -628,7 +628,7 @@ let BattleScripts = {
if (!source) source = this.event.source;
if (!effect) effect = this.effect;
}
if (typeof effect === 'string') effect = this.getEffect(effect);
if (typeof effect === 'string') effect = this.dex.getEffect(effect);
if (!target || !target.hp) return 0;
let success = null;
boost = this.runEvent('Boost', target, source, effect, Object.assign({}, boost));
@ -680,7 +680,7 @@ let BattleScripts = {
getDamage(pokemon, target, move, suppressMessages) {
// First of all, we get the move.
if (typeof move === 'string') {
move = this.getActiveMove(move);
move = this.dex.getActiveMove(move);
} else if (typeof move === 'number') {
// @ts-ignore
move = /** @type {ActiveMove} */ ({
@ -745,7 +745,7 @@ let BattleScripts = {
if (!basePower) {
return basePower === 0 ? undefined : basePower;
}
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
// Checking for the move's Critical Hit possibility. We check if it's a 100% crit move, otherwise we calculate the chance.
let isCrit = move.willCrit || false;
@ -760,7 +760,7 @@ let BattleScripts = {
critChance = Math.floor(critChance / 2);
} else {
// Normally, without focus energy, crit chance is multiplied by 2 and capped at 255 here.
critChance = this.clampIntRange(critChance * 2, 1, 255);
critChance = this.dex.clampIntRange(critChance * 2, 1, 255);
}
// Now we check for the move's critical hit ratio.
@ -769,7 +769,7 @@ let BattleScripts = {
critChance = Math.floor(critChance / 2);
} else if (move.critRatio === 2) {
// High crit ratio, we multiply the result so far by 4 and cap it at 255.
critChance = this.clampIntRange(critChance * 4, 1, 255);
critChance = this.dex.clampIntRange(critChance * 4, 1, 255);
}
// Last, we check deppending on ratio if the move critical hits or not.
@ -789,7 +789,7 @@ let BattleScripts = {
}
}
if (!basePower) return 0;
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
// We now check attacker's and defender's stats.
let level = pokemon.level;
@ -807,7 +807,7 @@ let BattleScripts = {
if ((defType === 'def' && defender.volatiles['reflect']) || (defType === 'spd' && defender.volatiles['lightscreen'])) {
this.debug('Screen doubling (Sp)Def');
defense *= 2;
defense = this.clampIntRange(defense, 1, 1998);
defense = this.dex.clampIntRange(defense, 1, 1998);
}
// In the event of a critical hit, the offense and defense changes are ignored.
@ -832,14 +832,14 @@ let BattleScripts = {
// When either attack or defense are higher than 256, they are both divided by 4 and moded by 256.
// This is what cuases the roll over bugs.
if (attack >= 256 || defense >= 256) {
attack = this.clampIntRange(Math.floor(attack / 4) % 256, 1);
attack = this.dex.clampIntRange(Math.floor(attack / 4) % 256, 1);
// Defense isn't checked on the cartridge, but we don't want those / 0 bugs on the sim.
defense = this.clampIntRange(Math.floor(defense / 4) % 256, 1);
defense = this.dex.clampIntRange(Math.floor(defense / 4) % 256, 1);
}
// Self destruct moves halve defense at this point.
if (move.selfdestruct && defType === 'def') {
defense = this.clampIntRange(Math.floor(defense / 2), 1);
defense = this.dex.clampIntRange(Math.floor(defense / 2), 1);
}
// Let's go with the calculation now that we have what we need.
@ -850,7 +850,7 @@ let BattleScripts = {
damage *= basePower;
damage *= attack;
damage = Math.floor(damage / defense);
damage = this.clampIntRange(Math.floor(damage / 50), 1, 997);
damage = this.dex.clampIntRange(Math.floor(damage / 50), 1, 997);
damage += 2;
// STAB damage bonus, the "???" type never gets STAB

View File

@ -24,7 +24,7 @@ let BattleStatuses = {
onAfterMoveSelfPriority: 2,
onAfterMoveSelf(pokemon) {
let toxicCounter = pokemon.volatiles['residualdmg'] ? pokemon.volatiles['residualdmg'].counter : 1;
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * toxicCounter, pokemon);
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * toxicCounter, pokemon);
if (pokemon.volatiles['residualdmg']) {
this.hint("In Gen 1, Toxic's counter is retained after Rest and applies to PSN/BRN.", true);
}
@ -33,7 +33,7 @@ let BattleStatuses = {
pokemon.addVolatile('brnattackdrop');
},
onAfterSwitchInSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
},
par: {
@ -122,13 +122,13 @@ let BattleStatuses = {
onAfterMoveSelfPriority: 2,
onAfterMoveSelf(pokemon) {
let toxicCounter = pokemon.volatiles['residualdmg'] ? pokemon.volatiles['residualdmg'].counter : 1;
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * toxicCounter, pokemon);
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * toxicCounter, pokemon);
if (pokemon.volatiles['residualdmg']) {
this.hint("In Gen 1, Toxic's counter is retained after Rest and applies to PSN/BRN.", true);
}
},
onAfterSwitchInSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
},
tox: {

View File

@ -39,7 +39,7 @@ let BattleMovedex = {
return false;
}
if (target.hp <= target.maxhp / 2) {
this.boost({atk: 2}, null, null, this.getEffect('bellydrum2'));
this.boost({atk: 2}, null, null, this.dex.getEffect('bellydrum2'));
return false;
}
this.directDamage(target.maxhp / 2);
@ -97,7 +97,7 @@ let BattleMovedex = {
return false;
}
if (!target.isActive) {
const possibleTarget = this.resolveTarget(pokemon, this.getMove('pound'));
const possibleTarget = this.resolveTarget(pokemon, this.dex.getMove('pound'));
if (!possibleTarget) {
this.add('-miss', pokemon);
return false;
@ -148,7 +148,7 @@ let BattleMovedex = {
desc: "Deals damage to the opposing Pokemon equal to twice the HP lost by the user from a physical attack this turn. This move considers Hidden Power as Normal type, and only the last hit of a multi-hit attack is counted. Fails if the user moves first, if the user was not hit by a physical attack this turn, or if the user did not lose HP from the attack. If the opposing Pokemon used Fissure or Horn Drill and missed, this move deals 65535 damage.",
damageCallback(pokemon, target) {
let lastAttackedBy = pokemon.getLastAttackedBy();
if (lastAttackedBy && lastAttackedBy.move && lastAttackedBy.thisTurn && (this.getCategory(lastAttackedBy.move) === 'Physical' || this.getMove(lastAttackedBy.move).id === 'hiddenpower') && (!target.lastMove || target.lastMove.id !== 'sleeptalk')) {
if (lastAttackedBy && lastAttackedBy.move && lastAttackedBy.thisTurn && (this.getCategory(lastAttackedBy.move) === 'Physical' || this.dex.getMove(lastAttackedBy.move).id === 'hiddenpower') && (!target.lastMove || target.lastMove.id !== 'sleeptalk')) {
return 2 * lastAttackedBy.damage;
}
return false;
@ -387,7 +387,7 @@ let BattleMovedex = {
if (target.runImmunity('Fighting')) {
let damage = this.getDamage(source, target, move, true);
if (typeof damage !== 'number') throw new Error("Couldn't get High Jump Kick recoil");
this.damage(this.clampIntRange(damage / 8, 1), source, source, move);
this.damage(this.dex.clampIntRange(damage / 8, 1), source, source, move);
}
},
},
@ -407,7 +407,7 @@ let BattleMovedex = {
if (target.runImmunity('Fighting')) {
let damage = this.getDamage(source, target, move, true);
if (typeof damage !== 'number') throw new Error("Couldn't get Jump Kick recoil");
this.damage(this.clampIntRange(damage / 8, 1), source, source, move);
this.damage(this.dex.clampIntRange(damage / 8, 1), source, source, move);
}
},
},
@ -429,7 +429,7 @@ let BattleMovedex = {
if (!leecher || leecher.fainted || leecher.hp <= 0) {
return;
}
let toLeech = this.clampIntRange(pokemon.maxhp / 8, 1);
let toLeech = this.dex.clampIntRange(pokemon.maxhp / 8, 1);
let damage = this.damage(toLeech, pokemon, leecher);
if (damage) {
this.heal(damage, leecher, pokemon);
@ -501,7 +501,7 @@ let BattleMovedex = {
desc: "Deals damage to the opposing Pokemon equal to twice the HP lost by the user from a special attack this turn. This move considers Hidden Power as Normal type, and only the last hit of a multi-hit attack is counted. Fails if the user moves first, if the user was not hit by a special attack this turn, or if the user did not lose HP from the attack.",
damageCallback(pokemon, target) {
let lastAttackedBy = pokemon.getLastAttackedBy();
if (lastAttackedBy && lastAttackedBy.move && lastAttackedBy.thisTurn && this.getCategory(lastAttackedBy.move) === 'Special' && this.getMove(lastAttackedBy.move).id !== 'hiddenpower' && (!target.lastMove || target.lastMove.id !== 'sleeptalk')) {
if (lastAttackedBy && lastAttackedBy.move && lastAttackedBy.thisTurn && this.getCategory(lastAttackedBy.move) === 'Special' && this.dex.getMove(lastAttackedBy.move).id !== 'hiddenpower' && (!target.lastMove || target.lastMove.id !== 'sleeptalk')) {
return 2 * lastAttackedBy.damage;
}
return false;
@ -769,7 +769,7 @@ let BattleMovedex = {
let moves = [];
for (const moveSlot of pokemon.moveSlots) {
let move = moveSlot.id;
if (move && !NoSleepTalk.includes(move) && !this.getMove(move).flags['charge']) {
if (move && !NoSleepTalk.includes(move) && !this.dex.getMove(move).flags['charge']) {
moves.push(move);
}
}

View File

@ -9,9 +9,9 @@ class RandomGen2Teams extends RandomGen3Teams {
let pokemon = [];
let pokemonPool = [];
for (let id in this.data.FormatsData) {
let template = this.getTemplate(id);
if (!template.isNonstandard && this.data.FormatsData[id].randomSet1) {
for (let id in this.dex.data.FormatsData) {
let template = this.dex.getTemplate(id);
if (!template.isNonstandard && this.dex.data.FormatsData[id].randomSet1) {
pokemonPool.push(id);
}
}
@ -38,7 +38,7 @@ class RandomGen2Teams extends RandomGen3Teams {
};
while (pokemonPool.length && pokemonLeft > 0) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
let skip = false;
@ -69,7 +69,7 @@ class RandomGen2Teams extends RandomGen3Teams {
// but ensure no more than 3 pokemon weak to the same regardless.
let weaknesses = [];
for (let type in weaknessCount) {
let weak = this.getImmunity(type, template) && this.getEffectiveness(type, template) > 0;
let weak = this.dex.getImmunity(type, template) && this.dex.getEffectiveness(type, template) > 0;
if (!weak) continue;
if (weaknessCount[type] > 2 || weaknessCount[type] - resistanceCount[type] > 1) {
skip = true;
@ -78,7 +78,7 @@ class RandomGen2Teams extends RandomGen3Teams {
}
let resistances = [];
for (let type in resistanceCount) {
let resist = !this.getImmunity(type, template) || this.getEffectiveness(type, template) < 0;
let resist = !this.dex.getImmunity(type, template) || this.dex.getEffectiveness(type, template) < 0;
if (resist) resistances.push(type);
}
@ -146,8 +146,8 @@ class RandomGen2Teams extends RandomGen3Teams {
*/
randomSet(template, restrictMoves, slot) {
if (slot === undefined) slot = 1;
template = this.getTemplate(template);
if (!template.exists) template = this.getTemplate('unown');
template = this.dex.getTemplate(template);
if (!template.exists) template = this.dex.getTemplate('unown');
let randomSetNumber = 0;
/**@type {RandomTeamsTypes.RandomSet} */

View File

@ -45,7 +45,7 @@ let BattleScripts = {
}
// Gen 2 caps stats at 999 and min is 1.
stat = this.battle.clampIntRange(stat, 1, 999);
stat = this.battle.dex.clampIntRange(stat, 1, 999);
if (fastReturn) return stat;
// Screens
@ -96,12 +96,12 @@ let BattleScripts = {
},
// Battle scripts.
runMove(moveOrMoveName, pokemon, targetLoc, sourceEffect) {
let move = this.getActiveMove(moveOrMoveName);
let move = this.dex.getActiveMove(moveOrMoveName);
let target = this.getTarget(pokemon, move, targetLoc);
if (!sourceEffect && move.id !== 'struggle') {
let changedMove = this.runEvent('OverrideAction', pokemon, target, move);
if (changedMove && changedMove !== true) {
move = this.getActiveMove(changedMove);
move = this.dex.getActiveMove(changedMove);
target = this.resolveTarget(pokemon, move);
}
}
@ -255,7 +255,7 @@ let BattleScripts = {
/**@type {number | undefined | false} */
let moveDamage;
let isSleepUsable = move.sleepUsable || this.getMove(move.sourceEffect).sleepUsable;
let isSleepUsable = move.sleepUsable || this.dex.getMove(move.sourceEffect).sleepUsable;
let i;
for (i = 0; i < hits && target.hp && pokemon.hp; i++) {
if (pokemon.status === 'slp' && !isSleepUsable) break;
@ -294,7 +294,7 @@ let BattleScripts = {
moveHit(target, pokemon, move, moveData, isSecondary, isSelf) {
/** @type {number | false | null | undefined} */
let damage = undefined;
move = this.getActiveMove(move);
move = this.dex.getActiveMove(move);
if (!moveData) moveData = move;
/**@type {?boolean | number} */
@ -475,7 +475,7 @@ let BattleScripts = {
getDamage(pokemon, target, move, suppressMessages) {
// First of all, we get the move.
if (typeof move === 'string') {
move = this.getActiveMove(move);
move = this.dex.getActiveMove(move);
} else if (typeof move === 'number') {
move = /** @type {ActiveMove} */ ({
basePower: move,
@ -532,11 +532,11 @@ let BattleScripts = {
if (basePower === 0) return; // Returning undefined means not dealing damage
return basePower;
}
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
// Checking for the move's Critical Hit ratio
let critRatio = this.runEvent('ModifyCritRatio', pokemon, target, move, move.critRatio || 0);
critRatio = this.clampIntRange(critRatio, 0, 5);
critRatio = this.dex.clampIntRange(critRatio, 0, 5);
let critMult = [0, 16, 8, 4, 3, 2];
let isCrit = move.willCrit || false;
if (typeof move.willCrit === 'undefined') {
@ -565,7 +565,7 @@ let BattleScripts = {
}
}
if (!basePower) return 0;
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
// We now check for attacker and defender
let level = pokemon.level;
@ -644,13 +644,13 @@ let BattleScripts = {
if (attack >= 1024 || defense >= 1024) {
this.hint("In Gen 2, a stat will roll over to a small number if it is larger than 1024.");
}
attack = this.clampIntRange(Math.floor(attack / 4) % 256, 1);
defense = this.clampIntRange(Math.floor(defense / 4) % 256, 1);
attack = this.dex.clampIntRange(Math.floor(attack / 4) % 256, 1);
defense = this.dex.clampIntRange(Math.floor(defense / 4) % 256, 1);
}
// Self destruct moves halve defense at this point.
if (move.selfdestruct && defType === 'def') {
defense = this.clampIntRange(Math.floor(defense / 2), 1);
defense = this.dex.clampIntRange(Math.floor(defense / 2), 1);
}
// Let's go with the calculation now that we have what we need.
@ -661,7 +661,7 @@ let BattleScripts = {
damage *= basePower;
damage *= attack;
damage = Math.floor(damage / defense);
damage = this.clampIntRange(Math.floor(damage / 50), 1, 997);
damage = this.dex.clampIntRange(Math.floor(damage / 50), 1, 997);
damage += 2;
// Weather modifiers

View File

@ -111,7 +111,7 @@ let BattleStatuses = {
},
onAfterMoveSelfPriority: 3,
onAfterMoveSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * pokemon.volatiles['residualdmg'].counter, pokemon, pokemon);
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1) * pokemon.volatiles['residualdmg'].counter, pokemon, pokemon);
},
onSwitchIn(pokemon) {
// Regular poison status and damage after a switchout -> switchin.
@ -119,7 +119,7 @@ let BattleStatuses = {
this.add('-status', pokemon, 'psn', '[silent]');
},
onAfterSwitchInSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
},
confusion: {
@ -198,7 +198,7 @@ let BattleStatuses = {
delete pokemon.volatiles['lockedmove'];
},
onBeforeTurn(pokemon) {
let move = this.getMove(this.effectData.move);
let move = this.dex.getMove(this.effectData.move);
if (move.id) {
this.debug('Forcing into ' + move.id);
this.changeAction(pokemon, {move: move.id});
@ -252,10 +252,10 @@ let BattleStatuses = {
*/
function residualdmg(battle, pokemon) {
if (pokemon.volatiles['residualdmg']) {
battle.damage(battle.clampIntRange(Math.floor(pokemon.maxhp / 16) * pokemon.volatiles['residualdmg'].counter, 1), pokemon);
battle.damage(battle.dex.clampIntRange(Math.floor(pokemon.maxhp / 16) * pokemon.volatiles['residualdmg'].counter, 1), pokemon);
battle.hint("In Gen 2, Toxic's counter is retained through Baton Pass/Heal Bell and applies to PSN/BRN.", true);
} else {
battle.damage(battle.clampIntRange(Math.floor(pokemon.maxhp / 8), 1), pokemon);
battle.damage(battle.dex.clampIntRange(Math.floor(pokemon.maxhp / 8), 1), pokemon);
}
}

View File

@ -178,7 +178,7 @@ let BattleAbilities = {
if (!pokemon.isStarted) return;
let target = pokemon.side.foe.randomActive();
if (!target || target.fainted) return;
let ability = this.getAbility(target.ability);
let ability = this.dex.getAbility(target.ability);
let bannedAbilities = ['forecast', 'multitype', 'trace'];
if (bannedAbilities.includes(target.ability)) {
return;

View File

@ -81,7 +81,7 @@ let BattleMovedex = {
return false;
}
if (!target.isActive) {
const possibleTarget = this.resolveTarget(pokemon, this.getMove('pound'));
const possibleTarget = this.resolveTarget(pokemon, this.dex.getMove('pound'));
if (!possibleTarget) {
this.add('-miss', pokemon);
return false;
@ -167,7 +167,7 @@ let BattleMovedex = {
desc: "The user's type changes to match the original type of one of its known moves besides Curse, at random, but not either of its current types. Fails if the user cannot change its type, or if this move would only be able to select one of the user's current types.",
onHit(target) {
let possibleTypes = target.moveSlots.map(moveSlot => {
let move = this.getMove(moveSlot.id);
let move = this.dex.getMove(moveSlot.id);
if (move.id !== 'curse' && !target.hasType(move.type)) {
return move.type;
}
@ -191,7 +191,7 @@ let BattleMovedex = {
desc: "Deals damage to the last opposing Pokemon to hit the user with a physical attack this turn equal to twice the HP lost by the user from that attack. If that opposing Pokemon's position is no longer in use and there is another opposing Pokemon on the field, the damage is done to it instead. This move considers Hidden Power as Normal type, and only the last hit of a multi-hit attack is counted. Fails if the user was not hit by an opposing Pokemon's physical attack this turn, or if the user did not lose HP from the attack.",
damageCallback(pokemon) {
let lastAttackedBy = pokemon.getLastAttackedBy();
if (lastAttackedBy && lastAttackedBy.move && lastAttackedBy.thisTurn && (this.getCategory(lastAttackedBy.move) === 'Physical' || this.getMove(lastAttackedBy.move).id === 'hiddenpower')) {
if (lastAttackedBy && lastAttackedBy.move && lastAttackedBy.thisTurn && (this.getCategory(lastAttackedBy.move) === 'Physical' || this.dex.getMove(lastAttackedBy.move).id === 'hiddenpower')) {
// @ts-ignore
return 2 * lastAttackedBy.damage;
}
@ -489,7 +489,7 @@ let BattleMovedex = {
if (target.runImmunity('Fighting')) {
let damage = this.getDamage(source, target, move, true);
if (typeof damage !== 'number') throw new Error("HJK recoil failed");
this.damage(this.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
this.damage(this.dex.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
}
},
},
@ -515,7 +515,7 @@ let BattleMovedex = {
if (target.runImmunity('Fighting')) {
let damage = this.getDamage(source, target, move, true);
if (typeof damage !== 'number') throw new Error("Jump Kick didn't recoil");
this.damage(this.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
this.damage(this.dex.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
}
},
},
@ -748,7 +748,7 @@ let BattleMovedex = {
let move = moveSlot.id;
let pp = moveSlot.pp;
let NoSleepTalk = ['assist', 'bide', 'focuspunch', 'metronome', 'mirrormove', 'sleeptalk', 'uproar'];
if (move && !(NoSleepTalk.includes(move) || this.getMove(move).flags['charge'])) {
if (move && !(NoSleepTalk.includes(move) || this.dex.getMove(move).flags['charge'])) {
moves.push({move: move, pp: pp});
}
}
@ -868,7 +868,7 @@ let BattleMovedex = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.move).category === 'Status') {
if (this.dex.getMove(moveSlot.move).category === 'Status') {
pokemon.disableMove(moveSlot.id);
}
}

View File

@ -9,11 +9,11 @@ class RandomGen3Teams extends RandomGen4Teams {
* @return {RandomTeamsTypes.RandomSet}
*/
randomSet(template, teamDetails = {}) {
let baseTemplate = (template = this.getTemplate(template));
let baseTemplate = (template = this.dex.getTemplate(template));
let species = template.species;
if (!template.exists || (!template.randomBattleMoves && !template.learnset)) {
template = this.getTemplate('unown');
template = this.dex.getTemplate('unown');
let err = new Error('Template incompatible with random battles: ' + species);
Monitor.crashlog(err, 'The gen 3 randbat set generator');
@ -115,7 +115,7 @@ class RandomGen3Teams extends RandomGen4Teams {
// Iterate through the moves again, this time to cull them:
for (const [i, setMoveid] of moves.entries()) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
let moveid = move.id;
let rejected = false;
let isSetup = false;
@ -365,7 +365,7 @@ class RandomGen3Teams extends RandomGen4Teams {
if (reqMove) {
// reject a move
for (let [i, move] of moves.entries()) {
if (move === 'weatherball' || this.getMove(move).type in hasType) continue;
if (move === 'weatherball' || this.dex.getMove(move).type in hasType) continue;
moves[i] = reqMove;
let reqMoveIndex = movePool.indexOf(reqMove);
if (reqMoveIndex !== -1) this.fastPop(movePool, reqMoveIndex);
@ -437,10 +437,10 @@ class RandomGen3Teams extends RandomGen4Teams {
ivs = {hp: 31, atk: 31, def: 31, spa: 31, spd: 31, spe: 31};
}
let abilities = Object.values(baseTemplate.abilities).filter(a => this.getAbility(a).gen === 3);
abilities.sort((a, b) => this.getAbility(b).rating - this.getAbility(a).rating);
let ability0 = this.getAbility(abilities[0]);
let ability1 = this.getAbility(abilities[1]);
let abilities = Object.values(baseTemplate.abilities).filter(a => this.dex.getAbility(a).gen === 3);
abilities.sort((a, b) => this.dex.getAbility(b).rating - this.dex.getAbility(a).rating);
let ability0 = this.dex.getAbility(abilities[0]);
let ability1 = this.dex.getAbility(abilities[1]);
if (abilities[1]) {
if (ability0.rating <= ability1.rating && this.randomChance(1, 2)) {
[ability0, ability1] = [ability1, ability0];
@ -610,13 +610,13 @@ class RandomGen3Teams extends RandomGen4Teams {
let allowedNFE = ['Scyther', 'Vigoroth'];
let pokemonPool = [];
for (let id in this.data.FormatsData) {
let template = this.getTemplate(id);
for (let id in this.dex.data.FormatsData) {
let template = this.dex.getTemplate(id);
if (template.isNonstandard || !template.randomBattleMoves) continue;
if (template.evos && !allowedNFE.includes(template.species)) {
let invalid = false;
for (const evo of template.evos) {
if (this.getTemplate(evo).gen <= 3) {
if (this.dex.getTemplate(evo).gen <= 3) {
invalid = true;
break;
}
@ -638,7 +638,7 @@ class RandomGen3Teams extends RandomGen4Teams {
let teamDetails = {};
while (pokemonPool.length && pokemon.length < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
// Limit to one of each species (Species Clause)

View File

@ -23,7 +23,7 @@ let BattleScripts = {
if (!sourceEffect && this.effect.id) sourceEffect = this.effect;
if (sourceEffect && sourceEffect.id === 'instruct') sourceEffect = null;
let move = this.getActiveMove(moveOrMoveName);
let move = this.dex.getActiveMove(moveOrMoveName);
if (this.activeMove) {
move.priority = this.activeMove.priority;
@ -61,7 +61,7 @@ let BattleScripts = {
let movename = move.name;
if (move.id === 'hiddenpower') movename = 'Hidden Power';
if (sourceEffect) attrs += `|[from]${this.getEffect(sourceEffect)}`;
if (sourceEffect) attrs += `|[from]${this.dex.getEffect(sourceEffect)}`;
this.addMove('move', pokemon, movename, target + attrs);
if (!target) {
@ -221,7 +221,7 @@ let BattleScripts = {
if (accuracy !== true) {
if (!move.ignoreAccuracy) {
boosts = this.runEvent('ModifyBoost', pokemon, null, null, Object.assign({}, pokemon.boosts));
boost = this.clampIntRange(boosts['accuracy'], -6, 6);
boost = this.dex.clampIntRange(boosts['accuracy'], -6, 6);
if (boost > 0) {
accuracy *= boostTable[boost];
} else {
@ -230,7 +230,7 @@ let BattleScripts = {
}
if (!move.ignoreEvasion) {
boosts = this.runEvent('ModifyBoost', target, null, null, Object.assign({}, target.boosts));
boost = this.clampIntRange(boosts['evasion'], -6, 6);
boost = this.dex.clampIntRange(boosts['evasion'], -6, 6);
if (boost > 0) {
accuracy /= boostTable[boost];
} else if (boost < 0) {
@ -301,7 +301,7 @@ let BattleScripts = {
/** @type {number | undefined | false} */
let moveDamage;
// There is no need to recursively check the ´sleepUsable´ flag as Sleep Talk can only be used while asleep.
let isSleepUsable = move.sleepUsable || this.getMove(move.sourceEffect).sleepUsable;
let isSleepUsable = move.sleepUsable || this.dex.getMove(move.sourceEffect).sleepUsable;
let i;
for (i = 0; i < hits && target.hp && pokemon.hp; i++) {
if (pokemon.status === 'slp' && !isSleepUsable) break;
@ -312,7 +312,7 @@ let BattleScripts = {
if (accuracy !== true) {
if (!move.ignoreAccuracy) {
boosts = this.runEvent('ModifyBoost', pokemon, null, null, Object.assign({}, pokemon.boosts));
boost = this.clampIntRange(boosts['accuracy'], -6, 6);
boost = this.dex.clampIntRange(boosts['accuracy'], -6, 6);
if (boost > 0) {
accuracy *= boostTable[boost];
} else {
@ -321,7 +321,7 @@ let BattleScripts = {
}
if (!move.ignoreEvasion) {
boosts = this.runEvent('ModifyBoost', target, null, null, Object.assign({}, target.boosts));
boost = this.clampIntRange(boosts['evasion'], -6, 6);
boost = this.dex.clampIntRange(boosts['evasion'], -6, 6);
if (boost > 0) {
accuracy /= boostTable[boost];
} else if (boost < 0) {
@ -375,7 +375,7 @@ let BattleScripts = {
calcRecoilDamage(damageDealt, move) {
// @ts-ignore
return this.clampIntRange(Math.floor(damageDealt * move.recoil[0] / move.recoil[1]), 1);
return this.dex.clampIntRange(Math.floor(damageDealt * move.recoil[0] / move.recoil[1]), 1);
},
};

View File

@ -111,7 +111,7 @@ let BattleAbilities = {
for (const target of pokemon.side.foe.active) {
if (target.fainted) continue;
for (const moveSlot of target.moveSlots) {
let move = this.getMove(moveSlot.move);
let move = this.dex.getMove(moveSlot.move);
let bp = move.basePower;
if (move.ohko) bp = 160;
if (move.id === 'counter' || move.id === 'metalburst' || move.id === 'mirrorcoat') bp = 120;
@ -420,7 +420,7 @@ let BattleAbilities = {
if (!pokemon.isStarted) return;
let target = pokemon.side.foe.randomActive();
if (!target || target.fainted) return;
let ability = this.getAbility(target.ability);
let ability = this.dex.getAbility(target.ability);
let bannedAbilities = ['forecast', 'multitype', 'trace'];
if (bannedAbilities.includes(target.ability)) {
return;

View File

@ -166,7 +166,7 @@ let BattleItems = {
duration: 1,
onAfterMoveSecondarySelf(source, target, move) {
if (move && move.effectType === 'Move' && source && source.volatiles['lifeorb']) {
this.damage(source.maxhp / 10, source, source, this.getItem('lifeorb'));
this.damage(source.maxhp / 10, source, source, this.dex.getItem('lifeorb'));
source.removeVolatile('lifeorb');
}
},

View File

@ -152,7 +152,7 @@ let BattleMovedex = {
return false;
}
if (!target.isActive) {
const possibleTarget = this.resolveTarget(pokemon, this.getMove('pound'));
const possibleTarget = this.resolveTarget(pokemon, this.dex.getMove('pound'));
if (!possibleTarget) {
this.add('-miss', pokemon);
return false;
@ -264,7 +264,7 @@ let BattleMovedex = {
flags: {},
onHit(target) {
let possibleTypes = target.moveSlots.map(moveSlot => {
let move = this.getMove(moveSlot.id);
let move = this.dex.getMove(moveSlot.id);
if (move.id !== 'conversion' && move.id !== 'curse' && !target.hasType(move.type)) {
return move.type;
}
@ -782,7 +782,7 @@ let BattleMovedex = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.id).flags['heal']) {
if (this.dex.getMove(moveSlot.id).flags['heal']) {
pokemon.disableMove(moveSlot.id);
}
}
@ -842,7 +842,7 @@ let BattleMovedex = {
move.causedCrashDamage = true;
let damage = this.getDamage(source, target, move, true);
if (!damage) damage = target.maxhp;
this.damage(this.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
this.damage(this.dex.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
},
},
iciclespear: {
@ -878,7 +878,7 @@ let BattleMovedex = {
move.causedCrashDamage = true;
let damage = this.getDamage(source, target, move, true);
if (!damage) damage = target.maxhp;
this.damage(this.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
this.damage(this.dex.clampIntRange(damage / 2, 1, Math.floor(target.maxhp / 2)), source, source, move);
},
},
knockoff: {
@ -980,7 +980,7 @@ let BattleMovedex = {
return;
}
target.removeVolatile('magiccoat');
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
this.useMove(newMove, target, source);
return null;
@ -1061,7 +1061,7 @@ let BattleMovedex = {
if (source.transformed || !target.lastMove || disallowedMoves.includes(target.lastMove.id) || source.moves.indexOf(target.lastMove.id) !== -1 || target.volatiles['substitute']) return false;
let mimicIndex = source.moves.indexOf('mimic');
if (mimicIndex < 0) return false;
let move = this.getMove(target.lastMove.id);
let move = this.dex.getMove(target.lastMove.id);
source.moveSlots[mimicIndex] = {
move: move.name,
id: move.id,
@ -1254,7 +1254,7 @@ let BattleMovedex = {
let sideConditions = ['spikes', 'toxicspikes', 'stealthrock', 'stickyweb'];
for (const condition of sideConditions) {
if (pokemon.side.removeSideCondition(condition)) {
this.add('-sideend', pokemon.side, this.getEffect(condition).name, '[from] move: Rapid Spin', '[of] ' + pokemon);
this.add('-sideend', pokemon.side, this.dex.getEffect(condition).name, '[from] move: Rapid Spin', '[of] ' + pokemon);
}
}
if (pokemon.volatiles['partiallytrapped']) {
@ -1382,7 +1382,7 @@ let BattleMovedex = {
if (source.transformed || !target.lastMove || disallowedMoves.includes(target.lastMove.id) || source.moves.includes(target.lastMove.id) || target.volatiles['substitute']) return false;
let sketchIndex = source.moves.indexOf('sketch');
if (sketchIndex < 0) return false;
let move = this.getMove(target.lastMove.id);
let move = this.dex.getMove(target.lastMove.id);
let sketchedMove = {
move: move.name,
id: move.id,
@ -1632,7 +1632,7 @@ let BattleMovedex = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.id).category === 'Status') {
if (this.dex.getMove(moveSlot.id).category === 'Status') {
pokemon.disableMove(moveSlot.id);
}
}

View File

@ -10,11 +10,11 @@ class RandomGen4Teams extends RandomGen5Teams {
* @return {RandomTeamsTypes.RandomSet}
*/
randomSet(template, teamDetails = {}, isLead = false) {
let baseTemplate = (template = this.getTemplate(template));
let baseTemplate = (template = this.dex.getTemplate(template));
let species = template.species;
if (!template.exists || (!template.randomBattleMoves && !template.learnset)) {
template = this.getTemplate('unown');
template = this.dex.getTemplate('unown');
let err = new Error('Template incompatible with random battles: ' + species);
Monitor.crashlog(err, 'The gen 4 randbat set generator');
@ -110,7 +110,7 @@ class RandomGen4Teams extends RandomGen5Teams {
// Iterate through the moves again, this time to cull them:
for (const [i, setMoveid] of moves.entries()) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
let moveid = move.id;
let rejected = false;
let isSetup = false;
@ -485,9 +485,9 @@ class RandomGen4Teams extends RandomGen5Teams {
}
let abilities = Object.values(baseTemplate.abilities);
abilities.sort((a, b) => this.getAbility(b).rating - this.getAbility(a).rating);
let ability0 = this.getAbility(abilities[0]);
let ability1 = this.getAbility(abilities[1]);
abilities.sort((a, b) => this.dex.getAbility(b).rating - this.dex.getAbility(a).rating);
let ability0 = this.dex.getAbility(abilities[0]);
let ability1 = this.dex.getAbility(abilities[1]);
if (abilities[1]) {
if (ability0.rating <= ability1.rating && this.randomChance(1, 2)) {
[ability0, ability1] = [ability1, ability0];
@ -638,7 +638,7 @@ class RandomGen4Teams extends RandomGen5Teams {
// This is the "REALLY can't think of a good item" cutoff
} else if (hasType['Poison']) {
item = 'Black Sludge';
} else if (this.getEffectiveness('Rock', template) >= 1 || hasMove['roar']) {
} else if (this.dex.getEffectiveness('Rock', template) >= 1 || hasMove['roar']) {
item = 'Leftovers';
} else if (counter.Status <= 1 && !hasMove['metalburst'] && !hasMove['rapidspin'] && !hasMove['superfang']) {
item = 'Life Orb';
@ -686,7 +686,7 @@ class RandomGen4Teams extends RandomGen5Teams {
if (hp % 4 === 0) evs.hp -= 4;
} else {
// Maximize number of Stealth Rock switch-ins
let srWeakness = this.getEffectiveness('Rock', template);
let srWeakness = this.dex.getEffectiveness('Rock', template);
if (srWeakness > 0 && hp % (4 / srWeakness) === 0) evs.hp -= 4;
}

View File

@ -5,8 +5,8 @@ let BattleFormats = {
validatestats: {
inherit: true,
onValidateSet(set) {
let template = this.getTemplate(set.species);
let item = this.getItem(set.item);
let template = this.dex.getTemplate(set.species);
let item = this.dex.getItem(set.item);
if (item && item.id === 'griseousorb' && template.num !== 487) {
return ['Griseous Orb can only be held by Giratina in Generation 4.'];
}

View File

@ -62,7 +62,7 @@ let BattleScripts = {
}
// types
let typeMod = target.runEffectiveness(move);
typeMod = this.clampIntRange(typeMod, -6, 6);
typeMod = this.dex.clampIntRange(typeMod, -6, 6);
target.getMoveHitData(move).typeMod = typeMod;
if (typeMod > 0) {
if (!suppressMessages) this.add('-supereffective', target);
@ -104,7 +104,7 @@ let BattleScripts = {
calcRecoilDamage(damageDealt, move) {
// @ts-ignore
return this.clampIntRange(Math.floor(damageDealt * move.recoil[0] / move.recoil[1]), 1);
return this.dex.clampIntRange(Math.floor(damageDealt * move.recoil[0] / move.recoil[1]), 1);
},
};

View File

@ -9,8 +9,8 @@ let BattleAbilities = {
for (const target of pokemon.side.foe.active) {
if (!target || target.fainted) continue;
for (const moveSlot of target.moveSlots) {
const move = this.getMove(moveSlot.move);
if (move.category !== 'Status' && (this.getImmunity(move.type, pokemon) && this.getEffectiveness(move.type, pokemon) > 0 || move.ohko)) {
const move = this.dex.getMove(moveSlot.move);
if (move.category !== 'Status' && (this.dex.getImmunity(move.type, pokemon) && this.dex.getEffectiveness(move.type, pokemon) > 0 || move.ohko)) {
this.add('-ability', pokemon, 'Anticipation');
return;
}

View File

@ -181,7 +181,7 @@ let BattleMovedex = {
shortDesc: "Changes user's type to match a known move.",
onHit(target) {
let possibleTypes = target.moveSlots.map(moveSlot => {
let move = this.getMove(moveSlot.id);
let move = this.dex.getMove(moveSlot.id);
if (move.id !== 'conversion' && !target.hasType(move.type)) {
return move.type;
}
@ -230,7 +230,7 @@ let BattleMovedex = {
let sideConditions = ['reflect', 'lightscreen', 'safeguard', 'mist', 'spikes', 'toxicspikes', 'stealthrock'];
for (const condition of sideConditions) {
if (pokemon.side.removeSideCondition(condition)) {
this.add('-sideend', pokemon.side, this.getEffect(condition).name, '[from] move: Defog', '[of] ' + pokemon);
this.add('-sideend', pokemon.side, this.dex.getEffect(condition).name, '[from] move: Defog', '[of] ' + pokemon);
}
}
},
@ -834,7 +834,7 @@ let BattleMovedex = {
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)
if (effect && (effect.id === 'feint' || this.getMove(effect.id).priority <= 0)) {
if (effect && (effect.id === 'feint' || this.dex.getMove(effect.id).priority <= 0)) {
return;
}
this.add('-activate', target, 'Quick Guard');
@ -970,7 +970,7 @@ let BattleMovedex = {
if (targetAbility === sourceAbility) {
return false;
}
this.add('-activate', source, 'move: Skill Swap', this.getAbility(targetAbility), this.getAbility(sourceAbility), '[of] ' + target);
this.add('-activate', source, 'move: Skill Swap', this.dex.getAbility(targetAbility), this.dex.getAbility(sourceAbility), '[of] ' + target);
source.setAbility(targetAbility);
target.setAbility(sourceAbility);
},

View File

@ -10,12 +10,12 @@ class RandomGen5Teams extends RandomGen6Teams {
* @return {RandomTeamsTypes.RandomSet}
*/
randomSet(template, teamDetails = {}, isLead = false) {
let baseTemplate = (template = this.getTemplate(template));
let baseTemplate = (template = this.dex.getTemplate(template));
let species = template.species;
if (!template.exists || (!template.randomBattleMoves && !template.learnset)) {
// GET IT? UNOWN? BECAUSE WE CAN'T TELL WHAT THE POKEMON IS
template = this.getTemplate('unown');
template = this.dex.getTemplate('unown');
let err = new Error('Template incompatible with random battles: ' + species);
Monitor.crashlog(err, 'The gen 5 randbat set generator');
@ -106,7 +106,7 @@ class RandomGen5Teams extends RandomGen6Teams {
// Iterate through the moves again, this time to cull them:
for (const [i, setMoveid] of moves.entries()) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
let moveid = move.id;
let rejected = false;
let isSetup = false;
@ -385,7 +385,7 @@ class RandomGen5Teams extends RandomGen6Teams {
// Handle Hidden Power IVs
if (moveid === 'hiddenpower') {
let HPivs = this.getType(move.type).HPivs;
let HPivs = this.dex.getType(move.type).HPivs;
for (let iv in HPivs) {
// @ts-ignore
ivs[iv] = HPivs[iv];
@ -400,10 +400,10 @@ class RandomGen5Teams extends RandomGen6Teams {
}
let abilities = Object.values(baseTemplate.abilities);
abilities.sort((a, b) => this.getAbility(b).rating - this.getAbility(a).rating);
let ability0 = this.getAbility(abilities[0]);
let ability1 = this.getAbility(abilities[1]);
let ability2 = this.getAbility(abilities[2]);
abilities.sort((a, b) => this.dex.getAbility(b).rating - this.dex.getAbility(a).rating);
let ability0 = this.dex.getAbility(abilities[0]);
let ability1 = this.dex.getAbility(abilities[1]);
let ability2 = this.dex.getAbility(abilities[2]);
if (abilities[1]) {
if (abilities[2] && ability1.rating <= ability2.rating && this.randomChance(1, 2)) {
[ability1, ability2] = [ability2, ability1];
@ -556,7 +556,7 @@ class RandomGen5Teams extends RandomGen6Teams {
// Give Unburden mons a random Gem of the type of one of their damaging moves
let eligibleTypes = [];
for (const setMoveid of moves) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
if (!move.basePower && !move.basePowerCallback) continue;
eligibleTypes.push(move.type);
}
@ -571,12 +571,12 @@ class RandomGen5Teams extends RandomGen6Teams {
item = 'Life Orb';
} else if ((hasMove['eruption'] || hasMove['waterspout']) && !counter['Status']) {
item = 'Choice Scarf';
} else if (this.getEffectiveness('Ground', template) >= 2 && ability !== 'Levitate' && !hasMove['magnetrise']) {
} else if (this.dex.getEffectiveness('Ground', template) >= 2 && ability !== 'Levitate' && !hasMove['magnetrise']) {
item = 'Air Balloon';
} else if (hasMove['substitute'] && hasMove['reversal']) {
let eligibleTypes = [];
for (const setMoveid of moves) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
if (!move.basePower && !move.basePowerCallback) continue;
eligibleTypes.push(move.type);
}
@ -601,7 +601,7 @@ class RandomGen5Teams extends RandomGen6Teams {
// This is the "REALLY can't think of a good item" cutoff
} else if (hasType['Poison']) {
item = 'Black Sludge';
} else if (this.getEffectiveness('Rock', template) >= 1 || hasMove['dragontail']) {
} else if (this.dex.getEffectiveness('Rock', template) >= 1 || hasMove['dragontail']) {
item = 'Leftovers';
} else if (counter.Status <= 1 && ability !== 'Sturdy' && !hasMove['rapidspin']) {
item = 'Life Orb';
@ -662,8 +662,8 @@ class RandomGen5Teams extends RandomGen6Teams {
const allowedNFE = ['Porygon2', 'Scyther'];
let pokemonPool = [];
for (let id in this.data.FormatsData) {
let template = this.getTemplate(id);
for (let id in this.dex.data.FormatsData) {
let template = this.dex.getTemplate(id);
if ((!template.nfe || allowedNFE.includes(template.species)) && !template.isNonstandard && template.randomBattleMoves) {
pokemonPool.push(id);
}
@ -681,7 +681,7 @@ class RandomGen5Teams extends RandomGen6Teams {
let teamDetails = {};
while (pokemonPool.length && pokemon.length < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
// Limit to one of each species (Species Clause)

View File

@ -75,7 +75,7 @@ let BattleAbilities = {
shortDesc: "This Pokemon's moves are changed to be Normal type.",
onModifyMovePriority: 1,
onModifyMove(move) {
if (move.id !== 'struggle' && this.getMove(move.id).type !== 'Normal') {
if (move.id !== 'struggle' && this.dex.getMove(move.id).type !== 'Normal') {
move.type = 'Normal';
}
},

View File

@ -77,7 +77,7 @@ let BattleItems = {
inherit: true,
onAfterMoveSecondarySelf(source, target, move) {
if (source && source !== target && move && move.category !== 'Status' && !move.ohko) {
this.damage(source.maxhp / 10, source, source, this.getItem('lifeorb'));
this.damage(source.maxhp / 10, source, source, this.dex.getItem('lifeorb'));
}
},
},

View File

@ -312,7 +312,7 @@ let BattleMovedex = {
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.damage(this.dex.clampIntRange(Math.round(pokemon.maxhp / 4), 1));
return false;
}
},

View File

@ -21,12 +21,12 @@ class RandomGen6Teams extends RandomTeams {
* @return {RandomTeamsTypes.RandomSet}
*/
randomSet(template, teamDetails = {}, isLead = false) {
let baseTemplate = (template = this.getTemplate(template));
let baseTemplate = (template = this.dex.getTemplate(template));
let species = template.species;
if (!template.exists || (!template.randomBattleMoves && !template.learnset)) {
// GET IT? UNOWN? BECAUSE WE CAN'T TELL WHAT THE POKEMON IS
template = this.getTemplate('unown');
template = this.dex.getTemplate('unown');
let err = new Error('Template incompatible with random battles: ' + species);
Monitor.crashlog(err, 'The gen 6 randbat set generator');
@ -38,7 +38,7 @@ class RandomGen6Teams extends RandomTeams {
}
let battleForme = this.checkBattleForme(template);
if (battleForme && battleForme.randomBattleMoves && template.otherFormes && (battleForme.isMega ? !teamDetails.megaStone : this.random(2))) {
template = this.getTemplate(template.otherFormes.length >= 2 ? this.sample(template.otherFormes) : template.otherFormes[0]);
template = this.dex.getTemplate(template.otherFormes.length >= 2 ? this.sample(template.otherFormes) : template.otherFormes[0]);
}
let movePool = (template.randomBattleMoves ? template.randomBattleMoves.slice() : template.learnset ? Object.keys(template.learnset) : []);
@ -128,7 +128,7 @@ class RandomGen6Teams extends RandomTeams {
// Iterate through the moves again, this time to cull them:
for (const [i, setMoveid] of moves.entries()) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
let moveid = move.id;
let rejected = false;
let isSetup = false;
@ -568,7 +568,7 @@ class RandomGen6Teams extends RandomTeams {
// Handle Hidden Power IVs
if (moveid === 'hiddenpower') {
let HPivs = this.getType(move.type).HPivs;
let HPivs = this.dex.getType(move.type).HPivs;
for (let iv in HPivs) {
// @ts-ignore
ivs[iv] = HPivs[iv];
@ -591,10 +591,10 @@ class RandomGen6Teams extends RandomTeams {
}
let abilities = Object.values(baseTemplate.abilities);
abilities.sort((a, b) => this.getAbility(b).rating - this.getAbility(a).rating);
let ability0 = this.getAbility(abilities[0]);
let ability1 = this.getAbility(abilities[1]);
let ability2 = this.getAbility(abilities[2]);
abilities.sort((a, b) => this.dex.getAbility(b).rating - this.dex.getAbility(a).rating);
let ability0 = this.dex.getAbility(abilities[0]);
let ability1 = this.dex.getAbility(abilities[1]);
let ability2 = this.dex.getAbility(abilities[2]);
if (abilities[1]) {
if (abilities[2] && ability1.rating <= ability2.rating && this.randomChance(1, 2)) {
[ability1, ability2] = [ability2, ability1];
@ -787,7 +787,7 @@ class RandomGen6Teams extends RandomTeams {
} else {
item = 'Red Card';
for (let m in moves) {
let move = this.getMove(moves[m]);
let move = this.dex.getMove(moves[m]);
if (hasType[move.type] && move.basePower >= 90) {
item = move.type + ' Gem';
break;
@ -822,7 +822,7 @@ class RandomGen6Teams extends RandomTeams {
item = 'Lum Berry';
} else if (hasMove['substitute']) {
item = counter.damagingMoves.length > 2 && !!counter['drain'] ? 'Life Orb' : 'Leftovers';
} else if (this.getEffectiveness('Ground', template) >= 2 && ability !== 'Levitate' && !hasMove['magnetrise']) {
} else if (this.dex.getEffectiveness('Ground', template) >= 2 && ability !== 'Levitate' && !hasMove['magnetrise']) {
item = 'Air Balloon';
} else if ((ability === 'Iron Barbs' || ability === 'Rough Skin') && this.randomChance(1, 2)) {
item = 'Rocky Helmet';
@ -884,7 +884,7 @@ class RandomGen6Teams extends RandomTeams {
if (customScale[species]) level = customScale[species];
// Prepare optimal HP
let srWeakness = this.getEffectiveness('Rock', template);
let srWeakness = this.dex.getEffectiveness('Rock', template);
while (evs.hp > 1) {
let hp = Math.floor(Math.floor(2 * template.baseStats.hp + ivs.hp + Math.floor(evs.hp / 4) + 100) * level / 100 + 10);
if (hasMove['substitute'] && hasMove['reversal']) {
@ -962,11 +962,11 @@ class RandomGen6Teams extends RandomTeams {
let effectivePool = [];
let priorityPool = [];
for (const curSet of setList) {
let itemData = this.getItem(curSet.item);
let itemData = this.dex.getItem(curSet.item);
if (teamData.megaCount > 0 && itemData.megaStone) continue; // reject 2+ mega stones
if (itemsMax[itemData.id] && teamData.has[itemData.id] >= itemsMax[itemData.id]) continue;
let abilityData = this.getAbility(curSet.ability);
let abilityData = this.dex.getAbility(curSet.ability);
if (weatherAbilitiesRequire[abilityData.id] && teamData.weather !== weatherAbilitiesRequire[abilityData.id]) continue;
if (teamData.weather && weatherAbilities.includes(abilityData.id)) continue; // reject 2+ weather setters
@ -1055,7 +1055,7 @@ class RandomGen6Teams extends RandomTeams {
};
while (pokemonPool.length && pokemon.length < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
let speciesFlags = this.randomFactorySets[chosenTier][template.speciesid].flags;
@ -1103,7 +1103,7 @@ class RandomGen6Teams extends RandomTeams {
teamData.baseFormes[template.baseSpecies] = 1;
let itemData = this.getItem(set.item);
let itemData = this.dex.getItem(set.item);
if (itemData.megaStone) teamData.megaCount++;
if (itemData.id in teamData.has) {
teamData.has[itemData.id]++;
@ -1111,7 +1111,7 @@ class RandomGen6Teams extends RandomTeams {
teamData.has[itemData.id] = 1;
}
let abilityData = this.getAbility(set.ability);
let abilityData = this.dex.getAbility(set.ability);
if (abilityData.id in weatherAbilitiesSet) {
teamData.weather = weatherAbilitiesSet[abilityData.id];
}
@ -1128,16 +1128,16 @@ class RandomGen6Teams extends RandomTeams {
}
}
for (let typeName in this.data.TypeChart) {
for (let typeName in this.dex.data.TypeChart) {
// Cover any major weakness (3+) with at least one resistance
if (teamData.resistances[typeName] >= 1) continue;
if (resistanceAbilities[abilityData.id] && resistanceAbilities[abilityData.id].includes(typeName) || !this.getImmunity(typeName, types)) {
if (resistanceAbilities[abilityData.id] && resistanceAbilities[abilityData.id].includes(typeName) || !this.dex.getImmunity(typeName, types)) {
// Heuristic: assume that Pokemon with these abilities don't have (too) negative typing.
teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
if (teamData.resistances[typeName] >= 1) teamData.weaknesses[typeName] = 0;
continue;
}
let typeMod = this.getEffectiveness(typeName, types);
let typeMod = this.dex.getEffectiveness(typeName, types);
if (typeMod < 0) {
teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
if (teamData.resistances[typeName] >= 1) teamData.weaknesses[typeName] = 0;

View File

@ -45,7 +45,7 @@ let BattleAbilities = {
let weather = move.weather;
move.weather = '';
move.onHit = function (target, source) {
this.field.setWeather(weather, source, this.getAbility('forecast'));
this.field.setWeather(weather, source, this.dex.getAbility('forecast'));
this.field.weatherData.duration = 0;
};
move.target = 'self';
@ -176,7 +176,7 @@ let BattleAbilities = {
let weather = move.weather;
move.weather = '';
move.onHit = function (target, source) {
this.field.setWeather(weather, source, this.getAbility('flowergift'));
this.field.setWeather(weather, source, this.dex.getAbility('flowergift'));
this.field.weatherData.duration = 0;
};
move.target = 'self';
@ -199,7 +199,7 @@ let BattleAbilities = {
onSwitchInPriority: 1,
onSwitchIn(target) {
if (!target.fainted) {
this.boost({spd: 1}, target, target, this.getAbility('flowergift'));
this.boost({spd: 1}, target, target, this.dex.getAbility('flowergift'));
}
target.side.removeSideCondition('flowergift');
},
@ -508,7 +508,7 @@ let BattleAbilities = {
onResidualOrder: 26,
onResidualSubOrder: 1,
onResidual(pokemon) {
if (!pokemon.m.gluttonyFlag && !pokemon.item && this.getItem(pokemon.lastItem).isBerry) {
if (!pokemon.m.gluttonyFlag && !pokemon.item && this.dex.getItem(pokemon.lastItem).isBerry) {
pokemon.m.gluttonyFlag = true;
pokemon.setItem(pokemon.lastItem);
pokemon.lastItem = '';

View File

@ -173,7 +173,7 @@ let BattleItems = {
},
// onResidual(pokemon) {
// if (pokemon.template.species === 'Shuckle') {
// this.heal(this.clampIntRange(pokemon.maxhp / 16, 1));
// this.heal(this.dex.clampIntRange(pokemon.maxhp / 16, 1));
// }
// },
desc: "Raises Farfetch'd's critical hit rate two stages.",

View File

@ -175,7 +175,7 @@ let BattleMovedex = {
this.add('-activate', target, 'Substitute', '[damage]');
}
if (move.recoil) {
this.damage(this.clampIntRange(Math.round(damage * move.recoil[0] / move.recoil[1]), 1), source, target, 'recoil');
this.damage(this.dex.clampIntRange(Math.round(damage * move.recoil[0] / move.recoil[1]), 1), source, target, 'recoil');
}
if (move.drain) {
this.heal(Math.ceil(damage * move.drain[0] / move.drain[1]), source, target, 'drain');
@ -1318,7 +1318,7 @@ let BattleMovedex = {
let sideConditions = ['spikes', 'toxicspikes', 'stealthrock'];
for (let condition in sideConditions) {
if (user.side.removeSideCondition(condition)) {
this.add('-sideend', user.side, this.getEffect(condition).name, '[from] move: Rapid Spin', '[of] ' + user);
this.add('-sideend', user.side, this.dex.getEffect(condition).name, '[from] move: Rapid Spin', '[of] ' + user);
doubled = true;
}
}
@ -2022,9 +2022,9 @@ let BattleMovedex = {
accuracy: 100,
onModifyMove(move, user) {
if (user.illusion) {
let illusionMoves = user.illusion.moves.filter(move => this.getMove(move).category !== 'Status');
let illusionMoves = user.illusion.moves.filter(move => this.dex.getMove(move).category !== 'Status');
if (!illusionMoves.length) return;
move.name = this.getMove(this.sample(illusionMoves)).name;
move.name = this.dex.getMove(this.sample(illusionMoves)).name;
}
},
desc: "Has a 40% chance to lower the target's accuracy by 1 stage. If Illusion is active, displays as a random non-Status move in the copied Pokémon's moveset.",

View File

@ -356,7 +356,7 @@ let BattleStatuses = {
let weather = move.weather;
move.weather = '';
move.onHit = function (target, source) {
this.field.setWeather(weather, source, this.getAbility('snowwarning'));
this.field.setWeather(weather, source, this.dex.getAbility('snowwarning'));
this.field.weatherData.duration = 0;
};
move.target = 'self';
@ -381,7 +381,7 @@ let BattleStatuses = {
let weather = move.weather;
move.weather = '';
move.onHit = function (target, source) {
this.field.setWeather(weather, source, this.getAbility('sandstream'));
this.field.setWeather(weather, source, this.dex.getAbility('sandstream'));
this.field.weatherData.duration = 0;
};
move.target = 'self';
@ -397,7 +397,7 @@ let BattleStatuses = {
let weather = move.weather;
move.weather = '';
move.onHit = function (target, source) {
this.field.setWeather(weather, source, this.getAbility('drizzle'));
this.field.setWeather(weather, source, this.dex.getAbility('drizzle'));
this.field.weatherData.duration = 0;
};
move.target = 'self';

View File

@ -52,7 +52,7 @@ let BattleMovedex = {
onHit(target, source, effect) {
let moves = [];
for (let i in exports.BattleMovedex) {
let move = this.getMove(i);
let move = this.dex.getMove(i);
if (i !== move.id) continue;
if (move.gen !== 1) continue;
// @ts-ignore

View File

@ -9,11 +9,11 @@ class RandomLetsGoTeams extends RandomTeams {
* @return {RandomTeamsTypes.RandomSet}
*/
randomSet(template, teamDetails = {}) {
template = this.getTemplate(template);
template = this.dex.getTemplate(template);
let species = template.species;
if (!template.exists || (!template.randomBattleMoves && !template.learnset)) {
template = this.getTemplate('bulbasaur');
template = this.dex.getTemplate('bulbasaur');
let err = new Error('Template incompatible with random battles: ' + species);
Monitor.crashlog(err, 'The Let\'s Go randbat set generator');
@ -56,7 +56,7 @@ class RandomLetsGoTeams extends RandomTeams {
// Iterate through the moves again, this time to cull them:
for (const [i, setMoveid] of moves.entries()) {
let move = this.getMove(setMoveid);
let move = this.dex.getMove(setMoveid);
let moveid = move.id;
let rejected = false;
let isSetup = false;
@ -220,8 +220,8 @@ class RandomLetsGoTeams extends RandomTeams {
let pokemon = [];
let pokemonPool = [];
for (let id in this.data.FormatsData) {
let template = this.getTemplate(id);
for (let id in this.dex.data.FormatsData) {
let template = this.dex.getTemplate(id);
if (template.num < 1 || (template.num > 151 && ![808, 809].includes(template.num)) || template.nfe || !template.randomBattleMoves || !template.randomBattleMoves.length) continue;
pokemonPool.push(id);
}
@ -236,7 +236,7 @@ class RandomLetsGoTeams extends RandomTeams {
let teamDetails = {};
while (pokemonPool.length && pokemon.length < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
// Limit to one of each species (Species Clause)

View File

@ -27,7 +27,7 @@ let BattleScripts = {
let stat = baseStats['hp'];
modStats['hp'] = Math.floor(Math.floor(2 * stat + set.ivs['hp'] + 100) * set.level / 100 + 10);
}
return this.natureModify(modStats, set);
return this.dex.natureModify(modStats, set);
},
/**
@ -36,7 +36,7 @@ let BattleScripts = {
* @return {StatsTable}
*/
natureModify(stats, set) {
let nature = this.getNature(set.nature);
let nature = this.dex.getNature(set.nature);
// @ts-ignore
if (nature.plus) stats[nature.plus] = Math.floor(stats[nature.plus] * 1.1);
// @ts-ignore

View File

@ -43,7 +43,7 @@ let BattleItems = {
pokemon.baseTemplate = template;
this.add('-start', pokemon, 'Red Orb', '[silent]');
let apparentSpecies = pokemon.illusion ? pokemon.illusion.template.species : pokemon.m.originalSpecies;
let oTemplate = this.getTemplate(apparentSpecies);
let oTemplate = this.dex.getTemplate(apparentSpecies);
if (pokemon.illusion) {
let types = oTemplate.types;
if (types.length > 1 || types[types.length - 1] !== 'Fire') {

View File

@ -39,12 +39,12 @@ let BattleScripts = {
// Do we have a proper sprite for it?
// @ts-ignore assert non-null pokemon.canMegaEvo
if (isUltraBurst || this.getTemplate(pokemon.canMegaEvo).baseSpecies === pokemon.m.originalSpecies) {
if (isUltraBurst || this.dex.getTemplate(pokemon.canMegaEvo).baseSpecies === pokemon.m.originalSpecies) {
pokemon.formeChange(template, pokemon.getItem(), true);
} else {
let oTemplate = this.getTemplate(pokemon.m.originalSpecies);
let oTemplate = this.dex.getTemplate(pokemon.m.originalSpecies);
// @ts-ignore
let oMegaTemplate = this.getTemplate(template.originalMega);
let oMegaTemplate = this.dex.getTemplate(template.originalMega);
pokemon.formeChange(template, pokemon.getItem(), true);
this.add('-start', pokemon, oMegaTemplate.requiredItem || oMegaTemplate.requiredMove, '[silent]');
if (oTemplate.types.length !== pokemon.template.types.length || oTemplate.types[1] !== pokemon.template.types[1]) {
@ -57,8 +57,8 @@ let BattleScripts = {
return true;
},
getMixedTemplate(originalSpecies, megaSpecies) {
let originalTemplate = this.getTemplate(originalSpecies);
let megaTemplate = this.getTemplate(megaSpecies);
let originalTemplate = this.dex.getTemplate(originalSpecies);
let megaTemplate = this.dex.getTemplate(megaSpecies);
if (originalTemplate.baseSpecies === megaTemplate.baseSpecies) return megaTemplate;
// @ts-ignore
let deltas = this.getMegaDeltas(megaTemplate);
@ -67,7 +67,7 @@ let BattleScripts = {
return template;
},
getMegaDeltas(megaTemplate) {
let baseTemplate = this.getTemplate(megaTemplate.baseSpecies);
let baseTemplate = this.dex.getTemplate(megaTemplate.baseSpecies);
/**@type {{ability: string, baseStats: {[k: string]: number}, weighthg: number, originalMega: string, requiredItem: string | undefined, type?: string, isMega?: boolean, isPrimal?: boolean}} */
let deltas = {
ability: megaTemplate.abilities['0'],
@ -93,7 +93,7 @@ let BattleScripts = {
},
doGetMixedTemplate(templateOrTemplateName, deltas) {
if (!deltas) throw new TypeError("Must specify deltas!");
let template = this.deepClone(this.getTemplate(templateOrTemplateName));
let template = this.dex.deepClone(this.dex.getTemplate(templateOrTemplateName));
template.abilities = {'0': deltas.ability};
if (template.types[0] === deltas.type) {
template.types = [deltas.type];
@ -102,7 +102,7 @@ let BattleScripts = {
}
let baseStats = template.baseStats;
for (let statName in baseStats) {
baseStats[statName] = this.clampIntRange(baseStats[statName] + deltas.baseStats[statName], 1, 255);
baseStats[statName] = this.dex.clampIntRange(baseStats[statName] + deltas.baseStats[statName], 1, 255);
}
template.weighthg = Math.max(1, template.weighthg + deltas.weighthg);
template.originalMega = deltas.originalMega;

View File

@ -5,8 +5,8 @@ exports.BattleMovedex = {
"skillswap": {
inherit: true,
onHit(target, source, move) {
let targetAbility = this.getAbility(target.ability);
let sourceAbility = this.getAbility(source.ability);
let targetAbility = this.dex.getAbility(target.ability);
let sourceAbility = this.dex.getAbility(source.ability);
if (target.side === source.side) {
this.add('-activate', source, 'move: Skill Swap', '', '', '[of] ' + target);
} else {

View File

@ -7,19 +7,19 @@ exports.BattleScripts = {
return name;
}
let id = toID(name);
if (id.startsWith('ability') && !['abilitypowerofalchemy', 'abilityreceiver', 'abilitytrace'].includes(id)) return Object.assign(Object.create(this.getAbility(id.slice(7))), {id});
if (id.startsWith('ability') && !['abilitypowerofalchemy', 'abilityreceiver', 'abilitytrace'].includes(id)) return Object.assign(Object.create(this.dex.getAbility(id.slice(7))), {id});
return Object.getPrototypeOf(this).getEffect.call(this, name);
},
pokemon: {
setAbility(ability, source, isFromFormechange) {
if (!this.hp) return false;
ability = this.battle.getAbility(ability);
ability = this.battle.dex.getAbility(ability);
let oldAbility = this.ability;
if (!isFromFormechange) {
if (['illusion', 'battlebond', 'comatose', 'disguise', 'multitype', 'powerconstruct', 'rkssystem', 'schooling', 'shieldsdown', 'stancechange'].includes(ability.id)) return false;
if (['battlebond', 'comatose', 'disguise', 'multitype', 'powerconstruct', 'rkssystem', 'schooling', 'shieldsdown', 'stancechange'].includes(oldAbility)) return false;
}
this.battle.singleEvent('End', this.battle.getAbility(oldAbility), this.abilityData, this, source);
this.battle.singleEvent('End', this.battle.dex.getAbility(oldAbility), this.abilityData, this, source);
let ally = this.side.active.find(ally => ally && ally !== this && !ally.fainted);
if (ally && ally.m.innate) {
ally.removeVolatile(ally.m.innate);

View File

@ -55,20 +55,20 @@ let BattleAbilities = {
if (target === source || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.useMove(newMove, target, source, this.getAbility('magicbounce'));
this.useMove(newMove, target, source, this.dex.getAbility('magicbounce'));
return null;
},
onAllyTryHitSide(target, source, move) {
if (target.side === source.side || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.useMove(newMove, this.effectData.target, source, this.getAbility('magicbounce'));
this.useMove(newMove, this.effectData.target, source, this.dex.getAbility('magicbounce'));
return null;
},
onDamagePriority: -100,
@ -188,7 +188,7 @@ let BattleAbilities = {
if (target === source || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.useMove(newMove, target, source);
@ -198,7 +198,7 @@ let BattleAbilities = {
if (target.side === source.side || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.useMove(newMove, this.effectData.target, source);
@ -231,7 +231,7 @@ let BattleAbilities = {
name: "Logia",
isNonstandard: "Custom",
onTryHit(target, source, move) {
let plateType = this.getItem(target.item).onPlate;
let plateType = this.dex.getItem(target.item).onPlate;
if (target !== source && (move.type === 'Normal' || plateType === move.type)) {
this.add('-immune', target, '[from] ability: Logia');
return null;
@ -250,7 +250,7 @@ let BattleAbilities = {
if (formes.includes(toID(source.template.species))) {
formes.splice(formes.indexOf(toID(source.template.species)), 1);
this.add('-activate', source, 'ability: Arabesque');
source.formeChange(formes[this.random(formes.length)], this.getAbility('arabesque'), true);
source.formeChange(formes[this.random(formes.length)], this.dex.getAbility('arabesque'), true);
}
},
},
@ -271,7 +271,7 @@ let BattleAbilities = {
onEffectiveness(typeMod, target, type, move) {
if (!target) return;
if (target.template.baseSpecies !== 'Shaymin' || target.transformed) return;
return this.getEffectiveness(move.type, 'Grass');
return this.dex.getEffectiveness(move.type, 'Grass');
},
onAfterDamage(damage, target, source, effect) {
if (source === target) return;
@ -433,8 +433,8 @@ let BattleAbilities = {
},
onAfterDamage(damage, target, source, effect) {
// Illusion that only breaks when hit with a move that is super effective VS dark
if (target.illusion && effect && effect.effectType === 'Move' && effect.id !== 'confused' && this.getEffectiveness(effect.type, target.getTypes()) > 0) {
this.singleEvent('End', this.getAbility('Illusion'), target.abilityData, target, source, effect);
if (target.illusion && effect && effect.effectType === 'Move' && effect.id !== 'confused' && this.dex.getEffectiveness(effect.type, target.getTypes()) > 0) {
this.singleEvent('End', this.dex.getAbility('Illusion'), target.abilityData, target, source, effect);
}
},
onEnd(pokemon) {
@ -446,12 +446,12 @@ let BattleAbilities = {
this.add('replace', pokemon, details);
this.add('-end', pokemon, 'Illusion');
// Handle hippopotas
if (this.getTemplate(disguisedAs).exists) disguisedAs += 'user';
if (this.dex.getTemplate(disguisedAs).exists) disguisedAs += 'user';
if (pokemon.volatiles[disguisedAs]) {
pokemon.removeVolatile(disguisedAs);
}
if (!pokemon.volatiles[toID(pokemon.name)]) {
let status = this.getEffect(toID(pokemon.name));
let status = this.dex.getEffect(toID(pokemon.name));
if (status && status.exists) {
pokemon.addVolatile(toID(pokemon.name), pokemon);
}
@ -725,7 +725,7 @@ let BattleAbilities = {
pokemon.moveSlots = [];
for (let i = 0; i < set.length; i++) {
let newMove = set[i];
let moveTemplate = this.getMove(newMove);
let moveTemplate = this.dex.getMove(newMove);
pokemon.moveSlots.push({
move: moveTemplate.name,
id: moveTemplate.id,
@ -1185,7 +1185,7 @@ let BattleAbilities = {
name: "Snow Storm",
isNonstandard: "Custom",
onStart() {
let snowStorm = this.getEffect('hail');
let snowStorm = this.dex.getEffect('hail');
this.field.setWeather(snowStorm);
},
},
@ -1201,12 +1201,12 @@ let BattleAbilities = {
this.add('replace', pokemon, details);
this.add('-end', pokemon, 'Illusion');
// Handle hippopotas
if (this.getTemplate(disguisedAs).exists) disguisedAs += 'user';
if (this.dex.getTemplate(disguisedAs).exists) disguisedAs += 'user';
if (pokemon.volatiles[disguisedAs]) {
pokemon.removeVolatile(disguisedAs);
}
if (!pokemon.volatiles[toID(pokemon.name)]) {
let status = this.getEffect(toID(pokemon.name));
let status = this.dex.getEffect(toID(pokemon.name));
if (status && status.exists) {
pokemon.addVolatile(toID(pokemon.name), pokemon);
}

View File

@ -59,7 +59,7 @@ let BattleMovedex = {
this.add('-anim', source, 'Boomburst', source);
},
onHit(target, source, move) {
this.boost({atk: 2}, source, source, this.getActiveMove('Noble Howl'));
this.boost({atk: 2}, source, source, this.dex.getActiveMove('Noble Howl'));
if (!(['', 'slp', 'frz'].includes(source.status))) {
source.cureStatus();
}
@ -68,12 +68,12 @@ let BattleMovedex = {
for (const targetCondition of removeTarget) {
if (target.side.removeSideCondition(targetCondition)) {
if (!removeAll.includes(targetCondition)) continue;
this.add('-sideend', target.side, this.getEffect(targetCondition).name, '[from] move: Noble Howl', '[of] ' + target);
this.add('-sideend', target.side, this.dex.getEffect(targetCondition).name, '[from] move: Noble Howl', '[of] ' + target);
}
}
for (const sideCondition of removeAll) {
if (source.side.removeSideCondition(sideCondition)) {
this.add('-sideend', source.side, this.getEffect(sideCondition).name, '[from] move: Noble Howl', '[of] ' + source);
this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Noble Howl', '[of] ' + source);
}
}
},
@ -201,7 +201,7 @@ let BattleMovedex = {
onAfterMoveSecondarySelf(pokemon) {
pokemon.clearBoosts();
this.add('-clearboost', pokemon);
this.boost({atk: -1, def: -1, spe: -1}, pokemon, pokemon, this.getActiveMove('Cataclysm'));
this.boost({atk: -1, def: -1, spe: -1}, pokemon, pokemon, this.dex.getActiveMove('Cataclysm'));
},
secondary: null,
target: "normal",
@ -232,10 +232,10 @@ let BattleMovedex = {
let silentRemove = ['reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist'];
for (const sideCondition of removeAll) {
if (target.side.removeSideCondition(sideCondition)) {
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', target.side, this.getEffect(sideCondition).name, '[from] move: Quick Reload', '[of] ' + source);
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', target.side, this.dex.getEffect(sideCondition).name, '[from] move: Quick Reload', '[of] ' + source);
}
if (source.side.removeSideCondition(sideCondition)) {
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', source.side, this.getEffect(sideCondition).name, '[from] move: Quick Reload', '[of] ' + source);
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Quick Reload', '[of] ' + source);
}
}
},
@ -526,7 +526,7 @@ let BattleMovedex = {
this.add('replace', target, pokemon.getDetails, target.hp / target.maxhp); // name change
target.setAbility(set.ability);
const format = this.getFormat();
const format = this.format;
if (format && format.onSwitchIn) format.onSwitchIn.call(this, target);
this.add('-message', `${oldName} was sent to the Distortion World and replaced with somebody else!`);
for (let stat of Object.keys(target.boosts)) {
@ -1009,10 +1009,10 @@ let BattleMovedex = {
let silentRemove = ['reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist'];
for (const sideCondition of removeAll) {
if (target.side.removeSideCondition(sideCondition)) {
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', target.side, this.getEffect(sideCondition).name, '[from] move: Blustery Winds', '[of] ' + source);
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', target.side, this.dex.getEffect(sideCondition).name, '[from] move: Blustery Winds', '[of] ' + source);
}
if (source.side.removeSideCondition(sideCondition)) {
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', source.side, this.getEffect(sideCondition).name, '[from] move: Blustery Winds', '[of] ' + source);
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Blustery Winds', '[of] ' + source);
}
}
this.field.clearWeather();
@ -1131,13 +1131,13 @@ let BattleMovedex = {
for (const targetCondition of removeTarget) {
if (target.side.removeSideCondition(targetCondition)) {
if (!removeAll.includes(targetCondition)) continue;
this.add('-sideend', target.side, this.getEffect(targetCondition).name, '[from] move: Defog', '[of] ' + source);
this.add('-sideend', target.side, this.dex.getEffect(targetCondition).name, '[from] move: Defog', '[of] ' + source);
success = true;
}
}
for (const sideCondition of removeAll) {
if (source.side.removeSideCondition(sideCondition)) {
this.add('-sideend', source.side, this.getEffect(sideCondition).name, '[from] move: Defog', '[of] ' + source);
this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Defog', '[of] ' + source);
success = true;
}
}
@ -1310,9 +1310,9 @@ let BattleMovedex = {
this.add('-anim', target, 'Nasty Plot', target);
},
onHit(target, source, move) {
this.heal(source.maxhp / 4, source, source, this.getActiveMove('Super Ego Inflation'));
this.boost({atk: 2, spa: 2}, target, source, this.getActiveMove('Super Ego Inflation'));
target.addVolatile('taunt', source, this.getActiveMove('Super Ego Inflation'));
this.heal(source.maxhp / 4, source, source, this.dex.getActiveMove('Super Ego Inflation'));
this.boost({atk: 2, spa: 2}, target, source, this.dex.getActiveMove('Super Ego Inflation'));
target.addVolatile('taunt', source, this.dex.getActiveMove('Super Ego Inflation'));
},
secondary: null,
target: "normal",
@ -1398,7 +1398,7 @@ let BattleMovedex = {
},
onHit(pokemon, move) {
if (this.field.pseudoWeather.gravity) return false;
this.boost({atk: 2}, pokemon, pokemon, this.getActiveMove('EarthsBlessing'));
this.boost({atk: 2}, pokemon, pokemon, this.dex.getActiveMove('EarthsBlessing'));
this.field.addPseudoWeather('gravity');
if (['', 'slp', 'frz'].includes(pokemon.status)) return;
pokemon.cureStatus();
@ -1470,12 +1470,12 @@ let BattleMovedex = {
victini: ['V-create', 'Blue Flare'],
};
let forme = Object.keys(formes)[this.random(5)];
source.formeChange(forme, this.getAbility('psychicsurge'), true);
source.formeChange(forme, this.dex.getAbility('psychicsurge'), true);
this.boost({atk: 1, spa: 1}, source, source, move);
this.useMove(formes[forme][0], source, target);
this.useMove(formes[forme][1], source, target);
this.boost({atk: -1, spa: -1}, source, source, move);
source.formeChange(baseForme, this.getAbility('psychicsurge'), true);
source.formeChange(baseForme, this.dex.getAbility('psychicsurge'), true);
},
secondary: null,
target: "normal",
@ -1956,7 +1956,7 @@ let BattleMovedex = {
// Pick a random hazard, and set it
let hazard1 = this.sample(hazardTypes);
// Theoretically, this should always work
this.add('-anim', source, this.getMove(hazard1).name, target);
this.add('-anim', source, this.dex.getMove(hazard1).name, target);
target.addSideCondition(hazard1, source, this.effect);
// If that was the last possible layer of that hazard, remove it from our list of possible hazards
if (hazards[hazard1] === 1) {
@ -1966,7 +1966,7 @@ let BattleMovedex = {
}
// Set the last hazard and animate the switch
let hazard2 = this.sample(hazardTypes);
this.add('-anim', source, this.getMove(hazard2).name, target);
this.add('-anim', source, this.dex.getMove(hazard2).name, target);
target.addSideCondition(hazard2, source, this.effect);
this.add('-anim', source, "Baton Pass", target);
},
@ -2041,23 +2041,23 @@ let BattleMovedex = {
this.add('message', `${pokemon.name} was corrupted by a bug in the Scripted Terrain!`);
// generate a movepool
let moves = [];
let pool = this.shuffle(Object.keys(this.data.Movedex));
let metronome = this.getMove('metronome');
let pool = this.dex.shuffle(Object.keys(this.dex.data.Movedex));
let metronome = this.dex.getMove('metronome');
for (let i of pool) {
let move = this.getMove(i);
let move = this.dex.getMove(i);
if (i !== move.id) continue;
if (move.isZ || move.isNonstandard) continue;
if (metronome.noMetronome && metronome.noMetronome.includes(move.id)) continue;
if (this.getMove(i).gen > this.gen) continue;
if (this.dex.getMove(i).gen > this.gen) continue;
moves.push(move);
if (moves.length >= 3) break;
}
moves.push('glitchout');
if (toID(pokemon.ability).includes('illusion') && pokemon.illusion) this.singleEvent('End', this.getAbility('Illusion'), pokemon.abilityData, pokemon, pokemon);
if (toID(pokemon.ability).includes('illusion') && pokemon.illusion) this.singleEvent('End', this.dex.getAbility('Illusion'), pokemon.abilityData, pokemon, pokemon);
pokemon.formeChange('missingno');
pokemon.moveSlots = [];
for (let moveid of moves) {
let move = this.getMove(moveid);
let move = this.dex.getMove(moveid);
if (!move.id) continue;
pokemon.moveSlots.push({
move: move.name,
@ -2105,12 +2105,12 @@ let BattleMovedex = {
},
onHit(target, source, effect) {
let moves = [];
for (let i in this.data.Movedex) {
let move = this.data.Movedex[i];
for (let i in this.dex.data.Movedex) {
let move = this.dex.data.Movedex[i];
if (i !== move.id) continue;
if (move.isZ || move.isNonstandard) continue;
if (effect.noMetronome && effect.noMetronome.includes(move.id)) continue;
if (this.getMove(i).gen > this.gen) continue;
if (this.dex.getMove(i).gen > this.gen) continue;
moves.push(move);
}
let randomMove = '';
@ -2810,7 +2810,7 @@ let BattleMovedex = {
},
onPrepareHit(target, source) {
this.add('-anim', source, "Recover", source);
this.heal(source.maxhp, source, source, this.getActiveMove('Blaze of Glory'));
this.heal(source.maxhp, source, source, this.dex.getActiveMove('Blaze of Glory'));
this.add('-anim', source, "Final Gambit", target);
},
selfdestruct: "ifHit",
@ -2925,9 +2925,9 @@ let BattleMovedex = {
}
}
let weaknesses = [];
for (let type in this.data.TypeChart) {
let typeMod = this.getEffectiveness(type, targetTypes);
if (typeMod > 0 && this.getImmunity(type, target)) weaknesses.push(type);
for (let type in this.dex.data.TypeChart) {
let typeMod = this.dex.getEffectiveness(type, targetTypes);
if (typeMod > 0 && this.dex.getImmunity(type, target)) weaknesses.push(type);
}
if (!weaknesses.length) {
return false;
@ -2935,9 +2935,9 @@ let BattleMovedex = {
let randomType = this.sample(weaknesses);
source.setItem(randomType + 'memory');
this.add('-item', source, source.getItem(), '[from] move: Type Analysis');
let template = this.getTemplate('Silvally-' + randomType);
source.formeChange(template, this.getAbility('rkssystem'), true);
let move = this.getActiveMove('multiattack');
let template = this.dex.getTemplate('Silvally-' + randomType);
source.formeChange(template, this.dex.getAbility('rkssystem'), true);
let move = this.dex.getActiveMove('multiattack');
move.basePower = 80;
this.useMove(move, source, target);
},
@ -2967,7 +2967,7 @@ let BattleMovedex = {
this.add('-anim', source, "Miracle Eye", target);
},
onHit(target, source) {
this.boost({atk: -2, spa: -2}, source, source, this.getActiveMove('/scavenges u'));
this.boost({atk: -2, spa: -2}, source, source, this.dex.getActiveMove('/scavenges u'));
let targetBoosts = {};
let sourceBoosts = {};
@ -3125,10 +3125,10 @@ let BattleMovedex = {
let removeAll = ['reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist', 'spikes', 'toxicspikes', 'stealthrock', 'stickyweb'];
for (const sideCondition of removeAll) {
if (source.side.foe.removeSideCondition(sideCondition)) {
this.add('-sideend', source.side.foe, this.getEffect(sideCondition).name, '[from] move: Prismatic Terrain', '[of] ' + source);
this.add('-sideend', source.side.foe, this.dex.getEffect(sideCondition).name, '[from] move: Prismatic Terrain', '[of] ' + source);
}
if (source.side.removeSideCondition(sideCondition)) {
this.add('-sideend', source.side, this.getEffect(sideCondition).name, '[from] move: Prismatic Terrain', '[of] ' + source);
this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Prismatic Terrain', '[of] ' + source);
}
}
},
@ -3174,7 +3174,7 @@ let BattleMovedex = {
effect: {
duration: 1,
onSwitchIn(pokemon) {
this.boost({spe: -1}, pokemon, pokemon.side.foe.active[0], this.getActiveMove('pyramidingsong'));
this.boost({spe: -1}, pokemon, pokemon.side.foe.active[0], this.dex.getActiveMove('pyramidingsong'));
},
},
forceSwitch: true,
@ -4049,7 +4049,7 @@ let BattleMovedex = {
this.attrLastMove('[still]');
},
onPrepareHit(target, source, move) {
let zmove = this.getMove(this.zMoveTable[move.type]);
let zmove = this.dex.getMove(this.zMoveTable[move.type]);
this.add('-anim', source, zmove.name, target);
this.add('-anim', source, "Transform", source);
},
@ -4076,7 +4076,7 @@ let BattleMovedex = {
// Tranform into it
pokemon.formeChange(set.species);
for (let newMove of set.moves) {
let moveTemplate = this.getMove(newMove);
let moveTemplate = this.dex.getMove(newMove);
if (pokemon.moves.includes(moveTemplate.id)) continue;
pokemon.moveSlots.push({
move: moveTemplate.name,
@ -4423,7 +4423,7 @@ let BattleMovedex = {
for (let i in sideConditions) {
let layers = source.side.sideConditions[i] ? (source.side.sideConditions[i].layers || 1) : 1;
if (source.side.removeSideCondition(i)) {
this.add('-sideend', source.side, this.getEffect(i).name, '[from] move: Smoke Bomb', '[of] ' + source);
this.add('-sideend', source.side, this.dex.getEffect(i).name, '[from] move: Smoke Bomb', '[of] ' + source);
for (layers; layers > 0; layers--) target.side.addSideCondition(i, source);
}
}
@ -4861,7 +4861,7 @@ let BattleMovedex = {
'assist', 'beakblast', 'belch', 'bide', 'celebrate', 'chatter', 'copycat', 'focuspunch', 'mefirst', 'metronome', 'mimic', 'mirrormove', 'naturepower', 'shelltrap', 'sketch', 'sleeptalk', 'uproar',
'teabreak', 'glitzerpopping', // Modded banlist
];
if (move && !(noSleepTalk.includes(move) || this.getMove(move).flags['charge'] || (this.getMove(move).isZ && this.getMove(move).basePower !== 1))) {
if (move && !(noSleepTalk.includes(move) || this.dex.getMove(move).flags['charge'] || (this.dex.getMove(move).isZ && this.dex.getMove(move).basePower !== 1))) {
moves.push(move);
}
}

View File

@ -789,7 +789,7 @@ class RandomStaffBrosTeams extends RandomTeams {
if (!this.allXfix) {
// Enforce typing limits
let types = this.getTemplate(ssbSet.species).types;
let types = this.dex.getTemplate(ssbSet.species).types;
let rejected = false;
for (let type of types) {
if (typePool[type] === undefined) typePool[type] = 0;
@ -842,8 +842,8 @@ class RandomStaffBrosTeams extends RandomTeams {
set.moves.push(move);
}
set.moves.push(ssbSet.signatureMove);
if (name === 'Arsenal' && this.getItem(set.item).onPlate) {
set.species = 'Arceus-' + this.getItem(set.item).onPlate;
if (name === 'Arsenal' && this.dex.getItem(set.item).onPlate) {
set.species = 'Arceus-' + this.dex.getItem(set.item).onPlate;
}
if (name === 'Gallant Spear' && set.item === 'Choice Band') set.moves[set.moves.indexOf('Recover')] = 'Aqua Tail';
if (name === 'The Immortal' && set.item === 'Choice Scarf') set.moves[3] = 'Superpower';

View File

@ -4,12 +4,12 @@
let BattleScripts = {
runMove(moveOrMoveName, pokemon, targetLoc, sourceEffect, zMove, externalMove) {
let target = this.getTarget(pokemon, zMove || moveOrMoveName, targetLoc);
let baseMove = this.getActiveMove(moveOrMoveName);
let baseMove = this.dex.getActiveMove(moveOrMoveName);
const pranksterBoosted = baseMove.pranksterBoosted;
if (!sourceEffect && baseMove.id !== 'struggle' && !zMove) {
let changedMove = this.runEvent('OverrideAction', pokemon, target, baseMove);
if (changedMove && changedMove !== true) {
baseMove = this.getActiveMove(changedMove);
baseMove = this.dex.getActiveMove(changedMove);
if (pranksterBoosted) baseMove.pranksterBoosted = pranksterBoosted;
target = this.resolveTarget(pokemon, baseMove);
}
@ -60,7 +60,7 @@ let BattleScripts = {
return;
}
} else {
sourceEffect = this.getEffect('lockedmove');
sourceEffect = this.dex.getEffect('lockedmove');
}
pokemon.moveUsed(move, targetLoc);
}
@ -71,7 +71,7 @@ let BattleScripts = {
if (zMove) {
if (pokemon.illusion) {
this.singleEvent('End', this.getAbility('Illusion'), pokemon.abilityData, pokemon);
this.singleEvent('End', this.dex.getAbility('Illusion'), pokemon.abilityData, pokemon);
}
this.add('-zpower', pokemon);
pokemon.m.zMoveUsed = true;
@ -100,7 +100,7 @@ let BattleScripts = {
for (const dancer of dancers) {
if (this.faintMessages()) break;
this.add('-activate', dancer, 'ability: Dancer');
this.runMove(move.id, dancer, 0, this.getAbility('dancer'), undefined, true);
this.runMove(move.id, dancer, 0, this.dex.getAbility('dancer'), undefined, true);
// Using a Dancer move is enough to spoil Fake Out etc.
dancer.activeTurns++;
}
@ -109,7 +109,7 @@ let BattleScripts = {
},
// Modded to allow arrays as Mega Stone options
canMegaEvo(pokemon) {
let altForme = pokemon.baseTemplate.otherFormes && this.getTemplate(pokemon.baseTemplate.otherFormes[0]);
let altForme = pokemon.baseTemplate.otherFormes && this.dex.getTemplate(pokemon.baseTemplate.otherFormes[0]);
let item = pokemon.getItem();
if (altForme && altForme.isMega && altForme.requiredMove && pokemon.baseMoves.includes(toID(altForme.requiredMove)) && !item.zMove) return altForme.species;
if (item.megaEvolves !== pokemon.baseTemplate.species || (Array.isArray(item.megaStone) && item.megaStone.includes(pokemon.species)) || (typeof item.megaStone === 'string' && item.megaStone === pokemon.species)) {
@ -178,7 +178,7 @@ let BattleScripts = {
let item = pokemon.getItem();
if (item.zMoveFrom && Array.isArray(item.zMoveFrom) ? item.zMoveFrom.includes(move.name) : item.zMoveFrom === move.name) {
// @ts-ignore
zMove = this.getActiveMove(item.zMove);
zMove = this.dex.getActiveMove(item.zMove);
// @ts-ignore Hack for Snaquaza's Z move
zMove.baseMove = move;
zMove.isZPowered = true;
@ -187,12 +187,12 @@ let BattleScripts = {
}
if (move.category === 'Status') {
zMove = this.getActiveMove(move);
zMove = this.dex.getActiveMove(move);
zMove.isZ = true;
zMove.isZPowered = true;
return zMove;
}
zMove = this.getActiveMove(this.zMoveTable[move.type]);
zMove = this.dex.getActiveMove(this.zMoveTable[move.type]);
// @ts-ignore
zMove.basePower = move.zMovePower;
zMove.category = move.category;
@ -213,10 +213,10 @@ let BattleScripts = {
zMoves.push(null);
continue;
}
let move = this.getMove(moveSlot.move);
let move = this.dex.getMove(moveSlot.move);
let zMoveName = this.getZMove(move, pokemon, true) || '';
if (zMoveName) {
let zMove = this.getMove(zMoveName);
let zMove = this.dex.getMove(zMoveName);
if (!zMove.isZ && zMove.category === 'Status') zMoveName = "Z-" + zMoveName;
zMoves.push({move: zMoveName, target: zMove.target});
} else {
@ -227,7 +227,7 @@ let BattleScripts = {
if (atLeastOne) return zMoves;
},
runZPower(move, pokemon) {
const zPower = this.getEffect('zpower');
const zPower = this.dex.getEffect('zpower');
if (move.category !== 'Status') {
this.attrLastMove('[zeffect]');
} else if (move.zMoveBoost) {
@ -312,7 +312,7 @@ let BattleScripts = {
}
// types
let typeMod = target.runEffectiveness(move);
typeMod = this.clampIntRange(typeMod, -6, 6);
typeMod = this.dex.clampIntRange(typeMod, -6, 6);
target.getMoveHitData(move).typeMod = typeMod;
if (typeMod > 0) {
if (!suppressMessages) this.add('-supereffective', target);
@ -382,7 +382,7 @@ let BattleScripts = {
},
setStatus(status, source = null, sourceEffect = null, ignoreImmunities = false) {
if (!this.hp) return false;
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
if (this.battle.event) {
if (!source) source = this.battle.event.source;
if (!sourceEffect) sourceEffect = this.battle.effect;

View File

@ -897,9 +897,9 @@ let BattleStatuses = {
for (const target of pokemon.side.foe.active) {
if (!target || target.fainted) continue;
for (const moveSlot of target.moveSlots) {
const move = this.getMove(moveSlot.move);
const move = this.dex.getMove(moveSlot.move);
const moveType = move.id === 'hiddenpower' ? target.hpType : move.type;
if (move.category !== 'Status' && (this.getImmunity(moveType, pokemon) && this.getEffectiveness(moveType, pokemon) > 0 || move.ohko)) {
if (move.category !== 'Status' && (this.dex.getImmunity(moveType, pokemon) && this.dex.getEffectiveness(moveType, pokemon) > 0 || move.ohko)) {
this.add('-ability', pokemon, 'Anticipation');
return;
}
@ -1472,10 +1472,10 @@ let BattleStatuses = {
let silentRemove = ['reflect', 'lightscreen', 'auroraveil', 'safeguard', 'mist'];
for (const sideCondition of removeAll) {
if (target.side.removeSideCondition(sideCondition)) {
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', target.side, this.getEffect(sideCondition).name, '[from] move: No Fun Zone', '[of] ' + source);
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', target.side, this.dex.getEffect(sideCondition).name, '[from] move: No Fun Zone', '[of] ' + source);
}
if (source.side.removeSideCondition(sideCondition)) {
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', source.side, this.getEffect(sideCondition).name, '[from] move: No Fun Zone', '[of] ' + source);
if (!(silentRemove.includes(sideCondition))) this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: No Fun Zone', '[of] ' + source);
}
}
this.add('-clearallboost');
@ -2052,7 +2052,7 @@ let BattleStatuses = {
this.add('-sidestart', side, 'move: Stealth Rock');
},
onSwitchIn(pokemon) {
let typeMod = this.clampIntRange(pokemon.runEffectiveness(this.getActiveMove('stealthrock')), -6, 6);
let typeMod = this.dex.clampIntRange(pokemon.runEffectiveness(this.dex.getActiveMove('stealthrock')), -6, 6);
this.damage(pokemon.maxhp * Math.pow(2, typeMod) / 8);
},
},
@ -2067,7 +2067,7 @@ let BattleStatuses = {
onSwitchIn(pokemon) {
if (!pokemon.isGrounded()) return;
this.add('-activate', pokemon, 'move: Sticky Web');
this.boost({spe: -1}, pokemon, pokemon.side.foe.active[0], this.getActiveMove('stickyweb'));
this.boost({spe: -1}, pokemon, pokemon.side.foe.active[0], this.dex.getActiveMove('stickyweb'));
},
},
toxicspikes: {

View File

@ -46,7 +46,7 @@ let BattleMovedex = {
this.debug('Nothing to leech into');
return;
}
let toLeech = this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1);
let toLeech = this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1);
let damage = this.damage(toLeech, pokemon, leecher);
if (damage) this.heal(damage, leecher, pokemon);
},

View File

@ -15,7 +15,7 @@ let BattleScripts = {
modifyStat(statName, modifier) {
if (!(statName in this.storedStats)) throw new Error("Invalid `statName` passed to `modifyStat`");
// @ts-ignore
this.modifiedStats[statName] = this.battle.clampIntRange(Math.floor(this.modifiedStats[statName] * modifier), 1);
this.modifiedStats[statName] = this.battle.dex.clampIntRange(Math.floor(this.modifiedStats[statName] * modifier), 1);
},
// This is run on Stadium after boosts and status changes.
recalculateStats() {
@ -79,7 +79,7 @@ let BattleScripts = {
},
// Battle scripts.
runMove(moveOrMoveName, pokemon, targetLoc, sourceEffect) {
let move = this.getActiveMove(moveOrMoveName);
let move = this.dex.getActiveMove(moveOrMoveName);
let target = this.getTarget(pokemon, move, targetLoc);
if (target && target.subFainted) target.subFainted = null;
@ -264,7 +264,7 @@ let BattleScripts = {
moveHit(target, pokemon, moveOrMoveName, moveData, isSecondary, isSelf) {
/** @type {number | null | false | undefined} */
let damage = 0;
let move = this.getActiveMove(moveOrMoveName);
let move = this.dex.getActiveMove(moveOrMoveName);
if (!isSecondary && !isSelf) this.setActiveMove(move, pokemon, target);
/** @type {number | boolean} */
@ -424,7 +424,7 @@ let BattleScripts = {
getDamage(pokemon, target, move, suppressMessages) {
// First of all, we get the move.
if (typeof move === 'string') {
move = this.getActiveMove(move);
move = this.dex.getActiveMove(move);
} else if (typeof move === 'number') {
move = /** @type {ActiveMove} */ ({
basePower: move,
@ -488,7 +488,7 @@ let BattleScripts = {
if (!basePower) {
return basePower === 0 ? undefined : basePower;
}
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
// Checking for the move's Critical Hit possibility. We check if it's a 100% crit move, otherwise we calculate the chance.
let isCrit = move.willCrit || false;
@ -521,7 +521,7 @@ let BattleScripts = {
}
// Now we make sure it's a number between 1 and 255.
critChance = this.clampIntRange(critChance, 1, 255);
critChance = this.dex.clampIntRange(critChance, 1, 255);
// Last, we check deppending on ratio if the move critical hits or not.
// We compare our critical hit chance against a random number between 0 and 255.
@ -543,7 +543,7 @@ let BattleScripts = {
}
}
if (!basePower) return 0;
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
// We now check attacker's and defender's stats.
let level = pokemon.level;
@ -561,7 +561,7 @@ let BattleScripts = {
if ((defType === 'def' && defender.volatiles['reflect']) || (defType === 'spd' && defender.volatiles['lightscreen'])) {
this.debug('Screen doubling (Sp)Def');
defense *= 2;
defense = this.clampIntRange(defense, 1, 1998);
defense = this.dex.clampIntRange(defense, 1, 1998);
}
// In the event of a critical hit, the offense and defense changes are ignored.
@ -585,14 +585,14 @@ let BattleScripts = {
// When either attack or defense are higher than 256, they are both divided by 4 and moded by 256.
// This is what cuases the roll over bugs.
if (attack >= 256 || defense >= 256) {
attack = this.clampIntRange(Math.floor(attack / 4) % 256, 1);
attack = this.dex.clampIntRange(Math.floor(attack / 4) % 256, 1);
// Defense isn't checked on the cartridge, but we don't want those / 0 bugs on the sim.
defense = this.clampIntRange(Math.floor(defense / 4) % 256, 1);
defense = this.dex.clampIntRange(Math.floor(defense / 4) % 256, 1);
}
// Self destruct moves halve defense at this point.
if (move.selfdestruct && defType === 'def') {
defense = this.clampIntRange(Math.floor(defense / 2), 1);
defense = this.dex.clampIntRange(Math.floor(defense / 2), 1);
}
// Let's go with the calculation now that we have what we need.
@ -603,7 +603,7 @@ let BattleScripts = {
damage *= basePower;
damage *= attack;
damage = Math.floor(damage / defense);
damage = this.clampIntRange(Math.floor(damage / 50), 1, 997);
damage = this.dex.clampIntRange(Math.floor(damage / 50), 1, 997);
damage += 2;
// STAB damage bonus, the "???" type never gets STAB
@ -613,7 +613,7 @@ let BattleScripts = {
// Type effectiveness.
// The order here is not correct, must change to check the move versus each type.
let totalTypeMod = this.getEffectiveness(type, target);
let totalTypeMod = this.dex.getEffectiveness(type, target);
// Super effective attack
if (totalTypeMod > 0) {
if (!suppressMessages) this.add('-supereffective', target);

View File

@ -12,10 +12,10 @@ let BattleStatuses = {
},
onAfterMoveSelfPriority: 2,
onAfterMoveSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
onAfterSwitchInSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
},
par: {
@ -98,10 +98,10 @@ let BattleStatuses = {
},
onAfterMoveSelfPriority: 2,
onAfterMoveSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
onAfterSwitchInSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
},
tox: {
@ -114,14 +114,14 @@ let BattleStatuses = {
},
onAfterMoveSelfPriority: 2,
onAfterMoveSelf(pokemon) {
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
onAfterSwitchInSelf(pokemon) {
// Regular poison status and damage after a switchout -> switchin.
pokemon.setStatus('psn');
pokemon.addVolatile('residualdmg');
pokemon.volatiles['residualdmg'].counter = 1;
this.damage(this.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
this.damage(this.dex.clampIntRange(Math.floor(pokemon.maxhp / 16), 1));
},
},
partiallytrapped: {

View File

@ -10,8 +10,8 @@ let BattleFormats = {
let alolaDex = [
"Rowlet", "Dartrix", "Decidueye", "Litten", "Torracat", "Incineroar", "Popplio", "Brionne", "Primarina", "Pikipek", "Trumbeak", "Toucannon", "Yungoos", "Gumshoos", "Rattata-Alola", "Raticate-Alola", "Caterpie", "Metapod", "Butterfree", "Ledyba", "Ledian", "Spinarak", "Ariados", "Pichu", "Pikachu", "Raichu-Alola", "Grubbin", "Charjabug", "Vikavolt", "Bonsly", "Sudowoodo", "Happiny", "Chansey", "Blissey", "Munchlax", "Snorlax", "Slowpoke", "Slowbro", "Slowking", "Wingull", "Pelipper", "Abra", "Kadabra", "Alakazam", "Meowth-Alola", "Persian-Alola", "Magnemite", "Magneton", "Magnezone", "Grimer-Alola", "Muk-Alola", "Growlithe", "Arcanine", "Drowzee", "Hypno", "Makuhita", "Hariyama", "Smeargle", "Crabrawler", "Crabominable", "Gastly", "Haunter", "Gengar", "Drifloon", "Drifblim", "Misdreavus", "Mismagius", "Zubat", "Golbat", "Crobat", "Diglett-Alola", "Dugtrio-Alola", "Spearow", "Fearow", "Rufflet", "Braviary", "Vullaby", "Mandibuzz", "Mankey", "Primeape", "Delibird", "Oricorio", "Cutiefly", "Ribombee", "Petilil", "Lilligant", "Cottonee", "Whimsicott", "Psyduck", "Golduck", "Magikarp", "Gyarados", "Barboach", "Whiscash", "Machop", "Machoke", "Machamp", "Roggenrola", "Boldore", "Gigalith", "Carbink", "Sableye", "Rockruff", "Lycanroc", "Spinda", "Tentacool", "Tentacruel", "Finneon", "Lumineon", "Wishiwashi", "Luvdisc", "Corsola", "Mareanie", "Toxapex", "Shellder", "Cloyster", "Bagon", "Shelgon", "Salamence", "Lillipup", "Herdier", "Stoutland", "Eevee", "Vaporeon", "Jolteon", "Flareon", "Espeon", "Umbreon", "Leafeon", "Glaceon", "Sylveon", "Mudbray", "Mudsdale", "Igglybuff", "Jigglypuff", "Wigglytuff", "Tauros", "Miltank", "Surskit", "Masquerain", "Dewpider", "Araquanid", "Fomantis", "Lurantis", "Morelull", "Shiinotic", "Paras", "Parasect", "Poliwag", "Poliwhirl", "Poliwrath", "Politoed", "Goldeen", "Seaking", "Feebas", "Milotic", "Alomomola", "Fletchling", "Fletchinder", "Talonflame", "Salandit", "Salazzle", "Cubone", "Marowak-Alola", "Kangaskhan", "Magby", "Magmar", "Magmortar", "Stufful", "Bewear", "Bounsweet", "Steenee", "Tsareena", "Comfey", "Pinsir", "Oranguru", "Passimian", "Goomy", "Sliggoo", "Goodra", "Castform", "Wimpod", "Golisopod", "Staryu", "Starmie", "Sandygast", "Palossand", "Cranidos", "Rampardos", "Shieldon", "Bastiodon", "Archen", "Archeops", "Tirtouga", "Carracosta", "Phantump", "Trevenant", "Nosepass", "Probopass", "Pyukumuku", "Chinchou", "Lanturn", "Type: Null", "Silvally", "Zygarde", "Trubbish", "Garbodor", "Skarmory", "Ditto", "Cleffa", "Clefairy", "Clefable", "Minior", "Beldum", "Metang", "Metagross", "Porygon", "Porygon2", "Porygon-Z", "Pancham", "Pangoro", "Komala", "Torkoal", "Turtonator", "Togedemaru", "Elekid", "Electabuzz", "Electivire", "Geodude-Alola", "Graveler-Alola", "Golem-Alola", "Sandile", "Krokorok", "Krookodile", "Trapinch", "Vibrava", "Flygon", "Gible", "Gabite", "Garchomp", "Klefki", "Mimikyu", "Bruxish", "Drampa", "Absol", "Snorunt", "Glalie", "Froslass", "Sneasel", "Weavile", "Sandshrew-Alola", "Sandslash-Alola", "Vulpix-Alola", "Ninetales-Alola", "Vanillite", "Vanillish", "Vanilluxe", "Snubbull", "Granbull", "Shellos", "Gastrodon", "Relicanth", "Dhelmise", "Carvanha", "Sharpedo", "Wailmer", "Wailord", "Lapras", "Exeggcute", "Exeggutor-Alola", "Jangmo-o", "Hakamo-o", "Kommo-o", "Emolga", "Scyther", "Scizor", "Murkrow", "Honchkrow", "Riolu", "Lucario", "Dratini", "Dragonair", "Dragonite", "Aerodactyl", "Tapu Koko", "Tapu Lele", "Tapu Bulu", "Tapu Fini", "Cosmog", "Cosmoem", "Solgaleo", "Lunala", "Nihilego", "Buzzwole", "Pheromosa", "Xurkitree", "Celesteela", "Kartana", "Guzzlord", "Necrozma", "Magearna", "Marshadow",
];
let template = this.getTemplate(set.species || set.name);
if (!alolaDex.includes(template.baseSpecies) && !alolaDex.includes(template.species) && !this.getRuleTable(format).has('+' + template.speciesid)) {
let template = this.dex.getTemplate(set.species || set.name);
if (!alolaDex.includes(template.baseSpecies) && !alolaDex.includes(template.species) && !this.ruleTable.has('+' + template.speciesid)) {
return [template.baseSpecies + " is not in the Alola Pokédex."];
}
},

View File

@ -640,7 +640,7 @@ let BattleMovedex = {
let noAssist = [
'assist', 'banefulbunker', 'beakblast', 'belch', 'bestow', 'bounce', 'celebrate', 'chatter', 'circlethrow', 'copycat', 'counter', 'covet', 'destinybond', 'detect', 'dig', 'dive', 'dragontail', 'endure', 'feint', 'fly', 'focuspunch', 'followme', 'helpinghand', 'holdhands', 'kingsshield', 'matblock', 'mefirst', 'metronome', 'mimic', 'mirrorcoat', 'mirrormove', 'naturepower', 'phantomforce', 'protect', 'ragepowder', 'roar', 'shadowforce', 'shelltrap', 'sketch', 'skydrop', 'sleeptalk', 'snatch', 'spikyshield', 'spotlight', 'struggle', 'switcheroo', 'thief', 'transform', 'trick', 'whirlwind',
];
if (!noAssist.includes(move) && !this.getMove(move).isZ) {
if (!noAssist.includes(move) && !this.dex.getMove(move).isZ) {
moves.push(move);
}
}
@ -1275,7 +1275,7 @@ let BattleMovedex = {
return false;
}
if (!target.isActive) {
const possibleTarget = this.resolveTarget(pokemon, this.getMove('pound'));
const possibleTarget = this.resolveTarget(pokemon, this.dex.getMove('pound'));
if (!possibleTarget) {
this.add('-miss', pokemon);
return false;
@ -2580,7 +2580,7 @@ let BattleMovedex = {
priority: 0,
flags: {snatch: 1},
onHit(target) {
let type = this.getMove(target.moveSlots[0].id).type;
let type = this.dex.getMove(target.moveSlots[0].id).type;
if (target.hasType(type) || !target.setType(type)) return false;
this.add('-start', target, 'typechange', type);
},
@ -2608,9 +2608,9 @@ let BattleMovedex = {
}
let possibleTypes = [];
let attackType = target.lastMove.type;
for (let type in this.data.TypeChart) {
for (let type in this.dex.data.TypeChart) {
if (source.hasType(type)) continue;
let typeCheck = this.data.TypeChart[type].damageTaken[attackType];
let typeCheck = this.dex.data.TypeChart[type].damageTaken[attackType];
if (typeCheck === 2 || typeCheck === 3) {
possibleTypes.push(type);
}
@ -3233,13 +3233,13 @@ let BattleMovedex = {
for (const targetCondition of removeTarget) {
if (target.side.removeSideCondition(targetCondition)) {
if (!removeAll.includes(targetCondition)) continue;
this.add('-sideend', target.side, this.getEffect(targetCondition).name, '[from] move: Defog', '[of] ' + source);
this.add('-sideend', target.side, this.dex.getEffect(targetCondition).name, '[from] move: Defog', '[of] ' + source);
success = true;
}
}
for (const sideCondition of removeAll) {
if (source.side.removeSideCondition(sideCondition)) {
this.add('-sideend', source.side, this.getEffect(sideCondition).name, '[from] move: Defog', '[of] ' + source);
this.add('-sideend', source.side, this.dex.getEffect(sideCondition).name, '[from] move: Defog', '[of] ' + source);
success = true;
}
}
@ -4619,7 +4619,7 @@ let BattleMovedex = {
onHit(target, source) {
let oldAbility = target.setAbility(source.ability);
if (oldAbility) {
this.add('-ability', target, this.getAbility(target.ability).name, '[from] move: Entrainment');
this.add('-ability', target, this.dex.getAbility(target.ability).name, '[from] move: Entrainment');
return;
}
return false;
@ -5295,7 +5295,7 @@ let BattleMovedex = {
}
for (const ally of target.side.active) {
if (ally && this.isAdjacent(target, ally)) {
this.damage(ally.maxhp / 16, ally, source, this.getEffect('Flame Burst'));
this.damage(ally.maxhp / 16, ally, source, this.dex.getEffect('Flame Burst'));
}
}
},
@ -5305,7 +5305,7 @@ let BattleMovedex = {
}
for (const ally of target.side.active) {
if (ally && this.isAdjacent(target, ally)) {
this.damage(ally.maxhp / 16, ally, source, this.getEffect('Flame Burst'));
this.damage(ally.maxhp / 16, ally, source, this.dex.getEffect('Flame Burst'));
}
}
},
@ -5690,7 +5690,7 @@ let BattleMovedex = {
pp: 10,
flags: {contact: 1, protect: 1, mirror: 1, gravity: 1, distance: 1, nonsky: 1},
onEffectiveness(typeMod, target, type, move) {
return typeMod + this.getEffectiveness('Flying', type);
return typeMod + this.dex.getEffectiveness('Flying', type);
},
priority: 0,
secondary: null,
@ -6106,7 +6106,7 @@ let BattleMovedex = {
if (!pokemon.volatiles.furycutter || move.hit === 1) {
pokemon.addVolatile('furycutter');
}
return this.clampIntRange(move.basePower * pokemon.volatiles.furycutter.multiplier, 1, 160);
return this.dex.clampIntRange(move.basePower * pokemon.volatiles.furycutter.multiplier, 1, 160);
},
category: "Physical",
desc: "Power doubles with each successful hit, up to a maximum of 160 power. The power is reset if this move misses or another move is used.",
@ -6269,7 +6269,7 @@ let BattleMovedex = {
// Ability suppression implemented in Pokemon.ignoringAbility() within sim/pokemon.js
onStart(pokemon) {
this.add('-endability', pokemon);
this.singleEvent('End', this.getAbility(pokemon.ability), pokemon.abilityData, pokemon, pokemon, 'gastroacid');
this.singleEvent('End', this.dex.getAbility(pokemon.ability), pokemon.abilityData, pokemon, pokemon, 'gastroacid');
},
},
secondary: null,
@ -6764,7 +6764,7 @@ let BattleMovedex = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.id).flags['gravity']) {
if (this.dex.getMove(moveSlot.id).flags['gravity']) {
pokemon.disableMove(moveSlot.id);
}
}
@ -6857,7 +6857,7 @@ let BattleMovedex = {
for (const moveSlot of source.moveSlots) {
if (moveSlot.id === source.lastMove.id) {
moveSlot.pp = 0;
this.add('-activate', source, 'move: Grudge', this.getMove(source.lastMove.id).name);
this.add('-activate', source, 'move: Grudge', this.dex.getMove(source.lastMove.id).name);
}
}
}
@ -6881,9 +6881,9 @@ let BattleMovedex = {
damageCallback(pokemon, target) {
if (target.volatiles['banefulbunker'] || target.volatiles['kingsshield'] || target.side.getSideCondition('matblock') || target.volatiles['protect'] || target.volatiles['spikyshield']) {
this.add('-zbroken', target);
return this.clampIntRange(Math.ceil(Math.floor(target.hp * 3 / 4) / 4 - 0.5), 1);
return this.dex.clampIntRange(Math.ceil(Math.floor(target.hp * 3 / 4) / 4 - 0.5), 1);
}
return this.clampIntRange(Math.floor(target.hp * 3 / 4), 1);
return this.dex.clampIntRange(Math.floor(target.hp * 3 / 4), 1);
},
category: "Special",
desc: "Deals damage to the target equal to 3/4 of its current HP, rounded down, but not less than 1 HP.",
@ -7269,7 +7269,7 @@ let BattleMovedex = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.id).flags['heal']) {
if (this.dex.getMove(moveSlot.id).flags['heal']) {
pokemon.disableMove(moveSlot.id);
}
}
@ -7923,7 +7923,7 @@ let BattleMovedex = {
flags: {contact: 1, protect: 1, mirror: 1, gravity: 1},
hasCustomRecoil: true,
onMoveFail(target, source, move) {
this.damage(source.maxhp / 2, source, source, this.getEffect('High Jump Kick'));
this.damage(source.maxhp / 2, source, source, this.dex.getEffect('High Jump Kick'));
},
secondary: null,
target: "normal",
@ -8879,7 +8879,7 @@ let BattleMovedex = {
flags: {contact: 1, protect: 1, mirror: 1, gravity: 1},
hasCustomRecoil: true,
onMoveFail(target, source, move) {
this.damage(source.maxhp / 2, source, source, this.getEffect('Jump Kick'));
this.damage(source.maxhp / 2, source, source, this.dex.getEffect('Jump Kick'));
},
secondary: null,
target: "normal",
@ -8968,13 +8968,13 @@ let BattleMovedex = {
}
}
if (move.flags['contact']) {
this.boost({atk: -2}, source, target, this.getActiveMove("King's Shield"));
this.boost({atk: -2}, source, target, this.dex.getActiveMove("King's Shield"));
}
return this.NOT_FAIL;
},
onHit(target, source, move) {
if (move.isZPowered && move.flags['contact']) {
this.boost({atk: -2}, source, target, this.getActiveMove("King's Shield"));
this.boost({atk: -2}, source, target, this.dex.getActiveMove("King's Shield"));
}
},
},
@ -9758,7 +9758,7 @@ let BattleMovedex = {
if (target === source || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = this.effectData.pranksterBoosted;
this.useMove(newMove, target, source);
@ -9768,7 +9768,7 @@ let BattleMovedex = {
if (target.side === source.side || move.hasBounced || !move.flags['reflectable']) {
return;
}
let newMove = this.getActiveMove(move.id);
let newMove = this.dex.getActiveMove(move.id);
newMove.hasBounced = true;
newMove.pranksterBoosted = false;
this.useMove(newMove, this.effectData.target, source);
@ -10139,7 +10139,7 @@ let BattleMovedex = {
let noMeFirst = [
'beakblast', 'chatter', 'counter', 'covet', 'focuspunch', 'mefirst', 'metalburst', 'mirrorcoat', 'shelltrap', 'struggle', 'thief',
];
let move = this.getActiveMove(action.move.id);
let move = this.dex.getActiveMove(action.move.id);
if (!action.zmove && !move.isZ && move.category !== 'Status' && !noMeFirst.includes(move.id)) {
pokemon.addVolatile('mefirst');
this.useMove(move, pokemon, target);
@ -10416,7 +10416,7 @@ let BattleMovedex = {
if (move.isZ || move.isNonstandard) continue;
// @ts-ignore
if (effect.noMetronome.includes(move.id)) continue;
if (this.getMove(i).gen > this.gen) continue;
if (this.dex.getMove(i).gen > this.gen) continue;
moves.push(move);
}
let randomMove = '';
@ -10471,7 +10471,7 @@ let BattleMovedex = {
if (source.transformed || !target.lastMove || disallowedMoves.includes(target.lastMove.id) || source.moves.indexOf(target.lastMove.id) >= 0 || target.lastMove.isZ) return false;
let mimicIndex = source.moves.indexOf('mimic');
if (mimicIndex < 0) return false;
let move = this.getMove(target.lastMove.id);
let move = this.dex.getMove(target.lastMove.id);
source.moveSlots[mimicIndex] = {
move: move.name,
id: move.id,
@ -10506,7 +10506,7 @@ let BattleMovedex = {
mindBlownRecoil: true,
onAfterMove(pokemon, target, move) {
if (move.mindBlownRecoil && !move.multihit) {
this.damage(Math.round(pokemon.maxhp / 2), pokemon, pokemon, this.getEffect('Mind Blown'), true);
this.damage(Math.round(pokemon.maxhp / 2), pokemon, pokemon, this.dex.getEffect('Mind Blown'), true);
}
},
secondary: null,
@ -11200,7 +11200,7 @@ let BattleMovedex = {
accuracy: 90,
basePower: 0,
damageCallback(pokemon, target) {
return this.clampIntRange(Math.floor(target.hp / 2), 1);
return this.dex.clampIntRange(Math.floor(target.hp / 2), 1);
},
category: "Special",
desc: "Deals damage to the target equal to half of its current HP, rounded down, but not less than 1 HP.",
@ -12217,7 +12217,7 @@ let BattleMovedex = {
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.damage(this.dex.clampIntRange(Math.round(pokemon.maxhp / 4), 1));
return false;
}
},
@ -13218,7 +13218,7 @@ let BattleMovedex = {
let sideConditions = ['spikes', 'toxicspikes', 'stealthrock', 'stickyweb'];
for (const condition of sideConditions) {
if (pokemon.hp && pokemon.side.removeSideCondition(condition)) {
this.add('-sideend', pokemon.side, this.getEffect(condition).name, '[from] move: Rapid Spin', '[of] ' + pokemon);
this.add('-sideend', pokemon.side, this.dex.getEffect(condition).name, '[from] move: Rapid Spin', '[of] ' + pokemon);
}
}
if (pokemon.hp && pokemon.volatiles['partiallytrapped']) {
@ -13341,7 +13341,7 @@ let BattleMovedex = {
if (pokemon.item || !pokemon.lastItem) return false;
let item = pokemon.lastItem;
pokemon.lastItem = '';
this.add('-item', pokemon, this.getItem(item), '[from] move: Recycle');
this.add('-item', pokemon, this.dex.getItem(item), '[from] move: Recycle');
pokemon.setItem(item);
},
secondary: null,
@ -13880,7 +13880,7 @@ let BattleMovedex = {
onHit(target, source) {
let oldAbility = source.setAbility(target.ability);
if (oldAbility) {
this.add('-ability', source, this.getAbility(source.ability).name, '[from] move: Role Play', '[of] ' + target);
this.add('-ability', source, this.dex.getAbility(source.ability).name, '[from] move: Role Play', '[of] ' + target);
return;
}
return false;
@ -15066,7 +15066,7 @@ let BattleMovedex = {
if (source.transformed || !target.lastMove || disallowedMoves.includes(target.lastMove.id) || source.moves.indexOf(target.lastMove.id) >= 0 || target.lastMove.isZ) return false;
let sketchIndex = source.moves.indexOf('sketch');
if (sketchIndex < 0) return false;
let move = this.getMove(target.lastMove);
let move = this.dex.getMove(target.lastMove);
let sketchedMove = {
move: move.name,
id: move.id,
@ -15105,8 +15105,8 @@ let BattleMovedex = {
}
},
onHit(target, source, move) {
let targetAbility = this.getAbility(target.ability);
let sourceAbility = this.getAbility(source.ability);
let targetAbility = this.dex.getAbility(target.ability);
let sourceAbility = this.dex.getAbility(source.ability);
if (target.side === source.side) {
this.add('-activate', source, 'move: Skill Swap', '', '', '[of] ' + target);
} else {
@ -15424,7 +15424,7 @@ let BattleMovedex = {
const noSleepTalk = [
'assist', 'beakblast', 'belch', 'bide', 'celebrate', 'chatter', 'copycat', 'focuspunch', 'mefirst', 'metronome', 'mimic', 'mirrormove', 'naturepower', 'shelltrap', 'sketch', 'sleeptalk', 'uproar',
];
if (move && !(noSleepTalk.includes(move) || this.getMove(move).flags['charge'] || (this.getMove(move).isZ && this.getMove(move).basePower !== 1))) {
if (move && !(noSleepTalk.includes(move) || this.dex.getMove(move).flags['charge'] || (this.dex.getMove(move).isZ && this.dex.getMove(move).basePower !== 1))) {
moves.push(move);
}
}
@ -16231,7 +16231,7 @@ let BattleMovedex = {
if (target.lastMove && !target.lastMove.isZ) {
let ppDeducted = target.deductPP(target.lastMove.id, 4);
if (ppDeducted) {
this.add("-activate", target, 'move: Spite', this.getMove(target.lastMove.id).name, ppDeducted);
this.add("-activate", target, 'move: Spite', this.dex.getMove(target.lastMove.id).name, ppDeducted);
return;
}
}
@ -16381,7 +16381,7 @@ let BattleMovedex = {
this.add('-sidestart', side, 'move: Stealth Rock');
},
onSwitchIn(pokemon) {
let typeMod = this.clampIntRange(pokemon.runEffectiveness(this.getActiveMove('stealthrock')), -6, 6);
let typeMod = this.dex.clampIntRange(pokemon.runEffectiveness(this.dex.getActiveMove('stealthrock')), -6, 6);
this.damage(pokemon.maxhp * Math.pow(2, typeMod) / 8);
},
},
@ -16481,7 +16481,7 @@ let BattleMovedex = {
onSwitchIn(pokemon) {
if (!pokemon.isGrounded()) return;
this.add('-activate', pokemon, 'move: Sticky Web');
this.boost({spe: -1}, pokemon, pokemon.side.foe.active[0], this.getActiveMove('stickyweb'));
this.boost({spe: -1}, pokemon, pokemon.side.foe.active[0], this.dex.getActiveMove('stickyweb'));
},
},
secondary: null,
@ -16989,7 +16989,7 @@ let BattleMovedex = {
accuracy: 90,
basePower: 0,
damageCallback(pokemon, target) {
return this.clampIntRange(Math.floor(target.hp / 2), 1);
return this.dex.clampIntRange(Math.floor(target.hp / 2), 1);
},
category: "Physical",
desc: "Deals damage to the target equal to half of its current HP, rounded down, but not less than 1 HP.",
@ -17486,7 +17486,7 @@ let BattleMovedex = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.id).category === 'Status') {
if (this.dex.getMove(moveSlot.id).category === 'Status') {
pokemon.disableMove(moveSlot.id);
}
}
@ -17780,7 +17780,7 @@ let BattleMovedex = {
},
onDisableMove(pokemon) {
for (const moveSlot of pokemon.moveSlots) {
if (this.getMove(moveSlot.id).flags['sound']) {
if (this.dex.getMove(moveSlot.id).flags['sound']) {
pokemon.disableMove(moveSlot.id);
}
}

View File

@ -27,14 +27,15 @@ const randomFactorySets = require('./factory-sets.json');
* @property {number} [eeveeLimCount]
*/
class RandomTeams extends Dex.ModdedDex {
class RandomTeams {
/**
* @param {Format | string} format
* @param {?PRNG | [number, number, number, number]} [prng]
*/
constructor(format, prng) {
format = Dex.getFormat(format);
super(format.mod);
this.dex = Dex.forFormat(format);
this.gen = this.dex.gen;
this.randomBSSFactorySets = randomBSSFactorySets;
this.randomFactorySets = randomFactorySets;
@ -125,7 +126,7 @@ class RandomTeams extends Dex.ModdedDex {
// No randomization, no choice. We are just checking its existence.
// Returns a Pokémon template for further details.
if (!template.otherFormes) return null;
let firstForme = this.getTemplate(template.otherFormes[0]);
let firstForme = this.dex.getTemplate(template.otherFormes[0]);
if (firstForme.isMega || firstForme.isPrimal) return firstForme;
return null;
}
@ -149,7 +150,7 @@ class RandomTeams extends Dex.ModdedDex {
// }
// hasMegaEvo(template) {
// if (!template.otherFormes) return false;
// let firstForme = this.getTemplate(template.otherFormes[0]);
// let firstForme = this.dex.getTemplate(template.otherFormes[0]);
// return !!firstForme.isMega;
// }
/**
@ -158,8 +159,8 @@ class RandomTeams extends Dex.ModdedDex {
randomCCTeam() {
let team = [];
let natures = Object.keys(this.data.Natures);
let items = Object.keys(this.data.Items);
let natures = Object.keys(this.dex.data.Natures);
let items = Object.keys(this.dex.data.Items);
let random6 = this.random6Pokemon();
@ -172,7 +173,7 @@ class RandomTeams extends Dex.ModdedDex {
if (this.gen >= 2) {
do {
item = this.sample(items);
} while (this.getItem(item).gen > this.gen || this.data.Items[item].isNonstandard);
} while (this.dex.getItem(item).gen > this.gen || this.dex.data.Items[item].isNonstandard);
}
// Make sure forme is legal
@ -182,16 +183,16 @@ class RandomTeams extends Dex.ModdedDex {
}
// Make sure that a base forme does not hold any forme-modifier items.
let itemData = this.getItem(item);
if (itemData.forcedForme && species === this.getTemplate(itemData.forcedForme).baseSpecies) {
let itemData = this.dex.getItem(item);
if (itemData.forcedForme && species === this.dex.getTemplate(itemData.forcedForme).baseSpecies) {
do {
item = this.sample(items);
itemData = this.getItem(item);
} while (itemData.gen > this.gen || itemData.isNonstandard || itemData.forcedForme && species === this.getTemplate(itemData.forcedForme).baseSpecies);
itemData = this.dex.getItem(item);
} while (itemData.gen > this.gen || itemData.isNonstandard || itemData.forcedForme && species === this.dex.getTemplate(itemData.forcedForme).baseSpecies);
}
// Random legal ability
let abilities = Object.values(template.abilities).filter(a => this.getAbility(a).gen <= this.gen);
let abilities = Object.values(template.abilities).filter(a => this.dex.getAbility(a).gen <= this.gen);
/**@type {string} */
// @ts-ignore
let ability = this.gen <= 2 ? 'None' : this.sample(abilities);
@ -200,16 +201,16 @@ class RandomTeams extends Dex.ModdedDex {
let moves;
let pool = ['struggle'];
if (species === 'Smeargle') {
pool = Object.keys(this.data.Movedex).filter(moveid => !(['chatter', 'struggle', 'paleowave', 'shadowstrike', 'magikarpsrevenge'].includes(moveid) || this.data.Movedex[moveid].isZ || this.data.Movedex[moveid].id === 'hiddenpower' && moveid !== 'hiddenpower'));
pool = Object.keys(this.dex.data.Movedex).filter(moveid => !(['chatter', 'struggle', 'paleowave', 'shadowstrike', 'magikarpsrevenge'].includes(moveid) || this.dex.data.Movedex[moveid].isZ || this.dex.data.Movedex[moveid].id === 'hiddenpower' && moveid !== 'hiddenpower'));
} else if (template.learnset) {
// @ts-ignore
pool = Object.keys(template.learnset).filter(moveid => template.learnset[moveid].find(learned => learned.startsWith(this.gen)));
if (template.species.substr(0, 6) === 'Rotom-') {
const learnset = this.getTemplate(template.baseSpecies).learnset;
const learnset = this.dex.getTemplate(template.baseSpecies).learnset;
if (learnset) pool = [...new Set(pool.concat(Object.keys(learnset)))];
}
} else {
const learnset = this.getTemplate(template.baseSpecies).learnset;
const learnset = this.dex.getTemplate(template.baseSpecies).learnset;
// @ts-ignore
if (learnset) pool = Object.keys(learnset).filter(moveid => learnset[moveid].find(learned => learned.startsWith(this.gen)));
}
@ -309,9 +310,9 @@ class RandomTeams extends Dex.ModdedDex {
/**@type {string[][]} */
let formes = [[], [], [], [], [], []];
for (let id in this.data.Pokedex) {
if (!(this.data.Pokedex[id].num in hasDexNumber)) continue;
let template = this.getTemplate(id);
for (let id in this.dex.data.Pokedex) {
if (!(this.dex.data.Pokedex[id].num in hasDexNumber)) continue;
let template = this.dex.getTemplate(id);
if (template.gen <= this.gen && template.species !== 'Pichu-Spiky-eared' && template.species.substr(0, 8) !== 'Pikachu-') {
formes[hasDexNumber[template.num]].push(template.species);
}
@ -330,23 +331,23 @@ class RandomTeams extends Dex.ModdedDex {
randomHCTeam() {
let team = [];
let itemPool = Object.keys(this.data.Items);
let abilityPool = Object.keys(this.data.Abilities);
let movePool = Object.keys(this.data.Movedex);
let naturePool = Object.keys(this.data.Natures);
let itemPool = Object.keys(this.dex.data.Items);
let abilityPool = Object.keys(this.dex.data.Abilities);
let movePool = Object.keys(this.dex.data.Movedex);
let naturePool = Object.keys(this.dex.data.Natures);
let random6 = this.random6Pokemon();
for (let i = 0; i < 6; i++) {
// Choose forme
let template = this.getTemplate(random6[i]);
let template = this.dex.getTemplate(random6[i]);
// Random unique item
let item = '';
if (this.gen >= 2) {
do {
item = this.sampleNoReplace(itemPool);
} while (this.getItem(item).gen > this.gen || this.data.Items[item].isNonstandard);
} while (this.dex.getItem(item).gen > this.gen || this.dex.data.Items[item].isNonstandard);
}
// Random unique ability
@ -354,14 +355,14 @@ class RandomTeams extends Dex.ModdedDex {
if (this.gen >= 3) {
do {
ability = this.sampleNoReplace(abilityPool);
} while (this.getAbility(ability).gen > this.gen || this.data.Abilities[ability].isNonstandard);
} while (this.dex.getAbility(ability).gen > this.gen || this.dex.data.Abilities[ability].isNonstandard);
}
// Random unique moves
let m = [];
do {
let moveid = this.sampleNoReplace(movePool);
if (this.getMove(moveid).gen <= this.gen && !this.data.Movedex[moveid].isNonstandard && (moveid === 'hiddenpower' || moveid.substr(0, 11) !== 'hiddenpower')) {
if (this.dex.getMove(moveid).gen <= this.gen && !this.dex.data.Movedex[moveid].isNonstandard && (moveid === 'hiddenpower' || moveid.substr(0, 11) !== 'hiddenpower')) {
m.push(moveid);
}
} while (m.length < 4);
@ -499,7 +500,7 @@ class RandomTeams extends Dex.ModdedDex {
// Iterate through all moves we've chosen so far and keep track of what they do:
for (const [k, moveId] of moves.entries()) {
let move = this.getMove(moveId);
let move = this.dex.getMove(moveId);
let moveid = move.id;
let movetype = move.type;
if (['judgment', 'multiattack', 'revelationdance'].includes(moveid)) movetype = Object.keys(hasType)[0];
@ -571,7 +572,7 @@ class RandomTeams extends Dex.ModdedDex {
// Keep track of the available moves
for (const moveid of movePool) {
let move = this.getMove(moveid);
let move = this.dex.getMove(moveid);
if (move.damageCallback) continue;
if (move.category === 'Physical') counter['physicalpool']++;
if (move.category === 'Special') counter['specialpool']++;
@ -611,13 +612,13 @@ class RandomTeams extends Dex.ModdedDex {
* @return {RandomTeamsTypes.RandomSet}
*/
randomSet(template, teamDetails = {}, isLead = false, isDoubles = false) {
template = this.getTemplate(template);
template = this.dex.getTemplate(template);
let baseTemplate = template;
let species = template.species;
if (!template.exists || ((!isDoubles || !template.randomDoubleBattleMoves) && !template.randomBattleMoves && !template.learnset)) {
// GET IT? UNOWN? BECAUSE WE CAN'T TELL WHAT THE POKEMON IS
template = this.getTemplate('unown');
template = this.dex.getTemplate('unown');
let err = new Error('Template incompatible with random battles: ' + species);
Monitor.crashlog(err, 'The randbat set generator');
@ -629,7 +630,7 @@ class RandomTeams extends Dex.ModdedDex {
}
let battleForme = this.checkBattleForme(template);
if (battleForme && battleForme.randomBattleMoves && template.otherFormes && (battleForme.isMega ? !teamDetails.megaStone : this.random(2))) {
template = this.getTemplate(template.otherFormes.length >= 2 ? this.sample(template.otherFormes) : template.otherFormes[0]);
template = this.dex.getTemplate(template.otherFormes.length >= 2 ? this.sample(template.otherFormes) : template.otherFormes[0]);
}
const randMoves = !isDoubles ? template.randomBattleMoves : template.randomDoubleBattleMoves || template.randomBattleMoves;
@ -720,7 +721,7 @@ class RandomTeams extends Dex.ModdedDex {
// Iterate through the moves again, this time to cull them:
for (const [k, moveId] of moves.entries()) {
let move = this.getMove(moveId);
let move = this.dex.getMove(moveId);
let moveid = move.id;
let rejected = false;
let isSetup = false;
@ -1214,10 +1215,10 @@ class RandomTeams extends Dex.ModdedDex {
/**@type {[string, string | undefined, string | undefined]} */
// @ts-ignore
let abilities = Object.values(baseTemplate.abilities);
abilities.sort((a, b) => this.getAbility(b).rating - this.getAbility(a).rating);
let ability0 = this.getAbility(abilities[0]);
let ability1 = this.getAbility(abilities[1]);
let ability2 = this.getAbility(abilities[2]);
abilities.sort((a, b) => this.dex.getAbility(b).rating - this.dex.getAbility(a).rating);
let ability0 = this.dex.getAbility(abilities[0]);
let ability1 = this.dex.getAbility(abilities[1]);
let ability2 = this.dex.getAbility(abilities[2]);
if (abilities[1]) {
if (abilities[2] && ability1.rating <= ability2.rating && this.randomChance(1, 2)) {
[ability1, ability2] = [ability2, ability1];
@ -1399,7 +1400,7 @@ class RandomTeams extends Dex.ModdedDex {
item = 'Ultranecrozium Z';
if (!hasMove['photongeyser']) {
for (const moveid of moves) {
let move = this.getMove(moveid);
let move = this.dex.getMove(moveid);
if (move.category === 'Status' || hasType[move.type]) continue;
moves[moves.indexOf(moveid)] = 'photongeyser';
break;
@ -1528,17 +1529,17 @@ class RandomTeams extends Dex.ModdedDex {
item = 'Lum Berry';
} else if (isDoubles && counter.damagingMoves.length >= 4 && template.baseStats.spe >= 60 && !hasMove['fakeout'] && !hasMove['flamecharge'] && !hasMove['suckerpunch'] && ability !== 'Multiscale' && ability !== 'Sturdy') {
item = 'Life Orb';
} else if (isDoubles && this.getEffectiveness('Ice', template) >= 2) {
} else if (isDoubles && this.dex.getEffectiveness('Ice', template) >= 2) {
item = 'Yache Berry';
} else if (isDoubles && this.getEffectiveness('Rock', template) >= 2) {
} else if (isDoubles && this.dex.getEffectiveness('Rock', template) >= 2) {
item = 'Charti Berry';
} else if (isDoubles && this.getEffectiveness('Fire', template) >= 2) {
} else if (isDoubles && this.dex.getEffectiveness('Fire', template) >= 2) {
item = 'Occa Berry';
} else if (isDoubles && this.getImmunity('Fighting', template) && this.getEffectiveness('Fighting', template) >= 2) {
} else if (isDoubles && this.dex.getImmunity('Fighting', template) && this.dex.getEffectiveness('Fighting', template) >= 2) {
item = 'Chople Berry';
} else if (hasMove['substitute']) {
item = counter.damagingMoves.length > 2 && !!counter['drain'] ? 'Life Orb' : 'Leftovers';
} else if (this.getEffectiveness('Ground', template) >= 2 && ability !== 'Levitate' && !hasMove['magnetrise']) {
} else if (this.dex.getEffectiveness('Ground', template) >= 2 && ability !== 'Levitate' && !hasMove['magnetrise']) {
item = 'Air Balloon';
} else if ((ability === 'Iron Barbs' || ability === 'Rough Skin') && this.randomChance(1, 2)) {
item = 'Rocky Helmet';
@ -1609,7 +1610,7 @@ class RandomTeams extends Dex.ModdedDex {
// Every 10.34 BST adds a level from 70 up to 99. Results are floored. Uses the Mega's stats if holding a Mega Stone
let baseStats = template.baseStats;
// If Wishiwashi, use the school-forme's much higher stats
if (template.baseSpecies === 'Wishiwashi') baseStats = this.getTemplate('wishiwashischool').baseStats;
if (template.baseSpecies === 'Wishiwashi') baseStats = this.dex.getTemplate('wishiwashischool').baseStats;
let bst = baseStats.hp + baseStats.atk + baseStats.def + baseStats.spa + baseStats.spd + baseStats.spe;
// Adjust levels of mons based on abilities (Pure Power, Sheer Force, etc.) and also Eviolite
@ -1633,7 +1634,7 @@ class RandomTeams extends Dex.ModdedDex {
} else if (item === 'Light Ball') {
bst += baseStats.atk + baseStats.spa;
}
level = 70 + Math.floor(((600 - this.clampIntRange(bst, 300, 600)) / 10.34));
level = 70 + Math.floor(((600 - this.dex.clampIntRange(bst, 300, 600)) / 10.34));
}
if (template.species === 'Stunfisk') {
@ -1644,7 +1645,7 @@ class RandomTeams extends Dex.ModdedDex {
}
// Prepare optimal HP
let srWeakness = this.getEffectiveness('Rock', template);
let srWeakness = this.dex.getEffectiveness('Rock', template);
while (evs.hp > 1) {
let hp = Math.floor(Math.floor(2 * template.baseStats.hp + ivs.hp + Math.floor(evs.hp / 4) + 100) * level / 100 + 10);
if (hasMove['substitute'] && hasMove['reversal']) {
@ -1703,12 +1704,12 @@ class RandomTeams extends Dex.ModdedDex {
const allowedNFE = ['Chansey', 'Doublade', 'Gligar', 'Pikachu', 'Porygon2', 'Scyther', 'Type: Null'];
const exclude = pokemon.map(p => toID(p.species));
const pokemonPool = [];
for (let id in this.data.FormatsData) {
let template = this.getTemplate(id);
for (let id in this.dex.data.FormatsData) {
let template = this.dex.getTemplate(id);
if (exclude.includes(template.id)) continue;
if (isMonotype) {
let types = template.types;
if (template.battleOnly) types = this.getTemplate(template.baseSpecies).types;
if (template.battleOnly) types = this.dex.getTemplate(template.baseSpecies).types;
if (types.indexOf(type) < 0) continue;
}
if (template.gen <= this.gen && (!template.nfe || allowedNFE.includes(template.species)) && !template.isMega && !template.isPrimal && !template.isNonstandard && template.randomBattleMoves) {
@ -1724,13 +1725,13 @@ class RandomTeams extends Dex.ModdedDex {
// For Monotype
let isMonotype = this.format.id === 'gen7monotyperandombattle';
let typePool = Object.keys(this.data.TypeChart);
let typePool = Object.keys(this.dex.data.TypeChart);
let type = this.sample(typePool);
// PotD stuff
let potd;
if (global.Config && Config.potd && this.getRuleTable(this.getFormat()).has('potd')) {
potd = this.getTemplate(Config.potd);
if (global.Config && Config.potd && this.dex.getRuleTable(this.format).has('potd')) {
potd = this.dex.getTemplate(Config.potd);
}
/**@type {{[k: string]: number}} */
@ -1750,7 +1751,7 @@ class RandomTeams extends Dex.ModdedDex {
if (pokemon.length >= 6) break;
const pokemonPool = this.getPokemonPool(type, pokemon, isMonotype);
while (pokemonPool.length && pokemon.length < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
// Limit to one of each species (Species Clause)
@ -1820,7 +1821,7 @@ class RandomTeams extends Dex.ModdedDex {
}
}
let item = this.getItem(set.item);
let item = this.dex.getItem(set.item);
// Limit 1 Z-Move per team
if (item.zMove && teamDetails['zMove']) continue;
@ -1904,12 +1905,12 @@ class RandomTeams extends Dex.ModdedDex {
let effectivePool = [];
let priorityPool = [];
for (const curSet of setList) {
let item = this.getItem(curSet.item);
let item = this.dex.getItem(curSet.item);
if (teamData.megaCount > 0 && item.megaStone) continue; // reject 2+ mega stones
if (teamData.zCount && teamData.zCount > 0 && item.zMove) continue; // reject 2+ Z stones
if (itemsMax[item.id] && teamData.has[item.id] >= itemsMax[item.id]) continue;
let ability = this.getAbility(curSet.ability);
let ability = this.dex.getAbility(curSet.ability);
// @ts-ignore
if (weatherAbilitiesRequire[ability.id] && teamData.weather !== weatherAbilitiesRequire[ability.id]) continue;
if (teamData.weather && weatherAbilities.includes(ability.id)) continue; // reject 2+ weather setters
@ -1996,7 +1997,7 @@ class RandomTeams extends Dex.ModdedDex {
let pokemon = [];
let pokemonPool = Object.keys(this.randomFactorySets[chosenTier]);
let typePool = Object.keys(this.data.TypeChart);
let typePool = Object.keys(this.dex.data.TypeChart);
const type = this.sample(typePool);
/**@type {TeamData} */
@ -2017,7 +2018,7 @@ class RandomTeams extends Dex.ModdedDex {
};
while (pokemonPool.length && pokemon.length < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
// Lessen the need of deleting sets of Pokemon after tier shifts
@ -2034,7 +2035,7 @@ class RandomTeams extends Dex.ModdedDex {
let set = this.randomFactorySet(template, pokemon.length, teamData, chosenTier);
if (!set) continue;
let itemData = this.getItem(set.item);
let itemData = this.dex.getItem(set.item);
// Actually limit the number of Megas to one
if (teamData.megaCount >= 1 && itemData.megaStone) continue;
@ -2048,7 +2049,7 @@ class RandomTeams extends Dex.ModdedDex {
if (chosenTier === 'Mono') {
// Prevents Mega Evolutions from breaking the type limits
if (itemData.megaStone) {
let megaTemplate = this.getTemplate(itemData.megaStone);
let megaTemplate = this.dex.getTemplate(itemData.megaStone);
if (types.length > megaTemplate.types.length) types = [template.types[0]];
// Only check the second type because a Mega Evolution should always share the first type with its base forme.
if (megaTemplate.types[1] && types[1] && megaTemplate.types[1] !== types[1]) {
@ -2099,7 +2100,7 @@ class RandomTeams extends Dex.ModdedDex {
teamData.has[itemData.id] = 1;
}
let abilityData = this.getAbility(set.ability);
let abilityData = this.dex.getAbility(set.ability);
if (abilityData.id in weatherAbilitiesSet) {
teamData.weather = weatherAbilitiesSet[abilityData.id];
}
@ -2116,16 +2117,16 @@ class RandomTeams extends Dex.ModdedDex {
}
}
for (let typeName in this.data.TypeChart) {
for (let typeName in this.dex.data.TypeChart) {
// Cover any major weakness (3+) with at least one resistance
if (teamData.resistances[typeName] >= 1) continue;
if (resistanceAbilities[abilityData.id] && resistanceAbilities[abilityData.id].includes(typeName) || !this.getImmunity(typeName, types)) {
if (resistanceAbilities[abilityData.id] && resistanceAbilities[abilityData.id].includes(typeName) || !this.dex.getImmunity(typeName, types)) {
// Heuristic: assume that Pokémon with these abilities don't have (too) negative typing.
teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
if (teamData.resistances[typeName] >= 1) teamData.weaknesses[typeName] = 0;
continue;
}
let typeMod = this.getEffectiveness(typeName, types);
let typeMod = this.dex.getEffectiveness(typeName, types);
if (typeMod < 0) {
teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
if (teamData.resistances[typeName] >= 1) teamData.weaknesses[typeName] = 0;
@ -2177,12 +2178,12 @@ class RandomTeams extends Dex.ModdedDex {
let effectivePool = [];
let priorityPool = [];
for (const curSet of setList) {
let item = this.getItem(curSet.item);
let item = this.dex.getItem(curSet.item);
if (teamData.megaCount > 1 && item.megaStone) continue; // reject 3+ mega stones
if (teamData.zCount && teamData.zCount > 1 && item.zMove) continue; // reject 3+ Z stones
if (teamData.has[item.id]) continue; // Item clause
let ability = this.getAbility(curSet.ability);
let ability = this.dex.getAbility(curSet.ability);
if (weatherAbilitiesRequire[ability.id] && teamData.weather !== weatherAbilitiesRequire[ability.id]) continue;
if (teamData.weather && weatherAbilities.includes(ability.id)) continue; // reject 2+ weather setters
@ -2268,7 +2269,7 @@ class RandomTeams extends Dex.ModdedDex {
};
while (pokemonPool.length && pokemon.length < 6) {
let template = this.getTemplate(this.sampleNoReplace(pokemonPool));
let template = this.dex.getTemplate(this.sampleNoReplace(pokemonPool));
if (!template.exists) continue;
let speciesFlags = this.randomBSSFactorySets[template.speciesid].flags;
@ -2321,12 +2322,12 @@ class RandomTeams extends Dex.ModdedDex {
teamData.baseFormes[template.baseSpecies] = 1;
// Limit Mega and Z-move
let itemData = this.getItem(set.item);
let itemData = this.dex.getItem(set.item);
if (itemData.megaStone) teamData.megaCount++;
if (itemData.zMove) teamData.zCount++;
teamData.has[itemData.id] = 1;
let abilityData = this.getAbility(set.ability);
let abilityData = this.dex.getAbility(set.ability);
if (abilityData.id in weatherAbilitiesSet) {
teamData.weather = weatherAbilitiesSet[abilityData.id];
}
@ -2343,16 +2344,16 @@ class RandomTeams extends Dex.ModdedDex {
}
}
for (let typeName in this.data.TypeChart) {
for (let typeName in this.dex.data.TypeChart) {
// Cover any major weakness (3+) with at least one resistance
if (teamData.resistances[typeName] >= 1) continue;
if (resistanceAbilities[abilityData.id] && resistanceAbilities[abilityData.id].includes(typeName) || !this.getImmunity(typeName, types)) {
if (resistanceAbilities[abilityData.id] && resistanceAbilities[abilityData.id].includes(typeName) || !this.dex.getImmunity(typeName, types)) {
// Heuristic: assume that Pokémon with these abilities don't have (too) negative typing.
teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
if (teamData.resistances[typeName] >= 1) teamData.weaknesses[typeName] = 0;
continue;
}
let typeMod = this.getEffectiveness(typeName, types);
let typeMod = this.dex.getEffectiveness(typeName, types);
if (typeMod < 0) {
teamData.resistances[typeName] = (teamData.resistances[typeName] || 0) + 1;
if (teamData.resistances[typeName] >= 1) teamData.weaknesses[typeName] = 0;

View File

@ -136,7 +136,7 @@ let BattleFormats = {
desc: "Validate all obtainability things that aren't moves/abilities (Hidden Power type, gender, stats, etc).",
// Mostly hardcoded in team-validator.ts
onChangeSet(set) {
let template = this.getTemplate(set.species);
let template = this.dex.getTemplate(set.species);
if (template.gender) {
if (set.gender !== template.gender) {
@ -154,7 +154,7 @@ let BattleFormats = {
/**@type {{[k: string]: true}} */
let hasMove = {};
for (const moveId of set.moves) {
let move = this.getMove(moveId);
let move = this.dex.getMove(moveId);
let moveid = move.id;
if (hasMove[moveid]) continue;
hasMove[moveid] = true;
@ -172,8 +172,8 @@ let BattleFormats = {
let hoennDex = [
"Abra", "Absol", "Aggron", "Alakazam", "Altaria", "Anorith", "Armaldo", "Aron", "Azumarill", "Azurill", "Bagon", "Baltoy", "Banette", "Barboach", "Beautifly", "Beldum", "Bellossom", "Blaziken", "Breloom", "Budew", "Cacnea", "Cacturne", "Camerupt", "Carvanha", "Cascoon", "Castform", "Chimecho", "Chinchou", "Chingling", "Clamperl", "Claydol", "Combusken", "Corphish", "Corsola", "Cradily", "Crawdaunt", "Crobat", "Delcatty", "Dodrio", "Doduo", "Donphan", "Dusclops", "Dusknoir", "Duskull", "Dustox", "Electrike", "Electrode", "Exploud", "Feebas", "Flygon", "Froslass", "Gallade", "Gardevoir", "Geodude", "Girafarig", "Glalie", "Gloom", "Golbat", "Goldeen", "Golduck", "Golem", "Gorebyss", "Graveler", "Grimer", "Grovyle", "Grumpig", "Gulpin", "Gyarados", "Hariyama", "Heracross", "Horsea", "Huntail", "Igglybuff", "Illumise", "Jigglypuff", "Kadabra", "Kecleon", "Kingdra", "Kirlia", "Koffing", "Lairon", "Lanturn", "Latias", "Latios", "Lileep", "Linoone", "Lombre", "Lotad", "Loudred", "Ludicolo", "Lunatone", "Luvdisc", "Machamp", "Machoke", "Machop", "Magcargo", "Magikarp", "Magnemite", "Magneton", "Magnezone", "Makuhita", "Manectric", "Marill", "Marshtomp", "Masquerain", "Mawile", "Medicham", "Meditite", "Metagross", "Metang", "Mightyena", "Milotic", "Minun", "Mudkip", "Muk", "Natu", "Nincada", "Ninetales", "Ninjask", "Nosepass", "Numel", "Nuzleaf", "Oddish", "Pelipper", "Phanpy", "Pichu", "Pikachu", "Pinsir", "Plusle", "Poochyena", "Probopass", "Psyduck", "Raichu", "Ralts", "Regice", "Regirock", "Registeel", "Relicanth", "Rhydon", "Rhyhorn", "Rhyperior", "Roselia", "Roserade", "Sableye", "Salamence", "Sandshrew", "Sandslash", "Sceptile", "Seadra", "Seaking", "Sealeo", "Seedot", "Seviper", "Sharpedo", "Shedinja", "Shelgon", "Shiftry", "Shroomish", "Shuppet", "Silcoon", "Skarmory", "Skitty", "Slaking", "Slakoth", "Slugma", "Snorunt", "Solrock", "Spheal", "Spinda", "Spoink", "Starmie", "Staryu", "Surskit", "Swablu", "Swalot", "Swampert", "Swellow", "Taillow", "Tentacool", "Tentacruel", "Torchic", "Torkoal", "Trapinch", "Treecko", "Tropius", "Vibrava", "Vigoroth", "Vileplume", "Volbeat", "Voltorb", "Vulpix", "Wailmer", "Wailord", "Walrein", "Weezing", "Whiscash", "Whismur", "Wigglytuff", "Wingull", "Wobbuffet", "Wurmple", "Wynaut", "Xatu", "Zangoose", "Zigzagoon", "Zubat",
];
let template = this.getTemplate(set.species || set.name);
if (!hoennDex.includes(template.baseSpecies) && !this.getRuleTable(format).has('+' + template.speciesid)) {
let template = this.dex.getTemplate(set.species || set.name);
if (!hoennDex.includes(template.baseSpecies) && !this.ruleTable.has('+' + template.speciesid)) {
return [template.baseSpecies + " is not in the Hoenn Pokédex."];
}
},
@ -186,8 +186,8 @@ let BattleFormats = {
let sinnohDex = [
"Turtwig", "Grotle", "Torterra", "Chimchar", "Monferno", "Infernape", "Piplup", "Prinplup", "Empoleon", "Starly", "Staravia", "Staraptor", "Bidoof", "Bibarel", "Kricketot", "Kricketune", "Shinx", "Luxio", "Luxray", "Abra", "Kadabra", "Alakazam", "Magikarp", "Gyarados", "Budew", "Roselia", "Roserade", "Zubat", "Golbat", "Crobat", "Geodude", "Graveler", "Golem", "Onix", "Steelix", "Cranidos", "Rampardos", "Shieldon", "Bastiodon", "Machop", "Machoke", "Machamp", "Psyduck", "Golduck", "Burmy", "Wormadam", "Mothim", "Wurmple", "Silcoon", "Beautifly", "Cascoon", "Dustox", "Combee", "Vespiquen", "Pachirisu", "Buizel", "Floatzel", "Cherubi", "Cherrim", "Shellos", "Gastrodon", "Heracross", "Aipom", "Ambipom", "Drifloon", "Drifblim", "Buneary", "Lopunny", "Gastly", "Haunter", "Gengar", "Misdreavus", "Mismagius", "Murkrow", "Honchkrow", "Glameow", "Purugly", "Goldeen", "Seaking", "Barboach", "Whiscash", "Chingling", "Chimecho", "Stunky", "Skuntank", "Meditite", "Medicham", "Bronzor", "Bronzong", "Ponyta", "Rapidash", "Bonsly", "Sudowoodo", "Mime Jr.", "Mr. Mime", "Happiny", "Chansey", "Blissey", "Cleffa", "Clefairy", "Clefable", "Chatot", "Pichu", "Pikachu", "Raichu", "Hoothoot", "Noctowl", "Spiritomb", "Gible", "Gabite", "Garchomp", "Munchlax", "Snorlax", "Unown", "Riolu", "Lucario", "Wooper", "Quagsire", "Wingull", "Pelipper", "Girafarig", "Hippopotas", "Hippowdon", "Azurill", "Marill", "Azumarill", "Skorupi", "Drapion", "Croagunk", "Toxicroak", "Carnivine", "Remoraid", "Octillery", "Finneon", "Lumineon", "Tentacool", "Tentacruel", "Feebas", "Milotic", "Mantyke", "Mantine", "Snover", "Abomasnow", "Sneasel", "Weavile", "Uxie", "Mesprit", "Azelf", "Dialga", "Palkia", "Manaphy", "Rotom", "Gligar", "Gliscor", "Nosepass", "Probopass", "Ralts", "Kirlia", "Gardevoir", "Gallade", "Lickitung", "Lickilicky", "Eevee", "Vaporeon", "Jolteon", "Flareon", "Espeon", "Umbreon", "Leafeon", "Glaceon", "Swablu", "Altaria", "Togepi", "Togetic", "Togekiss", "Houndour", "Houndoom", "Magnemite", "Magneton", "Magnezone", "Tangela", "Tangrowth", "Yanma", "Yanmega", "Tropius", "Rhyhorn", "Rhydon", "Rhyperior", "Duskull", "Dusclops", "Dusknoir", "Porygon", "Porygon2", "Porygon-Z", "Scyther", "Scizor", "Elekid", "Electabuzz", "Electivire", "Magby", "Magmar", "Magmortar", "Swinub", "Piloswine", "Mamoswine", "Snorunt", "Glalie", "Froslass", "Absol", "Giratina",
];
let template = this.getTemplate(set.species || set.name);
if ((!sinnohDex.includes(template.baseSpecies) || template.gen > 4) && !this.getRuleTable(format).has('+' + template.speciesid)) {
let template = this.dex.getTemplate(set.species || set.name);
if ((!sinnohDex.includes(template.baseSpecies) || template.gen > 4) && !this.ruleTable.has('+' + template.speciesid)) {
return [`${template.species} is not in the Sinnoh Pokédex.`];
}
},
@ -202,8 +202,8 @@ let BattleFormats = {
"Drifloon", "Drifblim", "Mienfoo", "Mienshao", "Zangoose", "Seviper", "Spoink", "Grumpig", "Absol", "Inkay", "Malamar", "Lunatone", "Solrock", "Bagon", "Shelgon", "Salamence", "Wingull", "Pelipper", "Taillow", "Swellow", "Binacle", "Barbaracle", "Dwebble", "Crustle", "Tentacool", "Tentacruel", "Wailmer", "Wailord", "Luvdisc", "Skrelp", "Dragalge", "Clauncher", "Clawitzer", "Staryu", "Starmie", "Shellder", "Cloyster", "Qwilfish", "Horsea", "Seadra", "Kingdra", "Relicanth", "Sandile", "Krokorok", "Krookodile", "Helioptile", "Heliolisk", "Hippopotas", "Hippowdon", "Rhyhorn", "Rhydon", "Rhyperior", "Onix", "Steelix", "Woobat", "Swoobat", "Machop", "Machoke", "Machamp", "Cubone", "Marowak", "Kangaskhan", "Mawile", "Tyrunt", "Tyrantrum", "Amaura", "Aurorus", "Aerodactyl", "Ferroseed", "Ferrothorn", "Snubbull", "Granbull", "Electrike", "Manectric", "Houndour", "Houndoom", "Eevee", "Vaporeon", "Jolteon", "Flareon", "Espeon", "Umbreon", "Leafeon", "Glaceon", "Sylveon", "Emolga", "Yanma", "Yanmega", "Hawlucha", "Sigilyph", "Golett", "Golurk", "Nosepass", "Probopass", "Makuhita", "Hariyama", "Throh", "Sawk", "Starly", "Staravia", "Staraptor", "Stunky", "Skuntank", "Nidoran-F", "Nidorina", "Nidoqueen", "Nidoran-M", "Nidorino", "Nidoking", "Dedenne", "Chingling", "Chimecho", "Mime Jr.", "Mr. Mime", "Solosis", "Duosion", "Reuniclus", "Wynaut", "Wobbuffet", "Roggenrola", "Boldore", "Gigalith", "Sableye", "Carbink", "Tauros", "Miltank", "Mareep", "Flaaffy", "Ampharos", "Pinsir", "Heracross", "Pachirisu", "Slowpoke", "Slowbro", "Slowking", "Exeggcute", "Exeggutor", "Chatot", "Mantyke", "Mantine", "Clamperl", "Huntail", "Gorebyss", "Remoraid", "Octillery", "Corsola", "Chinchou", "Lanturn", "Alomomola", "Lapras", "Articuno", "Zapdos", "Moltres",
"Diglett", "Dugtrio", "Trapinch", "Vibrava", "Flygon", "Gible", "Gabite", "Garchomp", "Geodude", "Graveler", "Golem", "Slugma", "Magcargo", "Shuckle", "Skorupi", "Drapion", "Wooper", "Quagsire", "Goomy", "Sliggoo", "Goodra", "Karrablast", "Escavalier", "Shelmet", "Accelgor", "Bellsprout", "Weepinbell", "Victreebel", "Carnivine", "Gastly", "Haunter", "Gengar", "Poliwag", "Poliwhirl", "Poliwrath", "Politoed", "Ekans", "Arbok", "Stunfisk", "Barboach", "Whiscash", "Purrloin", "Liepard", "Poochyena", "Mightyena", "Patrat", "Watchog", "Pawniard", "Bisharp", "Klefki", "Murkrow", "Honchkrow", "Foongus", "Amoonguss", "Lotad", "Lombre", "Ludicolo", "Buizel", "Floatzel", "Basculin", "Phantump", "Trevenant", "Pumpkaboo", "Gourgeist", "Litwick", "Lampent", "Chandelure", "Rotom", "Magnemite", "Magneton", "Magnezone", "Voltorb", "Electrode", "Trubbish", "Garbodor", "Swinub", "Piloswine", "Mamoswine", "Bergmite", "Avalugg", "Cubchoo", "Beartic", "Smoochum", "Jynx", "Vanillite", "Vanillish", "Vanilluxe", "Snover", "Abomasnow", "Delibird", "Sneasel", "Weavile", "Timburr", "Gurdurr", "Conkeldurr", "Torkoal", "Sandshrew", "Sandslash", "Aron", "Lairon", "Aggron", "Larvitar", "Pupitar", "Tyranitar", "Heatmor", "Durant", "Spinarak", "Ariados", "Spearow", "Fearow", "Cryogonal", "Skarmory", "Noibat", "Noivern", "Gligar", "Gliscor", "Hoothoot", "Noctowl", "Igglybuff", "Jigglypuff", "Wigglytuff", "Shuppet", "Banette", "Zorua", "Zoroark", "Gothita", "Gothorita", "Gothitelle", "Bonsly", "Sudowoodo", "Spinda", "Teddiursa", "Ursaring", "Lickitung", "Lickilicky", "Scyther", "Scizor", "Ditto", "Swablu", "Altaria", "Druddigon", "Deino", "Zweilous", "Hydreigon", "Dratini", "Dragonair", "Dragonite", "Xerneas", "Yveltal", "Zygarde", "Mewtwo",
];
let template = this.getTemplate(set.species || set.name);
if ((!kalosDex.includes(template.baseSpecies) || template.gen > 6) && !this.getRuleTable(format).has('+' + template.speciesid)) {
let template = this.dex.getTemplate(set.species || set.name);
if ((!kalosDex.includes(template.baseSpecies) || template.gen > 6) && !this.ruleTable.has('+' + template.speciesid)) {
return [`${template.species} is not in the Kalos Pokédex.`];
}
},
@ -216,8 +216,8 @@ let BattleFormats = {
let alolaDex = [
"Rowlet", "Dartrix", "Decidueye", "Litten", "Torracat", "Incineroar", "Popplio", "Brionne", "Primarina", "Pikipek", "Trumbeak", "Toucannon", "Yungoos", "Gumshoos", "Rattata-Alola", "Raticate-Alola", "Caterpie", "Metapod", "Butterfree", "Ledyba", "Ledian", "Spinarak", "Ariados", "Buneary", "Lopunny", "Inkay", "Malamar", "Zorua", "Zoroark", "Furfrou", "Pichu", "Pikachu", "Raichu-Alola", "Grubbin", "Charjabug", "Vikavolt", "Bonsly", "Sudowoodo", "Happiny", "Chansey", "Blissey", "Munchlax", "Snorlax", "Slowpoke", "Slowbro", "Slowking", "Wingull", "Pelipper", "Abra", "Kadabra", "Alakazam", "Meowth-Alola", "Persian-Alola", "Magnemite", "Magneton", "Magnezone", "Grimer-Alola", "Muk-Alola", "Mime Jr.", "Mr. Mime", "Ekans", "Arbok", "Dunsparce", "Growlithe", "Arcanine", "Drowzee", "Hypno", "Makuhita", "Hariyama", "Smeargle", "Crabrawler", "Crabominable", "Gastly", "Haunter", "Gengar", "Drifloon", "Drifblim", "Murkrow", "Honchkrow", "Zubat", "Golbat", "Crobat", "Noibat", "Noivern", "Diglett-Alola", "Dugtrio-Alola", "Spearow", "Fearow", "Rufflet", "Braviary", "Vullaby", "Mandibuzz", "Mankey", "Primeape", "Delibird", "Hawlucha", "Oricorio", "Cutiefly", "Ribombee", "Flabe\u0301be\u0301", "Floette", "Florges", "Petilil", "Lilligant", "Cottonee", "Whimsicott", "Psyduck", "Golduck", "Smoochum", "Jynx", "Magikarp", "Gyarados", "Barboach", "Whiscash", "Seal", "Dewgong", "Machop", "Machoke", "Machamp", "Roggenrola", "Boldore", "Gigalith", "Carbink", "Sableye", "Mawile", "Rockruff", "Lycanroc", "Spinda", "Tentacool", "Tentacruel", "Finneon", "Lumineon", "Wishiwashi", "Luvdisc", "Corsola", "Mareanie", "Toxapex", "Shellder", "Cloyster", "Clamperl", "Huntail", "Gorebyss", "Remoraid", "Octillery", "Mantyke", "Mantine", "Bagon", "Shelgon", "Salamence", "Lillipup", "Herdier", "Stoutland", "Eevee", "Vaporeon", "Jolteon", "Flareon", "Espeon", "Umbreon", "Leafeon", "Glaceon", "Sylveon", "Mareep", "Flaaffy", "Ampharos", "Mudbray", "Mudsdale", "Igglybuff", "Jigglypuff", "Wigglytuff", "Tauros", "Miltank", "Surskit", "Masquerain", "Dewpider", "Araquanid", "Fomantis", "Lurantis", "Morelull", "Shiinotic", "Paras", "Parasect", "Poliwag", "Poliwhirl", "Poliwrath", "Politoed", "Goldeen", "Seaking", "Basculin", "Feebas", "Milotic", "Alomomola", "Fletchling", "Fletchinder", "Talonflame", "Salandit", "Salazzle", "Cubone", "Marowak-Alola", "Kangaskhan", "Magby", "Magmar", "Magmortar", "Larvesta", "Volcarona", "Stufful", "Bewear", "Bounsweet", "Steenee", "Tsareena", "Comfey", "Pinsir", "Hoothoot", "Noctowl", "Kecleon", "Oranguru", "Passimian", "Goomy", "Sliggoo", "Goodra", "Castform", "Wimpod", "Golisopod", "Staryu", "Starmie", "Sandygast", "Palossand", "Omanyte", "Omastar", "Kabuto", "Kabutops", "Lileep", "Cradily", "Anorith", "Armaldo", "Cranidos", "Rampardos", "Shieldon", "Bastiodon", "Tirtouga", "Carracosta", "Archen", "Archeops", "Tyrunt", "Tyrantrum", "Amaura", "Aurorus", "Pupitar", "Larvitar", "Tyranitar", "Phantump", "Trevenant", "Natu", "Xatu", "Nosepass", "Probopass", "Pyukumuku", "Chinchou", "Lanturn", "Type: Null", "Silvally", "Poipole", "Naganadel", "Zygarde", "Trubbish", "Garbodor", "Minccino", "Cinccino", "Pineco", "Forretress", "Skarmory", "Ditto", "Cleffa", "Clefairy", "Clefable", "Elgyem", "Beheeyem", "Minior", "Beldum", "Metang", "Metagross", "Porygon", "Porygon2", "Porygon-Z", "Pancham", "Pangoro", "Komala", "Torkoal", "Turtonator", "Houndour", "Houndoom", "Dedenne", "Togedemaru", "Electrike", "Manectric", "Elekid", "Electabuzz", "Electivire", "Geodude-Alola", "Graveler-Alola", "Golem-Alola", "Sandile", "Krokorok", "Krookodile", "Trapinch", "Vibrava", "Flygon", "Gible", "Gabite", "Garchomp", "Baltoy", "Claydol", "Golett", "Golurk", "Klefki", "Mimikyu", "Shuppet", "Banette", "Frillish", "Jellicent", "Bruxish", "Drampa", "Absol", "Snorunt", "Glalie", "Froslass", "Sneasel", "Weavile", "Sandshrew-Alola", "Sandslash-Alola", "Vulpix-Alola", "Ninetales-Alola", "Vanillite", "Vanillish", "Vanilluxe", "Scraggy", "Scrafty", "Pawniard", "Bisharp", "Snubbull", "Granbull", "Shellos", "Gastrodon", "Relicanth", "Dhelmise", "Carvanha", "Sharpedo", "Skrelp", "Dragalge", "Clauncher", "Clawitzer", "Wailmer", "Wailord", "Lapras", "Tropius", "Exeggcute", "Exeggutor-Alola", "Corphish", "Crawdaunt", "Mienfoo", "Mienshao", "Jangmo-o", "Hakamo-o", "Kommo-o", "Emolga", "Scyther", "Scizor", "Heracross", "Aipom", "Ampibom", "Litleo", "Pyroar", "Misdreavus", "Mismagius", "Druddigon", "Lickitung", "Lickilicky", "Riolu", "Lucario", "Dratini", "Dragonair", "Dragonite", "Aerodactyl", "Tapu Koko", "Tapu Lele", "Tapu Bulu", "Tapu Fini", "Cosmog", "Cosmoem", "Solgaleo", "Lunala", "Nihilego", "Stakataka", "Blacephalon", "Buzzwole", "Pheromosa", "Xurkitree", "Celesteela", "Kartana", "Guzzlord", "Necrozma", "Magearna", "Marshadow", "Zeraora",
];
let template = this.getTemplate(set.species || set.name);
if (!alolaDex.includes(template.baseSpecies) && !alolaDex.includes(template.species) && !this.getRuleTable(format).has('+' + template.speciesid)) {
let template = this.dex.getTemplate(set.species || set.name);
if (!alolaDex.includes(template.baseSpecies) && !alolaDex.includes(template.species) && !this.ruleTable.has('+' + template.speciesid)) {
return [`${template.baseSpecies} is not in the Alola Pokédex.`];
}
},
@ -227,7 +227,7 @@ let BattleFormats = {
name: 'PotD',
onBegin() {
if (global.Config && global.Config.potd) {
this.add('rule', "Pokemon of the Day: " + this.getTemplate(Config.potd).name);
this.add('rule', "Pokemon of the Day: " + this.dex.getTemplate(Config.potd).name);
}
},
},
@ -251,11 +251,11 @@ let BattleFormats = {
name: 'Little Cup',
desc: "Only allows Pok&eacute;mon that can evolve and don't have any prior evolutions",
onValidateSet(set) {
let template = this.getTemplate(set.species || set.name);
if (template.prevo && this.getTemplate(template.prevo).gen <= this.gen) {
let template = this.dex.getTemplate(set.species || set.name);
if (template.prevo && this.dex.getTemplate(template.prevo).gen <= this.gen) {
return [set.species + " isn't the first in its evolution family."];
}
let futureGenEvo = template.evos && this.getTemplate(template.evos[0]).gen > this.gen;
let futureGenEvo = template.evos && this.dex.getTemplate(template.evos[0]).gen > this.gen;
if (!template.nfe || futureGenEvo) {
return [set.species + " doesn't have an evolution family."];
}
@ -289,7 +289,7 @@ let BattleFormats = {
/**@type {{[k: string]: true}} */
let speciesTable = {};
for (const set of team) {
let template = this.getTemplate(set.species);
let template = this.dex.getTemplate(set.species);
if (speciesTable[template.num]) {
return ["You are limited to one of each Pokémon by Species Clause.", "(You have more than one " + template.baseSpecies + ")"];
}
@ -307,7 +307,7 @@ let BattleFormats = {
for (const set of team) {
let name = set.name;
if (name) {
if (name === this.getTemplate(set.species).baseSpecies) continue;
if (name === this.dex.getTemplate(set.species).baseSpecies) continue;
if (nameTable[name]) {
return ["Your Pokémon must have different nicknames.", "(You have more than one " + name + ")"];
}
@ -332,7 +332,7 @@ let BattleFormats = {
let item = toID(set.item);
if (!item) continue;
if (itemTable[item]) {
return ["You are limited to one of each item by Item Clause.", "(You have more than one " + this.getItem(item).name + ")"];
return ["You are limited to one of each item by Item Clause.", "(You have more than one " + this.dex.getItem(item).name + ")"];
}
itemTable[item] = true;
}
@ -370,7 +370,7 @@ let BattleFormats = {
if (ability in base) ability = /** @type {ID} */(base[ability]);
if (ability in abilityTable) {
if (abilityTable[ability] >= 2) {
return ["You are limited to two of each ability by the Ability Clause.", `(You have more than two ${this.getAbility(ability).name} variants)`];
return ["You are limited to two of each ability by the Ability Clause.", `(You have more than two ${this.dex.getAbility(ability).name} variants)`];
}
abilityTable[ability]++;
} else {
@ -390,7 +390,7 @@ let BattleFormats = {
let problems = [];
if (set.moves) {
for (const moveId of set.moves) {
let move = this.getMove(moveId);
let move = this.dex.getMove(moveId);
if (move.ohko) problems.push(move.name + ' is banned by OHKO Clause.');
}
}
@ -462,7 +462,7 @@ let BattleFormats = {
onValidateSet(set, format, setHas) {
if (!('move:batonpass' in setHas)) return;
let item = this.getItem(set.item);
let item = this.dex.getItem(set.item);
let ability = toID(set.ability);
/**@type {boolean | string} */
let speedBoosted = false;
@ -470,7 +470,7 @@ let BattleFormats = {
let nonSpeedBoosted = false;
for (const moveId of set.moves) {
let move = this.getMove(moveId);
let move = this.dex.getMove(moveId);
if (move.id === 'flamecharge' || (move.boosts && move.boosts.spe && move.boosts.spe > 0)) {
speedBoosted = true;
}
@ -528,7 +528,7 @@ let BattleFormats = {
name: 'Z-Move Clause',
desc: "Bans Pok&eacute;mon from holding Z-Crystals",
onValidateSet(set) {
const item = this.getItem(set.item);
const item = this.dex.getItem(set.item);
if (item.zMove) return [`${set.name || set.species}'s item ${item.name} is banned by Z-Move Clause.`];
},
onBegin() {
@ -625,7 +625,7 @@ let BattleFormats = {
/**@type {string[]} */
let typeTable;
for (const [i, set] of team.entries()) {
let template = this.getTemplate(set.species);
let template = this.dex.getTemplate(set.species);
if (!template.types) return [`Invalid pokemon ${set.name || set.species}`];
if (i === 0) {
typeTable = template.types;
@ -634,13 +634,13 @@ let BattleFormats = {
typeTable = typeTable.filter(type => template.types.includes(type));
}
if (this.gen >= 7) {
let item = this.getItem(set.item);
let item = this.dex.getItem(set.item);
if (item.megaStone && template.species === item.megaEvolves) {
template = this.getTemplate(item.megaStone);
template = this.dex.getTemplate(item.megaStone);
typeTable = typeTable.filter(type => template.types.includes(type));
}
if (item.id === "ultranecroziumz" && template.baseSpecies === "Necrozma") {
template = this.getTemplate("Necrozma-Ultra");
template = this.dex.getTemplate("Necrozma-Ultra");
typeTable = typeTable.filter(type => template.types.includes(type));
}
}
@ -664,7 +664,7 @@ let BattleFormats = {
name: 'Arceus EV Clause',
desc: "Restricts Arceus to a maximum of 100 EVs in any one stat",
onValidateSet(set, format) {
let template = this.getTemplate(set.species);
let template = this.dex.getTemplate(set.species);
if (template.num === 493 && set.evs) {
for (let stat in set.evs) {
// @ts-ignore
@ -684,7 +684,7 @@ let BattleFormats = {
onEffectiveness(typeMod, target, type, move) {
// The effectiveness of Freeze Dry on Water isn't reverted
if (move && move.id === 'freezedry' && type === 'Water') return;
if (move && !this.getImmunity(move, type)) return 1;
if (move && !this.dex.getImmunity(move, type)) return 1;
return -typeMod;
},
},

View File

@ -18,12 +18,12 @@ let BattleScripts = {
*/
runMove(moveOrMoveName, pokemon, targetLoc, sourceEffect, zMove, externalMove) {
let target = this.getTarget(pokemon, zMove || moveOrMoveName, targetLoc);
let baseMove = this.getActiveMove(moveOrMoveName);
let baseMove = this.dex.getActiveMove(moveOrMoveName);
const pranksterBoosted = baseMove.pranksterBoosted;
if (baseMove.id !== 'struggle' && !zMove && !externalMove) {
let changedMove = this.runEvent('OverrideAction', pokemon, target, baseMove);
if (changedMove && changedMove !== true) {
baseMove = this.getActiveMove(changedMove);
baseMove = this.dex.getActiveMove(changedMove);
if (pranksterBoosted) baseMove.pranksterBoosted = pranksterBoosted;
target = this.resolveTarget(pokemon, baseMove);
}
@ -74,7 +74,7 @@ let BattleScripts = {
return;
}
} else {
sourceEffect = this.getEffect('lockedmove');
sourceEffect = this.dex.getEffect('lockedmove');
}
pokemon.moveUsed(move, targetLoc);
}
@ -85,7 +85,7 @@ let BattleScripts = {
if (zMove) {
if (pokemon.illusion) {
this.singleEvent('End', this.getAbility('Illusion'), pokemon.abilityData, pokemon);
this.singleEvent('End', this.dex.getAbility('Illusion'), pokemon.abilityData, pokemon);
}
this.add('-zpower', pokemon);
pokemon.side.zMoveUsed = true;
@ -117,7 +117,7 @@ let BattleScripts = {
// @ts-ignore - the Dancer ability can't trigger on a move where target is null because it does not copy failed moves.
const dancersTarget = target.side !== dancer.side && pokemon.side === dancer.side ? target : pokemon;
// @ts-ignore
this.runMove(move.id, dancer, this.getTargetLoc(dancersTarget, dancer), this.getAbility('dancer'), undefined, true);
this.runMove(move.id, dancer, this.getTargetLoc(dancersTarget, dancer), this.dex.getAbility('dancer'), undefined, true);
// Using a Dancer move is enough to spoil Fake Out etc.
dancer.activeTurns++;
}
@ -146,7 +146,7 @@ let BattleScripts = {
if (!sourceEffect && this.effect.id) sourceEffect = this.effect;
if (sourceEffect && ['instruct', 'custapberry'].includes(sourceEffect.id)) sourceEffect = null;
let move = this.getActiveMove(moveOrMoveName);
let move = this.dex.getActiveMove(moveOrMoveName);
if (move.id === 'weatherball' && zMove) {
// Z-Weather Ball only changes types if it's used directly,
// not if it's called by Z-Sleep Talk or something.
@ -194,7 +194,7 @@ let BattleScripts = {
let movename = move.name;
if (move.id === 'hiddenpower') movename = 'Hidden Power';
if (sourceEffect) attrs += '|[from]' + this.getEffect(sourceEffect);
if (sourceEffect) attrs += '|[from]' + this.dex.getEffect(sourceEffect);
if (zMove && move.isZ === true) {
attrs = '|[anim]' + movename + attrs;
movename = 'Z-' + movename;
@ -400,7 +400,7 @@ let BattleScripts = {
return hitResults;
}
for (let [i, target] of targets.entries()) {
if (target !== pokemon && !this.getImmunity('powder', target)) {
if (target !== pokemon && !this.dex.getImmunity('powder', target)) {
this.debug('natural powder immunity');
this.add('-immune', target);
hitResults[i] = false;
@ -419,7 +419,7 @@ let BattleScripts = {
return hitResults;
}
for (let [i, target] of targets.entries()) {
if (targets[i].side !== pokemon.side && !this.getImmunity('prankster', target)) {
if (targets[i].side !== pokemon.side && !this.dex.getImmunity('prankster', target)) {
this.debug('natural prankster immunity');
if (!target.illusion) this.hint("In gen 7, Dark is immune to Prankster moves.");
this.add('-immune', target);
@ -457,7 +457,7 @@ let BattleScripts = {
if (accuracy !== true) {
if (!move.ignoreAccuracy) {
boosts = this.runEvent('ModifyBoost', pokemon, null, null, Object.assign({}, pokemon.boosts));
boost = this.clampIntRange(boosts['accuracy'], -6, 6);
boost = this.dex.clampIntRange(boosts['accuracy'], -6, 6);
if (boost > 0) {
accuracy *= boostTable[boost];
} else {
@ -466,7 +466,7 @@ let BattleScripts = {
}
if (!move.ignoreEvasion) {
boosts = this.runEvent('ModifyBoost', target, null, null, Object.assign({}, target.boosts));
boost = this.clampIntRange(boosts['evasion'], -6, 6);
boost = this.dex.clampIntRange(boosts['evasion'], -6, 6);
if (boost > 0) {
accuracy /= boostTable[boost];
} else if (boost < 0) {
@ -606,7 +606,7 @@ let BattleScripts = {
/** @type {(number | boolean | undefined)[]} */
let moveDamage;
// There is no need to recursively check the ´sleepUsable´ flag as Sleep Talk can only be used while asleep.
let isSleepUsable = move.sleepUsable || this.getMove(move.sourceEffect).sleepUsable;
let isSleepUsable = move.sleepUsable || this.dex.getMove(move.sourceEffect).sleepUsable;
/** @type {(Pokemon | false | null)[]} */
let targetsCopy = targets.slice(0);
@ -626,7 +626,7 @@ let BattleScripts = {
if (accuracy !== true) {
if (!move.ignoreAccuracy) {
const boosts = this.runEvent('ModifyBoost', pokemon, null, null, Object.assign({}, pokemon.boosts));
const boost = this.clampIntRange(boosts['accuracy'], -6, 6);
const boost = this.dex.clampIntRange(boosts['accuracy'], -6, 6);
if (boost > 0) {
accuracy *= boostTable[boost];
} else {
@ -635,7 +635,7 @@ let BattleScripts = {
}
if (!move.ignoreEvasion) {
const boosts = this.runEvent('ModifyBoost', target, null, null, Object.assign({}, target.boosts));
const boost = this.clampIntRange(boosts['evasion'], -6, 6);
const boost = this.dex.clampIntRange(boosts['evasion'], -6, 6);
if (boost > 0) {
accuracy /= boostTable[boost];
} else if (boost < 0) {
@ -668,7 +668,7 @@ let BattleScripts = {
move.totalDamage += damage[i];
}
if (move.mindBlownRecoil) {
this.damage(Math.round(pokemon.maxhp / 2), pokemon, pokemon, this.getEffect('Mind Blown'), true);
this.damage(Math.round(pokemon.maxhp / 2), pokemon, pokemon, this.dex.getEffect('Mind Blown'), true);
move.mindBlownRecoil = false;
}
this.eachEvent('Update');
@ -688,7 +688,7 @@ let BattleScripts = {
if (move.struggleRecoil) {
// @ts-ignore
this.directDamage(this.clampIntRange(Math.round(pokemon.maxhp / 4), 1), pokemon, pokemon, {id: 'strugglerecoil'});
this.directDamage(this.dex.clampIntRange(Math.round(pokemon.maxhp / 4), 1), pokemon, pokemon, {id: 'strugglerecoil'});
}
for (let i = 0; i < targetsCopy.length; i++) {
@ -717,7 +717,7 @@ let BattleScripts = {
/** @type {(number | boolean | undefined)[]} */
let damage = [];
for (let i = 0; i < targets.length; i++) damage[i] = true;
const move = this.getActiveMove(moveOrMoveName);
const move = this.dex.getActiveMove(moveOrMoveName);
/** @type {?boolean | number} */
let hitResult = true;
if (!moveData) moveData = move;
@ -1024,7 +1024,7 @@ let BattleScripts = {
calcRecoilDamage(damageDealt, move) {
// @ts-ignore
return this.clampIntRange(Math.round(damageDealt * move.recoil[0] / move.recoil[1]), 1);
return this.dex.clampIntRange(Math.round(damageDealt * move.recoil[0] / move.recoil[1]), 1);
},
zMoveTable: {
@ -1076,19 +1076,19 @@ let BattleScripts = {
let item = pokemon.getItem();
if (move.name === item.zMoveFrom) {
// @ts-ignore
let zMove = this.getActiveMove(item.zMove);
let zMove = this.dex.getActiveMove(item.zMove);
zMove.isZPowered = true;
return zMove;
}
}
if (move.category === 'Status') {
let zMove = this.getActiveMove(move);
let zMove = this.dex.getActiveMove(move);
zMove.isZ = true;
zMove.isZPowered = true;
return zMove;
}
let zMove = this.getActiveMove(this.zMoveTable[move.type]);
let zMove = this.dex.getActiveMove(this.zMoveTable[move.type]);
// @ts-ignore
zMove.basePower = move.zMovePower;
zMove.category = move.category;
@ -1115,10 +1115,10 @@ let BattleScripts = {
if (!moveSlot.disabled) {
mustStruggle = false;
}
let move = this.getMove(moveSlot.move);
let move = this.dex.getMove(moveSlot.move);
let zMoveName = this.getZMove(move, pokemon, true) || '';
if (zMoveName) {
let zMove = this.getMove(zMoveName);
let zMove = this.dex.getMove(zMoveName);
if (!zMove.isZ && zMove.category === 'Status') zMoveName = "Z-" + zMoveName;
zMoves.push({move: zMoveName, target: zMove.target});
} else {
@ -1130,7 +1130,7 @@ let BattleScripts = {
},
canMegaEvo(pokemon) {
let altForme = pokemon.baseTemplate.otherFormes && this.getTemplate(pokemon.baseTemplate.otherFormes[0]);
let altForme = pokemon.baseTemplate.otherFormes && this.dex.getTemplate(pokemon.baseTemplate.otherFormes[0]);
let item = pokemon.getItem();
if (altForme && altForme.isMega && altForme.requiredMove && pokemon.baseMoves.includes(toID(altForme.requiredMove)) && !item.zMove) return altForme.species;
if (item.megaEvolves !== pokemon.baseTemplate.baseSpecies || item.megaStone === pokemon.species) {
@ -1176,7 +1176,7 @@ let BattleScripts = {
},
runZPower(move, pokemon) {
const zPower = this.getEffect('zpower');
const zPower = this.dex.getEffect('zpower');
if (move.category !== 'Status') {
this.attrLastMove('[zeffect]');
} else if (move.zMoveBoost) {

View File

@ -158,7 +158,7 @@ let BattleStatuses = {
if (this.effectData.stage < 15) {
this.effectData.stage++;
}
this.damage(this.clampIntRange(pokemon.maxhp / 16, 1) * this.effectData.stage);
this.damage(this.dex.clampIntRange(pokemon.maxhp / 16, 1) * this.effectData.stage);
},
},
confusion: {
@ -379,7 +379,7 @@ let BattleStatuses = {
onEnd(target) {
const data = this.effectData;
// time's up; time to hit! :D
const move = this.getMove(data.move);
const move = this.dex.getMove(data.move);
if (target.fainted || target === data.source) {
this.hint(`${move.name} did not hit because the target is ${(data.fainted ? 'fainted' : 'the user')}.`);
return;
@ -398,7 +398,7 @@ let BattleStatuses = {
if (data.source.hasAbility('adaptability') && this.gen >= 6) {
data.moveData.stab = 2;
}
const hitMove = new this.Data.Move(data.moveData);
const hitMove = new this.dex.Data.Move(data.moveData);
this.trySpreadMoveHit([target], data.source, /** @type {ActiveMove} */(/** @type {unknown} */(hitMove)));
},

View File

@ -47,18 +47,20 @@ type Part = string | number | boolean | AnyObject | null | undefined;
// An individual Side's request state is encapsulated in its `activeRequest` field.
export type RequestState = 'teampreview' | 'move' | 'switch' | '';
export class Battle extends Dex.ModdedDex {
export class Battle {
readonly id: ID;
readonly debugMode: boolean;
readonly deserialized: boolean;
readonly strictChoices: boolean;
readonly format: string;
readonly format: Format;
readonly formatData: AnyObject;
readonly cachedFormat: Format;
readonly gameType: GameType;
readonly field: Field;
readonly sides: [Side, Side] | [Side, Side, Side, Side];
readonly prngSeed: PRNGSeed;
dex: ModdedDex;
gen: number;
ruleTable: Data.RuleTable;
prng: PRNG;
rated: boolean | string;
reportExactHP: boolean;
@ -110,21 +112,24 @@ export class Battle extends Dex.ModdedDex {
readonly send: (type: string, data: string | string[]) => void;
trunc: (num: number, bits?: number) => number;
constructor(options: BattleOptions) {
const format = Dex.getFormat(options.formatid, true);
super(format.mod);
this.format = format;
this.dex = Dex.forFormat(format);
this.gen = this.dex.gen;
this.ruleTable = this.dex.getRuleTable(format);
this.zMoveTable = {};
Object.assign(this, this.data.Scripts);
Object.assign(this, this.dex.data.Scripts);
if (format.battle) Object.assign(this, format.battle);
this.id = '';
this.debugMode = format.debug || !!options.debug;
this.deserialized = !!options.deserialized;
this.strictChoices = !!options.strictChoices;
this.format = format.id;
this.formatData = {id: format.id};
this.cachedFormat = format;
this.gameType = (format.gameType || 'singles');
this.field = new Field(this);
const isFourPlayer = this.gameType === 'multi' || this.gameType === 'free-for-all';
@ -179,6 +184,7 @@ export class Battle extends Dex.ModdedDex {
this.SILENT_FAIL = null;
this.send = options.send || (() => {});
this.trunc = this.dex.trunc;
// bound function for faster speedSort
// (so speedSort doesn't need to bind before use)
@ -198,9 +204,9 @@ export class Battle extends Dex.ModdedDex {
}
this.inputLog.push(`>start ` + JSON.stringify(inputOptions));
for (const rule of this.getRuleTable(format).keys()) {
for (const rule of this.ruleTable.keys()) {
if (rule.startsWith('+') || rule.startsWith('-') || rule.startsWith('!')) continue;
const subFormat = this.getFormat(rule);
const subFormat = this.dex.getFormat(rule);
if (subFormat.exists) {
const hasEventHandler = Object.keys(subFormat).some(val =>
val.startsWith('on') && !['onBegin', 'onValidateTeam', 'onChangeSet', 'onValidateSet'].includes(val)
@ -252,10 +258,6 @@ export class Battle extends Dex.ModdedDex {
this.prng = new PRNG(this.prng.startingSeed);
}
getFormat(format?: string) {
return format ? super.getFormat(format, true) : this.cachedFormat;
}
suppressingAttackEvents() {
return this.activePokemon && this.activePokemon.isActive && this.activeMove && this.activeMove.ignoreAbility;
}
@ -862,7 +864,7 @@ export class Battle extends Dex.ModdedDex {
const handlers: AnyObject[] = [];
let callback;
const format = this.getFormat();
const format = this.format;
// @ts-ignore - dynamic lookup
callback = format[callbackName];
// @ts-ignore - dynamic lookup
@ -1061,7 +1063,7 @@ export class Battle extends Dex.ModdedDex {
}
getMaxTeamSize() {
const teamLengthData = this.getFormat().teamLength;
const teamLengthData = this.format.teamLength;
return (teamLengthData && teamLengthData.battle) || 6;
}
@ -1272,7 +1274,7 @@ export class Battle extends Dex.ModdedDex {
}
this.runEvent('SwitchOut', oldActive);
oldActive.illusion = null;
this.singleEvent('End', this.getAbility(oldActive.ability), oldActive.abilityData, oldActive);
this.singleEvent('End', this.dex.getAbility(oldActive.ability), oldActive.abilityData, oldActive);
oldActive.isActive = false;
oldActive.isStarted = false;
oldActive.usedItemThisTurn = false;
@ -1381,7 +1383,7 @@ export class Battle extends Dex.ModdedDex {
pokemon.trapped = pokemon.maybeTrapped = false;
this.runEvent('TrapPokemon', pokemon);
if (!pokemon.knownType || this.getImmunity('trapped', pokemon)) {
if (!pokemon.knownType || this.dex.getImmunity('trapped', pokemon)) {
this.runEvent('MaybeTrapPokemon', pokemon);
}
// canceling switches would leak information
@ -1398,17 +1400,17 @@ export class Battle extends Dex.ModdedDex {
// to run it again.
continue;
}
const ruleTable = this.getRuleTable(this.getFormat());
if ((ruleTable.has('+hackmons') || !ruleTable.has('obtainableabilities')) && !this.getFormat().team) {
const ruleTable = this.ruleTable;
if ((ruleTable.has('+hackmons') || !ruleTable.has('obtainableabilities')) && !this.format.team) {
// hackmons format
continue;
} else if (abilitySlot === 'H' && template.unreleasedHidden) {
// unreleased hidden ability
continue;
}
const ability = this.getAbility(abilityName);
const ability = this.dex.getAbility(abilityName);
if (ruleTable.has('-ability:' + ability.id)) continue;
if (pokemon.knownType && !this.getImmunity('trapped', pokemon)) continue;
if (pokemon.knownType && !this.dex.getImmunity('trapped', pokemon)) continue;
this.singleEvent('FoeMaybeTrapPokemon', ability, {}, pokemon, source);
}
}
@ -1448,7 +1450,7 @@ export class Battle extends Dex.ModdedDex {
private maybeTriggerEndlessBattleClause(
trappedBySide: boolean[], stalenessBySide: ('internal' | 'external' | undefined)[]
) {
if (!this.getRuleTable(this.getFormat()).has('endlessbattleclause')) return;
if (!this.ruleTable.has('endlessbattleclause')) return;
if ((this.turn >= 500 && this.turn % 100 === 0) ||
(this.turn >= 900 && this.turn % 10 === 0) ||
@ -1530,7 +1532,7 @@ export class Battle extends Dex.ModdedDex {
this.add('gametype', this.gameType);
this.add('gen', this.gen);
const format = this.getFormat();
const format = this.format;
this.add('tier', format.name);
if (this.rated) {
@ -1540,9 +1542,9 @@ export class Battle extends Dex.ModdedDex {
if (format.onBegin) format.onBegin.call(this);
if (format.trunc) this.trunc = format.trunc;
for (const rule of this.getRuleTable(format).keys()) {
for (const rule of this.ruleTable.keys()) {
if (rule.startsWith('+') || rule.startsWith('-') || rule.startsWith('!')) continue;
const subFormat = this.getFormat(rule);
const subFormat = this.dex.getFormat(rule);
if (subFormat.exists) {
if (subFormat.onBegin) subFormat.onBegin.call(this);
}
@ -1562,8 +1564,7 @@ export class Battle extends Dex.ModdedDex {
restart(send?: (type: string, data: string | string[]) => void) {
if (!this.deserialized) throw new Error('Attempt to restart a battle which has not been deserialized');
const format = this.getFormat();
if (format.trunc) this.trunc = format.trunc;
if (this.format.trunc) this.trunc = this.format.trunc;
// @ts-ignore - readonly
this.send = send;
@ -1639,7 +1640,7 @@ export class Battle extends Dex.ModdedDex {
) {
if (!targetArray) return [0];
let retVals: (number | false | undefined)[] = [];
if (typeof effect === 'string' || !effect) effect = this.getEffectByID((effect || '') as ID);
if (typeof effect === 'string' || !effect) effect = this.dex.getEffectByID((effect || '') as ID);
for (const [i, curDamage] of damage.entries()) {
const target = targetArray[i];
let targetDamage = curDamage;
@ -1655,7 +1656,7 @@ export class Battle extends Dex.ModdedDex {
retVals[i] = false;
continue;
}
if (targetDamage !== 0) targetDamage = this.clampIntRange(targetDamage, 1);
if (targetDamage !== 0) targetDamage = this.dex.clampIntRange(targetDamage, 1);
if (effect.id !== 'struggle-recoil') { // Struggle recoil is not affected by effects
if (effect.effectType === 'Weather' && !target.runStatusImmunity(effect.id)) {
@ -1670,10 +1671,10 @@ export class Battle extends Dex.ModdedDex {
continue;
}
}
if (targetDamage !== 0) targetDamage = this.clampIntRange(targetDamage, 1);
if (targetDamage !== 0) targetDamage = this.dex.clampIntRange(targetDamage, 1);
if (this.gen <= 1) {
if (this.currentMod === 'stadium' ||
if (this.dex.currentMod === 'stadium' ||
!['recoil', 'drain'].includes(effect.id) && effect.effectType !== 'Status') {
this.lastDamage = targetDamage;
}
@ -1707,11 +1708,11 @@ export class Battle extends Dex.ModdedDex {
if (targetDamage && effect.effectType === 'Move') {
if (this.gen <= 1 && effect.recoil && source) {
const amount = this.clampIntRange(Math.floor(targetDamage * effect.recoil[0] / effect.recoil[1]), 1);
const amount = this.dex.clampIntRange(Math.floor(targetDamage * effect.recoil[0] / effect.recoil[1]), 1);
this.damage(amount, source, target, 'recoil');
}
if (this.gen <= 4 && effect.drain && source) {
const amount = this.clampIntRange(Math.floor(targetDamage * effect.drain[0] / effect.drain[1]), 1);
const amount = this.dex.clampIntRange(Math.floor(targetDamage * effect.drain[0] / effect.drain[1]), 1);
this.heal(amount, source, target, 'drain');
}
if (this.gen > 4 && effect.drain && source) {
@ -1761,12 +1762,12 @@ export class Battle extends Dex.ModdedDex {
}
if (!target || !target.hp) return 0;
if (!damage) return 0;
damage = this.clampIntRange(damage, 1);
damage = this.dex.clampIntRange(damage, 1);
if (typeof effect === 'string' || !effect) effect = this.getEffectByID((effect || '') as ID);
if (typeof effect === 'string' || !effect) effect = this.dex.getEffectByID((effect || '') as ID);
// In Gen 1 BUT NOT STADIUM, Substitute also takes confusion and HJK recoil damage
if (this.gen <= 1 && this.currentMod !== 'stadium' &&
if (this.gen <= 1 && this.dex.currentMod !== 'stadium' &&
['confusion', 'jumpkick', 'highjumpkick'].includes(effect.id) && target.volatiles['substitute']) {
const hint = "In Gen 1, if a Pokemon with a Substitute hurts itself due to confusion or Jump Kick/Hi Jump Kick recoil and the target";
@ -1808,7 +1809,7 @@ export class Battle extends Dex.ModdedDex {
if (!source) source = this.event.source;
if (!effect) effect = this.effect;
}
if (effect === 'drain') effect = this.getEffectByID(effect as ID);
if (effect === 'drain') effect = this.dex.getEffectByID(effect as ID);
if (damage && damage <= 1) damage = 1;
damage = this.trunc(damage);
// for things like Liquid Ooze, the Heal event still happens when nothing is healed.
@ -1894,7 +1895,7 @@ export class Battle extends Dex.ModdedDex {
}
getCategory(move: string | Move) {
return this.getMove(move).category || 'Physical';
return this.dex.getMove(move).category || 'Physical';
}
/**
@ -1907,7 +1908,7 @@ export class Battle extends Dex.ModdedDex {
pokemon: Pokemon, target: Pokemon, move: string | number | ActiveMove,
suppressMessages: boolean = false
): number | undefined | null | false {
if (typeof move === 'string') move = this.getActiveMove(move);
if (typeof move === 'string') move = this.dex.getActiveMove(move);
if (typeof move === 'number') {
const basePower = move;
@ -1942,15 +1943,15 @@ export class Battle extends Dex.ModdedDex {
basePower = move.basePowerCallback.call(this, pokemon, target, move);
}
if (!basePower) return basePower === 0 ? undefined : basePower;
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
let critMult;
let critRatio = this.runEvent('ModifyCritRatio', pokemon, target, move, move.critRatio || 0);
if (this.gen <= 5) {
critRatio = this.clampIntRange(critRatio, 0, 5);
critRatio = this.dex.clampIntRange(critRatio, 0, 5);
critMult = [0, 16, 8, 4, 3, 2];
} else {
critRatio = this.clampIntRange(critRatio, 0, 4);
critRatio = this.dex.clampIntRange(critRatio, 0, 4);
if (this.gen === 6) {
critMult = [0, 16, 8, 2, 1];
} else {
@ -1974,7 +1975,7 @@ export class Battle extends Dex.ModdedDex {
basePower = this.runEvent('BasePower', pokemon, target, move, basePower, true);
if (!basePower) return 0;
basePower = this.clampIntRange(basePower, 1);
basePower = this.dex.clampIntRange(basePower, 1);
const level = pokemon.level;
@ -2071,7 +2072,7 @@ export class Battle extends Dex.ModdedDex {
}
// types
let typeMod = target.runEffectiveness(move);
typeMod = this.clampIntRange(typeMod, -6, 6);
typeMod = this.dex.clampIntRange(typeMod, -6, 6);
target.getMoveHitData(move).typeMod = typeMod;
if (typeMod > 0) {
if (!suppressMessages) this.add('-supereffective', target);
@ -2162,7 +2163,7 @@ export class Battle extends Dex.ModdedDex {
}
getTarget(pokemon: Pokemon, move: string | Move, targetLoc: number) {
move = this.getMove(move);
move = this.dex.getMove(move);
let target;
// Fails if the target is the user and the move can't target its own position
if (['adjacentAlly', 'any', 'normal'].includes(move.target) && targetLoc === -(pokemon.position + 1) &&
@ -2198,7 +2199,7 @@ export class Battle extends Dex.ModdedDex {
// moves that can target either allies or foes will only target foes
// when used without an explicit target.
move = this.getMove(move);
move = this.dex.getMove(move);
if (move.target === 'adjacentAlly') {
const allyActives = pokemon.side.active;
let adjacentAllies = [allyActives[pokemon.position - 1], allyActives[pokemon.position + 1]];
@ -2251,7 +2252,7 @@ export class Battle extends Dex.ModdedDex {
this.add('faint', faintData.target);
faintData.target.side.pokemonLeft--;
this.runEvent('Faint', faintData.target, faintData.source, faintData.effect);
this.singleEvent('End', this.getAbility(faintData.target.ability), faintData.target.abilityData, faintData.target);
this.singleEvent('End', this.dex.getAbility(faintData.target.ability), faintData.target.abilityData, faintData.target);
faintData.target.clearVolatile(false);
faintData.target.fainted = true;
faintData.target.isActive = false;
@ -2316,7 +2317,7 @@ export class Battle extends Dex.ModdedDex {
if (!action) throw new Error(`Action not passed to resolveAction`);
if (!action.side && action.pokemon) action.side = action.pokemon.side;
if (!action.move && action.moveid) action.move = this.getActiveMove(action.moveid);
if (!action.move && action.moveid) action.move = this.dex.getActiveMove(action.moveid);
if (!action.choice && action.move) action.choice = 'move';
if (!action.priority && action.priority !== 0) {
const priorities = {
@ -2354,7 +2355,7 @@ export class Battle extends Dex.ModdedDex {
}
} else if (action.choice === 'switch' || action.choice === 'instaswitch') {
if (typeof action.pokemon.switchFlag === 'string') {
action.sourceEffect = this.getMove(action.pokemon.switchFlag as ID) as any;
action.sourceEffect = this.dex.getMove(action.pokemon.switchFlag as ID) as any;
}
action.pokemon.switchFlag = false;
if (!action.speed) action.speed = action.pokemon.getActionSpeed();
@ -2364,7 +2365,7 @@ export class Battle extends Dex.ModdedDex {
const deferPriority = this.gen >= 7 && action.mega && action.mega !== 'done';
if (action.move) {
let target = null;
action.move = this.getActiveMove(action.move);
action.move = this.dex.getActiveMove(action.move);
if (!action.targetLoc) {
target = this.resolveTarget(action.pokemon, action.move);
@ -2377,7 +2378,7 @@ export class Battle extends Dex.ModdedDex {
if (action.zmove) {
const zMoveName = this.getZMove(action.move, action.pokemon, true);
if (zMoveName) {
const zMove = this.getActiveMove(zMoveName);
const zMove = this.dex.getActiveMove(zMoveName);
if (zMove.exists && zMove.isZ) {
move = zMove;
}
@ -2509,7 +2510,7 @@ export class Battle extends Dex.ModdedDex {
switch (action.choice) {
case 'start': {
// I GIVE UP, WILL WRESTLE WITH EVENT SYSTEM LATER
const format = this.getFormat();
const format = this.format;
// Remove Pokémon duplicates remaining after `team` decisions.
for (const side of this.sides) {
@ -2531,7 +2532,7 @@ export class Battle extends Dex.ModdedDex {
}
}
for (const pokemon of this.getAllPokemon()) {
this.singleEvent('Start', this.getEffectByID(pokemon.speciesid), pokemon.speciesData, pokemon);
this.singleEvent('Start', this.dex.getEffectByID(pokemon.speciesid), pokemon.speciesData, pokemon);
}
this.midTurn = true;
break;
@ -2571,8 +2572,8 @@ export class Battle extends Dex.ModdedDex {
return;
case 'instaswitch':
case 'switch':
if (action.choice === 'switch' && action.pokemon.status && this.data.Abilities.naturalcure) {
this.singleEvent('CheckShow', this.getAbility('naturalcure'), null, action.pokemon);
if (action.choice === 'switch' && action.pokemon.status && this.dex.data.Abilities.naturalcure) {
this.singleEvent('CheckShow', this.dex.getAbility('naturalcure'), null, action.pokemon);
}
if (action.pokemon.hp) {
action.pokemon.beingCalledBack = true;
@ -2596,7 +2597,7 @@ export class Battle extends Dex.ModdedDex {
}
}
action.pokemon.illusion = null;
this.singleEvent('End', this.getAbility(action.pokemon.ability), action.pokemon.abilityData, action.pokemon);
this.singleEvent('End', this.dex.getAbility(action.pokemon.ability), action.pokemon.abilityData, action.pokemon);
if (!action.pokemon.hp && !action.pokemon.fainted) {
// a pokemon fainted from Pursuit before it could switch
if (this.gen <= 4) {
@ -2963,17 +2964,16 @@ export class Battle extends Dex.ModdedDex {
// players
getTeam(options: PlayerOptions): PokemonSet[] {
const format = this.getFormat();
let team = options.team;
if (typeof team === 'string') team = Dex.fastUnpackTeam(team);
if ((!format.team || this.deserialized) && team) return team;
if ((!this.format.team || this.deserialized) && team) return team;
if (!options.seed) {
options.seed = PRNG.generateSeed();
}
if (!this.teamGenerator) {
this.teamGenerator = this.getTeamGenerator(format, options.seed);
this.teamGenerator = this.dex.getTeamGenerator(this.format, options.seed);
} else {
this.teamGenerator.setSeed(options.seed);
}
@ -3007,7 +3007,7 @@ export class Battle extends Dex.ModdedDex {
if (options.team) throw new Error(`Player ${slot} already has a team!`);
}
if (options.team && typeof options.team !== 'string') {
options.team = this.packTeam(options.team);
options.team = this.dex.packTeam(options.team);
}
if (!didSomething) return;
this.inputLog.push(`>player ${slot} ` + JSON.stringify(options));

View File

@ -214,7 +214,7 @@ export class ModdedDex {
return dexes;
}
mod(mod: string): ModdedDex {
mod(mod: string | undefined): ModdedDex {
if (!dexes['base'].modsLoaded) dexes['base'].includeMods();
return dexes[mod || 'base'];
}

View File

@ -33,7 +33,7 @@ export class Field {
}
setWeather(status: string | PureEffect, source: Pokemon | 'debug' | null = null, sourceEffect: Effect | null = null) {
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
if (!sourceEffect && this.battle.effect) sourceEffect = this.battle.effect;
if (!source && this.battle.event && this.battle.event.target) source = this.battle.event.target;
if (source === 'debug') source = this.battle.sides[0].active[0];
@ -117,11 +117,11 @@ export class Field {
}
getWeather() {
return this.battle.getEffectByID(this.weather);
return this.battle.dex.getEffectByID(this.weather);
}
setTerrain(status: string | Effect, source: Pokemon | 'debug' | null = null, sourceEffect: Effect | null = null) {
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
if (!sourceEffect && this.battle.effect) sourceEffect = this.battle.effect;
if (!source && this.battle.event && this.battle.event.target) source = this.battle.event.target;
if (source === 'debug') source = this.battle.sides[0].active[0];
@ -172,7 +172,7 @@ export class Field {
}
getTerrain() {
return this.battle.getEffectByID(this.terrain);
return this.battle.dex.getEffectByID(this.terrain);
}
addPseudoWeather(
@ -182,7 +182,7 @@ export class Field {
): boolean {
if (!source && this.battle.event && this.battle.event.target) source = this.battle.event.target;
if (source === 'debug') source = this.battle.sides[0].active[0];
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
let effectData = this.pseudoWeather[status.id];
if (effectData) {
@ -207,12 +207,12 @@ export class Field {
}
getPseudoWeather(status: string | Effect) {
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
return this.pseudoWeather[status.id] ? status : null;
}
removePseudoWeather(status: string | Effect) {
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
const effectData = this.pseudoWeather[status.id];
if (!effectData) return false;
this.battle.singleEvent('End', status, effectData, this);

View File

@ -996,12 +996,12 @@ interface FormatsData extends EventMethods {
checkLearnset?: (this: TeamValidator, move: Move, template: Template, setSources: PokemonSources, set: PokemonSet) => {type: string, [any: string]: any} | null
onAfterMega?: (this: Battle, pokemon: Pokemon) => void
onBegin?: (this: Battle) => void
onChangeSet?: (this: ModdedDex, set: PokemonSet, format: Format, setHas?: AnyObject, teamHas?: AnyObject) => string[] | void
onChangeSet?: (this: TeamValidator, set: PokemonSet, format: Format, setHas?: AnyObject, teamHas?: AnyObject) => string[] | void
onModifyTemplate?: (this: Battle, template: Template, target?: Pokemon, source?: Pokemon, effect?: Effect) => Template | void
onStart?: (this: Battle) => void
onTeamPreview?: (this: Battle) => void
onValidateSet?: (this: ModdedDex, set: PokemonSet, format: Format, setHas: AnyObject, teamHas: AnyObject) => string[] | void
onValidateTeam?: (this: ModdedDex, team: PokemonSet[], format: Format, teamHas: AnyObject) => string[] | void
onValidateSet?: (this: TeamValidator, set: PokemonSet, format: Format, setHas: AnyObject, teamHas: AnyObject) => string[] | void
onValidateTeam?: (this: TeamValidator, team: PokemonSet[], format: Format, teamHas: AnyObject) => string[] | void
validateSet?: (this: TeamValidator, set: PokemonSet, teamHas: AnyObject) => string[] | null
validateTeam?: (this: TeamValidator, team: PokemonSet[], removeNicknames: boolean) => string[] | void,
trunc?: (n: number) => number;
@ -1100,7 +1100,7 @@ interface ModdedBattleScriptsData extends Partial<BattleScriptsData> {
debug?: (this: Battle, activity: string) => void
getDamage?: (this: Battle, pokemon: Pokemon, target: Pokemon, move: string | number | ActiveMove, suppressMessages: boolean) => number | undefined | null | false
getEffect?: (this: Battle, name: string | Effect | null) => Effect
init?: (this: Battle) => void
init?: (this: ModdedDex) => void
modifyDamage?: (this: Battle, baseDamage: number, pokemon: Pokemon, target: Pokemon, move: ActiveMove, suppressMessages?: boolean) => void
natureModify?: (this: Battle, stats: StatsTable, set: PokemonSet) => StatsTable
spreadModify?: (this: Battle, baseStats: StatsTable, set: PokemonSet) => StatsTable

View File

@ -213,18 +213,18 @@ export class Pokemon {
this.side = side;
this.battle = side.battle;
const pokemonScripts = this.battle.data.Scripts.pokemon;
const pokemonScripts = this.battle.dex.data.Scripts.pokemon;
if (pokemonScripts) Object.assign(this, pokemonScripts);
if (typeof set === 'string') set = {name: set};
this.set = set as PokemonSet;
this.baseTemplate = this.battle.getTemplate(set.species || set.name);
this.baseTemplate = this.battle.dex.getTemplate(set.species || set.name);
if (!this.baseTemplate.exists) {
throw new Error(`Unidentified species: ${this.baseTemplate.name}`);
}
this.template = this.baseTemplate;
this.species = this.battle.getSpecies(set.species);
this.species = this.battle.dex.getSpecies(set.species);
this.speciesid = toID(this.species);
if (set.name === set.species || !set.name) {
set.name = this.baseTemplate.baseSpecies;
@ -235,23 +235,23 @@ export class Pokemon {
this.fullname = this.side.id + ': ' + this.name;
this.id = this.fullname;
set.level = this.battle.clampIntRange(set.forcedLevel || set.level || 100, 1, 9999);
set.level = this.battle.dex.clampIntRange(set.forcedLevel || set.level || 100, 1, 9999);
this.level = set.level;
const genders: {[key: string]: GenderName} = {M: 'M', F: 'F', N: 'N'};
this.gender = genders[set.gender] || this.template.gender || (this.battle.random() * 2 < 1 ? 'M' : 'F');
if (this.gender === 'N') this.gender = '';
this.happiness = typeof set.happiness === 'number' ? this.battle.clampIntRange(set.happiness, 0, 255) : 255;
this.happiness = typeof set.happiness === 'number' ? this.battle.dex.clampIntRange(set.happiness, 0, 255) : 255;
this.pokeball = this.set.pokeball || 'pokeball';
this.baseMoveSlots = [];
this.moveSlots = [];
if (this.set.moves) {
for (const moveid of this.set.moves) {
let move = this.battle.getMove(moveid);
let move = this.battle.dex.getMove(moveid);
if (!move.id) continue;
if (move.id === 'hiddenpower' && move.type !== 'Normal') {
if (!set.hpType) set.hpType = move.type;
move = this.battle.getMove('hiddenpower');
move = this.battle.dex.getMove('hiddenpower');
}
this.baseMoveSlots.push({
move: move.name,
@ -288,10 +288,10 @@ export class Pokemon {
if (!this.set.ivs[stat] && this.set.ivs[stat] !== 0) this.set.ivs[stat] = 31;
}
for (stat in this.set.evs) {
this.set.evs[stat] = this.battle.clampIntRange(this.set.evs[stat], 0, 255);
this.set.evs[stat] = this.battle.dex.clampIntRange(this.set.evs[stat], 0, 255);
}
for (stat in this.set.ivs) {
this.set.ivs[stat] = this.battle.clampIntRange(this.set.ivs[stat], 0, 31);
this.set.ivs[stat] = this.battle.dex.clampIntRange(this.set.ivs[stat], 0, 31);
}
if (this.battle.gen && this.battle.gen <= 2) {
// We represent DVs using even IVs. Ensure they are in fact even.
@ -300,7 +300,7 @@ export class Pokemon {
}
}
const hpData = this.battle.getHiddenPower(this.set.ivs);
const hpData = this.battle.dex.getHiddenPower(this.set.ivs);
this.hpType = set.hpType || hpData.type;
this.hpPower = hpData.power;
@ -513,7 +513,7 @@ export class Pokemon {
}
const combatPower = Math.floor(Math.floor(statSum * this.level * 6 / 100) +
(Math.floor(awakeningSum) * Math.floor((this.level * 4) / 100 + 2)));
return this.battle.clampIntRange(combatPower, 0, 10000);
return this.battle.dex.clampIntRange(combatPower, 0, 10000);
}
*/
@ -523,7 +523,7 @@ export class Pokemon {
}
getMoveData(move: string | Move) {
move = this.battle.getMove(move) as Move;
move = this.battle.dex.getMove(move) as Move;
for (const moveSlot of this.moveSlots) {
if (moveSlot.id === move.id) {
return moveSlot;
@ -614,7 +614,7 @@ export class Pokemon {
if (!move.flags['charge'] || this.volatiles['twoturnmove'] ||
(move.id.startsWith('solarb') && this.battle.field.isWeather(['sunnyday', 'desolateland'])) ||
(this.hasItem('powerherb') && move.id !== 'skydrop')) {
target = this.battle.priorityEvent('RedirectTarget', this, this, this.battle.getActiveMove(move), target);
target = this.battle.priorityEvent('RedirectTarget', this, this, this.battle.dex.getActiveMove(move), target);
}
}
if (target.fainted) {
@ -653,7 +653,7 @@ export class Pokemon {
deductPP(move: string | Move, amount?: number | null, target?: Pokemon | null | false) {
const gen = this.battle.gen;
move = this.battle.getMove(move) as Move;
move = this.battle.dex.getMove(move) as Move;
const ppData = this.getMoveData(move);
if (!ppData) return 0;
ppData.used = true;
@ -676,7 +676,7 @@ export class Pokemon {
gotAttacked(move: string | Move, damage: number | false | undefined, source: Pokemon) {
if (!damage) damage = 0;
move = this.battle.getMove(move) as Move;
move = this.battle.dex.getMove(move) as Move;
this.attackedBy.push({
source,
damage,
@ -716,7 +716,7 @@ export class Pokemon {
}
// does this happen?
return [{
move: this.battle.getMove(lockedMove).name,
move: this.battle.dex.getMove(lockedMove).name,
id: lockedMove,
}];
}
@ -729,15 +729,15 @@ export class Pokemon {
if (this.battle.gen < 6) moveName += ' ' + this.hpPower;
} else if (moveSlot.id === 'return') {
// @ts-ignore - Return's basePowerCallback only takes one parameter
moveName = 'Return ' + this.battle.getMove('return')!.basePowerCallback(this);
moveName = 'Return ' + this.battle.dex.getMove('return')!.basePowerCallback(this);
} else if (moveSlot.id === 'frustration') {
// @ts-ignore - Frustration's basePowerCallback only takes one parameter
moveName = 'Frustration ' + this.battle.getMove('frustration')!.basePowerCallback(this);
moveName = 'Frustration ' + this.battle.dex.getMove('frustration')!.basePowerCallback(this);
}
let target = moveSlot.target;
if (moveSlot.id === 'curse') {
if (!this.hasType('Ghost')) {
target = this.battle.getMove('curse').nonGhostTarget || moveSlot.target;
target = this.battle.dex.getMove('curse').nonGhostTarget || moveSlot.target;
}
}
let disabled = moveSlot.disabled;
@ -859,7 +859,7 @@ export class Pokemon {
this.clearVolatile();
this.boosts = pokemon.boosts;
for (const i in pokemon.volatiles) {
if (this.battle.getEffectByID(i as ID).noCopy) continue;
if (this.battle.dex.getEffectByID(i as ID).noCopy) continue;
// shallow clones
this.volatiles[i] = Object.assign({}, pokemon.volatiles[i]);
if (this.volatiles[i].linkedPokemon) {
@ -970,7 +970,7 @@ export class Pokemon {
this.knownType = true;
this.weighthg = template.weighthg;
const stats = this.battle.spreadModify(this.template.baseStats, this.set);
const stats = this.battle.dex.spreadModify(this.template.baseStats, this.set);
if (!this.baseStoredStats) this.baseStoredStats = stats;
let statName: StatNameExceptHP;
for (statName in this.storedStats) {
@ -995,7 +995,7 @@ export class Pokemon {
formeChange(
templateId: string | Template, source: Effect = this.battle.effect, isPermanent?: boolean,
message?: string, abilitySlot: '0' | '1' | 'H' | 'S' = '0') {
const rawTemplate = this.battle.getTemplate(templateId);
const rawTemplate = this.battle.dex.getTemplate(templateId);
const template = this.setTemplate(rawTemplate, source);
if (!template) return false;
@ -1224,7 +1224,7 @@ export class Pokemon {
ignoreImmunities: boolean = false
) {
if (!this.hp) return false;
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
if (this.battle.event) {
if (!source) source = this.battle.event.source;
if (!sourceEffect) sourceEffect = this.battle.effect;
@ -1289,7 +1289,7 @@ export class Pokemon {
}
getStatus() {
return this.battle.getEffectByID(this.status);
return this.battle.dex.getEffectByID(this.status);
}
eatItem(source?: Pokemon, sourceEffect?: Effect) {
@ -1385,7 +1385,7 @@ export class Pokemon {
setItem(item: string | Item, source?: Pokemon, effect?: Effect) {
if (!this.hp || !this.isActive) return false;
if (typeof item === 'string') item = this.battle.getItem(item) as Item;
if (typeof item === 'string') item = this.battle.dex.getItem(item) as Item;
const effectid = this.battle.effect ? this.battle.effect.id : '';
if (item.id === 'leppaberry') {
@ -1404,7 +1404,7 @@ export class Pokemon {
}
getItem() {
return this.battle.getItem(this.item);
return this.battle.dex.getItem(this.item);
}
hasItem(item: string | string[]) {
@ -1420,7 +1420,7 @@ export class Pokemon {
setAbility(ability: string | Ability, source?: Pokemon | null, isFromFormeChange?: boolean) {
if (!this.hp) return false;
if (typeof ability === 'string') ability = this.battle.getAbility(ability) as Ability;
if (typeof ability === 'string') ability = this.battle.dex.getAbility(ability) as Ability;
const oldAbility = this.ability;
if (!isFromFormeChange) {
const abilities = [
@ -1430,10 +1430,10 @@ export class Pokemon {
if (this.battle.gen >= 7 && (ability.id === 'zenmode' || oldAbility === 'zenmode')) return false;
}
if (!this.battle.runEvent('SetAbility', this, source, this.battle.effect, ability)) return false;
this.battle.singleEvent('End', this.battle.getAbility(oldAbility), this.abilityData, this, source);
this.battle.singleEvent('End', this.battle.dex.getAbility(oldAbility), this.abilityData, this, source);
if (this.battle.effect && this.battle.effect.effectType === 'Move') {
this.battle.add('-endability', this, this.battle.getAbility(oldAbility), '[from] move: ' +
this.battle.getMove(this.battle.effect.id));
this.battle.add('-endability', this, this.battle.dex.getAbility(oldAbility), '[from] move: ' +
this.battle.dex.getMove(this.battle.effect.id));
}
this.ability = ability.id;
this.abilityData = {id: ability.id, target: this};
@ -1445,7 +1445,7 @@ export class Pokemon {
}
getAbility() {
return this.battle.getAbility(this.ability);
return this.battle.dex.getAbility(this.ability);
}
hasAbility(ability: string | string[]) {
@ -1460,14 +1460,14 @@ export class Pokemon {
}
getNature() {
return this.battle.getNature(this.set.nature);
return this.battle.dex.getNature(this.set.nature);
}
addVolatile(
status: string | PureEffect, source: Pokemon | null = null, sourceEffect: Effect | null = null,
linkedStatus: string | PureEffect | null = null): boolean | any {
let result;
status = this.battle.getEffect(status) as PureEffect;
status = this.battle.dex.getEffect(status) as PureEffect;
if (!this.hp && !status.affectsFainted) return false;
if (linkedStatus && source && !source.hp) return false;
if (this.battle.event) {
@ -1522,14 +1522,14 @@ export class Pokemon {
}
getVolatile(status: string | Effect) {
status = this.battle.getEffect(status) as Effect;
status = this.battle.dex.getEffect(status) as Effect;
if (!this.volatiles[status.id]) return null;
return status;
}
removeVolatile(status: string | Effect) {
if (!this.hp) return false;
status = this.battle.getEffect(status) as Effect;
status = this.battle.dex.getEffect(status) as Effect;
if (!this.volatiles[status.id]) return false;
this.battle.singleEvent('End', status, this.volatiles[status.id], this);
const linkedPokemon = this.volatiles[status.id].linkedPokemon;
@ -1647,7 +1647,7 @@ export class Pokemon {
runEffectiveness(move: ActiveMove) {
let totalTypeMod = 0;
for (const type of this.getTypes()) {
let typeMod = this.battle.getEffectiveness(move, type);
let typeMod = this.battle.dex.getEffectiveness(move, type);
typeMod = this.battle.singleEvent('Effectiveness', move, null, this, type, move, typeMod);
totalTypeMod += this.battle.runEvent('Effectiveness', this, type, move, typeMod);
}
@ -1656,7 +1656,7 @@ export class Pokemon {
runImmunity(type: string, message?: string | boolean) {
if (!type || type === '???') return true;
if (!(type in this.battle.data.TypeChart)) {
if (!(type in this.battle.dex.data.TypeChart)) {
if (type === 'Fairy' || type === 'Dark' || type === 'Steel') return true;
throw new Error("Use runStatusImmunity for " + type);
}
@ -1674,7 +1674,7 @@ export class Pokemon {
}
}
if (!negateResult) return true;
if ((isGrounded === undefined && !this.battle.getImmunity(type, this)) || isGrounded === false) {
if ((isGrounded === undefined && !this.battle.dex.getImmunity(type, this)) || isGrounded === false) {
if (message) {
this.battle.add('-immune', this);
}
@ -1687,7 +1687,7 @@ export class Pokemon {
if (this.fainted) return false;
if (!type) return true;
if (!this.battle.getImmunity(type, this)) {
if (!this.battle.dex.getImmunity(type, this)) {
this.battle.debug('natural status immunity');
if (message) {
this.battle.add('-immune', this);

View File

@ -63,7 +63,7 @@ export class Side {
lastMove: Move | null;
constructor(name: string, battle: Battle, sideNum: number, team: PokemonSet[]) {
const sideScripts = battle.data.Scripts.side;
const sideScripts = battle.dex.data.Scripts.side;
if (sideScripts) Object.assign(this, sideScripts);
this.battle = battle;
@ -185,7 +185,7 @@ export class Side {
return move + toID(pokemon.hpType) + (this.battle.gen < 6 ? '' : pokemon.hpPower);
}
if (move === 'frustration' || move === 'return') {
const m = this.battle.getMove(move)!;
const m = this.battle.dex.getMove(move)!;
// @ts-ignore - Frustration and Return only require the source Pokemon
const basePower = m.basePowerCallback(pokemon);
return `${move}${basePower}`;
@ -218,7 +218,7 @@ export class Side {
if (source === 'debug') source = this.active[0];
if (!source) throw new Error(`setting sidecond without a source`);
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
if (this.sideConditions[status.id]) {
if (!status.onRestart) return false;
return this.battle.singleEvent('Restart', status, this.sideConditions[status.id], this, source, sourceEffect);
@ -245,7 +245,7 @@ export class Side {
if (this.n >= 2 && this.battle.gameType === 'multi') {
return this.battle.sides[this.n % 2].getSideCondition(status);
}
status = this.battle.getEffect(status) as Effect;
status = this.battle.dex.getEffect(status) as Effect;
if (!this.sideConditions[status.id]) return null;
return status;
}
@ -254,7 +254,7 @@ export class Side {
if (this.n >= 2 && this.battle.gameType === 'multi') {
return this.battle.sides[this.n % 2].getSideConditionData(status);
}
status = this.battle.getEffect(status) as Effect;
status = this.battle.dex.getEffect(status) as Effect;
return this.sideConditions[status.id] || null;
}
@ -262,7 +262,7 @@ export class Side {
if (this.n >= 2 && this.battle.gameType === 'multi') {
return this.battle.sides[this.n % 2].removeSideCondition(status);
}
status = this.battle.getEffect(status) as Effect;
status = this.battle.dex.getEffect(status) as Effect;
if (!this.sideConditions[status.id]) return false;
this.battle.singleEvent('End', status, this.sideConditions[status.id], this);
delete this.sideConditions[status.id];
@ -278,7 +278,7 @@ export class Side {
if (target instanceof Pokemon) target = target.position;
if (!source) throw new Error(`setting sidecond without a source`);
status = this.battle.getEffect(status);
status = this.battle.dex.getEffect(status);
if (this.slotConditions[target][status.id]) {
if (!status.onRestart) return false;
return this.battle.singleEvent('Restart', status, this.slotConditions[target][status.id], this, source, sourceEffect);
@ -303,14 +303,14 @@ export class Side {
getSlotCondition(target: Pokemon | number, status: string | Effect) {
if (target instanceof Pokemon) target = target.position;
status = this.battle.getEffect(status) as Effect;
status = this.battle.dex.getEffect(status) as Effect;
if (!this.slotConditions[target][status.id]) return null;
return status;
}
removeSlotCondition(target: Pokemon | number, status: string | Effect) {
if (target instanceof Pokemon) target = target.position;
status = this.battle.getEffect(status) as Effect;
status = this.battle.dex.getEffect(status) as Effect;
if (!this.slotConditions[target][status.id]) return false;
this.battle.singleEvent('End', status, this.slotConditions[target][status.id], this.active[target]);
delete this.slotConditions[target][status.id];
@ -408,7 +408,7 @@ export class Side {
break;
}
}
const move = this.battle.getMove(moveid);
const move = this.battle.dex.getMove(moveid);
// Z-move
@ -420,7 +420,7 @@ export class Side {
return this.emitChoiceError(`Can't move: You can't Z-move more than once per battle`);
}
if (zMove) targetType = this.battle.getMove(zMove).target;
if (zMove) targetType = this.battle.dex.getMove(zMove).target;
// Validate targetting

View File

@ -6,7 +6,6 @@
*/
import {Battle} from './battle';
import {Dex} from './dex';
import * as Data from './dex-data';
import {Field} from './field';
import {Pokemon} from './pokemon';
@ -36,7 +35,7 @@ type Referable = Battle | Field | Side | Pokemon | PureEffect | Ability | Item |
// Battle inherits from Dex, but all of Dex's fields are redundant - we can
// just recreate the Dex from the format.
const BATTLE = new Set([
...Object.keys(Dex), 'id', 'log', 'inherit', 'cachedFormat',
'dex', 'gen', 'ruleTable', 'id', 'log', 'inherit', 'format',
'zMoveTable', 'teamGenerator', 'NOT_FAIL', 'FAIL', 'SILENT_FAIL',
'field', 'sides', 'prng', 'hints', 'deserialized',
]);
@ -70,6 +69,7 @@ export const State = new class {
// We treat log specially because we only set it back on Battle after everything
// else has been deserialized to avoid anything accidentally `add`-ing to it.
state.log = battle.log;
state.formatid = battle.format.id;
return state;
}
@ -83,7 +83,7 @@ export const State = new class {
const state: /* Battle */ AnyObject =
typeof serialized === 'string' ? JSON.parse(serialized) : serialized;
const options = {
formatid: state.format,
formatid: state.formatid,
seed: state.prngSeed,
rated: state.rated,
debug: state.debugMode,
@ -256,7 +256,7 @@ export const State = new class {
// a bug in the simulator if it ever happened, but if not, the isActiveMove check can
// be extended.
private serializeActiveMove(move: ActiveMove, battle: Battle): /* ActiveMove */ AnyObject {
const base = battle.getMove(move.id);
const base = battle.dex.getMove(move.id);
const skip = new Set([...ACTIVE_MOVE]);
for (const [key, value] of Object.entries(base)) {
// This should really be a deepEquals check to see if anything on ActiveMove was
@ -271,7 +271,7 @@ export const State = new class {
}
private deserializeActiveMove(state: /* ActiveMove */ AnyObject, battle: Battle): ActiveMove {
const move = battle.getActiveMove(this.fromRef(state.move, battle)! as Move);
const move = battle.dex.getActiveMove(this.fromRef(state.move, battle)! as Move);
this.deserialize(state, move, ACTIVE_MOVE, battle);
return move;
}
@ -384,11 +384,11 @@ export const State = new class {
switch (type) {
case 'Side': return battle.sides[Number(id[1]) - 1];
case 'Pokemon': return battle.sides[Number(id[1]) - 1].pokemon[POSITIONS.indexOf(id[2])];
case 'Ability': return battle.getAbility(id);
case 'Item': return battle.getItem(id);
case 'Move': return battle.getMove(id);
case 'PureEffect': return battle.getEffect(id);
case 'Template': return battle.getTemplate(id);
case 'Ability': return battle.dex.getAbility(id);
case 'Item': return battle.dex.getItem(id);
case 'Move': return battle.dex.getMove(id);
case 'PureEffect': return battle.dex.getEffect(id);
case 'Template': return battle.dex.getTemplate(id);
default: return undefined; // maybe we actually got unlucky and its a string
}
}

View File

@ -173,11 +173,13 @@ export class PokemonSources {
export class TeamValidator {
readonly format: Format;
readonly dex: ModdedDex;
readonly gen: number;
readonly ruleTable: import('./dex-data').RuleTable;
constructor(format: string | Format) {
this.format = Dex.getFormat(format);
this.dex = Dex.forFormat(this.format);
this.gen = this.dex.gen;
this.ruleTable = this.dex.getRuleTable(this.format);
}
@ -263,11 +265,11 @@ export class TeamValidator {
for (const rule of ruleTable.keys()) {
const subformat = dex.getFormat(rule);
if (subformat.onValidateTeam && ruleTable.has(subformat.id)) {
problems = problems.concat(subformat.onValidateTeam.call(dex, team, format, teamHas) || []);
problems = problems.concat(subformat.onValidateTeam.call(this, team, format, teamHas) || []);
}
}
if (format.onValidateTeam) {
problems = problems.concat(format.onValidateTeam.call(dex, team, format, teamHas) || []);
problems = problems.concat(format.onValidateTeam.call(this, team, format, teamHas) || []);
}
if (!problems.length) return null;
@ -342,11 +344,11 @@ export class TeamValidator {
for (const [rule] of ruleTable) {
const subformat = dex.getFormat(rule);
if (subformat.onChangeSet && ruleTable.has(subformat.id)) {
problems = problems.concat(subformat.onChangeSet.call(dex, set, format, setHas, teamHas) || []);
problems = problems.concat(subformat.onChangeSet.call(this, set, format, setHas, teamHas) || []);
}
}
if (format.onChangeSet) {
problems = problems.concat(format.onChangeSet.call(dex, set, format, setHas, teamHas) || []);
problems = problems.concat(format.onChangeSet.call(this, set, format, setHas, teamHas) || []);
}
// onChangeSet can modify set.species, set.item, set.ability
@ -613,11 +615,11 @@ export class TeamValidator {
if (rule.startsWith('!')) continue;
const subformat = dex.getFormat(rule);
if (subformat.onValidateSet && ruleTable.has(subformat.id)) {
problems = problems.concat(subformat.onValidateSet.call(dex, set, format, setHas, teamHas) || []);
problems = problems.concat(subformat.onValidateSet.call(this, set, format, setHas, teamHas) || []);
}
}
if (format.onValidateSet) {
problems = problems.concat(format.onValidateSet.call(dex, set, format, setHas, teamHas) || []);
problems = problems.concat(format.onValidateSet.call(this, set, format, setHas, teamHas) || []);
}
if (!problems.length) {

View File

@ -16,7 +16,7 @@ describe('Battle Armor', function () {
[{species: 'Cryogonal', ability: 'noguard', moves: ['frostbreath']}],
]);
let successfulEvent = false;
battle.onEvent('ModifyDamage', battle.getFormat(), function (damage, attacker, defender, move) {
battle.onEvent('ModifyDamage', battle.format, function (damage, attacker, defender, move) {
if (move.id === 'frostbreath') {
successfulEvent = true;
assert.ok(!defender.getMoveHitData(move).crit);
@ -33,7 +33,7 @@ describe('Battle Armor', function () {
]);
battle.makeChoices('move quickattack', 'move frostbreath');
let successfulEvent = false;
battle.onEvent('ModifyDamage', battle.getFormat(), function (damage, attacker, defender, move) {
battle.onEvent('ModifyDamage', battle.format, function (damage, attacker, defender, move) {
if (move.id === 'frostbreath') {
successfulEvent = true;
assert.ok(defender.getMoveHitData(move).crit);

View File

@ -62,14 +62,14 @@ describe('Comatose', function () {
battle.setPlayer('p2', {team: [{species: "Smeargle", ability: 'technician', moves: ['hex', 'wakeupslap']}]});
let bp = 0;
battle.onEvent('BasePower', battle.getFormat(), function (basePower, pokemon, target, move) {
battle.onEvent('BasePower', battle.format, function (basePower, pokemon, target, move) {
bp = basePower;
});
battle.makeChoices('move endure', 'move hex');
assert.strictEqual(bp, battle.getMove('hex').basePower * 2);
assert.strictEqual(bp, battle.dex.getMove('hex').basePower * 2);
battle.makeChoices('move endure', 'move wakeupslap');
assert.strictEqual(bp, battle.getMove('wakeupslap').basePower * 2);
assert.strictEqual(bp, battle.dex.getMove('wakeupslap').basePower * 2);
});
});

View File

@ -74,7 +74,7 @@ describe('Desolate Land', function () {
{species: "Venusaur", ability: 'chlorophyll', moves: ['growth']},
{species: "Toxicroak", ability: 'dryskin', moves: ['bulkup']},
]});
battle.onEvent('Hit', battle.getFormat(), (target, pokemon, move) => {
battle.onEvent('Hit', battle.format, (target, pokemon, move) => {
if (move.id === 'weatherball') {
assert.strictEqual(move.type, 'Fire');
}

View File

@ -80,7 +80,7 @@ describe('Disguise', function () {
battle.setPlayer('p1', {team: [{species: 'Mimikyu', ability: 'disguise', moves: ['counter']}]});
battle.setPlayer('p2', {team: [{species: 'Cryogonal', ability: 'noguard', moves: ['frostbreath']}]});
let successfulEvent = false;
battle.onEvent('Damage', battle.getFormat(), function (damage, attacker, defender, move) {
battle.onEvent('Damage', battle.format, function (damage, attacker, defender, move) {
if (move.id === 'frostbreath') {
successfulEvent = true;
assert.ok(!defender.getMoveHitData(move).crit);

View File

@ -81,7 +81,7 @@ describe('Intimidate', function () {
battle.setPlayer('p1', {team: [{species: "Arcanine", ability: 'intimidate', moves: ['morningsun']}]});
battle.setPlayer('p2', {team: [{species: "Gyarados", ability: 'intimidate', moves: ['dragondance']}]});
let intimidateCount = 0;
battle.onEvent('Boost', battle.getFormat(), function (boost, target, source) {
battle.onEvent('Boost', battle.format, function (boost, target, source) {
assert.species(source, intimidateCount === 0 ? 'Arcanine' : 'Gyarados');
intimidateCount++;
});
@ -96,7 +96,7 @@ describe('Intimidate', function () {
battle.setPlayer('p1', {team: [{species: "Gyarados", ability: 'intimidate', moves: ['dragondance']}]});
battle.setPlayer('p2', {team: [{species: "Arcanine", ability: 'intimidate', moves: ['morningsun']}]});
intimidateCount = 0;
battle.onEvent('Boost', battle.getFormat(), function (boost, target, source) {
battle.onEvent('Boost', battle.format, function (boost, target, source) {
assert.species(source, intimidateCount === 0 ? 'Arcanine' : 'Gyarados');
intimidateCount++;
});
@ -120,7 +120,7 @@ describe('Intimidate', function () {
]});
const [p1active, p2active] = [battle.p1.active, battle.p2.active];
let intimidateCount = 0;
battle.onEvent('Boost', battle.getFormat(), function (boost, target, source) {
battle.onEvent('Boost', battle.format, function (boost, target, source) {
assert.species(source, intimidateCount % 2 === 0 ? 'Arcanine' : 'Gyarados');
intimidateCount++;
});

View File

@ -14,7 +14,7 @@ describe('Parental Bond', function () {
]);
basePowers = [];
battle.onEvent('BasePower', battle.getFormat(), -9, function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, -9, function (bp, attacker, defender, move) {
basePowers.push(this.modify(bp, this.event.modifier));
});
});
@ -47,7 +47,7 @@ describe('Parental Bond [Gen 6]', function () {
]);
basePowers = [];
battle.onEvent('BasePower', battle.getFormat(), -9, function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, -9, function (bp, attacker, defender, move) {
basePowers.push(this.modify(bp, this.event.modifier));
});
});

View File

@ -73,7 +73,7 @@ describe('Primordial Sea', function () {
{species: "Toxicroak", ability: 'dryskin', moves: ['bulkup']},
{species: "Manaphy", ability: 'hydration', item: 'laggingtail', moves: ['rest']},
]});
battle.onEvent('Hit', battle.getFormat(), (target, pokemon, move) => {
battle.onEvent('Hit', battle.format, (target, pokemon, move) => {
if (move.id === 'weatherball') {
assert.strictEqual(move.type, 'Water');
}

View File

@ -16,7 +16,7 @@ describe('Shell Armor', function () {
[{species: 'Cryogonal', ability: 'noguard', moves: ['frostbreath']}],
]);
let successfulEvent = false;
battle.onEvent('ModifyDamage', battle.getFormat(), function (damage, attacker, defender, move) {
battle.onEvent('ModifyDamage', battle.format, function (damage, attacker, defender, move) {
if (move.id === 'frostbreath') {
successfulEvent = true;
assert.false(defender.getMoveHitData(move).crit);
@ -32,7 +32,7 @@ describe('Shell Armor', function () {
[{species: 'Cryogonal', ability: 'moldbreaker', item: 'zoomlens', moves: ['frostbreath']}],
]);
let successfulEvent = false;
battle.onEvent('ModifyDamage', battle.getFormat(), function (damage, attacker, defender, move) {
battle.onEvent('ModifyDamage', battle.format, function (damage, attacker, defender, move) {
if (move.id === 'frostbreath') {
successfulEvent = true;
assert.ok(defender.getMoveHitData(move).crit);

View File

@ -33,7 +33,7 @@ describe('Shield Dust', function () {
[{species: 'Talonflame', ability: 'flamebody', item: 'kingsrock', moves: ['flamecharge']}],
[{species: 'Clefable', ability: 'shielddust', moves: ['cottonguard']}],
]);
battle.onEvent('ModifyMove', battle.getFormat(), function (move) {
battle.onEvent('ModifyMove', battle.format, function (move) {
if (move.secondaries) {
for (const secondary of move.secondaries) {
secondary.chance = 100;

View File

@ -19,7 +19,7 @@ describe('Thick Fat', function () {
// should not crit
battle.makeChoices('move splash', 'move incinerate');
assert.bounded(target.maxhp - target.hp, [29, 35]);
battle.heal(target.maxhp, target, target, battle.getFormat());
battle.heal(target.maxhp, target, target, battle.format);
battle.resetRNG();
// should not crit
battle.makeChoices('move splash', 'move icebeam');
@ -35,7 +35,7 @@ describe('Thick Fat', function () {
// should not crit
battle.makeChoices('move splash', 'move incinerate');
assert.bounded(target.maxhp - target.hp, [57, 68]);
battle.heal(target.maxhp, target, target, battle.getFormat());
battle.heal(target.maxhp, target, target, battle.format);
battle.resetRNG();
// should not crit
battle.makeChoices('move splash', 'move icebeam');

View File

@ -17,14 +17,14 @@ describe('Battle#on', function () {
]);
let eventCount = 0;
let eventCount2 = 0;
battle.onEvent('Hit', battle.getFormat(), function () {
battle.onEvent('Hit', battle.format, function () {
eventCount++;
});
battle.onEvent('Hit', battle.getFormat(), function () {
battle.onEvent('Hit', battle.format, function () {
eventCount++;
eventCount2++;
});
battle.onEvent('ModifyDamage', battle.getFormat(), function () {
battle.onEvent('ModifyDamage', battle.format, function () {
return 5;
});
battle.makeChoices('move bulkup', 'move peck');
@ -46,7 +46,7 @@ describe('Battle#on', function () {
};
};
for (let i = 0; i < 9; i++) {
battle.onEvent('ModifyDamage', battle.getFormat(), -i, modHandler(i));
battle.onEvent('ModifyDamage', battle.format, -i, modHandler(i));
}
battle.makeChoices('move bulkup', 'move peck');
assert.strictEqual(eventCount, 9);
@ -59,6 +59,6 @@ describe('Battle#on', function () {
]);
assert.throws(battle.onEvent, TypeError);
assert.throws(() => { battle.onEvent('Hit'); }, TypeError);
assert.throws(() => { battle.onEvent('Hit', battle.getFormat()); }, TypeError);
assert.throws(() => { battle.onEvent('Hit', battle.format); }, TypeError);
});
});

View File

@ -29,7 +29,7 @@ describe('Lansat Berry', function () {
let i = 0;
let expectedRatio = [1, 1, 1, 1, 1, 3];
battle.onEvent('ModifyCritRatio', battle.getFormat(), -99, function (critRatio, pokemon) {
battle.onEvent('ModifyCritRatio', battle.format, -99, function (critRatio, pokemon) {
assert.strictEqual(critRatio, expectedRatio[i++]);
});

View File

@ -19,7 +19,7 @@ describe('Fusion Bolt + Fusion Flare', function () {
battle.makeChoices();
let bpModifiers = new Map();
battle.onEvent('BasePower', battle.getFormat(), -100, function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, -100, function (bp, attacker, defender, move) {
bpModifiers.set(move.id, this.event.modifier);
});
battle.makeChoices('move fusionbolt 1, move fusionflare 1', 'default');
@ -37,7 +37,7 @@ describe('Fusion Bolt + Fusion Flare', function () {
battle.makeChoices();
let bpModifiers = new Map();
battle.onEvent('BasePower', battle.getFormat(), -100, function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, -100, function (bp, attacker, defender, move) {
bpModifiers.set(move.id, this.event.modifier);
});
battle.makeChoices('move fusionflare 2, move instruct -1', 'default');
@ -55,7 +55,7 @@ describe('Fusion Bolt + Fusion Flare', function () {
battle.makeChoices();
let bpModifiers = new Map();
battle.onEvent('BasePower', battle.getFormat(), -100, function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, -100, function (bp, attacker, defender, move) {
bpModifiers.set(move.id, this.event.modifier);
});
battle.makeChoices('move fusionbolt 1, move fusionflare 1', 'default');

View File

@ -150,7 +150,7 @@ describe('Freeze', function () {
[{species: 'Shaymin-Sky', ability: 'sturdy', moves: ['sleeptalk']}],
]);
// I didn't feel like manually testing seed after seed. Sue me.
battle.onEvent('ModifyMove', battle.getFormat(), function (move) {
battle.onEvent('ModifyMove', battle.format, function (move) {
if (move.secondaries) {
this.debug('Freeze test: Guaranteeing secondary');
for (const secondary of move.secondaries) {
@ -168,7 +168,7 @@ describe('Freeze', function () {
[{species: 'Ditto', ability: 'imposter', moves: ['transform']}],
[{species: 'Shaymin-Sky', ability: 'sturdy', moves: ['icebeam', 'sleeptalk']}],
]);
battle.onEvent('ModifyMove', battle.getFormat(), function (move) {
battle.onEvent('ModifyMove', battle.format, function (move) {
if (move.secondaries) {
this.debug('Freeze test: Guaranteeing secondary');
for (const secondary of move.secondaries) {

View File

@ -83,7 +83,7 @@ describe('Poison-inflicting status moves [Gen 2]', function () {
[{species: "Magneton", moves: ['sleeptalk']}],
]);
// Set all moves to perfect accuracy
battle.onEvent('Accuracy', battle.getFormat(), true);
battle.onEvent('Accuracy', battle.format, true);
const target = battle.p2.active[0];
for (const move of POISON_STATUS_MOVES) {

View File

@ -16,7 +16,7 @@ describe('Heavy Metal', function () {
[{species: "Simisage", ability: 'gluttony', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}
@ -31,7 +31,7 @@ describe('Heavy Metal', function () {
[{species: "Simisage", ability: 'moldbreaker', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}
@ -52,7 +52,7 @@ describe('Light Metal', function () {
[{species: "Simisage", ability: 'gluttony', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}
@ -67,7 +67,7 @@ describe('Light Metal', function () {
[{species: "Simisage", ability: 'moldbreaker', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}
@ -88,7 +88,7 @@ describe('Float Stone', function () {
[{species: "Simisage", ability: 'gluttony', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}
@ -109,7 +109,7 @@ describe('Autotomize', function () {
[{species: "Simisage", ability: 'gluttony', item: 'laggingtail', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}
@ -126,7 +126,7 @@ describe('Autotomize', function () {
[{species: "Simisage", ability: 'gluttony', item: 'laggingtail', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}
@ -141,7 +141,7 @@ describe('Autotomize', function () {
[{species: "Simisage", ability: 'gluttony', item: 'laggingtail', moves: ['grassknot']}],
]);
let basePower = 0;
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'grassknot') {
basePower = bp;
}

View File

@ -22,7 +22,7 @@ describe('Counter', function () {
battle.setPlayer('p1', {team: [{species: 'Sawk', ability: 'sturdy', moves: ['doublekick']}]});
battle.setPlayer('p2', {team: [{species: 'Throh', ability: 'guts', moves: ['counter']}]});
let lastDamage = 0;
battle.onEvent('Damage', battle.getFormat(), function (damage, attacker, defender, move) {
battle.onEvent('Damage', battle.format, function (damage, attacker, defender, move) {
if (move.id === 'doublekick') {
lastDamage = damage;
}
@ -90,7 +90,7 @@ describe('Mirror Coat', function () {
battle.setPlayer('p1', {team: [{species: 'Espeon', ability: 'synchronize', moves: ['watershuriken']}]});
battle.setPlayer('p2', {team: [{species: 'Umbreon', ability: 'synchronize', moves: ['mirrorcoat']}]});
let lastDamage = 0;
battle.onEvent('Damage', battle.getFormat(), function (damage, attacker, defender, move) {
battle.onEvent('Damage', battle.format, function (damage, attacker, defender, move) {
if (move.id === 'watershuriken') {
lastDamage = damage;
}

View File

@ -25,7 +25,7 @@ describe('Follow Me', function () {
{species: 'Alakazam', ability: 'synchronize', moves: ['lowkick']},
]});
let hitCount = 0;
battle.onEvent('Damage', battle.getFormat(), function (damage, pokemon) {
battle.onEvent('Damage', battle.format, function (damage, pokemon) {
if (pokemon.template.speciesid === 'clefable') {
hitCount++;
}

View File

@ -23,7 +23,7 @@ for (const move of moves) {
let ebp = 30;
let count = 0;
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
count++;
assert.strictEqual(basePower, ebp);
if (count % 5 === 0) {
@ -47,7 +47,7 @@ for (const move of moves) {
let ebp = 30;
let count = 0;
battle.onEvent('Accuracy', battle.getFormat(), function (accuracy, target, pokemon, move) {
battle.onEvent('Accuracy', battle.format, function (accuracy, target, pokemon, move) {
if (move.id === 'recover') return;
count++;
@ -58,7 +58,7 @@ for (const move of moves) {
return true;
}
});
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
assert.strictEqual(basePower, ebp);
ebp *= 2;
});
@ -77,7 +77,7 @@ for (const move of moves) {
let ebp = 30;
let count = 0;
battle.onEvent('BeforeMove', battle.getFormat(), function (attacker, defender, move) {
battle.onEvent('BeforeMove', battle.format, function (attacker, defender, move) {
if (move.id === 'recover') return;
count++;
@ -86,7 +86,7 @@ for (const move of moves) {
return false; // Imitate immobilization from Paralysis, etc.
}
});
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
assert.strictEqual(basePower, ebp);
ebp *= 2;
});
@ -104,7 +104,7 @@ for (const move of moves) {
]);
let runCount = 0;
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
assert.strictEqual(basePower, 60);
runCount++;
});
@ -121,7 +121,7 @@ for (const move of moves) {
]);
let hitCount = 0;
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
assert.strictEqual(basePower, 30);
hitCount++;
});

View File

@ -161,7 +161,7 @@ describe('Sky Drop', function () {
[{species: "Aerodactyl", ability: 'unnerve', moves: ['skydrop']}, {species: "Kabutops", ability: 'swiftswim', moves: ['aquajet']}],
[{species: "Lairon", ability: 'sturdy', moves: ['bulkup']}, {species: "Azumarill", ability: 'thickfat', moves: ['aquajet']}],
]);
battle.onEvent('Damage', battle.getFormat(), function (damage, target, source, effect) {
battle.onEvent('Damage', battle.format, function (damage, target, source, effect) {
// mod Sky Drop to deal no damage
if (effect.id === 'skydrop') return 0;
});

View File

@ -16,7 +16,7 @@ describe('Stomping Tantrum', function () {
[{species: 'Manaphy', ability: 'hydration', moves: ['rest']}],
]);
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
assert.strictEqual(basePower, 150);
});
@ -32,7 +32,7 @@ describe('Stomping Tantrum', function () {
[{species: 'Manaphy', ability: 'hydration', moves: ['protect', 'tailglow']}],
]);
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
assert.strictEqual(basePower, 75);
});
@ -51,7 +51,7 @@ describe('Stomping Tantrum', function () {
{species: 'Ho-Oh', ability: 'pressure', moves: ['recover']},
]});
battle.onEvent('BasePower', battle.getFormat(), function (basePower, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (basePower, attacker, defender, move) {
if (move.id === 'stompingtantrum') assert.strictEqual(basePower, 150);
});
@ -65,7 +65,7 @@ describe('Stomping Tantrum', function () {
[{species: 'Manaphy', ability: 'hydration', moves: ['rest']}],
]);
battle.onEvent('BasePower', battle.getFormat(), function (basePower) {
battle.onEvent('BasePower', battle.format, function (basePower) {
assert.strictEqual(basePower, 75);
});
@ -79,7 +79,7 @@ describe('Stomping Tantrum', function () {
[{species: 'Lycanroc-Midnight', ability: 'noguard', moves: ['sleeptalk']}],
]);
battle.onEvent('BasePower', battle.getFormat(), function (basePower, pokemon, target, move) {
battle.onEvent('BasePower', battle.format, function (basePower, pokemon, target, move) {
if (move.id === 'stompingtantrum') assert.strictEqual(basePower, 75);
});

View File

@ -65,7 +65,7 @@ describe('Transform', function () {
for (let i = 0; i < p1poke.moves.length; i++) {
let move = p1poke.moves[i];
assert.strictEqual(move, p2poke.moves[i]);
move = battle.getMove(move);
move = battle.dex.getMove(move);
let movepp = p1poke.getMoveData(move);
assert.strictEqual(movepp.pp, 5);
}

View File

@ -85,7 +85,7 @@ describe('Trick Room', function () {
battle.p1.active[0].boostBy({spe: 4}); // 1809 Speed
battle.p2.active[0].boostBy({spe: 6}); // 1808 Speed
battle.onEvent('BasePower', battle.getFormat(), function (bp, pokemon, target, move) {
battle.onEvent('BasePower', battle.format, function (bp, pokemon, target, move) {
if (move.id !== 'gyroball') return;
assert.strictEqual(bp, 25); // BP should theoretically be this based on speed values
});

View File

@ -17,7 +17,7 @@ describe('Trump Card', function () {
]);
const basePowers = [];
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'trumpcard') {
basePowers.push(bp);
}
@ -37,7 +37,7 @@ describe('Trump Card', function () {
]);
const basePowers = [];
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'trumpcard') {
basePowers.push(bp);
}
@ -59,7 +59,7 @@ describe('Trump Card', function () {
]);
const basePowers = [];
battle.onEvent('BasePower', battle.getFormat(), function (bp, attacker, defender, move) {
battle.onEvent('BasePower', battle.format, function (bp, attacker, defender, move) {
if (move.id === 'trumpcard') {
basePowers.push(bp);
}