Fix Summary screen lag with move relearner when there's a lot of TMs (#8503)

This commit is contained in:
PCG 2025-12-14 19:02:52 +05:30 committed by GitHub
parent 08a5a319bd
commit 6db75af625
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 224 additions and 127 deletions

View File

@ -130,6 +130,8 @@ extern const struct TmHmIndexKey gTMHMItemMoveIds[];
#define UNPACK_ITEM_TO_HM_INDEX(_hm) case CAT(ITEM_HM_, _hm): return CAT(ENUM_TM_HM_, _hm) + 1; #define UNPACK_ITEM_TO_HM_INDEX(_hm) case CAT(ITEM_HM_, _hm): return CAT(ENUM_TM_HM_, _hm) + 1;
#define UNPACK_ITEM_TO_TM_MOVE_ID(_tm) case CAT(ITEM_TM_, _tm): return CAT(MOVE_, _tm); #define UNPACK_ITEM_TO_TM_MOVE_ID(_tm) case CAT(ITEM_TM_, _tm): return CAT(MOVE_, _tm);
#define UNPACK_ITEM_TO_HM_MOVE_ID(_hm) case CAT(ITEM_HM_, _hm): return CAT(MOVE_, _hm); #define UNPACK_ITEM_TO_HM_MOVE_ID(_hm) case CAT(ITEM_HM_, _hm): return CAT(MOVE_, _hm);
#define UNPACK_TM_MOVE_TO_ITEM_ID(_move) case CAT(MOVE_, _move): return CAT(ITEM_TM_, _move);
#define UNPACK_HM_MOVE_TO_ITEM_ID(_move) case CAT(MOVE_, _move): return CAT(ITEM_HM_, _move);
static inline enum TMHMIndex GetItemTMHMIndex(u16 item) static inline enum TMHMIndex GetItemTMHMIndex(u16 item)
{ {
@ -165,10 +167,29 @@ static inline u16 GetItemTMHMMoveId(u16 item)
} }
} }
static inline enum TMHMItemId GetTMHMItemIdFromMoveId(u16 move)
{
switch (move)
{
/* Expands to:
* case MOVE_FOCUS_PUNCH:
* return ITEM_TM_FOCUS_PUNCH;
* case MOVE_DRAGON_CLAW:
* return ITEM_TM_DRAGON_CLAW;
* etc */
FOREACH_TM(UNPACK_TM_MOVE_TO_ITEM_ID)
FOREACH_HM(UNPACK_HM_MOVE_TO_ITEM_ID)
default:
return ITEM_NONE;
}
}
#undef UNPACK_ITEM_TO_TM_INDEX #undef UNPACK_ITEM_TO_TM_INDEX
#undef UNPACK_ITEM_TO_HM_INDEX #undef UNPACK_ITEM_TO_HM_INDEX
#undef UNPACK_ITEM_TO_TM_MOVE_ID #undef UNPACK_ITEM_TO_TM_MOVE_ID
#undef UNPACK_ITEM_TO_HM_MOVE_ID #undef UNPACK_ITEM_TO_HM_MOVE_ID
#undef UNPACK_TM_MOVE_TO_ITEM_ID
#undef UNPACK_HM_MOVE_TO_ITEM_ID
static inline enum TMHMItemId GetTMHMItemId(enum TMHMIndex index) static inline enum TMHMItemId GetTMHMItemId(enum TMHMIndex index)
{ {
@ -180,8 +201,6 @@ static inline u16 GetTMHMMoveId(enum TMHMIndex index)
return gTMHMItemMoveIds[index].moveId; return gTMHMItemMoveIds[index].moveId;
} }
enum TMHMItemId GetTMHMItemIdFromMoveId(u16 move);
void BagPocket_SetSlotData(struct BagPocket *pocket, u32 pocketPos, struct ItemSlot newSlot); void BagPocket_SetSlotData(struct BagPocket *pocket, u32 pocketPos, struct ItemSlot newSlot);
struct ItemSlot BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos); struct ItemSlot BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos);

View File

@ -841,14 +841,14 @@ void UpdatePartyPokerusTime(u16 days);
void PartySpreadPokerus(struct Pokemon *party); void PartySpreadPokerus(struct Pokemon *party);
bool8 TryIncrementMonLevel(struct Pokemon *mon); bool8 TryIncrementMonLevel(struct Pokemon *mon);
u8 CanLearnTeachableMove(u16 species, u16 move); u8 CanLearnTeachableMove(u16 species, u16 move);
u8 GetRelearnerLevelUpMoves(struct Pokemon *mon, u16 *moves); u32 GetRelearnerLevelUpMoves(struct Pokemon *mon, u16 *moves);
u8 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves); u32 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves);
u8 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves); u32 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves);
u8 GetRelearnerTutorMoves(struct Pokemon *mon, u16 *moves); u32 GetRelearnerTutorMoves(struct Pokemon *mon, u16 *moves);
u8 GetNumberOfLevelUpMoves(struct Pokemon *mon); bool32 HasRelearnerLevelUpMoves(struct Pokemon *mon);
u8 GetNumberOfEggMoves(struct Pokemon *mon); bool32 HasRelearnerEggMoves(struct Pokemon *mon);
u8 GetNumberOfTMMoves(struct Pokemon *mon); bool32 HasRelearnerTMMoves(struct Pokemon *mon);
u8 GetNumberOfTutorMoves(struct Pokemon *mon); bool32 HasRelearnerTutorMoves(struct Pokemon *mon);
u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves); u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves);
u16 SpeciesToPokedexNum(u16 species); u16 SpeciesToPokedexNum(u16 species);
bool32 IsSpeciesInHoennDex(u16 species); bool32 IsSpeciesInHoennDex(u16 species);

View File

@ -57,7 +57,5 @@ u8 GetMoveSlotToReplace(void);
void SummaryScreen_SetAnimDelayTaskId(u8 taskId); void SummaryScreen_SetAnimDelayTaskId(u8 taskId);
void ShowRelearnPrompt(void); void ShowRelearnPrompt(void);
void TryUpdateRelearnType(enum IncrDecrUpdateValues delta); void TryUpdateRelearnType(enum IncrDecrUpdateValues delta);
u32 GetCurrentRelearnMovesCount(void);
u32 GetRelearnMovesCount(enum MoveRelearnerStates state);
#endif // GUARD_POKEMON_SUMMARY_SCREEN_H #endif // GUARD_POKEMON_SUMMARY_SCREEN_H

View File

@ -88,19 +88,6 @@ static inline void NONNULL BagPocket_SetSlotDataPC(struct BagPocket *pocket, u32
pocket->itemSlots[pocketPos].quantity = newSlot.quantity; pocket->itemSlots[pocketPos].quantity = newSlot.quantity;
} }
enum TMHMItemId GetTMHMItemIdFromMoveId(u16 move)
{
if (move == MOVE_NONE)
return 0;
for (u16 i = 0; i < NUM_ALL_MACHINES; i++)
{
if (GetTMHMMoveId(i + 1) == move)
return GetTMHMItemId(i + 1);
}
return 0;
}
struct ItemSlot NONNULL BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos) struct ItemSlot NONNULL BagPocket_GetSlotData(struct BagPocket *pocket, u32 pocketPos)
{ {
switch (pocket->id) switch (pocket->id)

View File

@ -1099,16 +1099,16 @@ static void DisplayPartyPokemonDataForRelearner(u8 slot)
switch (gMoveRelearnerState) switch (gMoveRelearnerState)
{ {
case MOVE_RELEARNER_EGG_MOVES: case MOVE_RELEARNER_EGG_MOVES:
hasMoves = (GetNumberOfEggMoves(mon) > 0); hasMoves = HasRelearnerEggMoves(mon);
break; break;
case MOVE_RELEARNER_TM_MOVES: case MOVE_RELEARNER_TM_MOVES:
hasMoves = (GetNumberOfTMMoves(mon) > 0); hasMoves = HasRelearnerTMMoves(mon);
break; break;
case MOVE_RELEARNER_TUTOR_MOVES: case MOVE_RELEARNER_TUTOR_MOVES:
hasMoves = (GetNumberOfTutorMoves(mon) > 0); hasMoves = HasRelearnerTutorMoves(mon);
break; break;
default: default:
hasMoves = (GetNumberOfLevelUpMoves(mon) > 0); hasMoves = HasRelearnerLevelUpMoves(mon);
break; break;
} }
@ -2876,8 +2876,8 @@ static void SetPartyMonFieldSelectionActions(struct Pokemon *mons, u8 slotId)
if (P_PARTY_MOVE_RELEARNER if (P_PARTY_MOVE_RELEARNER
&& (GetMonData(&mons[slotId], MON_DATA_SPECIES) && (GetMonData(&mons[slotId], MON_DATA_SPECIES)
&& (GetNumberOfLevelUpMoves(&mons[slotId]) || GetNumberOfEggMoves(&mons[slotId]) && (HasRelearnerLevelUpMoves(&mons[slotId]) || HasRelearnerEggMoves(&mons[slotId])
|| GetNumberOfTMMoves(&mons[slotId]) || GetNumberOfTutorMoves(&mons[slotId])))) || HasRelearnerTMMoves(&mons[slotId]) || HasRelearnerTutorMoves(&mons[slotId]))))
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUB_MOVES); AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUB_MOVES);
// Add field moves to action list // Add field moves to action list
@ -2907,24 +2907,24 @@ static void SetPartyMonFieldSelectionActions(struct Pokemon *mons, u8 slotId)
static void SetPartyMonLearnMoveSelectionActions(struct Pokemon *mons, u8 slotId) static void SetPartyMonLearnMoveSelectionActions(struct Pokemon *mons, u8 slotId)
{ {
if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && GetNumberOfLevelUpMoves(&mons[slotId]) > 0) if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerLevelUpMoves(&mons[slotId]))
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_LEVEL_UP_MOVES); AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_LEVEL_UP_MOVES);
if (P_ENABLE_MOVE_RELEARNERS || (P_FLAG_EGG_MOVES != 0 && FlagGet(P_FLAG_EGG_MOVES))) if (P_ENABLE_MOVE_RELEARNERS || (P_FLAG_EGG_MOVES != 0 && FlagGet(P_FLAG_EGG_MOVES)))
{ {
if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && GetNumberOfEggMoves(&mons[slotId]) > 0) if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerEggMoves(&mons[slotId]))
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_EGG_MOVES); AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_EGG_MOVES);
} }
if (P_ENABLE_MOVE_RELEARNERS || P_TM_MOVES_RELEARNER) if (P_ENABLE_MOVE_RELEARNERS || P_TM_MOVES_RELEARNER)
{ {
if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && GetNumberOfTMMoves(&mons[slotId]) > 0) if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerTMMoves(&mons[slotId]))
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_TM_MOVES); AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_TM_MOVES);
} }
if (P_ENABLE_MOVE_RELEARNERS || (P_FLAG_TUTOR_MOVES != 0 && FlagGet(P_FLAG_TUTOR_MOVES))) if (P_ENABLE_MOVE_RELEARNERS || (P_FLAG_TUTOR_MOVES != 0 && FlagGet(P_FLAG_TUTOR_MOVES)))
{ {
if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && GetNumberOfTutorMoves(&mons[slotId]) > 0) if (GetMonData(&mons[slotId], MON_DATA_SPECIES) != SPECIES_NONE && HasRelearnerTutorMoves(&mons[slotId]))
AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_TUTOR_MOVES); AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_TUTOR_MOVES);
} }
@ -7968,16 +7968,16 @@ static void CB2_ChooseMonForMoveRelearner(void)
switch(gMoveRelearnerState) switch(gMoveRelearnerState)
{ {
case MOVE_RELEARNER_EGG_MOVES: case MOVE_RELEARNER_EGG_MOVES:
gSpecialVar_0x8005 = GetNumberOfEggMoves(&gPlayerParty[gSpecialVar_0x8004]); gSpecialVar_0x8005 = HasRelearnerEggMoves(&gPlayerParty[gSpecialVar_0x8004]);
break; break;
case MOVE_RELEARNER_TM_MOVES: case MOVE_RELEARNER_TM_MOVES:
gSpecialVar_0x8005 = GetNumberOfTMMoves(&gPlayerParty[gSpecialVar_0x8004]); gSpecialVar_0x8005 = HasRelearnerTMMoves(&gPlayerParty[gSpecialVar_0x8004]);
break; break;
case MOVE_RELEARNER_TUTOR_MOVES: case MOVE_RELEARNER_TUTOR_MOVES:
gSpecialVar_0x8005 = GetNumberOfTutorMoves(&gPlayerParty[gSpecialVar_0x8004]); gSpecialVar_0x8005 = HasRelearnerTutorMoves(&gPlayerParty[gSpecialVar_0x8004]);
break; break;
default: default:
gSpecialVar_0x8005 = GetNumberOfLevelUpMoves(&gPlayerParty[gSpecialVar_0x8004]); gSpecialVar_0x8005 = HasRelearnerLevelUpMoves(&gPlayerParty[gSpecialVar_0x8004]);
break; break;
} }
} }

View File

@ -5740,32 +5740,32 @@ static void QuickSortMoves(u16 *moves, s32 left, s32 right)
QuickSortMoves(moves, i, right); QuickSortMoves(moves, i, right);
} }
static void SortMovesAlphabetically(u16 *moves, u8 numMoves) static void SortMovesAlphabetically(u16 *moves, u32 numMoves)
{ {
if (numMoves > 1) if (numMoves > 1)
QuickSortMoves(moves, 0, numMoves - 1); QuickSortMoves(moves, 0, numMoves - 1);
} }
u8 GetRelearnerLevelUpMoves(struct Pokemon *mon, u16 *moves) u32 GetRelearnerLevelUpMoves(struct Pokemon *mon, u16 *moves)
{ {
u16 learnedMoves[MAX_MON_MOVES] = {0}; u16 learnedMoves[MAX_MON_MOVES] = {0};
u8 numMoves = 0; u32 numMoves = 0;
u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); u32 species = GetMonData(mon, MON_DATA_SPECIES, 0);
u8 level = (P_ENABLE_ALL_LEVEL_UP_MOVES ? MAX_LEVEL : GetMonData(mon, MON_DATA_LEVEL, 0)); u32 level = (P_ENABLE_ALL_LEVEL_UP_MOVES ? MAX_LEVEL : GetMonData(mon, MON_DATA_LEVEL, 0));
for (u8 i = 0; i < MAX_MON_MOVES; i++) for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
do do
{ {
const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species); const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species);
for (u16 i = 0; i < MAX_LEVEL_UP_MOVES && learnset[i].move != LEVEL_UP_MOVE_END; i++) for (u32 i = 0; i < MAX_LEVEL_UP_MOVES && learnset[i].move != LEVEL_UP_MOVE_END; i++)
{ {
if (learnset[i].level > level) if (learnset[i].level > level)
continue; break;
u16 j; u32 j;
for (j = 0; j < MAX_MON_MOVES; j++) for (j = 0; j < MAX_MON_MOVES; j++)
{ {
if (learnedMoves[j] == learnset[i].move) if (learnedMoves[j] == learnset[i].move)
@ -5794,11 +5794,14 @@ u8 GetRelearnerLevelUpMoves(struct Pokemon *mon, u16 *moves)
return numMoves; return numMoves;
} }
u8 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves) u32 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves)
{ {
u16 learnedMoves[MAX_MON_MOVES] = {0}; if (!FlagGet(P_FLAG_EGG_MOVES) && !P_ENABLE_MOVE_RELEARNERS)
u8 numMoves = 0; return 0;
u16 species = GetMonData(mon, MON_DATA_SPECIES);
u32 learnedMoves[MAX_MON_MOVES] = {0};
u32 numMoves = 0;
u32 species = GetMonData(mon, MON_DATA_SPECIES);
while (GetSpeciesPreEvolution(species) != SPECIES_NONE) while (GetSpeciesPreEvolution(species) != SPECIES_NONE)
species = GetSpeciesPreEvolution(species); species = GetSpeciesPreEvolution(species);
@ -5807,12 +5810,12 @@ u8 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves)
if (eggMoves == sNoneEggMoveLearnset) if (eggMoves == sNoneEggMoveLearnset)
return numMoves; return numMoves;
for (u8 i = 0; i < MAX_MON_MOVES; i++) for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
for (u16 i = 0; eggMoves[i] != MOVE_UNAVAILABLE; i++) for (u32 i = 0; eggMoves[i] != MOVE_UNAVAILABLE; i++)
{ {
u16 j; u32 j;
for (j = 0; j < MAX_MON_MOVES; j++) for (j = 0; j < MAX_MON_MOVES; j++)
{ {
if (learnedMoves[j] == eggMoves[i]) if (learnedMoves[j] == eggMoves[i])
@ -5838,28 +5841,35 @@ u8 GetRelearnerEggMoves(struct Pokemon *mon, u16 *moves)
return numMoves; return numMoves;
} }
u8 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves) u32 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves)
{ {
u16 learnedMoves[MAX_MON_MOVES] = {0}; if (!P_TM_MOVES_RELEARNER)
u8 numMoves = 0; return 0;
u16 species = GetMonData(mon, MON_DATA_SPECIES);
u16 allMoves[NUM_ALL_MACHINES];
u16 totalMoveCount = 0;
for (u16 i = 0; i < NUM_ALL_MACHINES; i++) u32 learnedMoves[MAX_MON_MOVES] = {0};
u32 numMoves = 0;
u32 species = GetMonData(mon, MON_DATA_SPECIES);
u16 allMoves[NUM_ALL_MACHINES];
u32 totalMoveCount = 0;
for (u32 i = 0; i < NUM_ALL_MACHINES; i++)
{ {
enum TMHMItemId item = GetTMHMItemId(i + 1); enum TMHMItemId item = GetTMHMItemId(i + 1);
u16 move = GetTMHMMoveId(i + 1); u32 move = GetTMHMMoveId(i + 1);
if (move == MOVE_NONE)
continue;
if ((P_ENABLE_ALL_TM_MOVES || CheckBagHasItem(item, 1)) && CanLearnTeachableMove(species, move) && move != MOVE_NONE) if ((P_ENABLE_ALL_TM_MOVES || CheckBagHasItem(item, 1)) && CanLearnTeachableMove(species, move) && move != MOVE_NONE)
allMoves[totalMoveCount++] = move; allMoves[totalMoveCount++] = move;
} }
for (u8 i = 0; i < MAX_MON_MOVES; i++) for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
for (u16 i = 0; i < totalMoveCount; i++) for (u32 i = 0; i < totalMoveCount; i++)
{ {
u16 j; u32 j;
for (j = 0; j < MAX_MON_MOVES; j++) for (j = 0; j < MAX_MON_MOVES; j++)
{ {
if (learnedMoves[j] == allMoves[i]) if (learnedMoves[j] == allMoves[i])
@ -5885,24 +5895,27 @@ u8 GetRelearnerTMMoves(struct Pokemon *mon, u16 *moves)
return numMoves; return numMoves;
} }
u8 GetRelearnerTutorMoves(struct Pokemon *mon, u16 *moves) u32 GetRelearnerTutorMoves(struct Pokemon *mon, u16 *moves)
{ {
if (!FlagGet(P_FLAG_TUTOR_MOVES) && !P_ENABLE_MOVE_RELEARNERS)
return 0;
#if P_TUTOR_MOVES_ARRAY #if P_TUTOR_MOVES_ARRAY
u16 learnedMoves[MAX_MON_MOVES] = {0}; u16 learnedMoves[MAX_MON_MOVES] = {0};
u8 numMoves = 0; u32 numMoves = 0;
u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); u32 species = GetMonData(mon, MON_DATA_SPECIES, 0);
for (u8 i = 0; i < MAX_MON_MOVES; i++) for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
for (u16 i = 0; gTutorMoves[i] != MOVE_UNAVAILABLE; i++) for (u32 i = 0; gTutorMoves[i] != MOVE_UNAVAILABLE; i++)
{ {
u16 move = gTutorMoves[i]; u32 move = gTutorMoves[i];
if (!CanLearnTeachableMove(species, move)) if (!CanLearnTeachableMove(species, move))
continue; continue;
u16 j; u32 j;
for (j = 0; j < MAX_MON_MOVES; j++) for (j = 0; j < MAX_MON_MOVES; j++)
{ {
if (learnedMoves[j] == move) if (learnedMoves[j] == move)
@ -5931,60 +5944,145 @@ u8 GetRelearnerTutorMoves(struct Pokemon *mon, u16 *moves)
#endif // P_TUTOR_MOVES_ARRAY #endif // P_TUTOR_MOVES_ARRAY
} }
u8 GetNumberOfLevelUpMoves(struct Pokemon *mon) static inline bool32 DoesMonHaveMove(const u16 *moves, u16 move)
{ {
u16 moves[MAX_RELEARNER_MOVES] = {0}; for (u32 i = 0; i < MAX_MON_MOVES; i++)
u16 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); {
if (moves[i] == move)
if (species == SPECIES_EGG) return TRUE;
return 0; }
return FALSE;
return GetRelearnerLevelUpMoves(mon, moves);
} }
u8 GetNumberOfEggMoves(struct Pokemon *mon) bool32 HasRelearnerLevelUpMoves(struct Pokemon *mon)
{
u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0);
if (species == SPECIES_EGG)
return FALSE;
u16 learnedMoves[MAX_MON_MOVES];
for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
u32 level = (P_ENABLE_ALL_LEVEL_UP_MOVES ? MAX_LEVEL : GetMonData(mon, MON_DATA_LEVEL, 0));
do
{
const struct LevelUpMove *learnset = GetSpeciesLevelUpLearnset(species);
for (u32 i = 0; i < MAX_LEVEL_UP_MOVES && learnset[i].move != LEVEL_UP_MOVE_END; i++)
{
if (learnset[i].level > level)
break;
if (!DoesMonHaveMove(learnedMoves, learnset[i].move))
return TRUE;
}
species = (P_PRE_EVO_MOVES ? GetSpeciesPreEvolution(species) : SPECIES_NONE);
} while (species != SPECIES_NONE);
return FALSE;
}
bool32 HasRelearnerEggMoves(struct Pokemon *mon)
{ {
if (!FlagGet(P_FLAG_EGG_MOVES) && !P_ENABLE_MOVE_RELEARNERS) if (!FlagGet(P_FLAG_EGG_MOVES) && !P_ENABLE_MOVE_RELEARNERS)
return 0; return FALSE;
u16 moves[EGG_MOVES_ARRAY_COUNT] = {0}; u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0);
u16 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0);
if (species == SPECIES_EGG) if (species == SPECIES_EGG)
return 0; return FALSE;
return GetRelearnerEggMoves(mon, moves); u16 learnedMoves[MAX_MON_MOVES];
for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
while (GetSpeciesPreEvolution(species) != SPECIES_NONE)
species = GetSpeciesPreEvolution(species);
const u16 *eggMoves = GetSpeciesEggMoves(species);
if (eggMoves == sNoneEggMoveLearnset)
return FALSE;
for (u32 i = 0; eggMoves[i] != MOVE_UNAVAILABLE; i++)
{
if (!DoesMonHaveMove(learnedMoves, eggMoves[i]))
return TRUE;
}
return FALSE;
} }
u8 GetNumberOfTMMoves(struct Pokemon *mon) bool32 HasRelearnerTMMoves(struct Pokemon *mon)
{ {
if (!P_TM_MOVES_RELEARNER) if (!P_TM_MOVES_RELEARNER)
return 0; return FALSE;
if (!P_ENABLE_ALL_TM_MOVES && !IsBagPocketNonEmpty(POCKET_TM_HM)) u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0);
return 0;
u16 moves[MAX_RELEARNER_MOVES] = {0};
u16 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0);
if (species == SPECIES_EGG) if (species == SPECIES_EGG)
return 0; return FALSE;
return GetRelearnerTMMoves(mon, moves); u16 learnedMoves[MAX_MON_MOVES];
for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
for (u32 i = 0; i < NUM_ALL_MACHINES; i++)
{
enum TMHMItemId item = GetTMHMItemId(i + 1);
u32 move = GetTMHMMoveId(i + 1);
if (move == MOVE_NONE)
continue;
if (!P_ENABLE_ALL_TM_MOVES || !CheckBagHasItem(item, 1))
continue;
if (!CanLearnTeachableMove(species, move))
continue;
if (!DoesMonHaveMove(learnedMoves, move))
return TRUE;
}
return FALSE;
} }
u8 GetNumberOfTutorMoves(struct Pokemon *mon) bool32 HasRelearnerTutorMoves(struct Pokemon *mon)
{ {
if (!FlagGet(P_FLAG_TUTOR_MOVES) && !P_ENABLE_MOVE_RELEARNERS) if (!FlagGet(P_FLAG_TUTOR_MOVES) && !P_ENABLE_MOVE_RELEARNERS)
return 0; return FALSE;
u16 moves[MAX_RELEARNER_MOVES] = {0}; #if P_TUTOR_MOVES_ARRAY
u16 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0);
if (species == SPECIES_EGG) if (species == SPECIES_EGG)
return 0; return FALSE;
return GetRelearnerTutorMoves(mon, moves); u16 learnedMoves[MAX_MON_MOVES];
for (u32 i = 0; i < MAX_MON_MOVES; i++)
learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0);
for (u32 i = 0; gTutorMoves[i] != MOVE_UNAVAILABLE; i++)
{
u32 move = gTutorMoves[i];
if (!CanLearnTeachableMove(species, move))
continue;
if (!DoesMonHaveMove(learnedMoves, move))
return TRUE;
}
#endif
return FALSE;
} }
u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves) u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves)

View File

@ -181,7 +181,7 @@ static EWRAM_DATA struct PokemonSummaryScreenData
u8 secondMoveIndex; u8 secondMoveIndex;
bool8 lockMovesFlag; // This is used to prevent the player from changing position of moves in a battle or when trading. bool8 lockMovesFlag; // This is used to prevent the player from changing position of moves in a battle or when trading.
u8 bgDisplayOrder; // Determines the order page backgrounds are loaded while scrolling between them u8 bgDisplayOrder; // Determines the order page backgrounds are loaded while scrolling between them
u8 relearnableMovesNum; bool8 hasRelearnableMoves;
u8 windowIds[8]; u8 windowIds[8];
u8 spriteIds[SPRITE_ARR_ID_COUNT]; u8 spriteIds[SPRITE_ARR_ID_COUNT];
bool8 handleDeoxys; bool8 handleDeoxys;
@ -1902,36 +1902,31 @@ void ExtractMonSkillEvData(struct Pokemon *mon, struct PokeSummary *sum)
sum->speed = GetMonData(mon, MON_DATA_SPEED_EV); sum->speed = GetMonData(mon, MON_DATA_SPEED_EV);
} }
u32 GetRelearnMovesCount(enum MoveRelearnerStates state) bool32 HasAnyRelearnableMoves(enum MoveRelearnerStates state)
{ {
struct Pokemon *mon = &sMonSummaryScreen->currentMon; struct Pokemon *mon = &sMonSummaryScreen->currentMon;
switch (state) switch (state)
{ {
case MOVE_RELEARNER_EGG_MOVES: case MOVE_RELEARNER_EGG_MOVES:
return GetNumberOfEggMoves(mon); return HasRelearnerEggMoves(mon);
case MOVE_RELEARNER_TM_MOVES: case MOVE_RELEARNER_TM_MOVES:
return GetNumberOfTMMoves(mon); return HasRelearnerTMMoves(mon);
case MOVE_RELEARNER_TUTOR_MOVES: case MOVE_RELEARNER_TUTOR_MOVES:
return GetNumberOfTutorMoves(mon); return HasRelearnerTutorMoves(mon);
case MOVE_RELEARNER_LEVEL_UP_MOVES: case MOVE_RELEARNER_LEVEL_UP_MOVES:
return GetNumberOfLevelUpMoves(mon); return HasRelearnerLevelUpMoves(mon);
default: default:
return 0; return FALSE;
} }
} }
u32 GetCurrentRelearnMovesCount(void)
{
return GetRelearnMovesCount(gMoveRelearnerState);
}
bool32 NoMovesAvailableToRelearn(void) bool32 NoMovesAvailableToRelearn(void)
{ {
u32 zeroCounter = 0; u32 zeroCounter = 0;
for (enum MoveRelearnerStates state = MOVE_RELEARNER_LEVEL_UP_MOVES; state < MOVE_RELEARNER_COUNT; state++) for (enum MoveRelearnerStates state = MOVE_RELEARNER_LEVEL_UP_MOVES; state < MOVE_RELEARNER_COUNT; state++)
{ {
if (GetRelearnMovesCount(state) == 0) if (!HasAnyRelearnableMoves(state))
zeroCounter++; zeroCounter++;
} }
@ -1960,7 +1955,7 @@ bool32 CheckRelearnerStateFlag(enum MoveRelearnerStates state)
void TryUpdateRelearnType(enum IncrDecrUpdateValues delta) void TryUpdateRelearnType(enum IncrDecrUpdateValues delta)
{ {
u32 moveCount = 0; bool32 hasRelearnableMoves = FALSE;
u32 zeroCounter = 0; u32 zeroCounter = 0;
enum MoveRelearnerStates state = gMoveRelearnerState; enum MoveRelearnerStates state = gMoveRelearnerState;
@ -1970,7 +1965,7 @@ void TryUpdateRelearnType(enum IncrDecrUpdateValues delta)
&& !FlagGet(P_FLAG_EGG_MOVES) && !FlagGet(P_FLAG_EGG_MOVES)
&& !FlagGet(P_FLAG_TUTOR_MOVES))) && !FlagGet(P_FLAG_TUTOR_MOVES)))
{ {
sMonSummaryScreen->relearnableMovesNum = GetRelearnMovesCount(MOVE_RELEARNER_LEVEL_UP_MOVES); sMonSummaryScreen->hasRelearnableMoves = HasAnyRelearnableMoves(MOVE_RELEARNER_LEVEL_UP_MOVES);
return; return;
} }
@ -1980,15 +1975,15 @@ void TryUpdateRelearnType(enum IncrDecrUpdateValues delta)
{ {
default: default:
case TRY_SET_UPDATE: case TRY_SET_UPDATE:
moveCount = GetCurrentRelearnMovesCount(); hasRelearnableMoves = HasAnyRelearnableMoves(gMoveRelearnerState);
if (moveCount == 0) if (!hasRelearnableMoves)
{ {
delta = TRY_INCREMENT; delta = TRY_INCREMENT;
continue; continue;
} }
else else
{ {
sMonSummaryScreen->relearnableMovesNum = moveCount; sMonSummaryScreen->hasRelearnableMoves = hasRelearnableMoves;
return; return;
} }
// should never reach this, but just in case // should never reach this, but just in case
@ -2004,16 +1999,16 @@ void TryUpdateRelearnType(enum IncrDecrUpdateValues delta)
if (!CheckRelearnerStateFlag(state)) if (!CheckRelearnerStateFlag(state))
continue; continue;
moveCount = GetRelearnMovesCount(state); hasRelearnableMoves = HasAnyRelearnableMoves(state);
if (moveCount != 0) if (hasRelearnableMoves)
{ {
gMoveRelearnerState = state; gMoveRelearnerState = state;
sMonSummaryScreen->relearnableMovesNum = moveCount; sMonSummaryScreen->hasRelearnableMoves = hasRelearnableMoves;
return; return;
} }
zeroCounter++; zeroCounter++;
} while (zeroCounter <= MOVE_RELEARNER_COUNT && moveCount == 0); } while (zeroCounter <= MOVE_RELEARNER_COUNT && !hasRelearnableMoves);
} }
static void ChangeSummaryPokemon(u8 taskId, s8 delta) static void ChangeSummaryPokemon(u8 taskId, s8 delta)
@ -2274,7 +2269,7 @@ static void ChangePage(u8 taskId, s8 delta)
} }
// to prevent nothing showing // to prevent nothing showing
if (currPageIndex >= PSS_PAGE_BATTLE_MOVES && sMonSummaryScreen->relearnableMovesNum == 0) if (currPageIndex >= PSS_PAGE_BATTLE_MOVES && !sMonSummaryScreen->hasRelearnableMoves)
TryUpdateRelearnType(TRY_SET_UPDATE); TryUpdateRelearnType(TRY_SET_UPDATE);
else else
ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN); ClearWindowTilemap(PSS_LABEL_WINDOW_PROMPT_RELEARN);
@ -4809,7 +4804,7 @@ static inline bool32 ShouldShowMoveRelearner(void)
&& !sMonSummaryScreen->isBoxMon && !sMonSummaryScreen->isBoxMon
&& sMonSummaryScreen->mode != SUMMARY_MODE_BOX && sMonSummaryScreen->mode != SUMMARY_MODE_BOX
&& sMonSummaryScreen->mode != SUMMARY_MODE_BOX_CURSOR && sMonSummaryScreen->mode != SUMMARY_MODE_BOX_CURSOR
&& sMonSummaryScreen->relearnableMovesNum > 0 && sMonSummaryScreen->hasRelearnableMoves
&& !InBattleFactory() && !InBattleFactory()
&& !InSlateportBattleTent() && !InSlateportBattleTent()
&& !NoMovesAvailableToRelearn()); && !NoMovesAvailableToRelearn());
@ -4918,7 +4913,7 @@ void ShowRelearnPrompt(void)
return; return;
} }
if (GetCurrentRelearnMovesCount() == 0) if (!HasAnyRelearnableMoves(gMoveRelearnerState))
return; return;
const u8* relearnText; const u8* relearnText;