diff --git a/include/battle.h b/include/battle.h index 13316eada9..8fe4fa8cce 100644 --- a/include/battle.h +++ b/include/battle.h @@ -600,7 +600,8 @@ struct PartyState u32 supersweetSyrup:1; u32 timesGotHit:5; u32 changedSpecies:11; // For forms when multiple mons can change into the same pokemon. - u32 padding:10; + u32 sentOut:1; + u32 padding:9; }; // Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise. diff --git a/include/config/battle.h b/include/config/battle.h index d6de6397fe..61603ba5b8 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -311,6 +311,7 @@ #define B_TOXIC_REVERSAL GEN_LATEST // In Gen5+, bad poison will change to regular poison at the end of battles. #define B_TRY_CATCH_TRAINER_BALL GEN_LATEST // In Gen4+, trying to catch a Trainer's Pokémon does not consume the Poké Ball. #define B_SLEEP_CLAUSE FALSE // Enables Sleep Clause all the time in every case, overriding B_FLAG_SLEEP_CLAUSE. Use that for modularity. +#define B_PARTNER_MONS_MARKED_SEEN FALSE // If TRUE, if your double battle partner sends out a Pokémon you haven't encountered yet, it will be marked as SEEN in your Pokédex. #define NUM_BEEPS_GEN_LATEST 4 // Loops 4 times #define NUM_BEEPS_GEN_3 -1 // Loops infinitely diff --git a/include/pokemon.h b/include/pokemon.h index ba459480e1..1e31c425b6 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -849,6 +849,7 @@ u8 GetOpposingLinkMultiBattlerId(bool8 rightSide, u8 multiplayerId); u16 FacilityClassToPicIndex(u16 facilityClass); u16 PlayerGenderToFrontTrainerPicId(u8 playerGender); void HandleSetPokedexFlag(enum NationalDexOrder nationalNum, u8 caseId, u32 personality); +void HandleSetPokedexFlagFromMon(struct Pokemon *mon, u32 caseId); bool8 HasTwoFramesAnimation(u16 species); struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 managerId, u8 mode); void DestroyMonSpritesGfxManager(u8 managerId); diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 6340b921c6..ed81c19659 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1522,7 +1522,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva return bestMonId; } -static u32 GetFirstNonIvalidMon(u32 firstId, u32 lastId, u32 invalidMons, u32 battlerIn1, u32 battlerIn2) +static u32 GetFirstNonInvalidMon(u32 firstId, u32 lastId, u32 invalidMons, u32 battlerIn1, u32 battlerIn2) { if (!IsDoubleBattle()) return PARTY_SIZE; @@ -2297,7 +2297,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, return aceMonId; // Fallback - u32 bestMonId = GetFirstNonIvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + u32 bestMonId = GetFirstNonInvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); if (bestMonId != PARTY_SIZE) return bestMonId; @@ -2419,7 +2419,7 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) return aceMonId; // Fallback - bestMonId = GetFirstNonIvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); + bestMonId = GetFirstNonInvalidMon(firstId, lastId, invalidMons, battlerIn1, battlerIn2); if (bestMonId != PARTY_SIZE) return bestMonId; diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 84b3d3c0a8..8c469733c1 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -567,12 +567,14 @@ static void OpponentHandleChoosePokemon(u32 battler) } } gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; + GetBattlerPartyState(battler)->sentOut = TRUE; } else { chosenMonId = gBattleStruct->AI_monToSwitchIntoId[battler]; gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE; gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; + GetBattlerPartyState(battler)->sentOut = TRUE; } #if TESTING TestRunner_Battle_CheckSwitch(battler, chosenMonId); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 5426f0239f..58911f1518 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -285,7 +285,6 @@ static void PlayerPartnerHandleChoosePokemon(u32 battler) else if (gBattleStruct->monToSwitchIntoId[battler] >= PARTY_SIZE || !IsValidForBattle(&gPlayerParty[gBattleStruct->monToSwitchIntoId[battler]])) { chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO); - if (chosenMonId == PARTY_SIZE || !IsValidForBattle(&gPlayerParty[chosenMonId])) // just switch to the next mon { s32 firstId = (IsAiVsAiBattle()) ? 0 : (PARTY_SIZE / 2); @@ -303,12 +302,14 @@ static void PlayerPartnerHandleChoosePokemon(u32 battler) } } gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; + GetBattlerPartyState(battler)->sentOut = TRUE; } else // Mon to switch out has been already chosen. { chosenMonId = gBattleStruct->monToSwitchIntoId[battler]; gBattleStruct->AI_monToSwitchIntoId[battler] = PARTY_SIZE; gBattleStruct->monToSwitchIntoId[battler] = chosenMonId; + GetBattlerPartyState(battler)->sentOut = TRUE; } BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, chosenMonId, NULL); BtlController_Complete(battler); diff --git a/src/battle_main.c b/src/battle_main.c index c39ea52905..967520f9fb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3735,6 +3735,10 @@ static void DoBattleIntro(void) gBattleStruct->overworldWeatherDone = FALSE; Ai_InitPartyStruct(); // Save mons party counts, and first 2/4 mons on the battlefield. + // mark all battlers as sent out + for (battler = 0; battler < gBattlersCount; battler++) + GetBattlerPartyState(battler)->sentOut = TRUE; + // Try to set a status to start the battle with gBattleStruct->startingStatus = 0; if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetTrainerStartingStatusFromId(TRAINER_BATTLE_PARAM.opponentB)) @@ -5562,14 +5566,31 @@ static void HandleEndTurn_FinishBattle(void) GetMonData(GetBattlerMon(battler), MON_DATA_NICKNAME, gBattleResults.playerMon2Name); } } - else if (!IsOnPlayerSide(battler)) - { - HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[battler].species), FLAG_SET_SEEN, gBattleMons[battler].personality); - } } TryPutPokemonTodayOnAir(); } + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK + | BATTLE_TYPE_EREADER_TRAINER + | BATTLE_TYPE_RECORDED_LINK + | BATTLE_TYPE_TRAINER_HILL + | BATTLE_TYPE_FRONTIER))) + { + for (u32 side = 0; side < NUM_BATTLE_SIDES; side++) + { + struct Pokemon *party = GetSideParty(side); + + if (side == B_SIDE_PLAYER && !B_PARTNER_MONS_MARKED_SEEN) + continue; + + for (u32 partySlot = 0; partySlot < PARTY_SIZE; partySlot++) + { + if (gBattleStruct->partyState[side][partySlot].sentOut) + HandleSetPokedexFlagFromMon(&party[partySlot], FLAG_SET_SEEN); + } + } + } + if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_TRAINER diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 114da2aed7..a1b66e83f5 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7176,13 +7176,7 @@ static void Cmd_switchinanim(void) battler = GetBattlerForBattleScript(cmd->battler); - if (!IsOnPlayerSide(battler) - && !(gBattleTypeFlags & (BATTLE_TYPE_LINK - | BATTLE_TYPE_EREADER_TRAINER - | BATTLE_TYPE_RECORDED_LINK - | BATTLE_TYPE_TRAINER_HILL - | BATTLE_TYPE_FRONTIER))) - HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[battler].species), FLAG_SET_SEEN, gBattleMons[battler].personality); + GetBattlerPartyState(battler)->sentOut = TRUE; gAbsentBattlerFlags &= ~(1u << battler); diff --git a/src/pokemon.c b/src/pokemon.c index 61270d72c3..eb2428f2fb 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -6349,6 +6349,14 @@ void HandleSetPokedexFlag(enum NationalDexOrder nationalNum, u8 caseId, u32 pers } } +void HandleSetPokedexFlagFromMon(struct Pokemon *mon, u32 caseId) +{ + u32 personality = GetMonData(mon, MON_DATA_PERSONALITY); + enum NationalDexOrder nationalNum = SpeciesToNationalPokedexNum(GetMonData(mon, MON_DATA_SPECIES)); + + HandleSetPokedexFlag(nationalNum, caseId, personality); +} + bool8 HasTwoFramesAnimation(u16 species) { return P_TWO_FRAME_FRONT_SPRITES