fix: seen flags for first mon in enemy party (#7791)

Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
This commit is contained in:
khbsd 2025-09-28 02:53:55 -05:00 committed by GitHub
parent e5e0800b90
commit a4ecd7338b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 45 additions and 16 deletions

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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