Fix Sparkling Aria's interaction with Shield Dust (#10882)
Some checks are pending
Node.js CI / build (18.x) (push) Waiting to run

This commit is contained in:
André Bastos Dias 2025-04-24 00:57:31 +01:00 committed by GitHub
parent c273081062
commit 6b3d0eefbd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 49 additions and 34 deletions

View File

@ -2428,16 +2428,21 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
magician: {
onAfterMoveSecondarySelf(source, target, move) {
if (!move || !target || source.switchFlag === true) return;
if (target !== source && move.category !== 'Status') {
if (source.item || source.volatiles['gem'] || move.id === 'fling') return;
const yourItem = target.takeItem(source);
if (!yourItem) return;
if (!source.setItem(yourItem)) {
target.item = yourItem.id; // bypass setItem so we don't break choicelock or anything
if (!move || source.switchFlag === true || !move.hitTargets || source.item || source.volatiles['gem'] ||
move.id === 'fling') return;
const hitTargets = move.hitTargets;
this.speedSort(hitTargets);
for (const pokemon of hitTargets) {
if (pokemon !== source && move.category !== 'Status') {
const yourItem = pokemon.takeItem(source);
if (!yourItem) continue;
if (!source.setItem(yourItem)) {
pokemon.item = yourItem.id; // bypass setItem so we don't break choicelock or anything
continue;
}
this.add('-item', source, yourItem, '[from] ability: Magician', `[of] ${pokemon}`);
return;
}
this.add('-item', source, yourItem, '[from] ability: Magician', `[of] ${target}`);
}
},
flags: {},
@ -4150,7 +4155,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
shielddust: {
onModifySecondaries(secondaries) {
this.debug('Shield Dust prevent secondary');
return secondaries.filter(effect => !!(effect.self || effect.dustproof));
return secondaries.filter(effect => !!effect.self);
},
flags: { breakable: 1 },
name: "Shield Dust",

View File

@ -1152,7 +1152,7 @@ export const Items: import('../sim/dex-items').ItemDataTable = {
},
onModifySecondaries(secondaries) {
this.debug('Covert Cloak prevent secondary');
return secondaries.filter(effect => !!(effect.self || effect.dustproof));
return secondaries.filter(effect => !!effect.self);
},
num: 1885,
gen: 9,

View File

@ -1869,7 +1869,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
},
onModifySecondaries(secondaries) {
this.debug('Fancy Scarf prevent secondary');
return secondaries.filter(effect => !!(effect.self || effect.dustproof));
return secondaries.filter(effect => !!effect.self);
},
flags: {},
},

View File

@ -18044,13 +18044,20 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = {
priority: 0,
flags: { protect: 1, mirror: 1, sound: 1, bypasssub: 1, metronome: 1 },
secondary: {
dustproof: true,
chance: 100,
volatileStatus: 'sparklingaria',
},
onAfterMove(source, target, move) {
for (const pokemon of this.getAllActive()) {
if (pokemon !== source && pokemon.removeVolatile('sparklingaria') && pokemon.status === 'brn' && !source.fainted) {
if (source.fainted || !move.hitTargets || move.hasSheerForce) {
// make sure the volatiles are cleared
for (const pokemon of this.getAllActive()) delete pokemon.volatiles['sparklingaria'];
return;
}
const numberTargets = move.hitTargets.length;
for (const pokemon of move.hitTargets) {
// bypasses Shield Dust when hitting multiple targets
if (pokemon !== source && pokemon.isActive && (pokemon.removeVolatile('sparklingaria') || numberTargets > 1) &&
pokemon.status === 'brn') {
pokemon.cureStatus();
}
}

View File

@ -606,6 +606,7 @@ export class BattleActions {
}
}
move.hitTargets = targets;
const moveResult = !!targets.length;
if (!moveResult && !atLeastOneFailure) pokemon.moveThisTurnResult = null;
const hitSlot = targets.map(p => p.getSlot());

View File

@ -87,11 +87,6 @@ export interface SecondaryEffect extends HitEffect {
chance?: number;
/** Used to flag a secondary effect as added by Poison Touch */
ability?: Ability;
/**
* Applies to Sparkling Aria's secondary effect: Affected by
* Sheer Force but not Shield Dust.
*/
dustproof?: boolean;
/**
* Gen 2 specific mechanics: Bypasses Substitute only on Twineedle,
* and allows it to flinch sleeping/frozen targets
@ -317,6 +312,7 @@ export interface ActiveMove extends MutableMove {
status?: ID;
hit: number;
moveHitData?: MoveHitData;
hitTargets?: Pokemon[];
ability?: Ability;
allies?: Pokemon[];
auraBooster?: Pokemon;

View File

@ -74,4 +74,18 @@ describe('Magician', () => {
battle.makeChoices();
assert.false.holdsItem(battle.p1.active[0], 'Klefki should not have stolen Weakness Policy.');
});
it(`should steal the item from the faster opponent hit`, () => {
battle = common.createBattle({ gameType: 'doubles' }, [[
{ species: "Hoopa", ability: 'magician', moves: ['expandingforce'] },
{ species: "Tapu Lele", ability: 'psychicsurge', moves: ['sleeptalk'] },
], [
{ species: "Shuckle", item: 'tr68', moves: ['sleeptalk'] },
{ species: "Zapdos", item: 'tr69', moves: ['sleeptalk'] }],
]);
battle.makeChoices();
assert.equal(battle.p1.active[0].item, 'tr69');
assert.equal(battle.p2.active[0].item, 'tr68');
assert.equal(battle.p2.active[1].item, '');
});
});

View File

@ -72,27 +72,19 @@ describe('Shield Dust', () => {
assert.statStage(battle.p2.active[0], 'spa', -1);
});
it.skip(`should only prevent Sparkling Aria from curing burn if there is only one target`, () => {
battle = common.createBattle([[
{ species: 'wynaut', ability: 'noguard', moves: ['willowisp', 'sparklingaria'] },
], [
{ species: 'dustox', ability: 'shielddust', moves: ['sleeptalk'] },
]]);
battle.makeChoices('move willowisp', 'auto');
battle.makeChoices('move sparklingaria', 'auto');
assert.equal(battle.p2.active[0].status, 'brn', `Shield Dust should prevent cured burn if it's the only target`);
it(`should only prevent Sparkling Aria from curing burn if there is only one target`, () => {
battle = common.createBattle({ gameType: 'doubles' }, [[
{ species: 'wynaut', ability: 'noguard', moves: ['willowisp', 'sparklingaria'] },
{ species: 'diglett', moves: ['sleeptalk'] },
{ species: 'diglett', moves: ['sleeptalk', 'protect'] },
], [
{ species: 'dustox', ability: 'shielddust', moves: ['sleeptalk'] },
{ species: 'magikarp', moves: ['sleeptalk'] },
{ species: 'magikarp', moves: ['sleeptalk', 'protect'] },
]]);
battle.makeChoices('move willowisp 1, move sleeptalk', 'auto');
battle.makeChoices('move sparklingaria, move sleeptalk', 'auto');
battle.makeChoices('move sparklingaria, move protect', 'move sleeptalk, move protect');
assert.equal(battle.p2.active[0].status, 'brn', `Shield Dust should prevent cured burn if it's the only target`);
battle.makeChoices('move sparklingaria, move sleeptalk', 'auto');
assert.equal(battle.p2.active[0].status, '', `Shield Dust should not prevent cured burn if it's one of many targets`);
});
});

View File

@ -28,7 +28,7 @@ describe('Roost', () => {
assert.equal(battle.p2.active[0].hp, battle.p2.active[0].maxhp);
});
it('should suppress user\'s current Flying type if succesful', () => {
it('should suppress user\'s current Flying type if successful', () => {
battle = common.createBattle();
battle.setPlayer('p1', { team: [{ species: "Aggron", item: 'leftovers', ability: 'sturdy', moves: ['mudslap', 'hiddenpowergrass'] }] });
battle.setPlayer('p2', { team: [{ species: "Aerodactyl", item: 'focussash', ability: 'wonderguard', moves: ['roost', 'doubleedge'] }] });