diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 1cedf81fa..71ca64097 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -185,6 +185,7 @@ extern struct UnusedControllerStruct gUnusedControllerStruct; void HandleLinkBattleSetup(void); void SetUpBattleVarsAndBirchZigzagoon(void); void InitBattleControllers(void); +bool32 IsValidForBattle(struct Pokemon *mon); void TryReceiveLinkBattleData(void); void PrepareBufferDataTransferLink(u8 bufferId, u16 size, u8 *data); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 89f73ffc4..59827ca80 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1034,20 +1034,25 @@ static void Intro_DelayAndEnd(void) } } +static bool32 TwoIntroMons(u32 battlerId) // Double battle with both player pokemon active. +{ + return (IsDoubleBattle() && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[battlerId ^ BIT_FLANK]])); +} + static void Intro_WaitForShinyAnimAndHealthbox(void) { bool8 healthboxAnimDone = FALSE; // Check if healthbox has finished sliding in - if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { - if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy + && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; } else { - if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy - && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == SpriteCallbackDummy) + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) healthboxAnimDone = TRUE; } @@ -1065,7 +1070,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(void) HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); - if (IsDoubleBattle()) + if (TwoIntroMons(gActiveBattler)) HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], gActiveBattler ^ BIT_FLANK); gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].introEndDelay = 3; @@ -1094,7 +1099,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) { if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].healthboxSlideInStarted) { - if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], HEALTHBOX_ALL); StartHealthboxSlideIn(gActiveBattler ^ BIT_FLANK); @@ -1125,15 +1130,7 @@ static void Intro_TryShinyAnimShowHealthbox(void) } // Wait for battler anims - if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) - { - if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy - && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) - { - battlerAnimsDone = TRUE; - } - } - else + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy @@ -1143,11 +1140,19 @@ static void Intro_TryShinyAnimShowHealthbox(void) battlerAnimsDone = TRUE; } } + else + { + if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy + && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + { + battlerAnimsDone = TRUE; + } + } // Clean up if (bgmRestored && battlerAnimsDone) { - if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) DestroySprite(&gSprites[gBattleControllerData[gActiveBattler ^ BIT_FLANK]]); DestroySprite(&gSprites[gBattleControllerData[gActiveBattler]]); @@ -3114,12 +3119,7 @@ static void Task_StartSendOutAnim(u8 taskId) u8 savedActiveBattler = gActiveBattler; gActiveBattler = gTasks[taskId].tBattlerId; - if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) - { - gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; - StartSendOutAnim(gActiveBattler, FALSE); - } - else + if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) { gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; StartSendOutAnim(gActiveBattler, FALSE); @@ -3129,6 +3129,11 @@ static void Task_StartSendOutAnim(u8 taskId) StartSendOutAnim(gActiveBattler, FALSE); gActiveBattler ^= BIT_FLANK; } + else + { + gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; + StartSendOutAnim(gActiveBattler, FALSE); + } gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox; gActiveBattler = savedActiveBattler; DestroyTask(taskId); diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 2fc7cac07..033a12122 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -588,6 +588,14 @@ static void InitLinkBtlControllers(void) } } +bool32 IsValidForBattle(struct Pokemon *mon) +{ + u32 species = GetMonData(mon, MON_DATA_SPECIES2); + return (species != SPECIES_NONE && species != SPECIES_EGG + && GetMonData(mon, MON_DATA_HP) != 0 + && GetMonData(mon, MON_DATA_IS_EGG) == 0); +} + static void SetBattlePartyIds(void) { s32 i, j; @@ -602,10 +610,7 @@ static void SetBattlePartyIds(void) { if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) { - if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0) + if (IsValidForBattle(&gPlayerParty[j])) { gBattlerPartyIndexes[i] = j; break; @@ -613,10 +618,7 @@ static void SetBattlePartyIds(void) } else { - if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0) + if (IsValidForBattle(&gEnemyParty[j])) { gBattlerPartyIndexes[i] = j; break; @@ -627,11 +629,7 @@ static void SetBattlePartyIds(void) { if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) { - if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES) != SPECIES_NONE // Probably a typo by Game Freak. The rest use SPECIES2. - && GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0 - && gBattlerPartyIndexes[i - 2] != j) + if (IsValidForBattle(&gPlayerParty[j]) && gBattlerPartyIndexes[i - 2] != j) { gBattlerPartyIndexes[i] = j; break; @@ -639,16 +637,18 @@ static void SetBattlePartyIds(void) } else { - if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_NONE - && GetMonData(&gEnemyParty[j], MON_DATA_SPECIES2) != SPECIES_EGG - && GetMonData(&gEnemyParty[j], MON_DATA_IS_EGG) == 0 - && gBattlerPartyIndexes[i - 2] != j) + if (IsValidForBattle(&gEnemyParty[j]) && gBattlerPartyIndexes[i - 2] != j) { gBattlerPartyIndexes[i] = j; break; } } + + // No valid mons were found. Add the empty slot. + if (gBattlerPartyIndexes[i - 2] == 0) + gBattlerPartyIndexes[i] = 1; + else + gBattlerPartyIndexes[i] = 0; } } } diff --git a/src/battle_main.c b/src/battle_main.c index 9cf56abf7..f6d1cbe62 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3454,6 +3454,13 @@ static void TryDoEventsBeforeFirstTurn(void) if (gBattleControllerExecFlags) return; + // Set invalid mons as absent(for example when starting a double battle with only one pokemon). + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE) + gAbsentBattlerFlags |= gBitTable[i]; + } + if (gBattleStruct->switchInAbilitiesCounter == 0) { for (i = 0; i < gBattlersCount; i++) @@ -4080,10 +4087,10 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CONFIRMED_STANDBY: - if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) + if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF << 28) - | (gBitTable[gActiveBattler] << 4) - | (gBitTable[gActiveBattler] << 8) + | (gBitTable[gActiveBattler] << 4) + | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 12)))) { if (AllAtActionConfirmed()) @@ -4646,7 +4653,7 @@ static void CheckQuickClaw_CustapBerryActivation(void) } } } - + // setup stuff before turns/actions TryClearRageAndFuryCutter(); gCurrentTurnActionNumber = 0; diff --git a/src/battle_message.c b/src/battle_message.c index c4f043e15..8ef2e4702 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2560,7 +2560,7 @@ void BufferStringBattle(u16 stringID) case STRINGID_INTROSENDOUT: // poke first send-out if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) { - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]])) { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) stringPtr = sText_InGamePartnerSentOutZGoN;