diff --git a/data/abilities.ts b/data/abilities.ts index 8048f5204e6c..e06c8e3b594d 100644 --- a/data/abilities.ts +++ b/data/abilities.ts @@ -2030,8 +2030,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.illusion) { this.debug('illusion cleared'); pokemon.illusion = null; - const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + const details = pokemon.getUpdatedDetails(); this.add('replace', pokemon, details); this.add('-end', pokemon, 'Illusion'); if (this.ruleTable.has('illusionlevelmod')) { @@ -4892,6 +4891,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.species.forme !== 'Terastal') { this.add('-activate', pokemon, 'ability: Tera Shift'); pokemon.formeChange('Terapagos-Terastal', this.effect, true); + pokemon.regressionForme = false; pokemon.baseMaxhp = Math.floor(Math.floor( 2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100 ) * pokemon.level / 100 + 10); @@ -5572,6 +5572,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.baseSpecies.baseSpecies !== 'Palafin') return; if (pokemon.species.forme !== 'Hero') { pokemon.formeChange('Palafin-Hero', this.effect, true); + pokemon.regressionForme = false; } }, onSwitchIn() { diff --git a/data/conditions.ts b/data/conditions.ts index 5c0f040ac391..5f1302d6afae 100644 --- a/data/conditions.ts +++ b/data/conditions.ts @@ -91,6 +91,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = { } if (target.species.name === 'Shaymin-Sky' && target.baseSpecies.baseSpecies === 'Shaymin') { target.formeChange('Shaymin', this.effect, true); + target.regressionForme = false; } }, onBeforeMovePriority: 10, diff --git a/data/mods/gen7pokebilities/scripts.ts b/data/mods/gen7pokebilities/scripts.ts index b0199e4bad6b..c88b861598cc 100644 --- a/data/mods/gen7pokebilities/scripts.ts +++ b/data/mods/gen7pokebilities/scripts.ts @@ -169,8 +169,7 @@ export const Scripts: ModdedBattleScriptsData = { this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { this.baseSpecies = rawSpecies; - this.details = species.name + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getUpdatedDetails(); this.battle.add('detailschange', this, (this.illusion || this).details); if (source.effectType === 'Item') { this.canTerastallize = null; // National Dex behavior diff --git a/data/mods/gen9ssb/abilities.ts b/data/mods/gen9ssb/abilities.ts index badd191ed69f..c483d3cf34d8 100644 --- a/data/mods/gen9ssb/abilities.ts +++ b/data/mods/gen9ssb/abilities.ts @@ -1755,8 +1755,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa target.clearBoosts(); this.add('-clearboost', target); this.boost({atk: 1, def: -1, spa: 1, spd: -1, spe: 1}); - const details = target.species.name + (target.level === 100 ? '' : ', L' + target.level) + - (target.gender === '' ? '' : ', ' + target.gender) + (target.set.shiny ? ', shiny' : ''); + const details = target.getUpdatedDetails(); target.details = details; this.add('replace', target, details); } diff --git a/data/mods/gen9ssb/moves.ts b/data/mods/gen9ssb/moves.ts index 35c1284202f1..230715795ec9 100644 --- a/data/mods/gen9ssb/moves.ts +++ b/data/mods/gen9ssb/moves.ts @@ -4236,8 +4236,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { pokemon.cureStatus(); this.boost({def: 1, spd: 1}); (pokemon as any).level += 5; - pokemon.details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getUpdatedDetails(); this.add('-anim', pokemon, 'Geomancy', pokemon); this.add('replace', pokemon, pokemon.details); this.add('-message', `${pokemon.name} gained 5 levels!`); @@ -5905,8 +5904,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { this.add(`c:|${getName((source.illusion || source).name)}|lol never do that ever again thanks`); this.add('custom', '-endterastallize', pokemon); delete pokemon.terastallized; - const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + const details = pokemon.getUpdatedDetails(); this.add('detailschange', pokemon, details); } }, diff --git a/data/mods/gen9ssb/scripts.ts b/data/mods/gen9ssb/scripts.ts index 3fe0e55a73b8..a610ea1453a1 100644 --- a/data/mods/gen9ssb/scripts.ts +++ b/data/mods/gen9ssb/scripts.ts @@ -89,8 +89,7 @@ export function changeSet(context: Battle, pokemon: Pokemon, newSet: SSBSet, cha pokemon.teraType = newSet.teraType === 'Any' ? context.sample(allTypes) : Array.isArray(newSet.teraType) ? context.sample(newSet.teraType) : newSet.teraType; } - const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + const details = pokemon.getUpdatedDetails(); if (oldShiny !== pokemon.set.shiny || oldGender !== pokemon.gender) context.add('replace', pokemon, details); if (changeAbility) pokemon.setAbility(newSet.ability as string, undefined, true); @@ -386,8 +385,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getUpdatedDetails(); // pokemon.setAbility(species.abilities['0'], null, true); // pokemon.baseAbility = pokemon.ability; @@ -916,9 +914,9 @@ export const Scripts: ModdedBattleScriptsData = { } this.battle.runEvent('BeforeSwitchIn', pokemon); if (sourceEffect) { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails, '[from] ' + sourceEffect); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails, '[from] ' + sourceEffect); } else { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails); } pokemon.abilityOrder = this.battle.abilityOrder++; if (isDrag && this.battle.gen === 2) pokemon.draggedIn = this.battle.turn; diff --git a/data/mods/mixandmega/scripts.ts b/data/mods/mixandmega/scripts.ts index a687f445ba51..c9c05eaf7d8d 100644 --- a/data/mods/mixandmega/scripts.ts +++ b/data/mods/mixandmega/scripts.ts @@ -67,8 +67,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getUpdatedDetails(); pokemon.ability = this.toID(species.abilities['0']); pokemon.baseAbility = pokemon.ability; } @@ -118,8 +117,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getUpdatedDetails(); pokemon.ability = this.toID(species.abilities['0']); pokemon.baseAbility = pokemon.ability; diff --git a/data/mods/pokebilities/scripts.ts b/data/mods/pokebilities/scripts.ts index e9564991a2ac..42716a34fbcc 100644 --- a/data/mods/pokebilities/scripts.ts +++ b/data/mods/pokebilities/scripts.ts @@ -169,8 +169,7 @@ export const Scripts: ModdedBattleScriptsData = { this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { this.baseSpecies = rawSpecies; - this.details = species.name + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getUpdatedDetails(); this.battle.add('detailschange', this, (this.illusion || this).details); if (source.effectType === 'Item') { this.canTerastallize = null; // National Dex behavior diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 4128c3f85d54..82f6b90f1740 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -136,9 +136,9 @@ export class BattleActions { } this.battle.runEvent('BeforeSwitchIn', pokemon); if (sourceEffect) { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails, '[from] ' + sourceEffect); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails, '[from] ' + sourceEffect); } else { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails); } pokemon.abilityOrder = this.battle.abilityOrder++; if (isDrag && this.battle.gen === 2) pokemon.draggedIn = this.battle.turn; @@ -1957,9 +1957,12 @@ export class BattleActions { pokemon.maxhp = newMaxHP; this.battle.add('-heal', pokemon, pokemon.getHealth, '[silent]'); } - if (pokemon.species.baseSpecies === 'Morpeko') { + if (pokemon.species.baseSpecies === 'Morpeko' && !pokemon.transformed && + pokemon.baseSpecies.id !== pokemon.species.id + ) { + pokemon.regressionForme = true; pokemon.baseSpecies = pokemon.species; - pokemon.details = pokemon.details.replace('Morpeko', pokemon.species.name); + pokemon.details = pokemon.getUpdatedDetails(); } this.battle.runEvent('AfterTerastallization', pokemon); } diff --git a/sim/battle.ts b/sim/battle.ts index dba8f006b52c..715e76f4f600 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2370,12 +2370,22 @@ export class Battle { if (pokemon.side.totalFainted < 100) pokemon.side.totalFainted++; this.runEvent('Faint', pokemon, faintData.source, faintData.effect); this.singleEvent('End', pokemon.getAbility(), pokemon.abilityState, pokemon); + if (pokemon.regressionForme) { + // before clearing volatiles + pokemon.baseSpecies = this.dex.species.get(pokemon.set.species || pokemon.set.name); + pokemon.baseAbility = toID(pokemon.set.ability); + } pokemon.clearVolatile(false); pokemon.fainted = true; pokemon.illusion = null; pokemon.isActive = false; pokemon.isStarted = false; delete pokemon.terastallized; + if (pokemon.regressionForme) { + // after clearing volatiles + pokemon.details = pokemon.getUpdatedDetails(); + pokemon.regressionForme = false; + } pokemon.side.faintedThisTurn = pokemon; if (this.faintQueue.length >= faintQueueLeft) checkWin = true; } @@ -2494,8 +2504,7 @@ export class Battle { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getUpdatedDetails(); pokemon.setAbility(species.abilities['0'], null, true); pokemon.baseAbility = pokemon.ability; diff --git a/sim/pokemon.ts b/sim/pokemon.ts index bb954c86b7d5..17f28c84ceb5 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -131,6 +131,9 @@ export class Pokemon { faintQueued: boolean; subFainted: boolean | null; + /** If this Pokemon should revert to its set species when it faints */ + regressionForme: boolean; + types: string[]; addedType: string; knownType: boolean; @@ -351,10 +354,7 @@ export class Pokemon { } this.position = 0; - let displayedSpeciesName = this.species.name; - if (displayedSpeciesName === 'Greninja-Bond') displayedSpeciesName = 'Greninja'; - this.details = displayedSpeciesName + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getUpdatedDetails(); this.status = ''; this.statusState = {}; @@ -419,6 +419,8 @@ export class Pokemon { this.faintQueued = false; this.subFainted = null; + this.regressionForme = false; + this.types = this.baseSpecies.types; this.baseTypes = this.types; this.addedType = ''; @@ -509,16 +511,19 @@ export class Pokemon { return this.isActive ? this.getSlot() + fullname.slice(2) : fullname; } - getDetails = () => { + getUpdatedDetails(illusionLevel?: number) { + let name = this.species.name; + if (name === 'Greninja-Bond') name = 'Greninja'; + const level = illusionLevel || this.level; + return name + (level === 100 ? '' : ', L' + level) + + (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + } + + getFullDetails = () => { const health = this.getHealth(); let details = this.details; if (this.illusion) { - const level = this.battle.ruleTable.has('illusionlevelmod') ? this.illusion.level : this.level; - let displayedSpeciesName = this.illusion.species.name; - if (displayedSpeciesName === 'Greninja-Bond') displayedSpeciesName = 'Greninja'; - const illusionDetails = displayedSpeciesName + (level === 100 ? '' : ', L' + level) + - (this.illusion.gender === '' ? '' : ', ' + this.illusion.gender) + (this.illusion.set.shiny ? ', shiny' : ''); - details = illusionDetails; + details = this.illusion.getUpdatedDetails(this.battle.ruleTable.has('illusionlevelmod') ? this.level : undefined); } if (this.terastallized) details += `, tera:${this.terastallized}`; return {side: health.side, secret: `${details}|${health.secret}`, shared: `${details}|${health.shared}`}; @@ -1320,8 +1325,7 @@ export class Pokemon { // Pokemon transformed into Ogerpon cannot Terastallize // restoring their ability to tera after they untransform is handled ELSEWHERE - if (this.species.baseSpecies === 'Ogerpon' && this.canTerastallize) this.canTerastallize = false; - if (this.species.baseSpecies === 'Terapagos' && this.canTerastallize) this.canTerastallize = false; + if (['Ogerpon', 'Terapagos'].includes(this.species.baseSpecies) && this.canTerastallize) this.canTerastallize = false; return true; } @@ -1329,7 +1333,7 @@ export class Pokemon { /** * Changes this Pokemon's species to the given speciesId (or species). * This function only handles changes to stats and type. - * Use formChange to handle changes to ability and sending client messages. + * Use formeChange to handle changes to ability and sending client messages. */ setSpecies(rawSpecies: Species, source: Effect | null = this.battle.effect, isTransform = false) { const species = this.battle.runEvent('ModifySpecies', this, null, source, rawSpecies); @@ -1386,9 +1390,9 @@ export class Pokemon { const apparentSpecies = this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { + if (!this.transformed) this.regressionForme = true; this.baseSpecies = rawSpecies; - this.details = species.name + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getUpdatedDetails(); let details = (this.illusion || this).details; if (this.terastallized) details += `, tera:${this.terastallized}`; this.battle.add('detailschange', this, details); diff --git a/test/assert.js b/test/assert.js index 2717be0d3781..ec30d7675700 100644 --- a/test/assert.js +++ b/test/assert.js @@ -81,6 +81,16 @@ assert.fullHP = function (pokemon, message) { }); }; +assert.hasAbility = function (pokemon, ability, message) { + const actual = pokemon.ability; + const expected = toID(ability); + if (actual === expected) return; + throw new AssertionError({ + message: message || `Expected ${pokemon} ability to be ${expected}, not ${actual}.`, + stackStartFunction: assert.hasAbility, + }); +}; + assert.holdsItem = function (pokemon, message) { if (pokemon.item) return; throw new AssertionError({ diff --git a/test/sim/misc/fainted-forme-regression.js b/test/sim/misc/fainted-forme-regression.js new file mode 100644 index 000000000000..1fa2c1967162 --- /dev/null +++ b/test/sim/misc/fainted-forme-regression.js @@ -0,0 +1,150 @@ +'use strict'; + +const assert = require('./../../assert'); +const common = require('./../../common'); + +let battle; + +describe(`Fainted forme regression`, function () { + afterEach(function () { + battle.destroy(); + }); + + it('[Hackmons] should be able to revert between different mega evolutions', function () { + battle = common.createBattle([[ + {species: 'charizardmegay', ability: 'drought', item: 'charizarditex', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento mega', 'auto'); + assert.species(pokemon, 'Charizard-Mega-Y'); + assert.hasAbility(pokemon, 'Drought'); + }); + + it(`should revert Mega Evolutions`, function () { + battle = common.createBattle([[ + {species: 'alakazam', ability: 'synchronize', item: 'alakazite', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento mega', 'auto'); + assert.species(pokemon, 'Alakazam'); + assert.hasAbility(pokemon, 'Synchronize'); + }); + + it(`should revert Rayquaza-Mega`, function () { + battle = common.gen(7).createBattle([[ + {species: 'rayquaza', ability: 'airlock', moves: ['memento', 'dragonascent']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento mega', 'auto'); + assert.species(pokemon, 'Rayquaza'); + assert.hasAbility(pokemon, 'Air Lock'); + }); + + it(`should revert Primal forms`, function () { + battle = common.createBattle([[ + {species: 'kyogre', ability: 'drizzle', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices(); + assert.species(pokemon, 'Kyogre'); + assert.hasAbility(pokemon, 'Drizzle'); + }); + + it(`shouldn't revert Arceus-forms to base Arceus`, function () { + battle = common.createBattle([[ + {species: 'arceusfire', ability: 'multitype', item: 'flameplate', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices(); + assert.species(pokemon, 'Arceus-Fire'); + assert.hasAbility(pokemon, 'Multitype'); + }); + + it("should revert Terastallized Morpeko-Hangry to base Morpeko", function () { + battle = common.createBattle([[ + {species: 'Morpeko', ability: 'hungerswitch', moves: ['memento', 'sleeptalk']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move sleeptalk', 'auto'); + assert.species(pokemon, 'Morpeko-Hangry'); + battle.makeChoices('move memento terastallize', 'auto'); + assert.species(pokemon, 'Morpeko'); + assert.hasAbility(pokemon, 'Hunger Switch'); + }); + + it(`shouldn't revert Palafin-Hero to base Palafin`, function () { + battle = common.createBattle([[ + {species: 'palafin', ability: 'zerotohero', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('switch 2', 'auto'); + battle.makeChoices('switch 2', 'auto'); + assert.species(pokemon, 'Palafin-Hero'); + battle.makeChoices('move memento', 'auto'); + assert.species(pokemon, 'Palafin-Hero'); + assert.hasAbility(pokemon, 'Zero to Hero'); + }); + + it(`should revert Ogerpon-Tera to base Ogerpon`, function () { + battle = common.createBattle([[ + { + species: 'ogerponwellspring', ability: 'waterabsorb', item: 'wellspring mask', + moves: ['memento'], teraType: 'Water', + }, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento terastallize', 'auto'); + assert.species(pokemon, 'Ogerpon-Wellspring'); + assert.hasAbility(pokemon, 'Water Absorb'); + }); + + it(`shouldn't revert Terapagos-Terastal to base Terapagos`, function () { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices(); + assert.species(pokemon, 'Terapagos-Terastal'); + assert.hasAbility(pokemon, 'Tera Shell'); + }); + + it(`should revert Terapagos-Stellar to base Terapagos`, function () { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento'], teraType: 'Stellar'}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento terastallize', 'auto'); + assert.species(pokemon, 'Terapagos'); + assert.hasAbility(pokemon, 'Tera Shift'); + }); +});