diff --git a/data/abilities.ts b/data/abilities.ts index 2482241efa85..46747db16e53 100644 --- a/data/abilities.ts +++ b/data/abilities.ts @@ -1167,14 +1167,12 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { }, embodyaspectcornerstone: { onStart(pokemon) { - if (pokemon.baseSpecies.name === 'Ogerpon-Cornerstone-Tera' && !this.effectState.embodied) { - this.effectState.embodied = true; + if (pokemon.baseSpecies.name === 'Ogerpon-Cornerstone-Tera' && + this.effectState.embodied !== pokemon.previouslySwitchedIn) { + this.effectState.embodied = pokemon.previouslySwitchedIn; this.boost({def: 1}, pokemon); } }, - onSwitchIn() { - delete this.effectState.embodied; - }, flags: {failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1}, name: "Embody Aspect (Cornerstone)", rating: 3.5, @@ -1182,14 +1180,12 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { }, embodyaspecthearthflame: { onStart(pokemon) { - if (pokemon.baseSpecies.name === 'Ogerpon-Hearthflame-Tera' && !this.effectState.embodied) { - this.effectState.embodied = true; + if (pokemon.baseSpecies.name === 'Ogerpon-Hearthflame-Tera' && + this.effectState.embodied !== pokemon.previouslySwitchedIn) { + this.effectState.embodied = pokemon.previouslySwitchedIn; this.boost({atk: 1}, pokemon); } }, - onSwitchIn() { - delete this.effectState.embodied; - }, flags: {failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1}, name: "Embody Aspect (Hearthflame)", rating: 3.5, @@ -1197,14 +1193,12 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { }, embodyaspectteal: { onStart(pokemon) { - if (pokemon.baseSpecies.name === 'Ogerpon-Teal-Tera' && !this.effectState.embodied) { - this.effectState.embodied = true; + if (pokemon.baseSpecies.name === 'Ogerpon-Teal-Tera' && + this.effectState.embodied !== pokemon.previouslySwitchedIn) { + this.effectState.embodied = pokemon.previouslySwitchedIn; this.boost({spe: 1}, pokemon); } }, - onSwitchIn() { - delete this.effectState.embodied; - }, flags: {failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1}, name: "Embody Aspect (Teal)", rating: 3.5, @@ -1212,14 +1206,12 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { }, embodyaspectwellspring: { onStart(pokemon) { - if (pokemon.baseSpecies.name === 'Ogerpon-Wellspring-Tera' && !this.effectState.embodied) { - this.effectState.embodied = true; + if (pokemon.baseSpecies.name === 'Ogerpon-Wellspring-Tera' && + this.effectState.embodied !== pokemon.previouslySwitchedIn) { + this.effectState.embodied = pokemon.previouslySwitchedIn; this.boost({spd: 1}, pokemon); } }, - onSwitchIn() { - delete this.effectState.embodied; - }, flags: {failroleplay: 1, noreceiver: 1, noentrain: 1, notrace: 1, failskillswap: 1, notransform: 1}, name: "Embody Aspect (Wellspring)", rating: 3.5, @@ -2272,18 +2264,15 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { }, libero: { onPrepareHit(source, target, move) { - if (this.effectState.libero) return; + if (this.effectState.libero === source.previouslySwitchedIn) return; if (move.hasBounced || move.flags['futuremove'] || move.sourceEffect === 'snatch' || move.callsMove) return; const type = move.type; if (type && type !== '???' && source.getTypes().join() !== type) { if (!source.setType(type)) return; - this.effectState.libero = true; + this.effectState.libero = source.previouslySwitchedIn; this.add('-start', source, 'typechange', type, '[from] ability: Libero'); } }, - onSwitchIn() { - delete this.effectState.libero; - }, flags: {}, name: "Libero", rating: 4, @@ -3416,18 +3405,15 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { }, protean: { onPrepareHit(source, target, move) { - if (this.effectState.protean) return; + if (this.effectState.protean === source.previouslySwitchedIn) return; if (move.hasBounced || move.flags['futuremove'] || move.sourceEffect === 'snatch' || move.callsMove) return; const type = move.type; if (type && type !== '???' && source.getTypes().join() !== type) { if (!source.setType(type)) return; - this.effectState.protean = true; + this.effectState.protean = source.previouslySwitchedIn; this.add('-start', source, 'typechange', type, '[from] ability: Protean'); } }, - onSwitchIn(pokemon) { - delete this.effectState.protean; - }, flags: {}, name: "Protean", rating: 4, diff --git a/data/mods/gen8/abilities.ts b/data/mods/gen8/abilities.ts index b43d0032258d..14767f4859bd 100644 --- a/data/mods/gen8/abilities.ts +++ b/data/mods/gen8/abilities.ts @@ -559,7 +559,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa this.add('-start', source, 'typechange', type, '[from] ability: Libero'); } }, - onSwitchIn() {}, rating: 4.5, }, lightmetal: { @@ -780,7 +779,6 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa this.add('-start', source, 'typechange', type, '[from] ability: Protean'); } }, - onSwitchIn() {}, rating: 4.5, }, psychicsurge: { diff --git a/test/sim/abilities/protean.js b/test/sim/abilities/protean.js index 8d91bbe3cea1..0c1f41a4172d 100644 --- a/test/sim/abilities/protean.js +++ b/test/sim/abilities/protean.js @@ -113,6 +113,73 @@ describe('Protean', function () { // More examples: https://www.smogon.com/forums/threads/sword-shield-battle-mechanics-research.3655528/post-8548957 }); + it(`should not allow the user to change its typing twice`, function () { + battle = common.createBattle([[ + {species: 'Cinderace', ability: 'protean', moves: ['tackle', 'watergun']}, + ], [ + {species: 'Gengar', moves: ['sleeptalk']}, + ]]); + + battle.makeChoices(); + const cinder = battle.p1.active[0]; + assert(cinder.hasType('Normal')); + + battle.makeChoices('move watergun', 'auto'); + assert.false(cinder.hasType('Water')); + }); + + it(`should not allow the user to change its typing twice if the Ability was suppressed`, function () { + battle = common.createBattle([[ + {species: 'Cinderace', ability: 'protean', moves: ['tackle', 'watergun']}, + ], [ + {species: 'Gengar', moves: ['sleeptalk']}, + {species: 'Weezing', ability: 'neutralizinggas', moves: ['sleeptalk']}, + ]]); + + battle.makeChoices('move tackle', 'auto'); + const cinder = battle.p1.active[0]; + assert(cinder.hasType('Normal')); + + battle.makeChoices('move watergun', 'switch 2'); + battle.makeChoices('move watergun', 'switch 2'); + + assert.false(cinder.hasType('Water')); + }); + + it(`should allow the user to change its typing twice if it lost and regained the Ability`, function () { + battle = common.createBattle([[ + {species: 'Cinderace', ability: 'protean', moves: ['tackle', 'watergun']}, + ], [ + {species: 'Gengar', ability: 'protean', moves: ['sleeptalk', 'skillswap']}, + ]]); + + battle.makeChoices('move tackle', 'move skillswap'); + const cinder = battle.p1.active[0]; + assert(cinder.hasType('Normal')); + + battle.makeChoices('move watergun', 'auto'); + assert(cinder.hasType('Water')); + }); + + it(`should not be prevented from resetting its effectState by Ability suppression`, function () { + battle = common.createBattle([[ + {species: 'Cinderace', ability: 'protean', moves: ['tackle']}, + {species: 'Wynaut', moves: ['sleeptalk']}, + ], [ + {species: 'Gengar', ability: 'protean', moves: ['sleeptalk']}, + {species: 'Weezing', ability: 'neutralizinggas', moves: ['sleeptalk']}, + ]]); + + battle.makeChoices('move tackle', 'auto'); + battle.makeChoices('move tackle', 'switch 2'); // Weezing comes in + battle.makeChoices('switch 2', 'auto'); // Cinderace switches out and back in + battle.makeChoices('switch 2', 'auto'); + battle.makeChoices('move tackle', 'switch 2'); // Weezing switches out + + const cinder = battle.p1.active[0]; + assert(cinder.hasType('Normal')); + }); + describe('Gen 6-8', function () { it(`should activate on both turns of a charge move`, function () { battle = common.gen(8).createBattle([[