diff --git a/include/battle.h b/include/battle.h index 7a19532258..73a6799adb 100644 --- a/include/battle.h +++ b/include/battle.h @@ -584,6 +584,7 @@ struct BattleStruct struct MegaEvolutionData mega; const u8 *trainerSlideMsg; bool8 trainerSlideLowHpMsgDone; + u8 introState; }; #define GET_MOVE_TYPE(move, typeArg) \ diff --git a/include/battle_util.h b/include/battle_util.h index ad166571e1..c2d207bcef 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -43,6 +43,7 @@ void PressurePPLose(u8 bankDef, u8 bankAtk, u16 move); void PressurePPLoseOnUsingPerishSong(u8 bankAtk); void PressurePPLoseOnUsingImprision(u8 bankAtk); void MarkAllBattlersForControllerExec(void); // unused +bool32 IsBattlerMarkedForControllerExec(u8 battlerId); void MarkBattlerForControllerExec(u8 battlerId); void sub_803F850(u8 arg0); void CancelMultiTurnMoves(u8 battlerId); diff --git a/include/constants/battle_config.h b/include/constants/battle_config.h index 2e44012c2d..8a65728746 100644 --- a/include/constants/battle_config.h +++ b/include/constants/battle_config.h @@ -15,4 +15,6 @@ #define B_EXP_CATCH GEN_6 // Starting from gen6, pokemon get experience from catching. #define B_ABILITY_POP_UP GEN_6 // Starting from gen5, the pokemon abilities are displayed in a pop-up, when they activate in battle. +#define B_FAST_INTRO TRUE // If set to TRUE, battle intro texts print at the same time as animation of a pokemon, as opposing to waiting for the animation to end. + #endif // GUARD_CONSTANTS_BATTLE_CONFIG_H diff --git a/src/battle_main.c b/src/battle_main.c index fab12d3edf..909d51d63b 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -117,18 +117,7 @@ static void SpecialStatusesClear(void); static void TurnValuesCleanUp(bool8 var0); static void SpriteCB_BounceEffect(struct Sprite *sprite); static void BattleStartClearSetData(void); -static void BattleIntroGetMonsData(void); -static void BattleIntroPrepareBackgroundSlide(void); -static void BattleIntroDrawTrainersOrMonsSprites(void); -static void BattleIntroDrawPartySummaryScreens(void); -static void BattleIntroPrintTrainerWantsToBattle(void); -static void BattleIntroPrintWildMonAttacked(void); -static void BattleIntroPrintOpponentSendsOut(void); -static void BattleIntroPrintPlayerSendsOut(void); -static void BattleIntroOpponent1SendsOutMonAnimation(void); -static void BattleIntroOpponent2SendsOutMonAnimation(void); -static void BattleIntroRecordMonsToDex(void); -static void BattleIntroPlayer1SendsOutMonAnimation(void); +static void DoBattleIntro(void); static void TryDoEventsBeforeFirstTurn(void); static void HandleTurnActionSelectionState(void); static void RunTurnActionsFunctions(void); @@ -2013,12 +2002,6 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir return gTrainers[trainerNum].partySize; } -void sub_8038A04(void) // unused -{ - if (REG_VCOUNT < 0xA0 && REG_VCOUNT >= 0x6F) - SetGpuReg(REG_OFFSET_BG0CNT, 0x9800); -} - void VBlankCB_Battle(void) { // Change gRngSeed every vblank unless the battle could be recorded. @@ -2661,13 +2644,6 @@ void SpriteCallbackDummy_2(struct Sprite *sprite) } -static void sub_80398BC(struct Sprite *sprite) // unused? -{ - sprite->data[3] = 6; - sprite->data[4] = 1; - sprite->callback = sub_80398D0; -} - static void sub_80398D0(struct Sprite *sprite) { sprite->data[4]--; @@ -2958,7 +2934,8 @@ void BeginBattleIntro(void) { BattleStartClearSetData(); gBattleCommunication[1] = 0; - gBattleMainFunc = BattleIntroGetMonsData; + gBattleStruct->introState = 0; + gBattleMainFunc = DoBattleIntro; } static void BattleMainCB1(void) @@ -3311,550 +3288,323 @@ void FaintClearSetData(void) UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]); } -static void BattleIntroGetMonsData(void) +static void DoBattleIntro(void) { - switch (gBattleCommunication[MULTIUSE_STATE]) + s32 i; + u8 *state = &gBattleStruct->introState; + + switch (*state) { - case 0: + case 0: // Get Data of all battlers. gActiveBattler = gBattleCommunication[1]; BtlController_EmitGetMonData(0, REQUEST_ALL_BATTLE, 0); MarkBattlerForControllerExec(gActiveBattler); - gBattleCommunication[MULTIUSE_STATE]++; + (*state)++; break; - case 1: - if (gBattleControllerExecFlags == 0) + case 1: // Loop through all battlers. + if (!gBattleControllerExecFlags) { - gBattleCommunication[1]++; - if (gBattleCommunication[1] == gBattlersCount) - gBattleMainFunc = BattleIntroPrepareBackgroundSlide; + if (++gBattleCommunication[1] == gBattlersCount) + (*state)++; else - gBattleCommunication[MULTIUSE_STATE] = 0; + *state = 0; } break; - } -} - -static void BattleIntroPrepareBackgroundSlide(void) -{ - if (gBattleControllerExecFlags == 0) - { - gActiveBattler = GetBattlerAtPosition(0); - BtlController_EmitIntroSlide(0, gBattleTerrain); - MarkBattlerForControllerExec(gActiveBattler); - gBattleMainFunc = BattleIntroDrawTrainersOrMonsSprites; - gBattleCommunication[0] = 0; - gBattleCommunication[1] = 0; - } -} - -static void BattleIntroDrawTrainersOrMonsSprites(void) -{ - u8 *ptr; - s32 i; - - if (gBattleControllerExecFlags) - return; - - for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) - { - if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) - && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + case 2: // Start graphical intro slide. + if (!gBattleControllerExecFlags) { - ptr = (u8 *)&gBattleMons[gActiveBattler]; - for (i = 0; i < sizeof(struct BattlePokemon); i++) - ptr[i] = 0; - } - else - { - u16* hpOnSwitchout; - - ptr = (u8 *)&gBattleMons[gActiveBattler]; - for (i = 0; i < sizeof(struct BattlePokemon); i++) - ptr[i] = gBattleBufferB[gActiveBattler][4 + i]; - - gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1; - gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2; - gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; - gBattleMons[gActiveBattler].ability = GetAbilityBySpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].altAbility); - hpOnSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(gActiveBattler)]; - *hpOnSwitchout = gBattleMons[gActiveBattler].hp; - for (i = 0; i < NUM_BATTLE_STATS; i++) - gBattleMons[gActiveBattler].statStages[i] = 6; - gBattleMons[gActiveBattler].status2 = 0; - } - - if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT) - { - BtlController_EmitDrawTrainerPic(0); + gActiveBattler = GetBattlerAtPosition(0); + BtlController_EmitIntroSlide(0, gBattleTerrain); MarkBattlerForControllerExec(gActiveBattler); + gBattleCommunication[0] = 0; + gBattleCommunication[1] = 0; + (*state)++; + } + break; + case 3: // Wait for intro slide. + if (!gBattleControllerExecFlags) + (*state)++; + break; + case 4: // Copy battler data gotten in cases 0 and 1. Draw trainer/mon sprite. + for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) + { + if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + memset(&gBattleMons[gActiveBattler], 0, sizeof(struct BattlePokemon)); + } + else + { + memcpy(&gBattleMons[gActiveBattler], &gBattleBufferB[gActiveBattler][4], sizeof(struct BattlePokemon)); + gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1; + gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2; + gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY; + gBattleMons[gActiveBattler].ability = GetAbilityBySpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].altAbility); + gBattleStruct->hpOnSwitchout[GetBattlerSide(gActiveBattler)] = gBattleMons[gActiveBattler].hp; + gBattleMons[gActiveBattler].status2 = 0; + for (i = 0; i < NUM_BATTLE_STATS; i++) + gBattleMons[gActiveBattler].statStages[i] = 6; + } + + // Draw sprite. + switch (GetBattlerPosition(gActiveBattler)) + { + case B_POSITION_PLAYER_LEFT: // player sprite + BtlController_EmitDrawTrainerPic(0); + MarkBattlerForControllerExec(gActiveBattler); + break; + case B_POSITION_OPPONENT_LEFT: + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) // opponent 1 sprite + { + BtlController_EmitDrawTrainerPic(0); + MarkBattlerForControllerExec(gActiveBattler); + } + else // wild mon 1 + { + BtlController_EmitLoadMonSprite(0); + MarkBattlerForControllerExec(gActiveBattler); + gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES, NULL); + } + break; + case B_POSITION_PLAYER_RIGHT: + if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) // partner sprite + { + BtlController_EmitDrawTrainerPic(0); + MarkBattlerForControllerExec(gActiveBattler); + } + break; + case B_POSITION_OPPONENT_RIGHT: + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS)) // opponent 2 if exists + { + BtlController_EmitDrawTrainerPic(0); + MarkBattlerForControllerExec(gActiveBattler); + } + } + else // wild mon 2 + { + BtlController_EmitLoadMonSprite(0); + MarkBattlerForControllerExec(gActiveBattler); + gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES, NULL); + } + break; + } + + if (gBattleTypeFlags & BATTLE_TYPE_ARENA) + BattleArena_InitPoints(); } if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - if (GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_LEFT) + (*state)++; + } + else // Skip party summary since it is a wild battle. + { + if (B_FAST_INTRO) + *state = 7; // Don't wait for sprite, print message at the same time. + else + *state = 6; // Wait for sprite to load. + } + break; + case 5: // draw party summary in trainer battles + if (!gBattleControllerExecFlags) + { + struct HpAndStatus hpStatus[PARTY_SIZE]; + + for (i = 0; i < PARTY_SIZE; i++) { - BtlController_EmitDrawTrainerPic(0); - MarkBattlerForControllerExec(gActiveBattler); + if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE + || GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) + { + hpStatus[i].hp = 0xFFFF; + hpStatus[i].status = 0; + } + else + { + hpStatus[i].hp = GetMonData(&gEnemyParty[i], MON_DATA_HP); + hpStatus[i].status = GetMonData(&gEnemyParty[i], MON_DATA_STATUS); + } } - if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT - && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_FRONTIER - | BATTLE_TYPE_LINK - | BATTLE_TYPE_x2000000 - | BATTLE_TYPE_TRAINER_HILL))) + + gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80); + MarkBattlerForControllerExec(gActiveBattler); + + for (i = 0; i < PARTY_SIZE; i++) { - HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality); + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE + || GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) + { + hpStatus[i].hp = 0xFFFF; + hpStatus[i].status = 0; + } + else + { + hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP); + hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS); + } + } + + gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80); + MarkBattlerForControllerExec(gActiveBattler); + + (*state)++; + } + break; + case 6: // wait for previous action to complete + if (!gBattleControllerExecFlags) + (*state)++; + break; + case 7: // print battle intro message + if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) + { + PrepareStringBattle(STRINGID_INTROMSG, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); + (*state)++; + } + break; + case 8: // wait for intro message to be printed + if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) + { + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + (*state)++; + } + else + { + if (B_FAST_INTRO) + *state = 15; // Wait for text to be printed. + else + *state = 14; // Wait for text and sprite. } } + break; + case 9: // print opponent sends out + if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000)) + PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); else + PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)); + (*state)++; + break; + case 10: // wait for opponent sends out text + if (!gBattleControllerExecFlags) + (*state)++; + break; + case 11: // first opponent's mon send out animation + if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000)) + gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + else + gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + + BtlController_EmitIntroTrainerBallThrow(0); + MarkBattlerForControllerExec(gActiveBattler); + (*state)++; + break; + case 12: // nothing + (*state)++; + case 13: // second opponent's mon send out + if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS)) { - if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT) + if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000)) + gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + else + gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + + BtlController_EmitIntroTrainerBallThrow(0); + MarkBattlerForControllerExec(gActiveBattler); + } + if (B_FAST_INTRO && !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_x2000000 | BATTLE_TYPE_x80000000 | BATTLE_TYPE_LINK))) + *state = 15; // Print at the same time as trainer sends out second mon. + else + (*state)++; + break; + case 14: // wait for opponent 2 send out + if (!gBattleControllerExecFlags) + (*state)++; + break; + case 15: // wait for wild battle message + if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT))) + (*state)++; + break; + case 16: // print player sends out + if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) + { + if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000)) + gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + else + gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + + // A hack that makes fast intro work in trainer battles too. + if (B_FAST_INTRO + && gBattleTypeFlags & BATTLE_TYPE_TRAINER + && !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_x2000000 | BATTLE_TYPE_x80000000 | BATTLE_TYPE_LINK)) + && gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_SIDE]].callback == SpriteCallbackDummy) { - if (!(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_FRONTIER - | BATTLE_TYPE_LINK - | BATTLE_TYPE_x2000000 - | BATTLE_TYPE_TRAINER_HILL))) + return; + } + + PrepareStringBattle(STRINGID_INTROSENDOUT, gActiveBattler); + } + (*state)++; + break; + case 17: // wait for player send out message + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleControllerExecFlags)) + { + if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000)) + gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + else + gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + + if (!IsBattlerMarkedForControllerExec(gActiveBattler)) + (*state)++; + } + break; + case 18: // player 1 send out + if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000)) + gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + else + gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + + BtlController_EmitIntroTrainerBallThrow(0); + MarkBattlerForControllerExec(gActiveBattler); + (*state)++; + break; + case 19: // player 2 send out + if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) + { + if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000)) + gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + else + gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + + BtlController_EmitIntroTrainerBallThrow(0); + MarkBattlerForControllerExec(gActiveBattler); + } + (*state)++; + break; + case 20: // set dex and battle vars + if (!gBattleControllerExecFlags) + { + for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) + { + if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT + && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_FRONTIER + | BATTLE_TYPE_LINK + | BATTLE_TYPE_x2000000 + | BATTLE_TYPE_TRAINER_HILL))) { HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality); } - BtlController_EmitLoadMonSprite(0); - MarkBattlerForControllerExec(gActiveBattler); - gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES, NULL); } + + gBattleStruct->switchInAbilitiesCounter = 0; + gBattleStruct->switchInItemsCounter = 0; + gBattleStruct->overworldWeatherDone = FALSE; + + gBattleMainFunc = TryDoEventsBeforeFirstTurn; } - - if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - { - if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT - || (GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_RIGHT && gBattleTypeFlags & BATTLE_TYPE_TRAINER)) - { - BtlController_EmitDrawTrainerPic(0); - MarkBattlerForControllerExec(gActiveBattler); - } - } - - if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_RIGHT) - { - BtlController_EmitDrawTrainerPic(0); - MarkBattlerForControllerExec(gActiveBattler); - } - - if (gBattleTypeFlags & BATTLE_TYPE_ARENA) - BattleArena_InitPoints(); - } - gBattleMainFunc = BattleIntroDrawPartySummaryScreens; -} - -static void BattleIntroDrawPartySummaryScreens(void) -{ - s32 i; - struct HpAndStatus hpStatus[PARTY_SIZE]; - - if (gBattleControllerExecFlags) - return; - - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - { - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE - || GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) - { - hpStatus[i].hp = 0xFFFF; - hpStatus[i].status = 0; - } - else - { - hpStatus[i].hp = GetMonData(&gEnemyParty[i], MON_DATA_HP); - hpStatus[i].status = GetMonData(&gEnemyParty[i], MON_DATA_STATUS); - } - } - gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80); - MarkBattlerForControllerExec(gActiveBattler); - - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE - || GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) - { - hpStatus[i].hp = 0xFFFF; - hpStatus[i].status = 0; - } - else - { - hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP); - hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS); - } - } - gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80); - MarkBattlerForControllerExec(gActiveBattler); - - gBattleMainFunc = BattleIntroPrintTrainerWantsToBattle; - } - else - { - // The struct gets set here, but nothing is ever done with it since - // wild battles don't show the party summary. - // Still, there's no point in having dead code. - - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE - || GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG) - { - hpStatus[i].hp = 0xFFFF; - hpStatus[i].status = 0; - } - else - { - hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP); - hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS); - } - } - - gBattleMainFunc = BattleIntroPrintWildMonAttacked; - } - -} - -static void BattleIntroPrintTrainerWantsToBattle(void) -{ - if (gBattleControllerExecFlags == 0) - { - gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - PrepareStringBattle(STRINGID_INTROMSG, gActiveBattler); - gBattleMainFunc = BattleIntroPrintOpponentSendsOut; - } -} - -static void BattleIntroPrintWildMonAttacked(void) -{ - if (gBattleControllerExecFlags == 0) - { - gBattleMainFunc = BattleIntroPrintPlayerSendsOut; - PrepareStringBattle(STRINGID_INTROMSG, 0); - } -} - -static void BattleIntroPrintOpponentSendsOut(void) -{ - u32 position; - - if (gBattleControllerExecFlags) - return; - - if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) - position = B_POSITION_OPPONENT_LEFT; - else if (gBattleTypeFlags & BATTLE_TYPE_x2000000) - { - if (gBattleTypeFlags & BATTLE_TYPE_x80000000) - position = B_POSITION_OPPONENT_LEFT; - else - position = B_POSITION_PLAYER_LEFT; - } - else - position = B_POSITION_OPPONENT_LEFT; - - PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(position)); - gBattleMainFunc = BattleIntroOpponent1SendsOutMonAnimation; -} - -static void BattleIntroOpponent2SendsOutMonAnimation(void) -{ - u32 position; - - if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) - position = B_POSITION_OPPONENT_RIGHT; - else if (gBattleTypeFlags & BATTLE_TYPE_x2000000) - { - if (gBattleTypeFlags & BATTLE_TYPE_x80000000) - position = B_POSITION_OPPONENT_RIGHT; - else - position = B_POSITION_PLAYER_RIGHT; - } - else - position = B_POSITION_OPPONENT_RIGHT; - - for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) - { - if (GetBattlerPosition(gActiveBattler) == position) - { - BtlController_EmitIntroTrainerBallThrow(0); - MarkBattlerForControllerExec(gActiveBattler); - } - } - - gBattleMainFunc = BattleIntroRecordMonsToDex; -} - -#ifdef NONMATCHING -static void BattleIntroOpponent1SendsOutMonAnimation(void) -{ - u32 position; - - if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) - position = B_POSITION_OPPONENT_LEFT; - else if (gBattleTypeFlags & BATTLE_TYPE_x2000000) - { - if (gBattleTypeFlags & BATTLE_TYPE_x80000000) - position = B_POSITION_OPPONENT_LEFT; - else - position = B_POSITION_PLAYER_LEFT; - } - else - position = B_POSITION_OPPONENT_LEFT; - - if (gBattleControllerExecFlags) - return; - - for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) - { - if (GetBattlerPosition(gActiveBattler) == position) - { - BtlController_EmitIntroTrainerBallThrow(0); - MarkBattlerForControllerExec(gActiveBattler); - if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS)) - { - gBattleMainFunc = BattleIntroOpponent2SendsOutMonAnimation; - return; - } - } - } - - gBattleMainFunc = BattleIntroRecordMonsToDex; -} -#else -NAKED -static void BattleIntroOpponent1SendsOutMonAnimation(void) -{ - asm(".syntax unified\n\ - push {r4-r6,lr}\n\ - ldr r0, =gBattleTypeFlags\n\ - ldr r2, [r0]\n\ - movs r0, 0x80\n\ - lsls r0, 17\n\ - ands r0, r2\n\ - cmp r0, 0\n\ - beq _0803B298\n\ - movs r0, 0x80\n\ - lsls r0, 18\n\ - ands r0, r2\n\ - cmp r0, 0\n\ - beq _0803B298\n\ - movs r1, 0x80\n\ - lsls r1, 24\n\ - ands r1, r2\n\ - negs r0, r1\n\ - orrs r0, r1\n\ - lsrs r5, r0, 31\n\ - b _0803B29A\n\ - .pool\n\ -_0803B288:\n\ - ldr r1, =gBattleMainFunc\n\ - ldr r0, =BattleIntroOpponent2SendsOutMonAnimation\n\ - b _0803B2F0\n\ - .pool\n\ -_0803B298:\n\ - movs r5, 0x1\n\ -_0803B29A:\n\ - ldr r0, =gBattleControllerExecFlags\n\ - ldr r2, [r0]\n\ - cmp r2, 0\n\ - bne _0803B2F2\n\ - ldr r0, =gActiveBattler\n\ - strb r2, [r0]\n\ - ldr r1, =gBattlersCount\n\ - adds r4, r0, 0\n\ - ldrb r1, [r1]\n\ - cmp r2, r1\n\ - bcs _0803B2EC\n\ - adds r6, r4, 0\n\ -_0803B2B2:\n\ - ldrb r0, [r4]\n\ - bl GetBattlerPosition\n\ - lsls r0, 24\n\ - lsrs r0, 24\n\ - cmp r0, r5\n\ - bne _0803B2D8\n\ - movs r0, 0\n\ - bl BtlController_EmitIntroTrainerBallThrow\n\ - ldrb r0, [r4]\n\ - bl MarkBattlerForControllerExec\n\ - ldr r0, =gBattleTypeFlags\n\ - ldr r0, [r0]\n\ - ldr r1, =0x00008040\n\ - ands r0, r1\n\ - cmp r0, 0\n\ - bne _0803B288\n\ -_0803B2D8:\n\ - ldrb r0, [r6]\n\ - adds r0, 0x1\n\ - strb r0, [r6]\n\ - ldr r1, =gBattlersCount\n\ - lsls r0, 24\n\ - lsrs r0, 24\n\ - ldr r4, =gActiveBattler\n\ - ldrb r1, [r1]\n\ - cmp r0, r1\n\ - bcc _0803B2B2\n\ -_0803B2EC:\n\ - ldr r1, =gBattleMainFunc\n\ - ldr r0, =BattleIntroRecordMonsToDex\n\ -_0803B2F0:\n\ - str r0, [r1]\n\ -_0803B2F2:\n\ - pop {r4-r6}\n\ - pop {r0}\n\ - bx r0\n\ - .pool\n\ - .syntax divided"); -} -#endif // NONMATCHING - -static void BattleIntroRecordMonsToDex(void) -{ - if (gBattleControllerExecFlags == 0) - { - for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) - { - if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT - && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_FRONTIER - | BATTLE_TYPE_LINK - | BATTLE_TYPE_x2000000 - | BATTLE_TYPE_TRAINER_HILL))) - { - HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality); - } - } - gBattleMainFunc = BattleIntroPrintPlayerSendsOut; - } -} - -void sub_803B3AC(void) // unused -{ - if (gBattleControllerExecFlags == 0) - gBattleMainFunc = BattleIntroPrintPlayerSendsOut; -} - -static void BattleIntroPrintPlayerSendsOut(void) -{ - if (gBattleControllerExecFlags == 0) - { - u8 position; - - if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) - position = B_POSITION_PLAYER_LEFT; - else if (gBattleTypeFlags & BATTLE_TYPE_x2000000) - { - if (gBattleTypeFlags & BATTLE_TYPE_x80000000) - position = B_POSITION_PLAYER_LEFT; - else - position = B_POSITION_OPPONENT_LEFT; - } - else - position = B_POSITION_PLAYER_LEFT; - - if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) - PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(position)); - - gBattleMainFunc = BattleIntroPlayer1SendsOutMonAnimation; - } -} - -static void BattleIntroPlayer2SendsOutMonAnimation(void) -{ - u32 position; - - if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) - position = B_POSITION_PLAYER_RIGHT; - else if (gBattleTypeFlags & BATTLE_TYPE_x2000000) - { - if (gBattleTypeFlags & BATTLE_TYPE_x80000000) - position = B_POSITION_PLAYER_RIGHT; - else - position = B_POSITION_OPPONENT_RIGHT; - } - else - position = B_POSITION_PLAYER_RIGHT; - - for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) - { - if (GetBattlerPosition(gActiveBattler) == position) - { - BtlController_EmitIntroTrainerBallThrow(0); - MarkBattlerForControllerExec(gActiveBattler); - } - } - - gBattleStruct->switchInAbilitiesCounter = 0; - gBattleStruct->switchInItemsCounter = 0; - gBattleStruct->overworldWeatherDone = FALSE; - - gBattleMainFunc = TryDoEventsBeforeFirstTurn; -} - -static void BattleIntroPlayer1SendsOutMonAnimation(void) -{ - u32 position; - - if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) - position = B_POSITION_PLAYER_LEFT; - else if (gBattleTypeFlags & BATTLE_TYPE_x2000000) - { - if (gBattleTypeFlags & BATTLE_TYPE_x80000000) - position = B_POSITION_PLAYER_LEFT; - else - position = B_POSITION_OPPONENT_LEFT; - } - else - position = B_POSITION_PLAYER_LEFT; - - if (gBattleControllerExecFlags) - return; - - for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) - { - if (GetBattlerPosition(gActiveBattler) == position) - { - BtlController_EmitIntroTrainerBallThrow(0); - MarkBattlerForControllerExec(gActiveBattler); - if (gBattleTypeFlags & (BATTLE_TYPE_MULTI)) - { - gBattleMainFunc = BattleIntroPlayer2SendsOutMonAnimation; - return; - } - } - } - - gBattleStruct->switchInAbilitiesCounter = 0; - gBattleStruct->switchInItemsCounter = 0; - gBattleStruct->overworldWeatherDone = FALSE; - - gBattleMainFunc = TryDoEventsBeforeFirstTurn; -} - -void sub_803B598(void) // unused -{ - if (gBattleControllerExecFlags == 0) - { - for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++) - { - if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) - { - BtlController_EmitSwitchInAnim(0, gBattlerPartyIndexes[gActiveBattler], FALSE); - MarkBattlerForControllerExec(gActiveBattler); - } - } - - gBattleStruct->switchInAbilitiesCounter = 0; - gBattleStruct->switchInItemsCounter = 0; - gBattleStruct->overworldWeatherDone = FALSE; - - gBattleMainFunc = TryDoEventsBeforeFirstTurn; + break; } } diff --git a/src/battle_util.c b/src/battle_util.c index e5f7f5b296..3b3a8fd67c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -440,6 +440,14 @@ void MarkAllBattlersForControllerExec(void) // unused } } +bool32 IsBattlerMarkedForControllerExec(u8 battlerId) +{ + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + return (gBattleControllerExecFlags & (gBitTable[battlerId] << 0x1C)) != 0; + else + return (gBattleControllerExecFlags & (gBitTable[battlerId])) != 0; +} + void MarkBattlerForControllerExec(u8 battlerId) { if (gBattleTypeFlags & BATTLE_TYPE_LINK)