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

White Herb doubles fix #5185

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from 21 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
8 changes: 8 additions & 0 deletions data/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -6009,9 +6009,17 @@ let BattleItems = {
},
},
onUpdate(pokemon) {
if ((this.gameType === "doubles")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look like a good idea to me, since it's too specific, but do you even need it any more?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not I was going to add some tests for singles and test without the check

for (const action of this.queue) {
if (action.choice === 'runSwitch') {
return;
}
}
}
let activate = false;
/**@type {{[k: string]: number}} */
let boosts = {};
/**@type {{[k: string]: number}} */
for (let i in pokemon.boosts) {
// @ts-ignore
if (pokemon.boosts[i] < 0) {
Expand Down
194 changes: 194 additions & 0 deletions test/simulator/items/whiteherb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
'use strict';

const assert = require('./../../assert');
const common = require('./../../common');

let battle;

describe('White Herb', function () {
afterEach(function () {
battle.destroy();
});
it('should use white herb after memento during active turn', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [
{species: "chansey", ability: 'shellarmor', item: 'ironball', moves: ['memento']},
{species: "clefable", ability: 'levitate', item: 'ironball', moves: ['memento']},
{species: "aerodactyl", ability: 'shellarmor', item: 'ironball', moves: ['stealthrock']},
{species: "rotom", ability: 'levitate', item: 'ironball', moves: ['rest']}]);
battle.join('p2', 'Guest 2', 2, [
{species: "aegislash", ability: 'stancechange', item: 'whiteherb', moves: ['autotomize']},
{species: "pelipper", ability: 'sandveil', item: 'lifeorb', moves: ['protect']}]);

battle.makeChoices('move memento 0, move memento 0', 'move autotomize, move protect');
battle.makeChoices('switch aerodactyl, switch rotom', 'move autotomize, move protect');

const holder = battle.p2.active[0];
assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', -2);
});
it('should use white herb after growl during active turn', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [
{species: "chansey", ability: 'shellarmor', item: 'ironball', moves: ['growl']},
{species: "clefable", ability: 'levitate', item: 'ironball', moves: ['growl']},
{species: "aerodactyl", ability: 'shellarmor', item: 'ironball', moves: ['stealthrock']},
{species: "rotom", ability: 'levitate', item: 'ironball', moves: ['rest']}]);
battle.join('p2', 'Guest 2', 2, [
{species: "aegislash", ability: 'stancechange', item: 'whiteherb', moves: ['autotomize']},
{species: "pelipper", ability: 'sandveil', item: 'lifeorb', moves: ['protect']}]);

battle.makeChoices('move growl 0, move growl 0', 'move autotomize, move protect');

const holder = battle.p2.active[0];
assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', -1);
});
it('should use white herb after partingshot during active turn', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [
{species: "chansey", ability: 'shellarmor', item: 'ironball', moves: ['partingshot']},
{species: "clefable", ability: 'levitate', item: 'ironball', moves: ['partingshot']},
{species: "aerodactyl", ability: 'shellarmor', item: 'ironball', moves: ['stealthrock']},
{species: "rotom", ability: 'levitate', item: 'ironball', moves: ['rest']}]);
battle.join('p2', 'Guest 2', 2, [
{species: "aegislash", ability: 'stancechange', item: 'whiteherb', moves: ['autotomize']},
{species: "pelipper", ability: 'sandveil', item: 'lifeorb', moves: ['protect']}]);

battle.makeChoices('move partingshot 0, move partingshot 0', 'move autotomize, move protect');
battle.makeChoices('switch aerodactyl, switch rotom', 'move autotomize, move protect');

const holder = battle.p2.active[0];
assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', -1);
});
it('should use white herb after both intimidate', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [{species: "Arcanine", ability: 'intimidate', moves: ['bodyslam']},
{species: "Incineroar", ability: 'intimidate', moves: ['agility']}]);
battle.join('p2', 'Guest 2', 1, [{species: "aegislash", ability: 'stancechange', item: 'whiteherb', moves: ['gyroball']},
{species: "pelipper", ability: 'sandveil', item: 'lifeorb', moves: ['airslash']}]);


battle.makeChoices('move bodyslam, move agility', 'move gyroball, move airslash');

const holder = battle.p2.active[0];

assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', 0);
});
it('should use white herb after one intimidate', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [{species: "Arcanine", ability: 'flashfire', moves: ['bodyslam']},
{species: "Incineroar", ability: 'intimidate', moves: ['agility']}]);
battle.join('p2', 'Guest 2', 1, [{species: "aegislash", ability: 'stancechange', item: 'whiteherb', moves: ['gyroball']},
{species: "pelipper", ability: 'sandveil', item: 'lifeorb', moves: ['airslash']}]);


battle.makeChoices('move bodyslam, move agility', 'move gyroball, move airslash');

const holder = battle.p2.active[0];

assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', 0);
});
it('should use white herb after two intimidate switch in', function () {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching in during a turn (one at a time) is fundamentally different from switching in at the beginning of a battle or to replace fainted Pokemon (all at once). This test you're doing here should activate White Herb before the second Pokemon even switches out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ok makes sense, will update the PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching in during a turn (one at a time) is fundamentally different from switching in at the beginning of a battle or to replace fainted Pokemon (all at once). This test you're doing here should activate White Herb before the second Pokemon even switches out.

@Marty-D

It seems runSwitch remains in queue when Pokemon are switching in at start or after feint. Checking for this before the update leads to White Herb being called after all Pokemon switch in after start or after feint and calls it right away after a player switches during a turn. Is this correct behavior?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it('should use white herb after two intimidate switch in', function () {
it('should use white herb after two Intimidate switch in', function () {

battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [
{species: "Aerodactyl", ability: 'shellarmor', item: 'ironball', moves: ['stealthrock']},
{species: "Rotom", ability: 'levitate', item: 'ironball', moves: ['rest']},
{species: "Arcanine", ability: 'intimidate', moves: ['bodyslam']},
{species: "Incineroar", ability: 'intimidate', moves: ['agility']}]);
battle.join('p2', 'Guest 2', 2, [
{species: "aegislash", ability: 'stancechange', item: 'whiteherb', moves: ['autotomize']},
{species: "pelipper", ability: 'sandveil', item: 'lifeorb', moves: ['airslash']},
{species: "Thundurus", ability: 'prankster', item: 'ironball', moves: ['electricterrain']},
{species: 'Klefki', ability: 'prankster', moves: ['confuseray']}]);

battle.makeChoices('move stealthrock, move rest', 'move gyroball, move airslash');

battle.makeChoices('switch Arcanine, switch Incineroar', 'move gyroball, move airslash');

const holder = battle.p2.active[0];

assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', -1);
});
it('should use white herb after two intimidate switch in after faint', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [
{species: "aegislash", ability: 'stancechange', item: 'ironball', moves: ['storedpower']},
{species: "aegislash", ability: 'stancechange', item: 'ironball', moves: ['storedpower']},
{species: "Arcanine", ability: 'intimidate', moves: ['bodyslam']},
{species: "Incineroar", ability: 'intimidate', moves: ['agility']}]);
battle.join('p2', 'Guest 2', 2, [
{species: "Rotom", ability: 'levitate', item: 'whiteherb', moves: ['overheat']},
{species: "Rotom", ability: 'levitate', item: 'whiteherb', moves: ['overheat']},
{species: "Thundurus", ability: 'prankster', item: 'ironball', moves: ['electricterrain']},
{species: 'Klefki', ability: 'prankster', moves: ['confuseray']}]);

battle.makeChoices('move stringshot, move stringshot', 'move overheat, move overheat');

battle.makeChoices('switch Arcanine, switch Incineroar', 'move overheat, move overheat');
battle.makeChoices('move stringshot, move stringshot', 'move overheat, move overheat');

const holder = battle.p2.active[0];

assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', -1);
});
it('should use white herb after all pokemon switch in after faint', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [
{species: "oddish", ability: 'stancechange', item: 'ironball', moves: ['storedpower']},
{species: "oddish", ability: 'stancechange', item: 'ironball', moves: ['storedpower']},
{species: "Arcanine", ability: 'intimidate', moves: ['bodyslam']},
{species: "Incineroar", ability: 'intimidate', moves: ['agility']}]);
battle.join('p2', 'Guest 2', 2, [
{species: "Rotom", ability: 'levitate', item: 'whiteherb', moves: ['searingshot']},
{species: "Rotom", ability: 'levitate', item: 'whiteherb', moves: ['searingshot']},
{species: "Thundurus", ability: 'prankster', item: 'whiteherb', moves: ['electricterrain']},
{species: 'Klefki', ability: 'prankster', moves: ['confuseray']}]);

battle.makeChoices('move storedpower, move storedpower', 'move searingshot, move searingshot');

battle.makeChoices('switch Arcanine, switch Incineroar', 'switch Thundurus, switch Klefki');
battle.makeChoices('move stringshot, move stringshot', 'move overheat, move overheat');

const holder = battle.p2.active[0];

assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', 0);
});
it('should use white herb after one intimidate switch in', function () {
battle = common.createBattle({gameType: 'doubles'});

battle.join('p1', 'Guest 1', 1, [
{species: "Aerodactyl", ability: 'shellarmor', item: 'ironball', moves: ['stealthrock']},
{species: "Rotom", ability: 'levitate', item: 'ironball', moves: ['rest']},
{species: "Arcanine", ability: 'intimidate', moves: ['bodyslam']},
{species: "Incineroar", ability: 'intimidate', moves: ['agility']}]);
battle.join('p2', 'Guest 2', 2, [
{species: "aegislash", ability: 'stancechange', item: 'whiteherb', moves: ['autotomize']},
{species: "pelipper", ability: 'sandveil', item: 'lifeorb', moves: ['airslash']},
{species: "Thundurus", ability: 'prankster', item: 'ironball', moves: ['electricterrain']},
{species: 'Klefki', ability: 'prankster', moves: ['confuseray']}]);

battle.makeChoices('move stealthrock, move rest', 'move gyroball, move airslash');

battle.makeChoices('switch Arcanine, move rest', 'move gyroball, move airslash');

const holder = battle.p2.active[0];

assert.false.holdsItem(holder);
assert.statStage(holder, 'atk', 0);
});
});