diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 53d824e7e1..635810c526 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4796,8 +4796,6 @@ BattleScript_PartyHealEnd:: BattleScript_EffectTripleKick:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce jumpifmove MOVE_TRIPLE_AXEL BS_TripleAxel addbyte sTRIPLE_KICK_POWER, 10 @ triple kick gets +10 power goto BattleScript_HitFromAtkString @@ -8717,10 +8715,7 @@ BattleScript_IntimidateLoop: jumpiftargetally BattleScript_IntimidateLoopIncrement jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_IntimidateLoopIncrement - jumpifholdeffect BS_TARGET, HOLD_EFFECT_CLEAR_AMULET, BattleScript_IntimidatePrevented_Item - jumpifability BS_TARGET, ABILITY_CLEAR_BODY, BattleScript_IntimidatePrevented jumpifability BS_TARGET, ABILITY_HYPER_CUTTER, BattleScript_IntimidatePrevented - jumpifability BS_TARGET, ABILITY_WHITE_SMOKE, BattleScript_IntimidatePrevented .if B_UPDATED_INTIMIDATE >= GEN_8 jumpifability BS_TARGET, ABILITY_INNER_FOCUS, BattleScript_IntimidatePrevented jumpifability BS_TARGET, ABILITY_SCRAPPY, BattleScript_IntimidatePrevented @@ -8761,7 +8756,6 @@ BattleScript_IntimidateContrary_WontIncrease: BattleScript_IntimidatePrevented: call BattleScript_AbilityPopUp pause B_WAIT_TIME_LONG -BattleScript_IntimidatePrevented_Item: setbyte gBattleCommunication STAT_ATK stattextbuffer BS_TARGET printstring STRINGID_STATWASNOTLOWERED @@ -9089,6 +9083,12 @@ BattleScript_AbilityNoStatLoss:: waitmessage B_WAIT_TIME_LONG return +BattleScript_ItemNoStatLoss:: + pause B_WAIT_TIME_SHORT + printstring STRINGID_STATWASNOTLOWERED + waitmessage B_WAIT_TIME_LONG + return + BattleScript_BRNPrevention:: pause B_WAIT_TIME_SHORT printfromtable gBRNPreventionStringIds diff --git a/include/battle_scripts.h b/include/battle_scripts.h index b2c7cac845..0033b011e4 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -168,6 +168,7 @@ extern const u8 BattleScript_MonMadeMoveUseless[]; extern const u8 BattleScript_FlashFireBoost_PPLoss[]; extern const u8 BattleScript_FlashFireBoost[]; extern const u8 BattleScript_AbilityNoStatLoss[]; +extern const u8 BattleScript_ItemNoStatLoss[]; extern const u8 BattleScript_BRNPrevention[]; extern const u8 BattleScript_PRLZPrevention[]; extern const u8 BattleScript_PSNPrevention[]; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7f4b4b1212..b8d8c68667 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11941,10 +11941,17 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr { BattleScriptPush(BS_ptr); gBattleScripting.battler = gActiveBattler; - gBattlerAbility = gActiveBattler; - gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss; - gLastUsedAbility = activeBattlerAbility; - RecordAbilityBattle(gActiveBattler, gLastUsedAbility); + if (GetBattlerHoldEffect(gActiveBattler, TRUE) == HOLD_EFFECT_CLEAR_AMULET) + { + gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss; + } + else + { + gBattlerAbility = gActiveBattler; + gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss; + gLastUsedAbility = activeBattlerAbility; + RecordAbilityBattle(gActiveBattler, gLastUsedAbility); + } gSpecialStatuses[gActiveBattler].statLowered = TRUE; } } @@ -12084,15 +12091,15 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr { gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); gProtectStructs[gActiveBattler].statRaised = TRUE; - + // check mirror herb for (index = 0; index < gBattlersCount; index++) { if (GetBattlerSide(index) == GetBattlerSide(gActiveBattler)) - continue; // Only triggers on opposing side + continue; // Only triggers on opposing side if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB && gBattleMons[index].statStages[statId] < MAX_STAT_STAGE) - { + { gProtectStructs[index].eatMirrorHerb = 1; gTotemBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk gTotemBoosts[index].statChanges[statId - 1] = statValue; @@ -16300,7 +16307,7 @@ void BS_CheckParentalBondCounter(void) void BS_GetBattlerSide(void) { NATIVE_ARGS(u8 battler); - gBattleCommunication[0] = GetBattlerSide(GetBattlerForBattleScript(cmd->battler)); + gBattleCommunication[0] = GetBattlerSide(GetBattlerForBattleScript(cmd->battler)); gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16326,7 +16333,7 @@ void BS_TrySymbiosis(void) gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; return; } - + gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/test/ability_clear_body.c b/test/ability_clear_body.c new file mode 100644 index 0000000000..11789aaf60 --- /dev/null +++ b/test/ability_clear_body.c @@ -0,0 +1,38 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Clear Body prevents intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY); + MESSAGE("Foe Beldum's Clear Body prevents stat loss!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +TO_DO_BATTLE_TEST("Clear Body prevents stat stage reduction from moves"); // Growl, Leer, Confide, Fake Tears, Scary Face, Sweet Scent, Sand Attack (Attack, Defense, Sp. Attack, Sp. Defense, Speed, Evasion, Accuracy +TO_DO_BATTLE_TEST("Clear Body prevents Sticky Web"); +TO_DO_BATTLE_TEST("Clear Body doesn't prevent stat stage reduction from moves used by the user"); // e.g. Superpower +TO_DO_BATTLE_TEST("Clear Body doesn't prevent Speed reduction from Iron Ball"); +TO_DO_BATTLE_TEST("Clear Body doesn't prevent Speed reduction from paralysis"); +TO_DO_BATTLE_TEST("Clear Body doesn't prevent Attack reduction from burn"); +TO_DO_BATTLE_TEST("Clear Body doesn't prevent receiving negative stat changes from Baton Pass"); +TO_DO_BATTLE_TEST("Clear Body doesn't prevent Topsy-Turvy"); +TO_DO_BATTLE_TEST("Clear Body doesn't prevent Spectral Thief from resetting positive stat changes"); +TO_DO_BATTLE_TEST("Clear Body is ignored by Mold Breaker"); diff --git a/test/ability_full_metal_body.c b/test/ability_full_metal_body.c new file mode 100644 index 0000000000..c47ce9d4dc --- /dev/null +++ b/test/ability_full_metal_body.c @@ -0,0 +1,38 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Full Metal Body prevents intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_SOLGALEO) { Ability(ABILITY_FULL_METAL_BODY); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ABILITY_POPUP(opponent, ABILITY_FULL_METAL_BODY); + MESSAGE("Foe Solgaleo's Full Metal Body prevents stat loss!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +TO_DO_BATTLE_TEST("Full Metal Body prevents stat stage reduction from moves"); // Growl, Leer, Confide, Fake Tears, Scary Face, Sweet Scent, Sand Attack (Attack, Defense, Sp. Attack, Sp. Defense, Speed, Evasion, Accuracy +TO_DO_BATTLE_TEST("Full Metal Body prevents Sticky Web"); +TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent stat stage reduction from moves used by the user"); // e.g. Superpower +TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Speed reduction from Iron Ball"); +TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Speed reduction from paralysis"); +TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Attack reduction from burn"); +TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent receiving negative stat changes from Baton Pass"); +TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Topsy-Turvy"); +TO_DO_BATTLE_TEST("Full Metal Body doesn't prevent Spectral Thief from resetting positive stat changes"); +TO_DO_BATTLE_TEST("Full Metal Body is ignored by Mold Breaker"); diff --git a/test/ability_hyper_cutter.c b/test/ability_hyper_cutter.c new file mode 100644 index 0000000000..67dac4c66e --- /dev/null +++ b/test/ability_hyper_cutter.c @@ -0,0 +1,35 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_KRABBY) { Ability(ABILITY_HYPER_CUTTER); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ABILITY_POPUP(opponent, ABILITY_HYPER_CUTTER); + MESSAGE("Foe Krabby's Attack was not lowered!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +TO_DO_BATTLE_TEST("Hyper Cutter prevents Attack stage reduction from moves"); // Growl +TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Attack stage reduction from moves used by the user"); // e.g. Superpower +TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Attack reduction from burn"); +TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent receiving negative Attack stage changes from Baton Pass"); +TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Topsy-Turvy"); +TO_DO_BATTLE_TEST("Hyper Cutter doesn't prevent Spectral Thief from resetting positive Attack stage changes"); +TO_DO_BATTLE_TEST("Hyper Cutter is ignored by Mold Breaker"); diff --git a/test/ability_inner_focus.c b/test/ability_inner_focus.c new file mode 100644 index 0000000000..5b713475dc --- /dev/null +++ b/test/ability_inner_focus.c @@ -0,0 +1,57 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Inner Focus prevents intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ABILITY_POPUP(opponent, ABILITY_INNER_FOCUS); + MESSAGE("Foe Zubat's Attack was not lowered!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +SINGLE_BATTLE_TEST("Inner Focus prevents flinching") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }; + } WHEN { + TURN { MOVE(player, MOVE_FAKE_OUT); + MOVE(opponent, MOVE_TACKLE); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_OUT, player); + NONE_OF { MESSAGE("Foe Zubat flinched!"); } + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + } +} + +SINGLE_BATTLE_TEST("Inner Focus is ignored by Mold Breaker") +{ + GIVEN { + PLAYER(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); }; + OPPONENT(SPECIES_ZUBAT) { Ability(ABILITY_INNER_FOCUS); }; + } WHEN { + TURN { MOVE(player, MOVE_FAKE_OUT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FAKE_OUT, player); + MESSAGE("Foe Zubat flinched!"); + } +} diff --git a/test/ability_own_tempo.c b/test/ability_own_tempo.c new file mode 100644 index 0000000000..2440ac7798 --- /dev/null +++ b/test/ability_own_tempo.c @@ -0,0 +1,119 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Own Tempo prevents intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO); + MESSAGE("Foe Slowpoke's Attack was not lowered!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +SINGLE_BATTLE_TEST("Own Tempo prevents confusion from moves by the opponent") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_CONFUSE_RAY].effect == EFFECT_CONFUSE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; + } WHEN { + TURN { MOVE(player, MOVE_CONFUSE_RAY); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO); + MESSAGE("Foe Slowpoke's Own Tempo prevents confusion!"); + } +} + +SINGLE_BATTLE_TEST("Own Tempo prevents confusion from moves by the user") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_PETAL_DANCE].effect == EFFECT_RAMPAGE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; + } WHEN { + TURN { MOVE(opponent, MOVE_PETAL_DANCE); } + TURN { MOVE(opponent, MOVE_PETAL_DANCE); } + TURN { MOVE(opponent, MOVE_PETAL_DANCE); } + TURN { MOVE(opponent, MOVE_PETAL_DANCE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_DANCE, opponent); + NONE_OF { MESSAGE("Foe Slowpoke became confused due to fatigue!"); } + } +} + +SINGLE_BATTLE_TEST("Own Tempo cures confusion obtained from an opponent with Mold Breaker") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(gBattleMoves[MOVE_CONFUSE_RAY].effect == EFFECT_CONFUSE); + PLAYER(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); }; + OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; + } WHEN { + TURN { MOVE(player, MOVE_CONFUSE_RAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, player); + MESSAGE("Foe Slowpoke became confused!"); + NONE_OF { + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, opponent); + } + ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO); + MESSAGE("Foe Slowpoke's Own Tempo cured its confusion problem!"); + } +} + +SINGLE_BATTLE_TEST("Own Tempo cures confusion if it's obtained via Skill Swap") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_CONFUSE_RAY].effect == EFFECT_CONFUSE); + ASSUME(gBattleMoves[MOVE_SKILL_SWAP].effect == EFFECT_SKILL_SWAP); + PLAYER(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CONFUSE_RAY); } + TURN { MOVE(player, MOVE_SKILL_SWAP); + MOVE(opponent, MOVE_TACKLE); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, player); + MESSAGE("Foe Wobbuffet became confused!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player); + ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO); + MESSAGE("Foe Wobbuffet's Own Tempo cured its confusion problem!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + } +} + +SINGLE_BATTLE_TEST("Own Tempo prevents confusion from items") +{ + GIVEN { + ASSUME(gItems[ITEM_BERSERK_GENE].holdEffect == HOLD_EFFECT_BERSERK_GENE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SLOWPOKE) { Ability(ABILITY_OWN_TEMPO); Item(ITEM_BERSERK_GENE); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + ABILITY_POPUP(opponent, ABILITY_OWN_TEMPO); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + } +} diff --git a/test/ability_pastel_veil.c b/test/ability_pastel_veil.c index ddc0806198..363c018c10 100644 --- a/test/ability_pastel_veil.c +++ b/test/ability_pastel_veil.c @@ -33,18 +33,20 @@ DOUBLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison on partner") SINGLE_BATTLE_TEST("Pastel Veil immediately cures Mold Breaker poison") { + KNOWN_FAILING; GIVEN { ASSUME(gBattleMoves[MOVE_TOXIC].effect == EFFECT_TOXIC); PLAYER(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); } OPPONENT(SPECIES_PONYTA_GALARIAN) { Ability(ABILITY_PASTEL_VEIL); } } WHEN { - TURN { MOVE(player, MOVE_TOXIC); } + TURN { MOVE(player, MOVE_TOXIC); MOVE(opponent, MOVE_TACKLE); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player); STATUS_ICON(opponent, badPoison: TRUE); ABILITY_POPUP(opponent, ABILITY_PASTEL_VEIL); MESSAGE("Foe Ponyta's Pastel Veil cured its poison problem!"); STATUS_ICON(opponent, none: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); } } diff --git a/test/ability_scrappy.c b/test/ability_scrappy.c new file mode 100644 index 0000000000..b4f83afcf8 --- /dev/null +++ b/test/ability_scrappy.c @@ -0,0 +1,66 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Scrappy prevents intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ABILITY_POPUP(opponent, ABILITY_SCRAPPY); + MESSAGE("Foe Kangaskhan's Attack was not lowered!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +SINGLE_BATTLE_TEST("Scrappy allows to hit Ghost-type Pokémon with Normal- and Fighting-type moves") +{ + u32 move; + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_KARATE_CHOP; } + + GIVEN { + PLAYER(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }; + OPPONENT(SPECIES_GASTLY); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + } +} + +SINGLE_BATTLE_TEST("Scrappy doesn't bypass a Ghost-type's Wonder Guard") +{ + u32 move; + PARAMETRIZE { move = MOVE_TACKLE; } + PARAMETRIZE { move = MOVE_KARATE_CHOP; } + + GIVEN { + PLAYER(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); }; + OPPONENT(SPECIES_SHEDINJA) { Ability(ABILITY_WONDER_GUARD); }; + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + } + ABILITY_POPUP(opponent, ABILITY_WONDER_GUARD); + MESSAGE("Foe Shedinja avoided damage with Wonder Guard!"); + } +} diff --git a/test/ability_white_smoke.c b/test/ability_white_smoke.c new file mode 100644 index 0000000000..9689aee6c2 --- /dev/null +++ b/test/ability_white_smoke.c @@ -0,0 +1,39 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("White Smoke prevents intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_TORKOAL) { Ability(ABILITY_WHITE_SMOKE); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + ABILITY_POPUP(opponent, ABILITY_WHITE_SMOKE); + MESSAGE("Foe Torkoal's White Smoke prevents stat loss!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + + +TO_DO_BATTLE_TEST("White Smoke prevents stat stage reduction from moves"); // Growl, Leer, Confide, Fake Tears, Scary Face, Sweet Scent, Sand Attack (Attack, Defense, Sp. Attack, Sp. Defense, Speed, Evasion, Accuracy +TO_DO_BATTLE_TEST("White Smoke prevents Sticky Web"); +TO_DO_BATTLE_TEST("White Smoke doesn't prevent stat stage reduction from moves used by the user"); // e.g. Superpower +TO_DO_BATTLE_TEST("White Smoke doesn't prevent Speed reduction from Iron Ball"); +TO_DO_BATTLE_TEST("White Smoke doesn't prevent Speed reduction from paralysis"); +TO_DO_BATTLE_TEST("White Smoke doesn't prevent Attack reduction from burn"); +TO_DO_BATTLE_TEST("White Smoke doesn't prevent receiving negative stat changes from Baton Pass"); +TO_DO_BATTLE_TEST("White Smoke doesn't prevent Topsy-Turvy"); +TO_DO_BATTLE_TEST("White Smoke doesn't prevent Spectral Thief from resetting positive stat changes"); +TO_DO_BATTLE_TEST("White Smoke is ignored by Mold Breaker"); diff --git a/test/hold_effect_clear_amulet.c b/test/hold_effect_clear_amulet.c new file mode 100644 index 0000000000..83c887b2d4 --- /dev/null +++ b/test/hold_effect_clear_amulet.c @@ -0,0 +1,111 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_CLEAR_AMULET].holdEffect == HOLD_EFFECT_CLEAR_AMULET); +} + +SINGLE_BATTLE_TEST("Clear Amulet prevents Intimidate") +{ + s16 turnOneHit; + s16 turnTwoHit; + + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_SHED_SKIN); }; + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }; + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); }; + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_TACKLE); } + } SCENE { + HP_BAR(player, captureDamage: &turnOneHit); + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); } + MESSAGE("Foe Wobbuffet's Attack was not lowered!"); + HP_BAR(player, captureDamage: &turnTwoHit); + } THEN { + EXPECT_EQ(turnOneHit, turnTwoHit); + } +} + +SINGLE_BATTLE_TEST("Clear Amulet prevents stat reducing effects") +{ + u32 move; + + PARAMETRIZE { move = MOVE_GROWL; } + PARAMETRIZE { move = MOVE_LEER; } + PARAMETRIZE { move = MOVE_CONFIDE; } + PARAMETRIZE { move = MOVE_FAKE_TEARS; } + PARAMETRIZE { move = MOVE_SCARY_FACE; } + PARAMETRIZE { move = MOVE_SWEET_SCENT; } + PARAMETRIZE { move = MOVE_SAND_ATTACK; } + + GIVEN { + ASSUME(gBattleMoves[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN); + ASSUME(gBattleMoves[MOVE_LEER].effect == EFFECT_DEFENSE_DOWN); + ASSUME(gBattleMoves[MOVE_CONFIDE].effect == EFFECT_SPECIAL_ATTACK_DOWN); + ASSUME(gBattleMoves[MOVE_FAKE_TEARS].effect == EFFECT_SPECIAL_DEFENSE_DOWN_2); + ASSUME(gBattleMoves[MOVE_SCARY_FACE].effect == EFFECT_SPEED_DOWN_2); + ASSUME(B_UPDATED_MOVE_DATA >= GEN_6); + ASSUME(gBattleMoves[MOVE_SWEET_SCENT].effect == EFFECT_EVASION_DOWN_2); + ASSUME(gBattleMoves[MOVE_SAND_ATTACK].effect == EFFECT_ACCURACY_DOWN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); }; + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } + switch (move) + { + case MOVE_GROWL: + MESSAGE("Foe Wobbuffet's Attack was not lowered!"); + break; + case MOVE_LEER: + MESSAGE("Foe Wobbuffet's Defense was not lowered!"); + break; + case MOVE_CONFIDE: + MESSAGE("Foe Wobbuffet's Sp. Atk was not lowered!"); + break; + case MOVE_FAKE_TEARS: + MESSAGE("Foe Wobbuffet's Sp. Def was not lowered!"); + break; + case MOVE_SCARY_FACE: + MESSAGE("Foe Wobbuffet's Speed was not lowered!"); + break; + case MOVE_SWEET_SCENT: + MESSAGE("Foe Wobbuffet's evasiveness was not lowered!"); + break; + case MOVE_SAND_ATTACK: + MESSAGE("Foe Wobbuffet's accuracy was not lowered!"); + break; + } + } +} + +SINGLE_BATTLE_TEST("Clear Amulet prevents secondary effects that reduce stats") +{ + u32 move; + + PARAMETRIZE { move = MOVE_AURORA_BEAM; } + PARAMETRIZE { move = MOVE_ROCK_SMASH; } + PARAMETRIZE { move = MOVE_SNARL; } + PARAMETRIZE { move = MOVE_PSYCHIC; } + PARAMETRIZE { move = MOVE_BUBBLE_BEAM; } + PARAMETRIZE { move = MOVE_MUD_SLAP; } + + GIVEN { + ASSUME(gBattleMoves[MOVE_AURORA_BEAM].effect == EFFECT_ATTACK_DOWN_HIT); + ASSUME(gBattleMoves[MOVE_ROCK_SMASH].effect == EFFECT_DEFENSE_DOWN_HIT); + ASSUME(gBattleMoves[MOVE_SNARL].effect == EFFECT_SPECIAL_ATTACK_DOWN_HIT); + ASSUME(gBattleMoves[MOVE_PSYCHIC].effect == EFFECT_SPECIAL_DEFENSE_DOWN_HIT); + ASSUME(gBattleMoves[MOVE_BUBBLE_BEAM].effect == EFFECT_SPEED_DOWN_HIT); + ASSUME(gBattleMoves[MOVE_MUD_SLAP].effect == EFFECT_ACCURACY_DOWN_HIT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_CLEAR_AMULET); }; + } WHEN { + TURN { MOVE(player, MOVE_ROCK_SMASH); } + } SCENE { + NONE_OF { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); } + } +}