Fixes Magic Bounce in double battles (#4464)
* Fixes Magic Bounce in double battles * Add Double Battle check
This commit is contained in:
parent
2aed78ebbb
commit
6d397f9867
5 changed files with 86 additions and 23 deletions
|
@ -157,7 +157,6 @@ struct ProtectStruct
|
|||
u32 flinchImmobility:1;
|
||||
u32 notFirstStrike:1;
|
||||
u32 palaceUnableToUseMove:1;
|
||||
u32 usesBouncedMove:1;
|
||||
u32 usedHealBlockedMove:1;
|
||||
u32 usedGravityPreventedMove:1;
|
||||
u32 powderSelfDmg:1;
|
||||
|
@ -736,9 +735,10 @@ struct BattleStruct
|
|||
u8 quickClawBattlerId;
|
||||
struct LostItem itemLost[PARTY_SIZE]; // Player's team that had items consumed or stolen (two bytes per party member)
|
||||
u8 forcedSwitch:4; // For each battler
|
||||
u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects
|
||||
u8 blunderPolicy:1; // should blunder policy activate
|
||||
u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
|
||||
u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects
|
||||
u8 bouncedMoveIsUsed:1;
|
||||
u8 ballSpriteIds[2]; // item gfx, window gfx
|
||||
u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change
|
||||
u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle.
|
||||
|
|
|
@ -3581,7 +3581,6 @@ const u8* FaintClearSetData(u32 battler)
|
|||
gProtectStructs[battler].flinchImmobility = FALSE;
|
||||
gProtectStructs[battler].notFirstStrike = FALSE;
|
||||
gProtectStructs[battler].usedHealBlockedMove = FALSE;
|
||||
gProtectStructs[battler].usesBouncedMove = FALSE;
|
||||
gProtectStructs[battler].usedGravityPreventedMove = FALSE;
|
||||
gProtectStructs[battler].usedThroatChopPreventedMove = FALSE;
|
||||
gProtectStructs[battler].statRaised = FALSE;
|
||||
|
|
|
@ -1394,9 +1394,9 @@ static void Cmd_attackcanceler(void)
|
|||
|
||||
if (gProtectStructs[gBattlerTarget].bounceMove
|
||||
&& gMovesInfo[gCurrentMove].magicCoatAffected
|
||||
&& !gProtectStructs[gBattlerAttacker].usesBouncedMove)
|
||||
&& !gBattleStruct->bouncedMoveIsUsed)
|
||||
{
|
||||
gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE;
|
||||
gBattleStruct->bouncedMoveIsUsed = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
|
||||
// Edge case for bouncing a powder move against a grass type pokemon.
|
||||
SetAtkCancellerForCalledMove();
|
||||
|
@ -1413,18 +1413,33 @@ static void Cmd_attackcanceler(void)
|
|||
}
|
||||
return;
|
||||
}
|
||||
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE
|
||||
&& gMovesInfo[gCurrentMove].magicCoatAffected
|
||||
&& !gProtectStructs[gBattlerAttacker].usesBouncedMove)
|
||||
else if (gMovesInfo[gCurrentMove].magicCoatAffected && !gBattleStruct->bouncedMoveIsUsed)
|
||||
{
|
||||
gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
|
||||
// Edge case for bouncing a powder move against a grass type pokemon.
|
||||
SetAtkCancellerForCalledMove();
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
return;
|
||||
u32 battler = gBattlerTarget;
|
||||
|
||||
if (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE)
|
||||
{
|
||||
battler = gBattlerTarget;
|
||||
gBattleStruct->bouncedMoveIsUsed = TRUE;
|
||||
}
|
||||
else if (IsDoubleBattle()
|
||||
&& gMovesInfo[gCurrentMove].target == MOVE_TARGET_OPPONENTS_FIELD
|
||||
&& GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) == ABILITY_MAGIC_BOUNCE)
|
||||
{
|
||||
gBattlerTarget = battler = BATTLE_PARTNER(gBattlerTarget);
|
||||
gBattleStruct->bouncedMoveIsUsed = TRUE;
|
||||
}
|
||||
|
||||
if (gBattleStruct->bouncedMoveIsUsed)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
|
||||
// Edge case for bouncing a powder move against a grass type pokemon.
|
||||
SetAtkCancellerForCalledMove();
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
|
||||
gBattlerAbility = battler;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Z-moves and Max Moves bypass protection, but deal reduced damage (factored in AccumulateOtherModifiers)
|
||||
|
@ -5920,9 +5935,10 @@ static void Cmd_moveend(void)
|
|||
return;
|
||||
}
|
||||
// Check if the move used was actually a bounced move. If so, we need to go back to the original attacker and make sure, its move hits all 2 or 3 pokemon.
|
||||
else if (gProtectStructs[gBattlerAttacker].usesBouncedMove)
|
||||
else if (gBattleStruct->bouncedMoveIsUsed)
|
||||
{
|
||||
u8 originalBounceTarget = gBattlerAttacker;
|
||||
gBattleStruct->bouncedMoveIsUsed = FALSE;
|
||||
gBattlerAttacker = gBattleStruct->attackerBeforeBounce;
|
||||
gBattleStruct->targetsDone[gBattlerAttacker] |= gBitTable[originalBounceTarget];
|
||||
gBattleStruct->targetsDone[originalBounceTarget] = 0;
|
||||
|
@ -6221,7 +6237,7 @@ static void Cmd_moveend(void)
|
|||
|
||||
if (!(gBattleStruct->lastMoveFailed & gBitTable[gBattlerAttacker]
|
||||
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove
|
||||
&& gProtectStructs[gBattlerAttacker].usesBouncedMove)))
|
||||
&& gBattleStruct->bouncedMoveIsUsed)))
|
||||
{ // Dance move succeeds
|
||||
// Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move
|
||||
if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove)
|
||||
|
@ -6316,7 +6332,6 @@ static void Cmd_moveend(void)
|
|||
CancelMultiTurnMoves(gBattlerAttacker); // Cancel it
|
||||
|
||||
gBattleStruct->targetsDone[gBattlerAttacker] = 0;
|
||||
gProtectStructs[gBattlerAttacker].usesBouncedMove = FALSE;
|
||||
gProtectStructs[gBattlerAttacker].targetAffected = FALSE;
|
||||
gProtectStructs[gBattlerAttacker].shellTrap = FALSE;
|
||||
gBattleStruct->ateBoost[gBattlerAttacker] = 0;
|
||||
|
@ -6333,6 +6348,7 @@ static void Cmd_moveend(void)
|
|||
gBattleStruct->hitSwitchTargetFailed = FALSE;
|
||||
gBattleStruct->isAtkCancelerForCalledMove = FALSE;
|
||||
gBattleStruct->swapDamageCategory = FALSE;
|
||||
gBattleStruct->bouncedMoveIsUsed = FALSE;
|
||||
gBattleStruct->enduredDamage = 0;
|
||||
gBattleStruct->additionalEffectsCounter = 0;
|
||||
gBattleScripting.moveendState++;
|
||||
|
|
|
@ -3489,10 +3489,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
|||
if (effect != 0)
|
||||
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;
|
||||
case CANCELLER_POWDER_STATUS:
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER)
|
||||
|
|
|
@ -81,3 +81,54 @@ DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting both foes at two foe
|
|||
MESSAGE("Foe Wynaut's Defense fell!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting foes field")
|
||||
{
|
||||
u32 battlerOne, battlerTwo, abilityBattlerOne, abilityBattlerTwo;
|
||||
|
||||
PARAMETRIZE { battlerOne = SPECIES_NATU; abilityBattlerOne = ABILITY_MAGIC_BOUNCE;
|
||||
battlerTwo = SPECIES_ESPEON; abilityBattlerTwo = ABILITY_SYNCHRONIZE; }
|
||||
PARAMETRIZE { battlerOne = SPECIES_NATU; abilityBattlerOne = ABILITY_KEEN_EYE;
|
||||
battlerTwo = SPECIES_ESPEON; abilityBattlerTwo = ABILITY_MAGIC_BOUNCE; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_STEALTH_ROCK].target == MOVE_TARGET_OPPONENTS_FIELD);
|
||||
PLAYER(SPECIES_ABRA);
|
||||
PLAYER(SPECIES_KADABRA);
|
||||
OPPONENT(battlerOne) { Ability(abilityBattlerOne); }
|
||||
OPPONENT(battlerTwo) { Ability(abilityBattlerTwo); }
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_STEALTH_ROCK); }
|
||||
} SCENE {
|
||||
if (abilityBattlerOne == ABILITY_MAGIC_BOUNCE)
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_MAGIC_BOUNCE);
|
||||
else
|
||||
ABILITY_POPUP(opponentRight, ABILITY_MAGIC_BOUNCE);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, playerLeft);
|
||||
if (abilityBattlerOne == ABILITY_MAGIC_BOUNCE) {
|
||||
MESSAGE("Abra's Stealth Rock was bounced back by Foe Natu's Magic Bounce!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentLeft);
|
||||
} else {
|
||||
MESSAGE("Abra's Stealth Rock was bounced back by Foe Espeon's Magic Bounce!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Magic Bounce bounced back status moves can not be bounced back by Magic Bounce")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_TOXIC].effect == EFFECT_TOXIC);
|
||||
PLAYER(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); }
|
||||
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("Espeon's Toxic was bounced back by Foe Espeon's Magic Bounce!");
|
||||
NOT ABILITY_POPUP(player, ABILITY_MAGIC_BOUNCE);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent);
|
||||
STATUS_ICON(player, badPoison: TRUE);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue