Fixes Ally Switch cancelling partner's moves targeting that side of the field (#6647)

This commit is contained in:
PhallenTree 2025-04-19 19:24:00 +01:00 committed by GitHub
parent d342b373f0
commit bd64ab599b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 63 additions and 11 deletions

View File

@ -6914,11 +6914,11 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId)
SWAP(gMoveSelectionCursor[battlerAtk], gMoveSelectionCursor[battlerPartner], temp);
// Swap turn order, so that all the battlers take action
SWAP(gChosenActionByBattler[battlerAtk], gChosenActionByBattler[battlerPartner], temp);
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
for (i = 0; i < gBattlersCount; i++)
{
if (gBattlerByTurnOrder[i] == battlerAtk || gBattlerByTurnOrder[i] == battlerPartner)
{
for (j = i + 1; j < MAX_BATTLERS_COUNT; j++)
for (j = i + 1; j < gBattlersCount; j++)
{
if (gBattlerByTurnOrder[j] == battlerAtk || gBattlerByTurnOrder[j] == battlerPartner)
break;
@ -6938,9 +6938,13 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId)
TrySwapWishBattlerIds(battlerAtk, battlerPartner);
// For Snipe Shot and abilities Stalwart/Propeller Tail - keep the original target.
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
for (i = 0; i < gBattlersCount; i++)
{
u16 ability = GetBattlerAbility(i);
// if not targeting a slot that got switched, continue
if (!IsBattlerAlly(gBattleStruct->moveTarget[i], battlerAtk))
continue;
if (gChosenMoveByBattler[i] == MOVE_SNIPE_SHOT || ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART)
gBattleStruct->moveTarget[i] ^= BIT_FLANK;
}

View File

@ -309,7 +309,7 @@ bool32 HandleMoveTargetRedirection(void)
// Functions
void HandleAction_UseMove(void)
{
u32 i;
u32 i, moveTarget;
gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
if (gBattleStruct->battlerState[gBattlerAttacker].absentBattlerFlags
@ -393,9 +393,10 @@ void HandleAction_UseMove(void)
gCurrentMove = gChosenMove = GetMaxMove(gBattlerAttacker, gCurrentMove);
}
moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
if (!HandleMoveTargetRedirection())
{
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM)
{
gBattlerTarget = SetRandomTarget(gBattlerAttacker);
@ -407,7 +408,7 @@ void HandleAction_UseMove(void)
}
else if (moveTarget == MOVE_TARGET_ALLY)
{
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)))
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)) && !gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch)
gBattlerTarget = BATTLE_PARTNER(gBattlerAttacker);
else
gBattlerTarget = gBattlerAttacker;
@ -422,6 +423,10 @@ void HandleAction_UseMove(void)
break;
}
}
else if (moveTarget == MOVE_TARGET_USER)
{
gBattlerTarget = gBattlerAttacker;
}
else
{
gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker);
@ -455,8 +460,13 @@ void HandleAction_UseMove(void)
}
}
if ((IsBattlerAlly(gBattlerAttacker, gBattlerTarget))
&& (!IsBattlerAlive(gBattlerTarget) || gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch))
if (IsBattlerAlly(gBattlerAttacker, gBattlerTarget) && !IsBattlerAlive(gBattlerTarget))
{
gBattlescriptCurrInstr = BattleScript_FailedFromAtkCanceler;
}
// If originally targetting an ally but now targetting user due to Ally Switch
else if (moveTarget & MOVE_TARGET_ALLY && gBattlerAttacker == gBattlerTarget
&& gProtectStructs[BATTLE_PARTNER(gBattlerAttacker)].usedAllySwitch)
{
gBattlescriptCurrInstr = BattleScript_FailedFromAtkCanceler;
}

View File

@ -16,20 +16,40 @@ DOUBLE_BATTLE_TEST("Acupressure fails on the user if it targeted its ally but sw
OPPONENT(SPECIES_KADABRA);
OPPONENT(SPECIES_ABRA);
} WHEN {
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(playerRight, MOVE_ACUPRESSURE, target:playerLeft); }
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(playerRight, MOVE_ACUPRESSURE, target: playerLeft); }
} SCENE {
MESSAGE("Wobbuffet used Ally Switch!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft);
MESSAGE("Wobbuffet and Wynaut switched places!");
MESSAGE("Wynaut used Acupressure!");
MESSAGE("But it failed!");
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
}
}
}
DOUBLE_BATTLE_TEST("Acupressure works on the ally if it targeted itself but switched positions via Ally Switch")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_KADABRA);
OPPONENT(SPECIES_ABRA);
} WHEN {
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(playerRight, MOVE_ACUPRESSURE, target: playerRight); }
} SCENE {
MESSAGE("Wobbuffet used Ally Switch!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft);
MESSAGE("Wobbuffet and Wynaut switched places!");
MESSAGE("Wynaut used Acupressure!");
NOT MESSAGE("But it failed!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_ACUPRESSURE, playerLeft);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
}
}
TO_DO_BATTLE_TEST("Acupressure works on the user if its side is protected by Crafty Shield");
TO_DO_BATTLE_TEST("Acupressure fails on the ally if its side is protected by Crafty Shield");

View File

@ -167,6 +167,24 @@ DOUBLE_BATTLE_TEST("Ally Switch - move fails if the target was ally which change
}
}
DOUBLE_BATTLE_TEST("Ally Switch doesn't make self-targeting status moves fail")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_HARDEN].target == MOVE_TARGET_USER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); MOVE(playerRight, MOVE_HARDEN); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_HARDEN, playerLeft);
} THEN {
EXPECT_EQ(playerLeft->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1);
}
}
DOUBLE_BATTLE_TEST("Ally Switch increases the Protect-like moves counter")
{
GIVEN {