diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8b2160cefc66..0620edb3d972 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8209,7 +8209,7 @@ BattleScript_DazzlingProtected:: attackstring ppreduce pause B_WAIT_TIME_SHORT - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpScripting printstring STRINGID_POKEMONCANNOTUSEMOVE waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd diff --git a/src/battle_util.c b/src/battle_util.c index 8cda4c4ecc21..ad558d309e56 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4977,30 +4977,69 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITYEFFECT_MOVES_BLOCK: // 2 { u16 moveTarget = GetBattlerMoveTargetType(battler, move); - u16 battlerAbility = GetBattlerAbility(battler); - u16 targetAbility = GetBattlerAbility(gBattlerTarget); - if ((gLastUsedAbility == ABILITY_SOUNDPROOF && gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER)) - || (gLastUsedAbility == ABILITY_BULLETPROOF && gMovesInfo[move].ballisticMove)) + switch (gLastUsedAbility) + { + case ABILITY_SOUNDPROOF: + if (gMovesInfo[move].soundMove && !(moveTarget & MOVE_TARGET_USER)) + effect = 1; + break; + case ABILITY_BULLETPROOF: + if (gMovesInfo[move].ballisticMove) + effect = 1; + break; + case ABILITY_DAZZLING: + case ABILITY_QUEENLY_MAJESTY: + case ABILITY_ARMOR_TAIL: + if (GetChosenMovePriority(gBattlerAttacker) > 0 && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) + effect = 2; + break; + case ABILITY_GOOD_AS_GOLD: + if (IS_MOVE_STATUS(gCurrentMove) + && !(moveTarget & MOVE_TARGET_USER) + && !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) + && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) + effect = 3; + break; + } + + if (!effect) + { + switch (GetBattlerAbility(BATTLE_PARTNER(battler))) + { + case ABILITY_DAZZLING: + case ABILITY_QUEENLY_MAJESTY: + case ABILITY_ARMOR_TAIL: + if (GetChosenMovePriority(gBattlerAttacker) > 0 && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) + effect = 4; + break; + } + } + + if (effect == 1) { if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattlescriptCurrInstr = BattleScript_SoundproofProtected; - effect = 1; } - else if ((gLastUsedAbility == ABILITY_DAZZLING || gLastUsedAbility == ABILITY_QUEENLY_MAJESTY || gLastUsedAbility == ABILITY_ARMOR_TAIL || IsBattlerAlive(battler ^= BIT_FLANK)) - && (battlerAbility == ABILITY_DAZZLING || battlerAbility == ABILITY_QUEENLY_MAJESTY || battlerAbility == ABILITY_ARMOR_TAIL) - && GetChosenMovePriority(gBattlerAttacker) > 0 - && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(battler)) + else if (effect == 2 || effect == 4) { + if (effect == 4) + gBattleScripting.battler = BATTLE_PARTNER(battler); + else + gBattleScripting.battler = battler; + if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS) gHitMarker |= HITMARKER_NO_PPDEDUCT; gBattlescriptCurrInstr = BattleScript_DazzlingProtected; - effect = 1; + } + else if (effect == 3) + { + gBattlescriptCurrInstr = BattleScript_GoodAsGoldActivates; } else if (GetChosenMovePriority(gBattlerAttacker) > 0 - && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) - && !(IS_MOVE_STATUS(move) && (targetAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) + && BlocksPrankster(move, gBattlerAttacker, gBattlerTarget, TRUE) + && !(IS_MOVE_STATUS(move) && (gLastUsedAbility == ABILITY_MAGIC_BOUNCE || gProtectStructs[gBattlerTarget].bounceMove))) { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(moveTarget & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY))) CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected @@ -5008,15 +5047,6 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster; effect = 1; } - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_GOOD_AS_GOLD - && IS_MOVE_STATUS(gCurrentMove) - && !(moveTarget & MOVE_TARGET_USER) - && !(moveTarget & MOVE_TARGET_OPPONENTS_FIELD) - && !(moveTarget & MOVE_TARGET_ALL_BATTLERS)) - { - gBattlescriptCurrInstr = BattleScript_GoodAsGoldActivates; - effect = 1; - } break; } case ABILITYEFFECT_ABSORBING: // 3 diff --git a/test/battle/ability/dazzling.c b/test/battle/ability/dazzling.c new file mode 100644 index 000000000000..9eedb56a4957 --- /dev/null +++ b/test/battle/ability/dazzling.c @@ -0,0 +1,52 @@ +#include "global.h" +#include "test/battle.h" + + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_QUICK_ATTACK].priority > 0); +} + +DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect the user from priority moves") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } + PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } + PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_QUICK_ATTACK, target: opponentLeft); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, opponentRight); + ABILITY_POPUP(opponentLeft, ability); + MESSAGE("Wobbuffet cannot use Quick Attack!"); + } +} + +DOUBLE_BATTLE_TEST("Dazzling, Queenly Majesty and Armor Tail protect users partner from priority moves") +{ + u32 species, ability; + + PARAMETRIZE { species = SPECIES_BRUXISH; ability = ABILITY_DAZZLING; } + PARAMETRIZE { species = SPECIES_FARIGIRAF; ability = ABILITY_ARMOR_TAIL; } + PARAMETRIZE { species = SPECIES_TSAREENA; ability = ABILITY_QUEENLY_MAJESTY; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(species) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_QUICK_ATTACK, target: opponentRight); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, opponentRight); + ABILITY_POPUP(opponentLeft, ability); + MESSAGE("Wobbuffet cannot use Quick Attack!"); + } +} diff --git a/test/battle/ability/good_as_gold.c b/test/battle/ability/good_as_gold.c new file mode 100644 index 000000000000..596bb6c4c7b7 --- /dev/null +++ b/test/battle/ability/good_as_gold.c @@ -0,0 +1,70 @@ +#include "global.h" +#include "test/battle.h" + + +SINGLE_BATTLE_TEST("Good as Gold protects from status moves") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_TOXIC].category == DAMAGE_CATEGORY_STATUS); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GHOLDENGO) { Ability(ABILITY_GOOD_AS_GOLD); } + } WHEN { + TURN { MOVE(player, MOVE_TOXIC); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player); + ABILITY_POPUP(opponent, ABILITY_GOOD_AS_GOLD); + MESSAGE("It doesn't affect Foe Gholdengo…"); + } +} + +SINGLE_BATTLE_TEST("Good as Gold doesn't protect the user from it's own moves") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_NASTY_PLOT].category == DAMAGE_CATEGORY_STATUS); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GHOLDENGO) { Ability(ABILITY_GOOD_AS_GOLD); } + } WHEN { + TURN { MOVE(opponent, MOVE_NASTY_PLOT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_NASTY_PLOT, opponent); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_GOOD_AS_GOLD); + MESSAGE("It doesn't affect Foe Gholdengo…"); + } + } +} + +SINGLE_BATTLE_TEST("Good as Gold doesn't protect from moves that target the field") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_STEALTH_ROCK].category == DAMAGE_CATEGORY_STATUS); + ASSUME(gMovesInfo[MOVE_STEALTH_ROCK].target == MOVE_TARGET_OPPONENTS_FIELD); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GHOLDENGO) { Ability(ABILITY_GOOD_AS_GOLD); } + } WHEN { + TURN { MOVE(player, MOVE_STEALTH_ROCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, player); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_GOOD_AS_GOLD); + MESSAGE("It doesn't affect Foe Gholdengo…"); + } + } +} + +DOUBLE_BATTLE_TEST("Good as Gold protects from partner's status moves") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_HELPING_HAND].category == DAMAGE_CATEGORY_STATUS); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GHOLDENGO) { Ability(ABILITY_GOOD_AS_GOLD); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, MOVE_HELPING_HAND); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HELPING_HAND, opponentRight); + ABILITY_POPUP(opponentLeft, ABILITY_GOOD_AS_GOLD); + MESSAGE("It doesn't affect Foe Gholdengo…"); + } +}