mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-21 17:25:10 -05:00
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:
parent
3cd04c349e
commit
2d3614f325
|
|
@ -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."];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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} */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.'];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 = '';
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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') {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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."];
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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é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é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;
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
},
|
||||
|
|
|
|||
120
sim/battle.ts
120
sim/battle.ts
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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'];
|
||||
}
|
||||
|
|
|
|||
14
sim/field.ts
14
sim/field.ts
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
22
sim/side.ts
22
sim/side.ts
|
|
@ -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
|
||||
|
||||
|
|
|
|||
20
sim/state.ts
20
sim/state.ts
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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++]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user