Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Protean + Neutralizing Gas interaction #10805

Merged
merged 8 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 16 additions & 30 deletions data/abilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1167,59 +1167,51 @@ 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,
num: 304,
},
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,
num: 303,
},
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,
num: 301,
},
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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 0 additions & 2 deletions data/mods/gen8/abilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -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: {
Expand Down
67 changes: 67 additions & 0 deletions test/sim/abilities/protean.js
Original file line number Diff line number Diff line change
Expand Up @@ -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([[
Expand Down
Loading