Ally Switch extra battlerId tracking (#5823)

Co-authored-by: ghoulslash <pokevoyager0@gmail.com>
This commit is contained in:
ghoulslash 2024-12-18 08:39:34 -05:00 committed by GitHub
parent 99ba36b446
commit 11bc9bd2f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 179 additions and 0 deletions

View file

@ -6642,6 +6642,79 @@ static void ReloadBattlerSprites(u32 battler, struct Pokemon *party)
}
}
static void TrySwapSkyDropTargets(u32 battlerAtk, u32 battlerPartner)
{
u32 i, temp;
// battlerAtk is using Ally Switch
// check if our partner is the target of sky drop
// If so, change that index to battlerAtk
for (i = 0; i < gBattlersCount; i++) {
if (gBattleStruct->skyDropTargets[i] == battlerPartner) {
gBattleStruct->skyDropTargets[i] = battlerAtk;
break;
}
}
// Then swap our own sky drop targets with the partner in case our partner is mid-skydrop
SWAP(gBattleStruct->skyDropTargets[battlerAtk], gBattleStruct->skyDropTargets[battlerPartner], temp);
}
#define TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, side, field) \
if (gSideTimers[side].field == battlerAtk) \
gSideTimers[side].field = battlerPartner; \
else if (gSideTimers[side].field == battlerPartner) \
gSideTimers[side].field = battlerAtk;
static void TrySwapStickyWebBattlerId(u32 battlerAtk, u32 battlerPartner)
{
u32 atkSide = GetBattlerSide(battlerAtk);
u32 oppSide = GetBattlerSide(BATTLE_OPPOSITE(battlerAtk));
// not all of these are needed to be swapped, but are done so to be robust to anything in the future that might care about them
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, reflectBattlerId);
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, lightscreenBattlerId);
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, mistBattlerId);
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, safeguardBattlerId);
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, auroraVeilBattlerId);
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, tailwindBattlerId);
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, atkSide, luckyChantBattlerId);
// if we've set sticky web on the opposing side, need to swap stickyWebBattlerId for mirror armor
TRY_SIDE_TIMER_BATTLER_ID_SWAP(battlerAtk, battlerPartner, oppSide, stickyWebBattlerId);
}
#undef TRY_SIDE_TIMER_BATTLER_ID_SWAP
static void TrySwapWishBattlerIds(u32 battlerAtk, u32 battlerPartner)
{
u32 i, temp;
u32 oppSide = GetBattlerSide(BATTLE_OPPOSITE(battlerAtk));
// if used future sight on opposing side, properly track who used it
if (gSideStatuses[oppSide] & SIDE_STATUS_FUTUREATTACK) {
for (i = 0; i < gBattlersCount; i++) {
if (IsAlly(i,battlerAtk))
continue; // only on opposing side
if (gWishFutureKnock.futureSightBattlerIndex[i] == battlerAtk) {
// if target was attacked with future sight from us, now they'll be the partner slot
gWishFutureKnock.futureSightBattlerIndex[i] = battlerPartner;
gWishFutureKnock.futureSightPartyIndex[i] = gBattlerPartyIndexes[battlerPartner];
break;
} else if (gWishFutureKnock.futureSightBattlerIndex[i] == battlerPartner) {
gWishFutureKnock.futureSightBattlerIndex[i] = battlerAtk;
gWishFutureKnock.futureSightPartyIndex[i] = gBattlerPartyIndexes[battlerAtk];
break;
}
}
}
// swap wish party indices
if (gWishFutureKnock.wishCounter[battlerAtk] > 0
|| gWishFutureKnock.wishCounter[battlerPartner] > 0) {
SWAP(gWishFutureKnock.wishPartyId[battlerAtk], gWishFutureKnock.wishPartyId[battlerPartner], temp);
}
}
static void AnimTask_AllySwitchDataSwap(u8 taskId)
{
s32 i, j;
@ -6692,6 +6765,10 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId)
SwitchTwoBattlersInParty(battlerAtk, battlerPartner);
SWAP(gBattlerPartyIndexes[battlerAtk], gBattlerPartyIndexes[battlerPartner], temp);
TrySwapSkyDropTargets(battlerAtk, battlerPartner);
TrySwapStickyWebBattlerId(battlerAtk, battlerPartner);
TrySwapWishBattlerIds(battlerAtk, battlerPartner);
// For Snipe Shot and abilities Stalwart/Propeller Tail - keep the original target.
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{

View file

@ -203,5 +203,79 @@ DOUBLE_BATTLE_TEST("Ally Switch works if ally used two-turn move like Dig")
}
}
DOUBLE_BATTLE_TEST("Ally switch swaps sky drop targets if being used by partner")
{
u8 visibility;
GIVEN {
ASSUME(gMovesInfo[MOVE_SKY_DROP].effect == EFFECT_SKY_DROP);
PLAYER(SPECIES_FEAROW) { Speed(100); }
PLAYER(SPECIES_XATU) { Speed(150); }
OPPONENT(SPECIES_ARON) { Speed(25); Ability(ABILITY_STURDY); }
OPPONENT(SPECIES_WYNAUT) { Speed(30); }
} WHEN {
TURN { MOVE(playerLeft, MOVE_SKY_DROP, target: opponentLeft); }
TURN { MOVE(playerRight, MOVE_ALLY_SWITCH); SKIP_TURN(playerLeft); MOVE(opponentRight, MOVE_MUD_SPORT); MOVE(opponentLeft, MOVE_IRON_DEFENSE); }
} SCENE {
MESSAGE("Fearow used Sky Drop!");
MESSAGE("Fearow took the opposing Aron into the sky!");
// turn 2
MESSAGE("Xatu used Ally Switch!");
MESSAGE("Xatu and Fearow switched places!");
MESSAGE("Fearow used Sky Drop!");
HP_BAR(opponentLeft);
MESSAGE("The opposing Wynaut used Mud Sport!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_MUD_SPORT, opponentRight);
MESSAGE("The opposing Aron used Iron Defense!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_IRON_DEFENSE, opponentLeft);
} THEN {
// all battlers should be visible
visibility = gBattleSpritesDataPtr->battlerData[0].invisible;
EXPECT_EQ(visibility, 0);
visibility = gBattleSpritesDataPtr->battlerData[1].invisible;
EXPECT_EQ(visibility, 0);
visibility = gBattleSpritesDataPtr->battlerData[2].invisible;
EXPECT_EQ(visibility, 0);
visibility = gBattleSpritesDataPtr->battlerData[3].invisible;
EXPECT_EQ(visibility, 0);
}
}
DOUBLE_BATTLE_TEST("Ally switch swaps opposing sky drop targets if partner is being held in the air")
{
u8 visibility;
GIVEN {
ASSUME(gMovesInfo[MOVE_SKY_DROP].effect == EFFECT_SKY_DROP);
PLAYER(SPECIES_ARON) { Speed(25); Ability(ABILITY_STURDY); }
PLAYER(SPECIES_WYNAUT) { Speed(30); }
OPPONENT(SPECIES_FEAROW) { Speed(100); }
OPPONENT(SPECIES_XATU) { Speed(150); }
} WHEN {
TURN { MOVE(opponentLeft, MOVE_SKY_DROP, target: playerLeft); }
TURN { MOVE(opponentRight, MOVE_ALLY_SWITCH); SKIP_TURN(opponentLeft); MOVE(playerRight, MOVE_MUD_SPORT); MOVE(playerLeft, MOVE_IRON_DEFENSE); }
} SCENE {
MESSAGE("The opposing Fearow used Sky Drop!");
MESSAGE("The opposing Fearow took Aron into the sky!");
// turn 2
MESSAGE("The opposing Xatu used Ally Switch!");
MESSAGE("The opposing Xatu and the opposing Fearow switched places!");
MESSAGE("The opposing Fearow used Sky Drop!");
HP_BAR(playerLeft);
MESSAGE("Wynaut used Mud Sport!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_MUD_SPORT, playerRight);
MESSAGE("Aron used Iron Defense!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_IRON_DEFENSE, playerLeft);
} THEN {
// all battlers should be visible
visibility = gBattleSpritesDataPtr->battlerData[0].invisible;
EXPECT_EQ(visibility, 0);
visibility = gBattleSpritesDataPtr->battlerData[1].invisible;
EXPECT_EQ(visibility, 0);
visibility = gBattleSpritesDataPtr->battlerData[2].invisible;
EXPECT_EQ(visibility, 0);
visibility = gBattleSpritesDataPtr->battlerData[3].invisible;
EXPECT_EQ(visibility, 0);
}
}
// Triple Battles required to test
//TO_DO_BATTLE_TEST("Ally Switch fails if the user is in the middle of the field in a Triple Battle");

View file

@ -271,3 +271,31 @@ SINGLE_BATTLE_TEST("Sticky Web is placed on the correct side after Memento")
MESSAGE("A sticky web has been laid out on the ground around your team!");
}
}
DOUBLE_BATTLE_TEST("Sticky Web setter has their speed lowered with Mirror Armor even after Ally Switch")
{
GIVEN {
PLAYER(SPECIES_SQUIRTLE);
PLAYER(SPECIES_CHARMANDER);
PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); Item(ITEM_IRON_BALL); } // Iron Ball, so that flying type Corviknight is affected by Sticky Web.
OPPONENT(SPECIES_CATERPIE);
OPPONENT(SPECIES_NATU);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); }
TURN { MOVE(opponentRight, MOVE_ALLY_SWITCH); }
TURN { SWITCH(playerRight, 2); }
} SCENE {
// Turn 1 - set up sticky web
ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentLeft);
MESSAGE("A sticky web has been laid out on the ground around your team!");
// Turn 2 - ally switch
MESSAGE("The opposing Natu used Ally Switch!");
// turn 3 - send our corviknight
SEND_IN_MESSAGE("Corviknight");
MESSAGE("Corviknight was caught in a sticky web!");
ABILITY_POPUP(playerRight, ABILITY_MIRROR_ARMOR);
// sticky web setter - caterpie (now opponentRight) gets speed lowered
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
MESSAGE("The opposing Caterpie's Speed fell!");
}
}