From 0ed8d09d4777608d7749a66d171c438fca655f0c Mon Sep 17 00:00:00 2001 From: WillKolada <57021938+WillKolada@users.noreply.github.com> Date: Fri, 31 May 2024 15:33:31 -0500 Subject: [PATCH 1/3] Revert Dynamax HP on fainting (#4681) * Revert Dynamax HP on fainting Calls UndoDynamax whenever a mon faints to ensure that its HP is reverted and the relevant data is cleared. Updates UndoDynamax to CalculateMonStats after applying the HP reversion to prevent fainted mons from retaining their boosted Max HP until the end of the battle. * Update src/battle_main.c --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_dynamax.c | 1 + src/battle_main.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 7286045684..557ed604fe 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -207,6 +207,7 @@ void UndoDynamax(u16 battlerId) u16 mult = UQ_4_12(1.0/1.5); // placeholder gBattleMons[battlerId].hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * mult + 1) + UQ_4_12_ROUND); // round up SetMonData(mon, MON_DATA_HP, &gBattleMons[battlerId].hp); + CalculateMonStats(mon); } // Makes sure there are no Dynamax flags set, including on switch / faint. diff --git a/src/battle_main.c b/src/battle_main.c index 3bf3a3e638..0ab3a67fa8 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3677,6 +3677,9 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->zmove.active = FALSE; gBattleStruct->zmove.toBeUsed[battler] = MOVE_NONE; gBattleStruct->zmove.effect = EFFECT_HIT; + // Clear Dynamax data + UndoDynamax(battler); + return result; } From 0a8284ce9fa11da5dc729c4784d46da79269f181 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 1 Jun 2024 09:07:51 -0400 Subject: [PATCH 2/3] Added missing Move Effect TODO tests - Volume B (#4682) * Added missing Move Effect TODO tests - Volume B * Apply suggestions from code review Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Removed unused bulldoze effect file * Removed individual tests for Baton Pass + Status1 in favor of the existing single test --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_main.c | 1 + src/battle_ai_util.c | 4 +- test/battle/move_effect/aqua_ring.c | 2 +- test/battle/move_effect/baddy_bad.c | 6 + test/battle/move_effect/baton_pass.c | 54 +++++++++ test/battle/move_effect/beak_blast.c | 3 + test/battle/move_effect/beat_up.c | 31 +++++ test/battle/move_effect/belch.c | 6 + test/battle/move_effect/belly_drum.c | 5 + test/battle/move_effect/bestow.c | 10 ++ test/battle/move_effect/bide.c | 3 + test/battle/move_effect/blizzard.c | 4 + test/battle/move_effect/body_press.c | 12 ++ test/battle/move_effect/bolt_beak.c | 5 + test/battle/move_effect/brick_break.c | 21 ---- test/battle/move_effect/brine.c | 4 + test/battle/move_effect/bulk_up.c | 4 + test/battle/move_effect/earthquake.c | 28 +++++ test/battle/move_effect/embargo.c | 2 +- test/battle/move_effect/gastro_acid.c | 3 + test/battle/move_effect/leech_seed.c | 1 + test/battle/move_effect/pursuit.c | 2 + test/battle/move_effect/raging_bull.c | 160 ++++++++++++++++++++++++++ test/battle/move_effect/substitute.c | 2 + test/battle/move_effect/telekinesis.c | 4 + test/battle/terrain/grassy.c | 27 ----- test/dynamax.c | 4 + 27 files changed, 357 insertions(+), 51 deletions(-) create mode 100644 test/battle/move_effect/baddy_bad.c create mode 100644 test/battle/move_effect/baton_pass.c create mode 100644 test/battle/move_effect/beat_up.c create mode 100644 test/battle/move_effect/bestow.c create mode 100644 test/battle/move_effect/blizzard.c create mode 100644 test/battle/move_effect/body_press.c create mode 100644 test/battle/move_effect/bolt_beak.c create mode 100644 test/battle/move_effect/brine.c create mode 100644 test/battle/move_effect/bulk_up.c create mode 100644 test/battle/move_effect/earthquake.c create mode 100644 test/battle/move_effect/raging_bull.c diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 6d9a7cacde..71817646b1 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4042,6 +4042,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(WEAK_EFFECT); // Recycle healing berry if we can't otherwise faint the target and the target wont kill us after we activate the berry } break; + case EFFECT_RAGING_BULL: case EFFECT_BRICK_BREAK: if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_REFLECT) ADJUST_SCORE(DECENT_EFFECT); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index afcd1121e6..489588c33a 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2976,7 +2976,9 @@ bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, u32 moveEffect) { u32 atkSide = GetBattlerSide(battlerAtk); - if (HasMoveEffect(battlerDef, EFFECT_BRICK_BREAK)) // Don't waste a turn if screens will be broken + // Don't waste a turn if screens will be broken + if (HasMoveEffect(battlerDef, EFFECT_BRICK_BREAK) + || HasMoveEffect(battlerDef, EFFECT_RAGING_BULL)) return FALSE; switch (moveEffect) diff --git a/test/battle/move_effect/aqua_ring.c b/test/battle/move_effect/aqua_ring.c index c31bfbd8df..158c839d79 100644 --- a/test/battle/move_effect/aqua_ring.c +++ b/test/battle/move_effect/aqua_ring.c @@ -3,4 +3,4 @@ TO_DO_BATTLE_TEST("Aqua Ring recovers 1/16th HP at end of turn"); TO_DO_BATTLE_TEST("Aqua Ring can be used under Heal Block but will not heal the user"); -TO_DO_BATTLE_TEST("Aqua Ring can be Baton Passed"); +TO_DO_BATTLE_TEST("Baton Pass passes Aqua Ring's effect"); diff --git a/test/battle/move_effect/baddy_bad.c b/test/battle/move_effect/baddy_bad.c new file mode 100644 index 0000000000..e2ee4a6d84 --- /dev/null +++ b/test/battle/move_effect/baddy_bad.c @@ -0,0 +1,6 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Baddy Bad sets up Reflect, reducing physical damage"); +TO_DO_BATTLE_TEST("Baddy Bad's Reflect lasts for 5 turns"); +TO_DO_BATTLE_TEST("Baddy Bad can still damage the target when Reflect is already set up"); diff --git a/test/battle/move_effect/baton_pass.c b/test/battle/move_effect/baton_pass.c new file mode 100644 index 0000000000..6fad1c1605 --- /dev/null +++ b/test/battle/move_effect/baton_pass.c @@ -0,0 +1,54 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Baton Pass switches out the user"); +TO_DO_BATTLE_TEST("Baton Pass fails if there's no valid party Pokémon left"); +TO_DO_BATTLE_TEST("Baton Pass passes both positive and negative stat changes"); +TO_DO_BATTLE_TEST("AI doesn't choose Baton Pass if the Ace Pokémon is the last one available to switch in"); +TO_DO_BATTLE_TEST("Baton Pass doesn't pass non-volatile status conditions"); // Status1 +TO_DO_BATTLE_TEST("Baton Pass doesn't pass infatuation"); +TO_DO_BATTLE_TEST("Baton Pass doesn't pass type changes"); +TO_DO_BATTLE_TEST("Baton Pass doesn't pass ability changes"); + +// +// Move these to the corresponding effect files. +// +TO_DO_BATTLE_TEST("Baton Pass passes confusion status"); // test/battle/status2/confusion.c + +TO_DO_BATTLE_TEST("Baton Pass passes Cursed status"); // test/battle/move_effect/curse.c +TO_DO_BATTLE_TEST("Baton Pass doesn't pass Disable's effect"); // test/battle/move_effect/disable.c +TO_DO_BATTLE_TEST("Baton Pass passes Dragon Cheer's effect"); // test/battle/move_effect/dragon_cheer.c +TO_DO_BATTLE_TEST("Baton Pass passes Fairy lock's escape prevention effect"); // test/battle/move_effect/fairy_lock.c +TO_DO_BATTLE_TEST("Baton Pass passes Focus Energy's effect"); // test/battle/move_effect/focus_energy.c +TO_DO_BATTLE_TEST("Baton Pass passes Heal Block's effect"); // test/battle/move_effect/heal_block.c +TO_DO_BATTLE_TEST("Baton Pass doesn't pass Imprison's effect"); // test/battle/move_effect/imprison.c +TO_DO_BATTLE_TEST("Baton Pass passes Ingrain's effect"); // test/battle/move_effect/ingrain.c +TO_DO_BATTLE_TEST("Baton Pass passes Magnet Rise's effect"); // test/battle/move_effect/magnet_rise.c +TO_DO_BATTLE_TEST("Baton Pass passes escape prevention primary effect if it's used by the target"); // test/battle/move_effect/mean_look.c (Spider Web, Mean Look, Block) +TO_DO_BATTLE_TEST("Baton Pass doesn't pass escape prevention primary effects if it's used by the user"); // test/battle/move_effect/mean_look.c (Spider Web, Mean Look, Block) +TO_DO_BATTLE_TEST("Baton Pass doesn't pass Mimic's learnt move"); // test/battle/move_effect/mimic.c +TO_DO_BATTLE_TEST("Baton Pass passes Minimize's evasion but not the weakness to stomping moves"); // test/battle/move_effect/minimize.c +TO_DO_BATTLE_TEST("Baton Pass passes No Retreat's escape prevention effect"); // test/battle/move_effect/no_retreat.c +TO_DO_BATTLE_TEST("Baton Pass passes Octolock's escape prevention effect"); // test/battle/move_effect/octolock.c +TO_DO_BATTLE_TEST("Baton Pass passes Perish Song's effect"); // test/battle/move_effect/perish_song.c +TO_DO_BATTLE_TEST("Baton Pass passes Power Trick's effect"); // test/battle/move_effect/power_trick.c +TO_DO_BATTLE_TEST("Baton Pass doesn't pass Rollout's multiplier"); // test/battle/move_effect/rollout.c +TO_DO_BATTLE_TEST("Baton Pass passes Sappy Seed's effect"); // test/battle/move_effect/sappy_seed.c +TO_DO_BATTLE_TEST("Baton Pass doesn't pass Transformations"); // test/battle/move_effect/transform.c +TO_DO_BATTLE_TEST("Baton Pass doesn't pass Yawn's effect"); // test/battle/move_effect/yawn.c + +TO_DO_BATTLE_TEST("Baton Pass passes Core Enforcer's effect"); // test/battle/move_effect_secondary/core_enforcer.c +TO_DO_BATTLE_TEST("Baton Pass passes escape prevention secondary effect"); // test/battle/move_effect_secondary/prevent_escape.c (Thousand Waves, Spirit Shackle, Anchor Shot) +TO_DO_BATTLE_TEST("Baton Pass doesn't pass escape prevention secondary effect if it's used by the user"); // test/battle/move_effect_secondary/prevent_escape.c (Thousand Waves, Spirit Shackle, Anchor Shot) + +// Unconfirmed by Bulbapedia, should be tested in-game: +// - Nightmare +// - Encore +// - Spotlight +// - Taunt +// - Throat Chop +// - Torment +// - Splinters +// - Power Boost +// - Power Drop +// - Guard Boost diff --git a/test/battle/move_effect/beak_blast.c b/test/battle/move_effect/beak_blast.c index eeb3d59bf0..d3c8d01919 100644 --- a/test/battle/move_effect/beak_blast.c +++ b/test/battle/move_effect/beak_blast.c @@ -111,3 +111,6 @@ SINGLE_BATTLE_TEST("Beak Blast burns only when contact moves are used") HP_BAR(opponent); } } + +TO_DO_BATTLE_TEST("Beak Blast's charging message is shown regardless if it would've missed"); +TO_DO_BATTLE_TEST("Bulletproof is immune to Beak Blast but not to the burn it causes"); diff --git a/test/battle/move_effect/beat_up.c b/test/battle/move_effect/beat_up.c new file mode 100644 index 0000000000..5e11360531 --- /dev/null +++ b/test/battle/move_effect/beat_up.c @@ -0,0 +1,31 @@ +#include "global.h" +#include "test/battle.h" + +// General +TO_DO_BATTLE_TEST("Beat Up hits the target for each non-fainted, non-statused member in the party"); +TO_DO_BATTLE_TEST("Beat Up's strikes have each an independent chance of a critical hit"); + +// B_BEAT_UP Gen2-4 +TO_DO_BATTLE_TEST("Beat Up lists each party member's name"); +TO_DO_BATTLE_TEST("Beat Up's damage is typeless"); +TO_DO_BATTLE_TEST("Beat Up's damage doesn't consider STAB"); +TO_DO_BATTLE_TEST("Beat Up's last strike-only can trigger King's Rock"); +TO_DO_BATTLE_TEST("Beat Up's base power is the same for each strike"); +TO_DO_BATTLE_TEST("Beat Up's damage is determined by each striking Pokémon's base attack and level and the target's defense"); +TO_DO_BATTLE_TEST("Beat Up ignores stat stage changes"); //eg. Swords Dance +TO_DO_BATTLE_TEST("Beat Up ignores Huge Power"); +TO_DO_BATTLE_TEST("Beat Up ignores Choice Band"); + +// B_BEAT_UP Gen5+ +TO_DO_BATTLE_TEST("Beat Up doesn't list party member's name"); +TO_DO_BATTLE_TEST("Beat Up's damage is Dark-typed"); +TO_DO_BATTLE_TEST("Beat Up's damage receives STAB"); +TO_DO_BATTLE_TEST("Beat Up's can trigger King's Rock on all strikes"); +TO_DO_BATTLE_TEST("Beat Up's base power is determined by each striking Pokémon"); +TO_DO_BATTLE_TEST("Beat Up's damage is determined by the user's attack and the target's defense"); +TO_DO_BATTLE_TEST("Beat Up's damage considers stat stage changes"); //eg. Swords Dance +TO_DO_BATTLE_TEST("Beat Up's damage considers Huge Power"); +TO_DO_BATTLE_TEST("Beat Up's damage considers Choice Band"); + +// Unconfirmed by Bulbapedia +// - Technician interacion diff --git a/test/battle/move_effect/belch.c b/test/battle/move_effect/belch.c index 34e026abe5..2a732e0e45 100644 --- a/test/battle/move_effect/belch.c +++ b/test/battle/move_effect/belch.c @@ -39,6 +39,7 @@ SINGLE_BATTLE_TEST("Belch cannot be used if the user has not eaten a berry") else { TURN { MOVE(player, MOVE_STUFF_CHEEKS); } TURN { MOVE(player, MOVE_BELCH); } + TURN { MOVE(player, MOVE_BELCH); } } } SCENE { if (item == ITEM_NONE) { @@ -47,6 +48,11 @@ SINGLE_BATTLE_TEST("Belch cannot be used if the user has not eaten a berry") else { ANIMATION(ANIM_TYPE_MOVE, MOVE_STUFF_CHEEKS, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_BELCH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELCH, player); } } } + +TO_DO_BATTLE_TEST("Belch can still be used after switching out"); +TO_DO_BATTLE_TEST("Belch can still be used after fainting"); +TO_DO_BATTLE_TEST("Belch can still be used after restoring the consumed berry"); diff --git a/test/battle/move_effect/belly_drum.c b/test/battle/move_effect/belly_drum.c index bbaa910d27..82abaf30c4 100644 --- a/test/battle/move_effect/belly_drum.c +++ b/test/battle/move_effect/belly_drum.c @@ -104,3 +104,8 @@ SINGLE_BATTLE_TEST("Belly Drum's HP cost doesn't trigger effects that trigger on NOT MESSAGE("Wobbuffet's Air Balloon popped!"); } } + +TO_DO_BATTLE_TEST("Belly Drum maximizes the user's Attack stat, even when below 0"); +TO_DO_BATTLE_TEST("Belly Drum minimizes the user's Attack stat if it has Contrary"); // Should still say "maximized attack" +TO_DO_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even with Contrary"); +TO_DO_BATTLE_TEST("Belly Drum deducts HP if the user has contrary and is at -6"); diff --git a/test/battle/move_effect/bestow.c b/test/battle/move_effect/bestow.c new file mode 100644 index 0000000000..1161cdf8ae --- /dev/null +++ b/test/battle/move_effect/bestow.c @@ -0,0 +1,10 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Bestow transfers its held item to the target"); +TO_DO_BATTLE_TEST("Bestow fails if the user has no held item"); +TO_DO_BATTLE_TEST("Bestow fails if the target already has a held item"); +TO_DO_BATTLE_TEST("Bestow fails if the target is behind a Substitute"); +TO_DO_BATTLE_TEST("Bestow fails if the user is holding Mail"); +TO_DO_BATTLE_TEST("Bestow fails if the user's held item changes its form"); +TO_DO_BATTLE_TEST("Bestow fails if the user's held item is a Z-Crystal"); diff --git a/test/battle/move_effect/bide.c b/test/battle/move_effect/bide.c index 39efe281ec..41a6e01416 100644 --- a/test/battle/move_effect/bide.c +++ b/test/battle/move_effect/bide.c @@ -32,3 +32,6 @@ SINGLE_BATTLE_TEST("Bide deals twice the taken damage over two turns") EXPECT_EQ(bideDamage, 2 * (damage1 + damage2)); } } + +TO_DO_BATTLE_TEST("Bide hits the last Pokémon that attacked the user, even allies"); +TO_DO_BATTLE_TEST("Bide has +1 priority if called via a different move"); // Gen 5 onwards diff --git a/test/battle/move_effect/blizzard.c b/test/battle/move_effect/blizzard.c new file mode 100644 index 0000000000..1e566f98fc --- /dev/null +++ b/test/battle/move_effect/blizzard.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Blizzard ignores accuracy check durin Hail and Snow"); diff --git a/test/battle/move_effect/body_press.c b/test/battle/move_effect/body_press.c new file mode 100644 index 0000000000..e1bf54f4e8 --- /dev/null +++ b/test/battle/move_effect/body_press.c @@ -0,0 +1,12 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Body Press's damage depends on the user's base Defense instead of its base Attack"); +TO_DO_BATTLE_TEST("Body Press's damage depends on the user's Defense stat stages"); + +// Could be split into multiple tests or maybe to separate files based on the modifier? +TO_DO_BATTLE_TEST("Body Press's damage is influenced by all other Attack modifiers that are not stat stages"); +TO_DO_BATTLE_TEST("Body Press's damage is NOT influenced by any other Defense besides stat stages"); + +// Unconfirmed by Bulbapedia: +// - Defeatist interaction diff --git a/test/battle/move_effect/bolt_beak.c b/test/battle/move_effect/bolt_beak.c new file mode 100644 index 0000000000..fdd95da700 --- /dev/null +++ b/test/battle/move_effect/bolt_beak.c @@ -0,0 +1,5 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Bolt Beak's base power is doubled if it attacks before the target"); +TO_DO_BATTLE_TEST("Bolt Beak's base power is doubled the target switches out"); diff --git a/test/battle/move_effect/brick_break.c b/test/battle/move_effect/brick_break.c index 4fbc65a4d5..513369b5a1 100644 --- a/test/battle/move_effect/brick_break.c +++ b/test/battle/move_effect/brick_break.c @@ -137,24 +137,3 @@ DOUBLE_BATTLE_TEST("Brick Break can remove Light Screen, Reflect and Aurora Veil HP_BAR(playerLeft); } } - -SINGLE_BATTLE_TEST("Move Raging Bull changes it's type depending on the Tauros Form") -{ - u16 speciesPlayer; - u16 speciesOpponent; - - PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_COMBAT_BREED; speciesOpponent = SPECIES_CHARIZARD; } - PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_BLAZE_BREED; speciesOpponent = SPECIES_BLASTOISE; } - PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_AQUA_BREED; speciesOpponent = SPECIES_VENUSAUR; } - - GIVEN { - PLAYER(speciesPlayer); - OPPONENT(speciesOpponent); - } WHEN { - TURN { MOVE(player, MOVE_RAGING_BULL); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, player); - HP_BAR(opponent); - MESSAGE("It's not very effective…"); - } -} diff --git a/test/battle/move_effect/brine.c b/test/battle/move_effect/brine.c new file mode 100644 index 0000000000..9165257859 --- /dev/null +++ b/test/battle/move_effect/brine.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Brine's power doubles if the target is at 50% or below max HP"); diff --git a/test/battle/move_effect/bulk_up.c b/test/battle/move_effect/bulk_up.c new file mode 100644 index 0000000000..7f47d5d48e --- /dev/null +++ b/test/battle/move_effect/bulk_up.c @@ -0,0 +1,4 @@ +#include "global.h" +#include "test/battle.h" + +TO_DO_BATTLE_TEST("Bulk Up increases the user's Attack and Defense"); diff --git a/test/battle/move_effect/earthquake.c b/test/battle/move_effect/earthquake.c new file mode 100644 index 0000000000..93955e15b4 --- /dev/null +++ b/test/battle/move_effect/earthquake.c @@ -0,0 +1,28 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Earthquake's and Bulldoze's damage is halved when Grassy Terrain is in effect", s16 damage) +{ + bool32 terrain; + u16 move; + PARAMETRIZE { terrain = FALSE; move = MOVE_EARTHQUAKE; } // 0 + PARAMETRIZE { terrain = TRUE; move = MOVE_EARTHQUAKE; } // 1 + PARAMETRIZE { terrain = FALSE; move = MOVE_BULLDOZE; } // 2 + PARAMETRIZE { terrain = TRUE; move = MOVE_BULLDOZE; } // 3 + GIVEN { + ASSUME(gMovesInfo[MOVE_EARTHQUAKE].effect == EFFECT_EARTHQUAKE); + ASSUME(gMovesInfo[MOVE_BULLDOZE].effect == EFFECT_EARTHQUAKE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (terrain) + TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage); + } +} diff --git a/test/battle/move_effect/embargo.c b/test/battle/move_effect/embargo.c index 8d9cc9c86d..628fc44119 100644 --- a/test/battle/move_effect/embargo.c +++ b/test/battle/move_effect/embargo.c @@ -203,7 +203,7 @@ SINGLE_BATTLE_TEST("Embargo doesn't stop an item flung at an affected target fro } } -SINGLE_BATTLE_TEST("Embargo is passed via Baton Pass") +SINGLE_BATTLE_TEST("Baton Pass passes Embargo's effect") { GIVEN { PLAYER(SPECIES_WOBBUFFET); diff --git a/test/battle/move_effect/gastro_acid.c b/test/battle/move_effect/gastro_acid.c index a9fba14f89..b76cef8dc6 100644 --- a/test/battle/move_effect/gastro_acid.c +++ b/test/battle/move_effect/gastro_acid.c @@ -39,3 +39,6 @@ SINGLE_BATTLE_TEST("Gastro Acid fails if target has a banned ability") MESSAGE("But it failed!"); } } + +TO_DO_BATTLE_TEST("Baton Pass passes Gastro Acid's effect"); +TO_DO_BATTLE_TEST("Baton Pass removes Gastro Acid if its ability cannot be surpressed"); diff --git a/test/battle/move_effect/leech_seed.c b/test/battle/move_effect/leech_seed.c index 6faf4e8031..1e71437f80 100644 --- a/test/battle/move_effect/leech_seed.c +++ b/test/battle/move_effect/leech_seed.c @@ -24,3 +24,4 @@ TO_DO_BATTLE_TEST("Leech Seed doesn't affect already seeded targets") TO_DO_BATTLE_TEST("Leech Seeded targets lose 1/8 of its max HP every turn and give it to the user") TO_DO_BATTLE_TEST("Leech Seed's effect is paused until a new battler replaces the original user's position") // Faint, can't be replaced, then revived. TO_DO_BATTLE_TEST("Leech Seed's effect pause still prevents it from being seeded again") +TO_DO_BATTLE_TEST("Baton Pass passes Leech Seed's effect"); diff --git a/test/battle/move_effect/pursuit.c b/test/battle/move_effect/pursuit.c index 4cc1662413..0b517d4228 100644 --- a/test/battle/move_effect/pursuit.c +++ b/test/battle/move_effect/pursuit.c @@ -24,3 +24,5 @@ SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and ac MESSAGE("Go! Wobbuffet!"); } } + +TO_DO_BATTLE_TEST("Baton Pass doesn't cause Pursuit to increase its power or priority"); diff --git a/test/battle/move_effect/raging_bull.c b/test/battle/move_effect/raging_bull.c new file mode 100644 index 0000000000..23b138ca41 --- /dev/null +++ b/test/battle/move_effect/raging_bull.c @@ -0,0 +1,160 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_RAGING_BULL].effect == EFFECT_RAGING_BULL); + ASSUME(gMovesInfo[MOVE_SNOWSCAPE].effect == EFFECT_SNOWSCAPE); + ASSUME(gMovesInfo[MOVE_LIGHT_SCREEN].effect == EFFECT_LIGHT_SCREEN); + ASSUME(gMovesInfo[MOVE_REFLECT].effect == EFFECT_REFLECT); + ASSUME(gMovesInfo[MOVE_AURORA_VEIL].effect == EFFECT_AURORA_VEIL); +} + +SINGLE_BATTLE_TEST("Raging Bull removes Light Screen, Reflect and Aurora Veil from the target's side of the field") +{ + u16 move; + + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_AURORA_VEIL; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SNOWSCAPE); } + TURN { MOVE(opponent, move); MOVE(player, MOVE_RAGING_BULL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, player); + MESSAGE("The wall shattered!"); + HP_BAR(opponent); + } +} + +SINGLE_BATTLE_TEST("Raging Bull doesn't remove Light Screen, Reflect and Aurora Veil if the target is immune") +{ + u16 move; + + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_AURORA_VEIL; } + + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GASTLY); + } WHEN { + TURN { MOVE(player, MOVE_SNOWSCAPE); } + TURN { MOVE(opponent, move); MOVE(player, MOVE_RAGING_BULL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, player); + MESSAGE("The wall shattered!"); + HP_BAR(opponent); + } + } +} + +SINGLE_BATTLE_TEST("Raging Bull doesn't remove Light Screen, Reflect and Aurora Veil if the target Protected") +{ + u16 move; + + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_AURORA_VEIL; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SNOWSCAPE); MOVE(opponent, move); } + TURN { MOVE(player, MOVE_RAGING_BULL); MOVE(opponent, MOVE_PROTECT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, player); + MESSAGE("The wall shattered!"); + HP_BAR(opponent); + } + } +} + +SINGLE_BATTLE_TEST("Raging Bull doesn't remove Light Screen, Reflect and Aurora Veil if it misses") +{ + u16 move; + + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_AURORA_VEIL; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_BRIGHT_POWDER); } + } WHEN { + TURN { MOVE(player, MOVE_SNOWSCAPE); MOVE(opponent, move); } + TURN { MOVE(player, MOVE_RAGING_BULL, hit: FALSE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, player); + MESSAGE("The wall shattered!"); + HP_BAR(opponent); + } + } +} + +DOUBLE_BATTLE_TEST("Raging Bull can remove Light Screen, Reflect and Aurora Veil on users side") +{ + u16 move; + + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_AURORA_VEIL; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(opponentLeft, MOVE_SNOWSCAPE); + MOVE(playerLeft, move); + MOVE(playerRight, MOVE_RAGING_BULL, target: playerLeft); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, playerRight); + MESSAGE("The wall shattered!"); + HP_BAR(playerLeft); + } +} + +SINGLE_BATTLE_TEST("Move Raging Bull changes it's type depending on the Tauros Form") +{ + u16 speciesPlayer; + u16 speciesOpponent; + + PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_COMBAT_BREED; speciesOpponent = SPECIES_CHARIZARD; } + PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_BLAZE_BREED; speciesOpponent = SPECIES_BLASTOISE; } + PARAMETRIZE { speciesPlayer = SPECIES_TAUROS_PALDEAN_AQUA_BREED; speciesOpponent = SPECIES_VENUSAUR; } + + GIVEN { + PLAYER(speciesPlayer); + OPPONENT(speciesOpponent); + } WHEN { + TURN { MOVE(player, MOVE_RAGING_BULL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAGING_BULL, player); + HP_BAR(opponent); + MESSAGE("It's not very effective…"); + } +} diff --git a/test/battle/move_effect/substitute.c b/test/battle/move_effect/substitute.c index a2e4c686ec..5a3c973ebb 100644 --- a/test/battle/move_effect/substitute.c +++ b/test/battle/move_effect/substitute.c @@ -68,3 +68,5 @@ SINGLE_BATTLE_TEST("Substitute's HP cost doesn't trigger effects that trigger on NOT MESSAGE("Wobbuffet's Air Balloon popped!"); } } + +TO_DO_BATTLE_TEST("Baton Pass passes Substitutes"); diff --git a/test/battle/move_effect/telekinesis.c b/test/battle/move_effect/telekinesis.c index 6e8ef409f0..4210b1865b 100644 --- a/test/battle/move_effect/telekinesis.c +++ b/test/battle/move_effect/telekinesis.c @@ -68,3 +68,7 @@ SINGLE_BATTLE_TEST("Telekinesis makes the target immune to Ground-type attacks") MESSAGE("It doesn't affect Foe Wynaut…"); } } + +TO_DO_BATTLE_TEST("Baton Pass passes Telekinesis' effect"); +//Bulbapedia doesn't confirm what happens with Diglett, Dugtrio, Sandygast and Palossand, so it needs to be tested in-game. +TO_DO_BATTLE_TEST("Baton Pass removes Telekinesis' effect disappears if the switching-in mon is Mega Gengar"); diff --git a/test/battle/terrain/grassy.c b/test/battle/terrain/grassy.c index af0776d3df..678352dc5e 100644 --- a/test/battle/terrain/grassy.c +++ b/test/battle/terrain/grassy.c @@ -57,33 +57,6 @@ SINGLE_BATTLE_TEST("Grassy Terrain increases power of Grass-type moves by 30/50 } } -// Magnitude is not tested because its damage is variable. -SINGLE_BATTLE_TEST("Grassy Terrain decreases power of Earthquake and Bulldoze by 50 percent", s16 damage) -{ - bool32 terrain; - u16 move; - PARAMETRIZE { terrain = FALSE; move = MOVE_EARTHQUAKE; } // 0 - PARAMETRIZE { terrain = TRUE; move = MOVE_EARTHQUAKE; } // 1 - PARAMETRIZE { terrain = FALSE; move = MOVE_BULLDOZE; } // 2 - PARAMETRIZE { terrain = TRUE; move = MOVE_BULLDOZE; } // 3 - GIVEN { - ASSUME(gMovesInfo[MOVE_EARTHQUAKE].effect == EFFECT_EARTHQUAKE); - ASSUME(gMovesInfo[MOVE_BULLDOZE].effect == EFFECT_EARTHQUAKE); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - if (terrain) - TURN { MOVE(player, MOVE_GRASSY_TERRAIN); } - TURN { MOVE(player, move); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, move, player); - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); - EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage); - } -} - SINGLE_BATTLE_TEST("Grassy Terrain lasts for 5 turns") { GIVEN { diff --git a/test/dynamax.c b/test/dynamax.c index 03ff3c2ade..09b48be1e8 100644 --- a/test/dynamax.c +++ b/test/dynamax.c @@ -1158,6 +1158,8 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Terror traps both opponents") } } +TO_DO_BATTLE_TEST("(DYNAMAX) Baton Pass passes G-Max Terror's escape prevention effect"); + DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Meltdown torments both opponents for 3 turns") { GIVEN { @@ -1391,6 +1393,8 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance") } } +TO_DO_BATTLE_TEST("(DYNAMAX) Baton Pass doesn't pass G-Max Chi Strike's effect"); + DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Depletion takes away 2 PP from the target's last move") { GIVEN { From 43e2a973fcbe5a279aadd5c269d4aa01df708382 Mon Sep 17 00:00:00 2001 From: Isaac Rivera <40581123+iriv24@users.noreply.github.com> Date: Sat, 1 Jun 2024 19:00:17 -0400 Subject: [PATCH 3/3] add check for held item before using poltergeist and a check that it is the first turn for moves that are first turn only (#4693) --- src/battle_ai_util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 489588c33a..4524e3b25b 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -446,6 +446,14 @@ bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) && gMovesInfo[move].argument == ARG_TRY_REMOVE_TERRAIN_FAIL) return TRUE; break; + case EFFECT_POLTERGEIST: + if (AI_DATA->items[battlerDef] == ITEM_NONE) + return TRUE; + break; + case EFFECT_FIRST_TURN_ONLY: + if (!gDisableStructs[battlerAtk].isFirstTurn) + return TRUE; + break; } return FALSE;