This commit is contained in:
André Bastos Dias 2026-06-02 14:06:55 +01:00 committed by GitHub
commit 43849873cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 150 additions and 52 deletions

View File

@ -4793,6 +4793,16 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
},
symbiosis: {
onAllyAfterUseItem(item, pokemon) {
this.effectState.pokemon = pokemon;
// during a move execution, only trigger during the AfterMove event
if (this.activeMove) return;
((this.effect as any).onAnyAfterMove as () => void).call(this);
},
onAnyAfterMove() {
const pokemon = this.effectState.pokemon;
if (!pokemon) return;
delete this.effectState.pokemon;
if (pokemon.switchFlag) return;
const source = this.effectState.target;
const myItem = source.takeItem();
@ -4806,6 +4816,9 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = {
}
this.add('-activate', source, 'ability: Symbiosis', myItem, `[of] ${pokemon}`);
},
onEnd() {
delete this.effectState.pokemon;
},
flags: {},
name: "Symbiosis",
rating: 0,

View File

@ -1690,11 +1690,9 @@ export const Items: import('../sim/dex-items').ItemDataTable = {
for (const pokemon of this.getAllActive()) {
if (pokemon.switchFlag === true) return;
}
target.switchFlag = true;
if (target.useItem()) {
target.switchFlag = true;
source.switchFlag = false;
} else {
target.switchFlag = false;
}
}
},

View File

@ -110,6 +110,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa
}
this.add('-activate', source, 'ability: Symbiosis', myItem, `[of] ${pokemon}`);
},
onAnyAfterMove: undefined, // no inherit
},
weakarmor: {
inherit: true,

View File

@ -36,7 +36,49 @@ describe('Symbiosis', () => {
assert.equal(battle.p1.active[1].item, '');
});
it('should not trigger on an ally losing their Eject Button in Generation 7 or later', () => {
it('should not consume two White Herbs in one boost', () => {
battle = common.createBattle({ gameType: 'doubles' }, [[
{ species: 'Smeargle', item: 'whiteherb', moves: ['sleeptalk'] },
{ species: 'Oranguru', ability: 'symbiosis', item: 'whiteherb', moves: ['sleeptalk'] },
], [
{ species: 'Murkrow', moves: ['screech'] },
{ species: 'Smeargle', moves: ['sleeptalk'] },
]]);
battle.makeChoices();
battle.makeChoices();
assert.equal(battle.p1.active[0].boosts.def, 0);
});
it('during switches, should trigger right after the item is consumed', () => {
battle = common.createBattle({ gameType: 'doubles' }, [[
{ species: 'Smeargle', ability: 'symbiosis', item: 'lifeorb', moves: ['sleeptalk'] },
{ species: 'Roaring Moon', ability: 'protosynthesis', item: 'boosterenergy', moves: ['sleeptalk'] },
], [
{ species: 'Raging Bolt', ability: 'protosynthesis', item: 'boosterenergy', moves: ['sleeptalk'] },
{ species: 'Smeargle', moves: ['sleeptalk'] },
]]);
assert.equal(battle.p1.active[1].item, 'lifeorb');
const log = battle.getDebugLog();
const symbiosisIndex = log.lastIndexOf('|-activate|p1a: Smeargle|ability: Symbiosis');
const protosynthesisIndex = log.lastIndexOf('|-activate|p1b: Roaring Moon|ability: Protosynthesis');
assert(symbiosisIndex < protosynthesisIndex, 'Symbiosis should trigger before Protosynthesis');
});
it('during moves, should trigger after the action is concluded', () => {
battle = common.createBattle({ gameType: 'doubles' }, [[
{ species: 'Smeargle', ability: 'symbiosis', item: 'lifeorb', moves: ['sleeptalk'] },
{ species: 'Venusaur', ability: 'overgrow', item: 'powerherb', moves: ['solarbeam'] },
], [
{ species: 'Smeargle', moves: ['sleeptalk'] },
{ species: 'Smeargle', moves: ['sleeptalk'] },
]]);
battle.makeChoices();
const venusaur = battle.p1.active[1];
assert.equal(venusaur.item, 'lifeorb');
assert.fullHP(venusaur);
});
it('should not trigger on an ally losing their Eject Button', () => {
battle = common.createBattle({ gameType: 'doubles' }, [[
{ species: 'oranguru', ability: 'symbiosis', item: 'leftovers', moves: ['sleeptalk'] },
{ species: 'wynaut', item: 'ejectbutton', moves: ['sleeptalk'] },
@ -51,22 +93,7 @@ describe('Symbiosis', () => {
assert.equal(battle.p1.active[1].item, '');
});
it('should trigger on an ally losing their Eject Button in Generation 6', () => {
battle = common.gen(6).createBattle({ gameType: 'doubles' }, [[
{ species: 'oranguru', ability: 'symbiosis', item: 'leftovers', moves: ['sleeptalk'] },
{ species: 'wynaut', item: 'ejectbutton', moves: ['sleeptalk'] },
{ species: 'corphish', moves: ['sleeptalk'] },
], [
{ species: 'wynaut', moves: ['tackle'] },
{ species: 'wynaut', moves: ['sleeptalk'] },
]]);
battle.makeChoices('auto', 'move tackle 2, move sleeptalk');
assert.equal(battle.p1.active[0].item, '');
assert.equal(battle.p1.active[1].item, 'leftovers');
});
it.skip(`should not trigger on an ally using their Eject Pack`, () => {
it(`should not trigger on an ally using their Eject Pack`, () => {
battle = common.createBattle({ gameType: 'doubles' }, [[
{ species: 'oranguru', ability: 'symbiosis', item: 'leftovers', moves: ['sleeptalk'] },
{ species: 'wynaut', item: 'ejectpack', moves: ['superpower'] },
@ -81,49 +108,108 @@ describe('Symbiosis', () => {
assert.equal(battle.p1.active[1].item, '');
});
// See Marty's research for many more examples: https://www.smogon.com/forums/threads/battle-mechanics-research.3489239/post-6401506
describe.skip('Symbiosis Eject Button Glitch (Gen 6 only)', () => {
it('should cause Leftovers to restore HP 4 times', () => {
describe('[Gen 6]', () => {
it('during moves, should trigger right after the item is consumed', () => {
battle = common.gen(6).createBattle({ gameType: 'doubles' }, [[
{ species: 'florges', ability: 'symbiosis', item: 'leftovers', moves: ['sleeptalk'] },
{ species: 'roggenrola', level: 50, ability: 'sturdy', item: 'ejectbutton', moves: ['sleeptalk'] },
{ species: 'corphish', moves: ['sleeptalk'] },
{ species: 'Smeargle', ability: 'symbiosis', item: 'lifeorb', moves: ['sleeptalk'] },
{ species: 'Venusaur', ability: 'overgrow', item: 'powerherb', moves: ['solarbeam'] },
], [
{ species: 'wynaut', moves: ['sleeptalk', 'closecombat'] },
{ species: 'wynaut', moves: ['sleeptalk'] },
{ species: 'Smeargle', moves: ['sleeptalk'] },
{ species: 'Smeargle', moves: ['sleeptalk'] },
]]);
battle.makeChoices('auto', 'move closecombat 2, move sleeptalk');
assert.equal(battle.p1.active[0].item, '');
assert.equal(battle.p1.active[1].item, 'leftovers');
battle.makeChoices('switch 3');
battle.makeChoices('move sleeptalk, switch 3', 'auto');
// Close Combat brought Roggenrola down to Sturdy = 1 HP
const roggenrola = battle.p1.active[1];
const targetHP = 1 + (Math.floor(roggenrola.maxhp / 16) * 4);
assert.equal(targetHP, roggenrola.hp);
battle.makeChoices();
const venusaur = battle.p1.active[1];
assert.equal(venusaur.item, 'lifeorb');
assert.false.fullHP(venusaur);
});
it('should cause Choice items to apply 2 times', () => {
it('should not consume a second Gem in the same turn', () => {
battle = common.gen(6).createBattle({ gameType: 'doubles' }, [[
{ species: 'florges', ability: 'symbiosis', item: 'choiceband', moves: ['sleeptalk'] },
{ species: 'roggenrola', evs: { atk: 8 }, item: 'ejectbutton', moves: ['smackdown'] },
{ species: 'Smeargle', ability: 'symbiosis', item: 'electricgem', moves: ['sleeptalk'] },
{ species: 'Venusaur', ability: 'overgrow', item: 'electricgem', moves: ['thunderbolt'] },
], [
{ species: 'Smeargle', moves: ['sleeptalk'] },
{ species: 'Smeargle', moves: ['sleeptalk'] },
]]);
battle.makeChoices();
assert.equal(battle.p1.active[0].item, '');
assert.equal(battle.p1.active[1].item, 'electricgem');
});
it('should trigger on an ally losing their Eject Button', () => {
battle = common.gen(6).createBattle({ gameType: 'doubles' }, [[
{ species: 'oranguru', ability: 'symbiosis', item: 'leftovers', moves: ['sleeptalk'] },
{ species: 'wynaut', item: 'ejectbutton', moves: ['sleeptalk'] },
{ species: 'corphish', moves: ['sleeptalk'] },
], [
{ species: 'wynaut', moves: ['sleeptalk', 'tackle'] },
{ species: 'torkoal', moves: ['sleeptalk'] },
{ species: 'wynaut', moves: ['tackle'] },
{ species: 'wynaut', moves: ['sleeptalk'] },
]]);
battle.makeChoices('auto', 'move tackle 2, move sleeptalk');
battle.makeChoices('switch 3');
battle.makeChoices('move sleeptalk, switch 3', 'auto');
battle.makeChoices('move sleeptalk, move smackdown 1', 'auto');
// Choice Band applied twice, effectively making Roggenrola's Attack 423
const wynaut = battle.p2.active[0];
const damage = wynaut.maxhp - wynaut.hp;
assert.bounded(damage, [172, 204]);
assert.equal(battle.p1.active[0].item, '');
assert.equal(battle.p1.active[1].item, 'leftovers');
});
it('should trigger even if the ally fainted', () => {
battle = common.gen(6).createBattle({ gameType: 'doubles' }, [[
{ species: 'oranguru', ability: 'symbiosis', item: 'sitrusberry', moves: ['sleeptalk'] },
{ species: 'wynaut', level: 1, item: 'colburberry', moves: ['sleeptalk'] },
], [
{ species: 'wynaut', moves: ['darkpulse'] },
{ species: 'wynaut', moves: ['sleeptalk'] },
]]);
battle.makeChoices('auto', 'move darkpulse 2, move sleeptalk');
assert.equal(battle.p1.active[0].item, '');
assert.equal(battle.p1.active[1].item, 'sitrusberry');
assert.fainted(battle.p1.active[1]);
});
// See Marty's research for many more examples: https://www.smogon.com/forums/threads/battle-mechanics-research.3489239/post-6401506
describe.skip('Symbiosis Eject Button Glitch', () => {
it('should cause Leftovers to restore HP 4 times', () => {
battle = common.gen(6).createBattle({ gameType: 'doubles' }, [[
{ species: 'florges', ability: 'symbiosis', item: 'leftovers', moves: ['sleeptalk'] },
{ species: 'roggenrola', level: 50, ability: 'sturdy', item: 'ejectbutton', moves: ['sleeptalk'] },
{ species: 'corphish', moves: ['sleeptalk'] },
], [
{ species: 'wynaut', moves: ['sleeptalk', 'closecombat'] },
{ species: 'wynaut', moves: ['sleeptalk'] },
]]);
battle.makeChoices('auto', 'move closecombat 2, move sleeptalk');
assert.equal(battle.p1.active[0].item, '');
assert.equal(battle.p1.active[1].item, 'leftovers');
battle.makeChoices('switch 3');
battle.makeChoices('move sleeptalk, switch 3', 'auto');
// Close Combat brought Roggenrola down to Sturdy = 1 HP
const roggenrola = battle.p1.active[1];
const targetHP = 1 + (Math.floor(roggenrola.maxhp / 16) * 4);
assert.equal(targetHP, roggenrola.hp);
});
it('should cause Choice items to apply 2 times', () => {
battle = common.gen(6).createBattle({ gameType: 'doubles' }, [[
{ species: 'florges', ability: 'symbiosis', item: 'choiceband', moves: ['sleeptalk'] },
{ species: 'roggenrola', evs: { atk: 8 }, item: 'ejectbutton', moves: ['smackdown'] },
{ species: 'corphish', moves: ['sleeptalk'] },
], [
{ species: 'wynaut', moves: ['sleeptalk', 'tackle'] },
{ species: 'torkoal', moves: ['sleeptalk'] },
]]);
battle.makeChoices('auto', 'move tackle 2, move sleeptalk');
battle.makeChoices('switch 3');
battle.makeChoices('move sleeptalk, switch 3', 'auto');
battle.makeChoices('move sleeptalk, move smackdown 1', 'auto');
// Choice Band applied twice, effectively making Roggenrola's Attack 423
const wynaut = battle.p2.active[0];
const damage = wynaut.maxhp - wynaut.hp;
assert.bounded(damage, [172, 204]);
});
});
});
});