Fix Magic bounce powder moves against grass types (#2633)

* Fix Magic bounce powder moves against grass types
This commit is contained in:
DizzyEggg 2023-02-17 14:55:51 +01:00 committed by GitHub
parent 56c9564e7a
commit 0c523f9518
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 171 additions and 32 deletions

View File

@ -7688,6 +7688,9 @@ BattleScript_MagicCoatBounce::
attackstring attackstring
ppreduce ppreduce
pause B_WAIT_TIME_SHORT pause B_WAIT_TIME_SHORT
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0, BattleScript_MagicCoatBounce_Print
call BattleScript_AbilityPopUp
BattleScript_MagicCoatBounce_Print:
printfromtable gMagicCoatBounceStringIds printfromtable gMagicCoatBounceStringIds
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP orword gHitMarker, HITMARKER_ATTACKSTRING_PRINTED | HITMARKER_NO_PPDEDUCT | HITMARKER_ALLOW_NO_PP

View File

@ -64,6 +64,35 @@ struct TypePower
u16 effect; u16 effect;
}; };
enum
{
CANCELLER_FLAGS,
CANCELLER_SKY_DROP,
CANCELLER_ASLEEP,
CANCELLER_FROZEN,
CANCELLER_TRUANT,
CANCELLER_RECHARGE,
CANCELLER_FLINCH,
CANCELLER_DISABLED,
CANCELLER_GRAVITY,
CANCELLER_HEAL_BLOCKED,
CANCELLER_TAUNTED,
CANCELLER_IMPRISONED,
CANCELLER_CONFUSED,
CANCELLER_PARALYSED,
CANCELLER_IN_LOVE,
CANCELLER_BIDE,
CANCELLER_THAW,
CANCELLER_POWDER_MOVE,
CANCELLER_POWDER_STATUS,
CANCELLER_THROAT_CHOP,
CANCELLER_MULTIHIT_MOVES,
CANCELLER_Z_MOVES,
CANCELLER_END,
CANCELLER_PSYCHIC_TERRAIN,
CANCELLER_END2,
};
extern const struct TypePower gNaturalGiftTable[]; extern const struct TypePower gNaturalGiftTable[];
void HandleAction_ThrowBall(void); void HandleAction_ThrowBall(void);

View File

@ -1530,6 +1530,7 @@ static void Cmd_attackcanceler(void)
PressurePPLose(gBattlerAttacker, gBattlerTarget, MOVE_MAGIC_COAT); PressurePPLose(gBattlerAttacker, gBattlerTarget, MOVE_MAGIC_COAT);
gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE; gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE;
gBattleCommunication[MULTISTRING_CHOOSER] = 0; gBattleCommunication[MULTISTRING_CHOOSER] = 0;
gBattleStruct->atkCancellerTracker = CANCELLER_POWDER_MOVE; // Edge case for bouncing a powder move against a grass type pokemon.
if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker, TRUE)) if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker, TRUE))
{ {
// Opponent used a prankster'd magic coat -> reflected status move should fail against a dark-type attacker // Opponent used a prankster'd magic coat -> reflected status move should fail against a dark-type attacker
@ -1547,11 +1548,12 @@ static void Cmd_attackcanceler(void)
&& gBattleMoves[gCurrentMove].flags & FLAG_MAGIC_COAT_AFFECTED && gBattleMoves[gCurrentMove].flags & FLAG_MAGIC_COAT_AFFECTED
&& !gProtectStructs[gBattlerAttacker].usesBouncedMove) && !gProtectStructs[gBattlerAttacker].usesBouncedMove)
{ {
RecordAbilityBattle(gBattlerTarget, ABILITY_MAGIC_BOUNCE);
gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE; gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE;
gBattleCommunication[MULTISTRING_CHOOSER] = 1; gBattleCommunication[MULTISTRING_CHOOSER] = 1;
gBattleStruct->atkCancellerTracker = CANCELLER_POWDER_MOVE; // Edge case for bouncing a powder move against a grass type pokemon.
BattleScriptPushCursor(); BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MagicCoatBounce; gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
gBattlerAbility = gBattlerTarget;
return; return;
} }

View File

@ -3410,35 +3410,6 @@ void TryClearRageAndFuryCutter(void)
} }
} }
enum
{
CANCELLER_FLAGS,
CANCELLER_SKY_DROP,
CANCELLER_ASLEEP,
CANCELLER_FROZEN,
CANCELLER_TRUANT,
CANCELLER_RECHARGE,
CANCELLER_FLINCH,
CANCELLER_DISABLED,
CANCELLER_GRAVITY,
CANCELLER_HEAL_BLOCKED,
CANCELLER_TAUNTED,
CANCELLER_IMPRISONED,
CANCELLER_CONFUSED,
CANCELLER_PARALYSED,
CANCELLER_IN_LOVE,
CANCELLER_BIDE,
CANCELLER_THAW,
CANCELLER_POWDER_MOVE,
CANCELLER_POWDER_STATUS,
CANCELLER_THROAT_CHOP,
CANCELLER_MULTIHIT_MOVES,
CANCELLER_Z_MOVES,
CANCELLER_END,
CANCELLER_PSYCHIC_TERRAIN,
CANCELLER_END2,
};
u8 AtkCanceller_UnableToUseMove(void) u8 AtkCanceller_UnableToUseMove(void)
{ {
u8 effect = 0; u8 effect = 0;
@ -3753,6 +3724,9 @@ u8 AtkCanceller_UnableToUseMove(void)
if (effect != 0) if (effect != 0)
gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect;
} }
if (gProtectStructs[gBattlerAttacker].usesBouncedMove) // Edge case for bouncing a powder move against a grass type pokemon.
gBattleStruct->atkCancellerTracker = CANCELLER_END;
else
gBattleStruct->atkCancellerTracker++; gBattleStruct->atkCancellerTracker++;
break; break;
case CANCELLER_POWDER_STATUS: case CANCELLER_POWDER_STATUS:

View File

@ -0,0 +1,84 @@
#include "global.h"
#include "test_battle.h"
SINGLE_BATTLE_TEST("Magic Bounce bounces back status moves")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_TOXIC].effect == EFFECT_TOXIC);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE);};
} WHEN {
TURN { MOVE(player, MOVE_TOXIC); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_MAGIC_BOUNCE);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player);
MESSAGE("Wynaut's Toxic was bounced back by Foe Espeon's Magic Bounce!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent);
STATUS_ICON(player, badPoison: TRUE);
}
}
SINGLE_BATTLE_TEST("Magic Bounce bounces back powder moves")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER);
ASSUME(gBattleMoves[MOVE_STUN_SPORE].effect == EFFECT_PARALYZE);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE);};
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_MAGIC_BOUNCE);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player);
MESSAGE("Wynaut's Stun Spore was bounced back by Foe Espeon's Magic Bounce!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, opponent);
STATUS_ICON(player, paralysis: TRUE);
}
}
SINGLE_BATTLE_TEST("Magic Bounce cannot bounce back powder moves against Grass Types")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER);
ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS);
PLAYER(SPECIES_ODDISH);
OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE);};
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_MAGIC_BOUNCE);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player);
MESSAGE("Oddish's Stun Spore was bounced back by Foe Espeon's Magic Bounce!");
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, opponent);
MESSAGE("It doesn't affect Oddish…");
NOT STATUS_ICON(player, paralysis: TRUE);
}
}
DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting both foes at two foes")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_LEER].effect == EFFECT_DEFENSE_DOWN);
ASSUME(gBattleMoves[MOVE_LEER].target == MOVE_TARGET_BOTH);
PLAYER(SPECIES_ABRA);
PLAYER(SPECIES_KADABRA);
OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE);};
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_LEER); }
} SCENE {
ABILITY_POPUP(opponentLeft, ABILITY_MAGIC_BOUNCE);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_LEER, playerLeft);
MESSAGE("Abra's Leer was bounced back by Foe Espeon's Magic Bounce!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_LEER, opponentLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
MESSAGE("Abra's defense fell!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
MESSAGE("Kadabra's defense fell!");
// Also check if second original target gets hit by Leer as this was once bugged
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
MESSAGE("Foe Wynaut's defense fell!");
}
}

47
test/powder_moves.c Normal file
View File

@ -0,0 +1,47 @@
#include "global.h"
#include "test_battle.h"
SINGLE_BATTLE_TEST("Powder Moves are blocked by Grass Types")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER);
ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ODDISH);
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player);
MESSAGE("It doesn't affect Foe Oddish…");
}
}
SINGLE_BATTLE_TEST("Powder Moves are blocked by Ability Overcoat")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT);};
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_OVERCOAT);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player);
MESSAGE("It doesn't affect Foe Pineco…");
}
}
SINGLE_BATTLE_TEST("Powder Moves are blocked by Item Safety Goggles")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER);
ASSUME(gItems[ITEM_SAFETY_GOGGLES].holdEffect == HOLD_EFFECT_SAFETY_GOGGLES);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_ABRA) { Item(ITEM_SAFETY_GOGGLES);};
} WHEN {
TURN { MOVE(player, MOVE_STUN_SPORE); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player);
MESSAGE("Foe Abra is not affected thanks to its SafetyGoggles!");
}
}