Allow one mon double battles

This commit is contained in:
DizzyEggg 2021-06-08 16:40:47 +02:00
parent 339f297949
commit 4b29ae39ad
5 changed files with 58 additions and 45 deletions

View File

@ -185,6 +185,7 @@ extern struct UnusedControllerStruct gUnusedControllerStruct;
void HandleLinkBattleSetup(void); void HandleLinkBattleSetup(void);
void SetUpBattleVarsAndBirchZigzagoon(void); void SetUpBattleVarsAndBirchZigzagoon(void);
void InitBattleControllers(void); void InitBattleControllers(void);
bool32 IsValidForBattle(struct Pokemon *mon);
void TryReceiveLinkBattleData(void); void TryReceiveLinkBattleData(void);
void PrepareBufferDataTransferLink(u8 bufferId, u16 size, u8 *data); void PrepareBufferDataTransferLink(u8 bufferId, u16 size, u8 *data);

View File

@ -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) static void Intro_WaitForShinyAnimAndHealthbox(void)
{ {
bool8 healthboxAnimDone = FALSE; bool8 healthboxAnimDone = FALSE;
// Check if healthbox has finished sliding in // 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; healthboxAnimDone = TRUE;
} }
else else
{ {
if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
&& gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]].callback == SpriteCallbackDummy)
healthboxAnimDone = TRUE; healthboxAnimDone = TRUE;
} }
@ -1065,7 +1070,7 @@ static void Intro_WaitForShinyAnimAndHealthbox(void)
HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler);
if (IsDoubleBattle()) if (TwoIntroMons(gActiveBattler))
HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], gActiveBattler ^ BIT_FLANK); HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], gActiveBattler ^ BIT_FLANK);
gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].introEndDelay = 3; gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].introEndDelay = 3;
@ -1094,7 +1099,7 @@ static void Intro_TryShinyAnimShowHealthbox(void)
{ {
if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].healthboxSlideInStarted) 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); UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], HEALTHBOX_ALL);
StartHealthboxSlideIn(gActiveBattler ^ BIT_FLANK); StartHealthboxSlideIn(gActiveBattler ^ BIT_FLANK);
@ -1125,15 +1130,7 @@ static void Intro_TryShinyAnimShowHealthbox(void)
} }
// Wait for battler anims // Wait for battler anims
if (!IsDoubleBattle() || (IsDoubleBattle() && (gBattleTypeFlags & BATTLE_TYPE_MULTI))) if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI))
{
if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy
&& gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
{
battlerAnimsDone = TRUE;
}
}
else
{ {
if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy
&& gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy && gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy
@ -1143,11 +1140,19 @@ static void Intro_TryShinyAnimShowHealthbox(void)
battlerAnimsDone = TRUE; battlerAnimsDone = TRUE;
} }
} }
else
{
if (gSprites[gBattleControllerData[gActiveBattler]].callback == SpriteCallbackDummy
&& gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
{
battlerAnimsDone = TRUE;
}
}
// Clean up // Clean up
if (bgmRestored && battlerAnimsDone) 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 ^ BIT_FLANK]]);
DestroySprite(&gSprites[gBattleControllerData[gActiveBattler]]); DestroySprite(&gSprites[gBattleControllerData[gActiveBattler]]);
@ -3114,12 +3119,7 @@ static void Task_StartSendOutAnim(u8 taskId)
u8 savedActiveBattler = gActiveBattler; u8 savedActiveBattler = gActiveBattler;
gActiveBattler = gTasks[taskId].tBattlerId; gActiveBattler = gTasks[taskId].tBattlerId;
if (!IsDoubleBattle() || (gBattleTypeFlags & BATTLE_TYPE_MULTI)) if (TwoIntroMons(gActiveBattler) && !(gBattleTypeFlags & BATTLE_TYPE_MULTI))
{
gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler];
StartSendOutAnim(gActiveBattler, FALSE);
}
else
{ {
gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler];
StartSendOutAnim(gActiveBattler, FALSE); StartSendOutAnim(gActiveBattler, FALSE);
@ -3129,6 +3129,11 @@ static void Task_StartSendOutAnim(u8 taskId)
StartSendOutAnim(gActiveBattler, FALSE); StartSendOutAnim(gActiveBattler, FALSE);
gActiveBattler ^= BIT_FLANK; gActiveBattler ^= BIT_FLANK;
} }
else
{
gBattleResources->bufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler];
StartSendOutAnim(gActiveBattler, FALSE);
}
gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox; gBattlerControllerFuncs[gActiveBattler] = Intro_TryShinyAnimShowHealthbox;
gActiveBattler = savedActiveBattler; gActiveBattler = savedActiveBattler;
DestroyTask(taskId); DestroyTask(taskId);

View File

@ -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) static void SetBattlePartyIds(void)
{ {
s32 i, j; s32 i, j;
@ -602,10 +610,7 @@ static void SetBattlePartyIds(void)
{ {
if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER)
{ {
if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 if (IsValidForBattle(&gPlayerParty[j]))
&& GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_NONE
&& GetMonData(&gPlayerParty[j], MON_DATA_SPECIES2) != SPECIES_EGG
&& GetMonData(&gPlayerParty[j], MON_DATA_IS_EGG) == 0)
{ {
gBattlerPartyIndexes[i] = j; gBattlerPartyIndexes[i] = j;
break; break;
@ -613,10 +618,7 @@ static void SetBattlePartyIds(void)
} }
else else
{ {
if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 if (IsValidForBattle(&gEnemyParty[j]))
&& 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] = j; gBattlerPartyIndexes[i] = j;
break; break;
@ -627,11 +629,7 @@ static void SetBattlePartyIds(void)
{ {
if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER) if (GET_BATTLER_SIDE2(i) == B_SIDE_PLAYER)
{ {
if (GetMonData(&gPlayerParty[j], MON_DATA_HP) != 0 if (IsValidForBattle(&gPlayerParty[j]) && gBattlerPartyIndexes[i - 2] != j)
&& 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)
{ {
gBattlerPartyIndexes[i] = j; gBattlerPartyIndexes[i] = j;
break; break;
@ -639,16 +637,18 @@ static void SetBattlePartyIds(void)
} }
else else
{ {
if (GetMonData(&gEnemyParty[j], MON_DATA_HP) != 0 if (IsValidForBattle(&gEnemyParty[j]) && gBattlerPartyIndexes[i - 2] != j)
&& 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)
{ {
gBattlerPartyIndexes[i] = j; gBattlerPartyIndexes[i] = j;
break; break;
} }
} }
// No valid mons were found. Add the empty slot.
if (gBattlerPartyIndexes[i - 2] == 0)
gBattlerPartyIndexes[i] = 1;
else
gBattlerPartyIndexes[i] = 0;
} }
} }
} }

View File

@ -3454,6 +3454,13 @@ static void TryDoEventsBeforeFirstTurn(void)
if (gBattleControllerExecFlags) if (gBattleControllerExecFlags)
return; 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) if (gBattleStruct->switchInAbilitiesCounter == 0)
{ {
for (i = 0; i < gBattlersCount; i++) for (i = 0; i < gBattlersCount; i++)
@ -4080,10 +4087,10 @@ static void HandleTurnActionSelectionState(void)
} }
break; break;
case STATE_WAIT_ACTION_CONFIRMED_STANDBY: case STATE_WAIT_ACTION_CONFIRMED_STANDBY:
if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler])
| (0xF << 28) | (0xF << 28)
| (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 4)
| (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 8)
| (gBitTable[gActiveBattler] << 12)))) | (gBitTable[gActiveBattler] << 12))))
{ {
if (AllAtActionConfirmed()) if (AllAtActionConfirmed())
@ -4646,7 +4653,7 @@ static void CheckQuickClaw_CustapBerryActivation(void)
} }
} }
} }
// setup stuff before turns/actions // setup stuff before turns/actions
TryClearRageAndFuryCutter(); TryClearRageAndFuryCutter();
gCurrentTurnActionNumber = 0; gCurrentTurnActionNumber = 0;

View File

@ -2560,7 +2560,7 @@ void BufferStringBattle(u16 stringID)
case STRINGID_INTROSENDOUT: // poke first send-out case STRINGID_INTROSENDOUT: // poke first send-out
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) 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) if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
stringPtr = sText_InGamePartnerSentOutZGoN; stringPtr = sText_InGamePartnerSentOutZGoN;