From 5e79fcd5b42499d320108faab8cdaa69841f214b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Mon, 19 Feb 2024 14:42:56 -0300 Subject: [PATCH 1/2] Added FREE_EXTRA_SEEN_FLAGS to Pokedex struct (#4213) * Added FREE_EXTRA_SEEN_FLAGS to Pokedex struct * Fixed SaveBlock1 comment (please squash) * Separated FREE_EXTRA_SEEN_FLAGS for each SaveBlock --- include/config/save.h | 7 ++++--- include/global.h | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/config/save.h b/include/config/save.h index 46ebe39cad..bf89bae9fb 100644 --- a/include/config/save.h +++ b/include/config/save.h @@ -2,7 +2,7 @@ #define GUARD_CONFIG_SAVE_H // SaveBlock1 configs -#define FREE_EXTRA_SEEN_FLAGS FALSE // Free up unused Pokédex seen flags (52 bytes). +#define FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK1 FALSE // Free up unused Pokédex seen flags (52 bytes). #define FREE_TRAINER_HILL FALSE // Frees up Trainer Hill data (28 bytes). #define FREE_MYSTERY_EVENT_BUFFERS FALSE // Frees up ramScript (1104 bytes). #define FREE_MATCH_CALL FALSE // Frees up match call and rematch data. (104 bytes). @@ -15,8 +15,9 @@ #define FREE_BATTLE_TOWER_E_READER FALSE // Frees up Battle Tower E-Reader data (188 bytes). #define FREE_POKEMON_JUMP FALSE // Frees up Pokémon Jump data (16 bytes). #define FREE_RECORD_MIXING_HALL_RECORDS FALSE // Frees up hall records for record mixing (1032 bytes). - // SaveBlock2 total: 1166 bytes +#define FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK2 FALSE // Free up unused Pokédex seen flags (108 bytes). + // SaveBlock2 total: 1274 bytes - // Grand Total: 3682 + // Grand Total: 3790 #endif // GUARD_CONFIG_SAVE_H diff --git a/include/global.h b/include/global.h index fac78b0eed..83bff49c0c 100644 --- a/include/global.h +++ b/include/global.h @@ -190,7 +190,9 @@ struct Pokedex /*0x04*/ u32 unownPersonality; // set when you first see Unown /*0x08*/ u32 spindaPersonality; // set when you first see Spinda /*0x0C*/ u32 unknown3; +#if FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK2 == FALSE /*0x10*/ u8 filler[0x68]; // Previously Dex Flags, feel free to remove. +#endif //FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK2 }; struct PokemonJumpRecords @@ -997,9 +999,9 @@ struct SaveBlock1 /*0x690*/ struct ItemSlot bagPocket_TMHM[BAG_TMHM_COUNT]; /*0x790*/ struct ItemSlot bagPocket_Berries[BAG_BERRIES_COUNT]; /*0x848*/ struct Pokeblock pokeblocks[POKEBLOCKS_COUNT]; -#if FREE_EXTRA_SEEN_FLAGS == FALSE +#if FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK1 == FALSE /*0x988*/ u8 filler1[0x34]; // Previously Dex Flags, feel free to remove. -#endif //FREE_EXTRA_SEEN_FLAGS +#endif //FREE_EXTRA_SEEN_FLAGS_SAVEBLOCK1 /*0x9BC*/ u16 berryBlenderRecords[3]; /*0x9C2*/ u8 unused_9C2[6]; #if FREE_MATCH_CALL == FALSE From 0522ec0247d6bd881909a1c8844e139acd7bba69 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Thu, 22 Feb 2024 10:22:57 -0300 Subject: [PATCH 2/2] Trainer data encapsulation (#4216) * Moved existing sanitized trainer data functions to include/data.h * Sanitized encounterMusic_gender * Sanitized trainer class ID * Sanitized trainer pic ID * Sanitized trainer starting status * Sanitized obtaining Trainer struct * Sanitized trainer double battle flag * Sanitized trainer party size * Sanitized trainer mugshot data * Sanitized trainer name * Consolidated Dome Brain trainer data to the rest of the frontier data * Sanitized trainer items * Removed accidental test data * Sanitized trainer party * Sanitized trainer AI flags * Final encapsulation bit --- include/data.h | 78 +++++++++++++++++++++++++- include/pokemon.h | 2 - src/battle_ai_main.c | 7 ++- src/battle_bg.c | 10 ++-- src/battle_controller_opponent.c | 13 +++-- src/battle_controller_player_partner.c | 4 +- src/battle_dome.c | 42 ++++---------- src/battle_main.c | 16 +++--- src/battle_message.c | 4 +- src/battle_script_commands.c | 10 ++-- src/battle_setup.c | 28 ++++----- src/battle_tower.c | 4 +- src/battle_transition.c | 5 +- src/frontier_util.c | 8 ++- src/match_call.c | 11 ++-- src/pokemon.c | 41 ++++---------- src/pokenav_match_call_data.c | 2 +- src/pokenav_match_call_list.c | 6 +- 18 files changed, 167 insertions(+), 124 deletions(-) diff --git a/include/data.h b/include/data.h index 6baf5b3059..28faf0716a 100644 --- a/include/data.h +++ b/include/data.h @@ -99,8 +99,6 @@ struct TrainerClass u16 ball; }; -#define TRAINER_ENCOUNTER_MUSIC(trainer)((gTrainers[trainer].encounterMusic_gender & 0x7F)) - extern const u16 gMinigameDigits_Pal[]; extern const u32 gMinigameDigits_Gfx[]; @@ -133,4 +131,80 @@ extern const struct Trainer gBattlePartners[]; extern const struct TrainerClass gTrainerClasses[TRAINER_CLASS_COUNT]; +static inline u16 SanitizeTrainerId(u16 trainerId) +{ + if (trainerId >= TRAINERS_COUNT) + return TRAINER_NONE; + return trainerId; +} + +static inline const struct Trainer *GetTrainerStructFromId(u16 trainerId) +{ + return &gTrainers[SanitizeTrainerId(trainerId)]; +} + +static inline const u8 GetTrainerClassFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].trainerClass; +} + +static inline const u8 *GetTrainerClassNameFromId(u16 trainerId) +{ + if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) + return gTrainerClasses[gBattlePartners[trainerId].trainerClass].name; + return gTrainerClasses[GetTrainerClassFromId(trainerId)].name; +} + +static inline const u8 *GetTrainerNameFromId(u16 trainerId) +{ + if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) + return gBattlePartners[trainerId].trainerName; + return gTrainers[SanitizeTrainerId(trainerId)].trainerName; +} + +static inline const u8 GetTrainerPicFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].trainerPic; +} + +static inline const u8 GetTrainerStartingStatusFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].startingStatus; +} + +static inline const bool32 IsTrainerDoubleBattle(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].doubleBattle; +} + +static inline const u8 GetTrainerPartySizeFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].partySize; +} + +static inline const bool32 DoesTrainerHaveMugshot(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].mugshotEnabled; +} + +static inline const u8 GetTrainerMugshotColorFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].mugshotColor; +} + +static inline const u16 *GetTrainerItemsFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].items; +} + +static inline const struct TrainerMon *GetTrainerPartyFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].party; +} + +static inline const bool32 GetTrainerAIFlagsFromId(u16 trainerId) +{ + return gTrainers[SanitizeTrainerId(trainerId)].aiFlags; +} + #endif // GUARD_DATA_H diff --git a/include/pokemon.h b/include/pokemon.h index 2ca1b09d1a..e91acebc60 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -777,8 +777,6 @@ u8 GetOpposingLinkMultiBattlerId(bool8 rightSide, u8 multiplayerId); u16 FacilityClassToPicIndex(u16 facilityClass); u16 PlayerGenderToFrontTrainerPicId(u8 playerGender); void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality); -const u8 *GetTrainerClassNameFromId(u16 trainerId); -const u8 *GetTrainerNameFromId(u16 trainerId); bool8 HasTwoFramesAnimation(u16 species); struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 managerId, u8 mode); void DestroyMonSpritesGfxManager(u8 managerId); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 2a0181d1d1..809784c159 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -96,6 +96,7 @@ void BattleAI_SetupItems(void) { s32 i; u8 *data = (u8 *)BATTLE_HISTORY; + const u16 *items = GetTrainerItemsFromId(gTrainerBattleOpponent_A); for (i = 0; i < sizeof(struct BattleHistory); i++) data[i] = 0; @@ -110,9 +111,9 @@ void BattleAI_SetupItems(void) { for (i = 0; i < MAX_TRAINER_ITEMS; i++) { - if (gTrainers[gTrainerBattleOpponent_A].items[i] != 0) + if (items[i] != ITEM_NONE) { - BATTLE_HISTORY->trainerItems[BATTLE_HISTORY->itemsNo] = gTrainers[gTrainerBattleOpponent_A].items[i]; + BATTLE_HISTORY->trainerItems[BATTLE_HISTORY->itemsNo] = items[i]; BATTLE_HISTORY->itemsNo++; } } @@ -166,7 +167,7 @@ static u32 GetAiFlags(u16 trainerId) else if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE)) flags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT; else - flags = gTrainers[trainerId].aiFlags; + flags = GetTrainerAIFlagsFromId(trainerId); } if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) diff --git a/src/battle_bg.c b/src/battle_bg.c index 496618f315..8f647f8d59 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -789,7 +789,7 @@ void DrawMainBattleBackground(void) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u8 trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; + u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); @@ -1190,7 +1190,7 @@ void DrawBattleEntryBackground(void) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u8 trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; + u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); @@ -1255,7 +1255,7 @@ bool8 LoadChosenBattleElement(u8 caseId) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u8 trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; + u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); @@ -1317,7 +1317,7 @@ bool8 LoadChosenBattleElement(u8 caseId) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u8 trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; + u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); @@ -1379,7 +1379,7 @@ bool8 LoadChosenBattleElement(u8 caseId) { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) { - u8 trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; + u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { LoadCompressedPalette(gBattleTerrainPalette_BuildingLeader, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index c299b61c72..395ad81ad9 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -455,13 +455,13 @@ static u32 OpponentGetTrainerPicId(u32 battlerId) else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (battlerId != 1) - trainerPicId = gTrainers[gTrainerBattleOpponent_B].trainerPic; + trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_B); else - trainerPicId = gTrainers[gTrainerBattleOpponent_A].trainerPic; + trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); } else { - trainerPicId = gTrainers[gTrainerBattleOpponent_A].trainerPic; + trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); } return trainerPicId; @@ -549,7 +549,10 @@ static void OpponentHandleChooseMove(u32 battler) u16 chosenMove = moveInfo->moves[chosenMoveId]; bool32 isSecondTrainer = (GetBattlerPosition(battler) == B_POSITION_OPPONENT_RIGHT) && (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && !BATTLE_TWO_VS_ONE_OPPONENT; u16 trainerId = isSecondTrainer ? gTrainerBattleOpponent_B : gTrainerBattleOpponent_A; - const struct TrainerMon *party = gTrainers[trainerId].party; + const struct TrainerMon *party = GetTrainerPartyFromId(trainerId); + bool32 shouldDynamax = FALSE; + if (party != NULL) + shouldDynamax = party[isSecondTrainer ? gBattlerPartyIndexes[battler] - MULTI_PARTY_SIZE : gBattlerPartyIndexes[battler]].shouldDynamax; if (GetBattlerMoveTargetType(battler, chosenMove) & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) gBattlerTarget = battler; @@ -568,7 +571,7 @@ static void OpponentHandleChooseMove(u32 battler) else if (CanUltraBurst(battler)) BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (RET_ULTRA_BURST) | (gBattlerTarget << 8)); // If opponent can Dynamax and is allowed in the partydata, do it. - else if (CanDynamax(battler) && party[isSecondTrainer ? gBattlerPartyIndexes[battler] - MULTI_PARTY_SIZE : gBattlerPartyIndexes[battler]].shouldDynamax) + else if (CanDynamax(battler) && shouldDynamax) BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (RET_DYNAMAX) | (gBattlerTarget << 8)); else BtlController_EmitTwoReturnValues(battler, BUFFER_B, 10, (chosenMoveId) | (gBattlerTarget << 8)); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index b9dbfdd2c6..5c3fd41762 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -305,7 +305,7 @@ static void PlayerPartnerHandleDrawTrainerPic(u32 battler) } else if (IsAiVsAiBattle()) { - trainerPicId = gTrainers[gPartnerTrainerId].trainerPic; + trainerPicId = GetTrainerPicFromId(gPartnerTrainerId); xPos = 60; yPos = 80; } @@ -437,7 +437,7 @@ static void PlayerPartnerHandleIntroTrainerBallThrow(u32 battler) if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) trainerPal = gTrainerBacksprites[gPartnerSpriteId].palette.data; else if (IsAiVsAiBattle()) - trainerPal = gTrainerSprites[gTrainers[gPartnerTrainerId].trainerPic].palette.data; + trainerPal = gTrainerSprites[GetTrainerPicFromId(gPartnerTrainerId)].palette.data; else trainerPal = gTrainerSprites[GetFrontierTrainerFrontSpriteId(gPartnerTrainerId)].palette.data; // 2 vs 2 multi battle in Battle Frontier, load front sprite and pal. diff --git a/src/battle_dome.c b/src/battle_dome.c index 23d844a30f..cf9d97f483 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -126,9 +126,6 @@ static void VblankCb_TourneyInfoCard(void); static void DisplayMatchInfoOnCard(u8, u8); static void DisplayTrainerInfoOnCard(u8, u8); static int BufferDomeWinString(u8, u8 *); -static u8 GetDomeBrainTrainerPicId(void); -static u8 GetDomeBrainTrainerClass(void); -static void CopyDomeBrainTrainerName(u8 *); static void CopyDomeTrainerName(u8 *, u16); static void HblankCb_TourneyTree(void); static void VblankCb_TourneyTree(void); @@ -4197,7 +4194,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId) if (trainerId == TRAINER_PLAYER) sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(PlayerGenderToFrontTrainerPicId(gSaveBlock2Ptr->playerGender), TRUE, x + 48, y + 64, palSlot + 12, TAG_NONE); else if (trainerId == TRAINER_FRONTIER_BRAIN) - sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(GetDomeBrainTrainerPicId(), TRUE, x + 48, y + 64, palSlot + 12, TAG_NONE); + sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(GetFrontierBrainTrainerPicIndex(), TRUE, x + 48, y + 64, palSlot + 12, TAG_NONE); else sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(GetFrontierTrainerFrontSpriteId(trainerId), TRUE, x + 48, y + 64, palSlot + 12, TAG_NONE); @@ -4257,7 +4254,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId) if (trainerId == TRAINER_PLAYER) j = gFacilityClassToTrainerClass[FACILITY_CLASS_BRENDAN]; else if (trainerId == TRAINER_FRONTIER_BRAIN) - j = GetDomeBrainTrainerClass(); + j = GetFrontierBrainTrainerClass(); else j = GetFrontierOpponentClass(trainerId); @@ -4272,7 +4269,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId) } else if (trainerId == TRAINER_FRONTIER_BRAIN) { - CopyDomeBrainTrainerName(gStringVar2); + CopyFrontierBrainTrainerName(gStringVar2); StringAppend(gStringVar1, gStringVar2); } else @@ -4631,7 +4628,7 @@ static int BufferDomeWinString(u8 matchNum, u8 *tournamentIds) if (DOME_TRAINERS[tournamentId].trainerId == TRAINER_PLAYER) StringCopy(gStringVar1, gSaveBlock2Ptr->playerName); else if (DOME_TRAINERS[tournamentId].trainerId == TRAINER_FRONTIER_BRAIN) - CopyDomeBrainTrainerName(gStringVar1); + CopyFrontierBrainTrainerName(gStringVar1); else CopyDomeTrainerName(gStringVar1, DOME_TRAINERS[tournamentId].trainerId); count++; @@ -4666,7 +4663,7 @@ static int BufferDomeWinString(u8 matchNum, u8 *tournamentIds) if (DOME_TRAINERS[tournamentId].trainerId == TRAINER_PLAYER) StringCopy(gStringVar1, gSaveBlock2Ptr->playerName); else if (DOME_TRAINERS[tournamentId].trainerId == TRAINER_FRONTIER_BRAIN) - CopyDomeBrainTrainerName(gStringVar1); + CopyFrontierBrainTrainerName(gStringVar1); else CopyDomeTrainerName(gStringVar1, DOME_TRAINERS[tournamentId].trainerId); } @@ -4723,7 +4720,7 @@ static void DisplayMatchInfoOnCard(u8 flags, u8 matchNo) if (trainerIds[0] == TRAINER_PLAYER) sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(PlayerGenderToFrontTrainerPicId(gSaveBlock2Ptr->playerGender), TRUE, x + 48, y + 88, palSlot + 12, TAG_NONE); else if (trainerIds[0] == TRAINER_FRONTIER_BRAIN) - sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(GetDomeBrainTrainerPicId(), TRUE, x + 48, y + 88, palSlot + 12, TAG_NONE); + sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(GetFrontierBrainTrainerPicIndex(), TRUE, x + 48, y + 88, palSlot + 12, TAG_NONE); else sInfoCard->spriteIds[arrId] = CreateTrainerPicSprite(GetFrontierTrainerFrontSpriteId(trainerIds[0]), TRUE, x + 48, y + 88, palSlot + 12, TAG_NONE); @@ -4736,7 +4733,7 @@ static void DisplayMatchInfoOnCard(u8 flags, u8 matchNo) if (trainerIds[1] == TRAINER_PLAYER) sInfoCard->spriteIds[1 + arrId] = CreateTrainerPicSprite(PlayerGenderToFrontTrainerPicId(gSaveBlock2Ptr->playerGender), TRUE, x + 192, y + 88, palSlot + 13, TAG_NONE); else if (trainerIds[1] == TRAINER_FRONTIER_BRAIN) - sInfoCard->spriteIds[1 + arrId] = CreateTrainerPicSprite(GetDomeBrainTrainerPicId(), TRUE, x + 192, y + 88, palSlot + 13, TAG_NONE); + sInfoCard->spriteIds[1 + arrId] = CreateTrainerPicSprite(GetFrontierBrainTrainerPicIndex(), TRUE, x + 192, y + 88, palSlot + 13, TAG_NONE); else sInfoCard->spriteIds[1 + arrId] = CreateTrainerPicSprite(GetFrontierTrainerFrontSpriteId(trainerIds[1]), TRUE, x + 192, y + 88, palSlot + 13, TAG_NONE); @@ -4850,7 +4847,7 @@ static void DisplayMatchInfoOnCard(u8 flags, u8 matchNo) if (trainerIds[0] == TRAINER_PLAYER) StringCopy(gStringVar1, gSaveBlock2Ptr->playerName); else if (trainerIds[0] == TRAINER_FRONTIER_BRAIN) - CopyDomeBrainTrainerName(gStringVar1); + CopyFrontierBrainTrainerName(gStringVar1); else CopyDomeTrainerName(gStringVar1, trainerIds[0]); @@ -4868,7 +4865,7 @@ static void DisplayMatchInfoOnCard(u8 flags, u8 matchNo) if (trainerIds[1] == TRAINER_PLAYER) StringCopy(gStringVar1, gSaveBlock2Ptr->playerName); else if (trainerIds[1] == TRAINER_FRONTIER_BRAIN) - CopyDomeBrainTrainerName(gStringVar1); + CopyFrontierBrainTrainerName(gStringVar1); else CopyDomeTrainerName(gStringVar1, trainerIds[1]); @@ -6045,7 +6042,7 @@ static void CopyDomeTrainerName(u8 *str, u16 trainerId) if (trainerId == TRAINER_FRONTIER_BRAIN) { - CopyDomeBrainTrainerName(str); + CopyFrontierBrainTrainerName(str); } else { @@ -6062,22 +6059,3 @@ static void CopyDomeTrainerName(u8 *str, u16 trainerId) str[i] = EOS; } } - -static u8 GetDomeBrainTrainerPicId(void) -{ - return gTrainers[TRAINER_TUCKER].trainerPic; -} - -static u8 GetDomeBrainTrainerClass(void) -{ - return gTrainers[TRAINER_TUCKER].trainerClass; -} - -static void CopyDomeBrainTrainerName(u8 *str) -{ - int i; - - for (i = 0; i < PLAYER_NAME_LENGTH; i++) - str[i] = gTrainers[TRAINER_TUCKER].trainerName[i]; - str[i] = EOS; -} diff --git a/src/battle_main.c b/src/battle_main.c index 28729be2a9..eed1620dd9 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -2055,13 +2055,13 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir u8 retVal; if (trainerNum == TRAINER_SECRET_BASE) return 0; - retVal = CreateNPCTrainerPartyFromTrainer(party, &gTrainers[trainerNum], firstTrainer, gBattleTypeFlags); + retVal = CreateNPCTrainerPartyFromTrainer(party, GetTrainerStructFromId(trainerNum), firstTrainer, gBattleTypeFlags); if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL))) { - gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle; + gBattleTypeFlags |= (IsTrainerDoubleBattle(trainerNum) ? BATTLE_TYPE_DOUBLE : 0); } return retVal; } @@ -2070,7 +2070,7 @@ void CreateTrainerPartyForPlayer(void) { ZeroPlayerPartyMons(); gPartnerTrainerId = gSpecialVar_0x8004; - CreateNPCTrainerPartyFromTrainer(gPlayerParty, &gTrainers[gSpecialVar_0x8004], TRUE, BATTLE_TYPE_TRAINER); + CreateNPCTrainerPartyFromTrainer(gPlayerParty, GetTrainerStructFromId(gSpecialVar_0x8004), TRUE, BATTLE_TYPE_TRAINER); } void VBlankCB_Battle(void) @@ -3714,14 +3714,14 @@ static void DoBattleIntro(void) // Try to set a status to start the battle with gBattleStruct->startingStatus = 0; - if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && gTrainers[gTrainerBattleOpponent_B].startingStatus) + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetTrainerStartingStatusFromId(gTrainerBattleOpponent_B)) { - gBattleStruct->startingStatus = gTrainers[gTrainerBattleOpponent_B].startingStatus; + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_B); gBattleStruct->startingStatusTimer = 0; // infinite } - else if (gTrainers[gTrainerBattleOpponent_A].startingStatus) + else if (GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A)) { - gBattleStruct->startingStatus = gTrainers[gTrainerBattleOpponent_A].startingStatus; + gBattleStruct->startingStatus = GetTrainerStartingStatusFromId(gTrainerBattleOpponent_A); gBattleStruct->startingStatusTimer = 0; // infinite } else if (B_VAR_STARTING_STATUS != 0) @@ -5294,7 +5294,7 @@ static void HandleEndTurn_BattleWon(void) BattleStopLowHpSound(); gBattlescriptCurrInstr = BattleScript_LocalTrainerBattleWon; - switch (gTrainers[gTrainerBattleOpponent_A].trainerClass) + switch (GetTrainerClassFromId(gTrainerBattleOpponent_A)) { case TRAINER_CLASS_ELITE_FOUR: case TRAINER_CLASS_CHAMPION: diff --git a/src/battle_message.c b/src/battle_message.c index c17997dab0..580e21d00d 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3147,7 +3147,7 @@ static const u8 *BattleStringGetOpponentNameByTrainerId(u16 trainerId, u8 *text, } else { - toCpy = gTrainers[trainerId].trainerName; + toCpy = GetTrainerNameFromId(trainerId); } return toCpy; @@ -3242,7 +3242,7 @@ static const u8 *BattleStringGetOpponentClassByTrainerId(u16 trainerId) else if (gBattleTypeFlags & BATTLE_TYPE_EREADER_TRAINER) toCpy = gTrainerClasses[GetEreaderTrainerClassId()].name; else - toCpy = gTrainerClasses[gTrainers[trainerId].trainerClass].name; + toCpy = gTrainerClasses[GetTrainerClassFromId(trainerId)].name; return toCpy; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 7a3dc7ff76..26a8fdb2a0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7469,7 +7469,7 @@ static u32 GetTrainerMoneyToGive(u16 trainerId) { u32 lastMonLevel = 0; u32 moneyReward; - u8 trainerMoney; + u8 trainerMoney = 0; if (trainerId == TRAINER_SECRET_BASE) { @@ -7477,9 +7477,11 @@ static u32 GetTrainerMoneyToGive(u16 trainerId) } else { - const struct TrainerMon *party = gTrainers[trainerId].party; - lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl; - trainerMoney = gTrainerClasses[gTrainers[trainerId].trainerClass].money; + const struct TrainerMon *party = GetTrainerPartyFromId(trainerId); + if (party == NULL) + return 20; + lastMonLevel = party[GetTrainerPartySizeFromId(trainerId) - 1].lvl; + trainerMoney = gTrainerClasses[GetTrainerClassFromId(trainerId)].money; if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * trainerMoney; diff --git a/src/battle_setup.c b/src/battle_setup.c index 5515c7c5bf..92fc2bea25 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -839,13 +839,13 @@ static u8 GetSumOfEnemyPartyLevel(u16 opponentId, u8 numMons) u32 count = numMons; const struct TrainerMon *party; - if (gTrainers[opponentId].partySize < count) - count = gTrainers[opponentId].partySize; + if (GetTrainerPartySizeFromId(opponentId) < count) + count = GetTrainerPartySizeFromId(opponentId); sum = 0; - party = gTrainers[opponentId].party; - for (i = 0; i < count; i++) + party = GetTrainerPartyFromId(opponentId); + for (i = 0; i < count && party != NULL; i++) sum += party[i].lvl; return sum; @@ -879,27 +879,29 @@ u8 GetTrainerBattleTransition(void) u8 transitionType; u8 enemyLevel; u8 playerLevel; + u32 trainerId = SanitizeTrainerId(gTrainerBattleOpponent_A); + u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); - if (gTrainers[gTrainerBattleOpponent_A].mugshotEnabled) + if (DoesTrainerHaveMugshot(trainerId)) return B_TRANSITION_MUGSHOT; - if (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_TEAM_MAGMA - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_MAGMA_LEADER - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_MAGMA_ADMIN) + if (trainerClass == TRAINER_CLASS_TEAM_MAGMA + || trainerClass == TRAINER_CLASS_MAGMA_LEADER + || trainerClass == TRAINER_CLASS_MAGMA_ADMIN) return B_TRANSITION_MAGMA; - if (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_TEAM_AQUA - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_AQUA_LEADER - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_AQUA_ADMIN) + if (trainerClass == TRAINER_CLASS_TEAM_AQUA + || trainerClass == TRAINER_CLASS_AQUA_LEADER + || trainerClass == TRAINER_CLASS_AQUA_ADMIN) return B_TRANSITION_AQUA; - if (gTrainers[gTrainerBattleOpponent_A].doubleBattle == TRUE) + if (IsTrainerDoubleBattle(trainerId)) minPartyCount = 2; // double battles always at least have 2 Pokémon. else minPartyCount = 1; transitionType = GetBattleTransitionTypeByMap(); - enemyLevel = GetSumOfEnemyPartyLevel(gTrainerBattleOpponent_A, minPartyCount); + enemyLevel = GetSumOfEnemyPartyLevel(trainerId, minPartyCount); playerLevel = GetSumOfPlayerPartyLevel(minPartyCount); if (enemyLevel < playerLevel) diff --git a/src/battle_tower.c b/src/battle_tower.c index 44506298d7..477a08742b 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -1435,7 +1435,7 @@ u8 GetFrontierOpponentClass(u16 trainerId) } else if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) { - trainerClass = gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerClass; + trainerClass = gBattlePartners[GetTrainerClassFromId(trainerId - TRAINER_PARTNER(PARTNER_NONE))].trainerClass; } else if (trainerId < FRONTIER_TRAINERS_COUNT) { @@ -3107,7 +3107,7 @@ static void FillPartnerParty(u16 trainerId) StringCopy(trainerName, gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName); SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_NAME, trainerName); - j = gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].encounterMusic_gender >> 7; + j = gBattlePartners[SanitizeTrainerId(trainerId - TRAINER_PARTNER(PARTNER_NONE))].encounterMusic_gender >> 7; SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_GENDER, &j); } } diff --git a/src/battle_transition.c b/src/battle_transition.c index 962e274ed1..3e11ccb43e 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -2258,8 +2258,7 @@ static bool8 Mugshot_SetGfx(struct Task *task) s16 i, j; u16 *tilemap, *tileset; const u16 *mugshotsMap = sMugshotsTilemap; - u8 mugshotColor = gTrainers[gTrainerBattleOpponent_A].mugshotColor; - + u8 mugshotColor = GetTrainerMugshotColorFromId(gTrainerBattleOpponent_A); GetBg0TilesDst(&tilemap, &tileset); CpuSet(sEliteFour_Tileset, tileset, 0xF0); @@ -2518,7 +2517,7 @@ static void Mugshots_CreateTrainerPics(struct Task *task) { struct Sprite *opponentSprite, *playerSprite; - u8 trainerPicId = gTrainers[gTrainerBattleOpponent_A].trainerPic; + u8 trainerPicId = GetTrainerPicFromId(gTrainerBattleOpponent_A); s16 opponentRotationScales = 0; gReservedSpritePaletteCount = 10; diff --git a/src/frontier_util.c b/src/frontier_util.c index bf3cd14ae8..7f9b37b957 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -2409,7 +2409,7 @@ u8 GetFrontierBrainTrainerPicIndex(void) else facility = VarGet(VAR_FRONTIER_FACILITY); - return gTrainers[sFrontierBrainTrainerIds[facility]].trainerPic; + return GetTrainerPicFromId(sFrontierBrainTrainerIds[facility]); } u8 GetFrontierBrainTrainerClass(void) @@ -2421,21 +2421,23 @@ u8 GetFrontierBrainTrainerClass(void) else facility = VarGet(VAR_FRONTIER_FACILITY); - return gTrainers[sFrontierBrainTrainerIds[facility]].trainerClass; + return GetTrainerClassFromId(sFrontierBrainTrainerIds[facility]); } void CopyFrontierBrainTrainerName(u8 *dst) { s32 i; s32 facility; + const u8 *trainerName; if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) facility = GetRecordedBattleFrontierFacility(); else facility = VarGet(VAR_FRONTIER_FACILITY); + trainerName = GetTrainerNameFromId(sFrontierBrainTrainerIds[facility]); for (i = 0; i < PLAYER_NAME_LENGTH; i++) - dst[i] = gTrainers[sFrontierBrainTrainerIds[facility]].trainerName[i]; + dst[i] = trainerName[i]; dst[i] = EOS; } diff --git a/src/match_call.c b/src/match_call.c index 5f14c24a09..95028221c2 100644 --- a/src/match_call.c +++ b/src/match_call.c @@ -1693,7 +1693,7 @@ static void PopulateTrainerName(int matchCallId, u8 *destStr) } } - StringCopy(destStr, gTrainers[trainerId].trainerName); + StringCopy(destStr, GetTrainerNameFromId(trainerId)); } static void PopulateMapName(int matchCallId, u8 *destStr) @@ -1799,9 +1799,12 @@ static void PopulateSpeciesFromTrainerParty(int matchCallId, u8 *destStr) const u8 *speciesName; trainerId = GetLastBeatenRematchTrainerId(sMatchCallTrainers[matchCallId].trainerId); - party = gTrainers[trainerId].party; - monId = Random() % gTrainers[trainerId].partySize; - speciesName = GetSpeciesName(party[monId].species); + party = GetTrainerPartyFromId(trainerId); + monId = Random() % GetTrainerPartySizeFromId(trainerId); + if (party != NULL) + speciesName = GetSpeciesName(party[monId].species); + else + speciesName = GetSpeciesName(SPECIES_NONE); StringCopy(destStr, speciesName); } diff --git a/src/pokemon.c b/src/pokemon.c index 10cde40f8a..4268515b65 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4753,7 +4753,7 @@ u8 GetTrainerEncounterMusicId(u16 trainerOpponentId) else if (InTrainerHillChallenge()) return GetTrainerEncounterMusicIdInTrainerHill(trainerOpponentId); else - return TRAINER_ENCOUNTER_MUSIC(trainerOpponentId); + return gTrainers[SanitizeTrainerId(trainerOpponentId)].encounterMusic_gender & (F_TRAINER_FEMALE - 1); } u16 ModifyStatByNature(u8 nature, u16 stat, u8 statIndex) @@ -4792,11 +4792,11 @@ u16 ModifyStatByNature(u8 nature, u16 stat, u8 statIndex) return retVal; } -#define IS_LEAGUE_BATTLE \ - ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) \ - && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR \ - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER \ - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION)) \ +#define IS_LEAGUE_BATTLE(trainerClass) \ + ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) \ + && (trainerClass == TRAINER_CLASS_ELITE_FOUR \ + || trainerClass == TRAINER_CLASS_LEADER \ + || trainerClass == TRAINER_CLASS_CHAMPION)) \ void AdjustFriendship(struct Pokemon *mon, u8 event) { @@ -4829,6 +4829,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) { u8 friendshipLevel = 0; s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); + u32 opponentTrainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (friendship > 99) friendshipLevel++; @@ -4836,7 +4837,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) friendshipLevel++; if ((event != FRIENDSHIP_EVENT_WALKING || !(Random() & 1)) - && (event != FRIENDSHIP_EVENT_LEAGUE_BATTLE || IS_LEAGUE_BATTLE)) + && (event != FRIENDSHIP_EVENT_LEAGUE_BATTLE || IS_LEAGUE_BATTLE(opponentTrainerClass))) { s8 mod = sFriendshipEventModifiers[event][friendshipLevel]; if (mod > 0 && holdEffect == HOLD_EFFECT_FRIENDSHIP_UP) @@ -5383,7 +5384,7 @@ u16 GetBattleBGM(void) else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL) trainerClass = TRAINER_CLASS_EXPERT; else - trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; + trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); switch (trainerClass) { @@ -5402,7 +5403,7 @@ u16 GetBattleBGM(void) case TRAINER_CLASS_RIVAL: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) return MUS_VS_RIVAL; - if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName)) + if (!StringCompare(GetTrainerNameFromId(gTrainerBattleOpponent_A), gText_BattleWallyName)) return MUS_VS_TRAINER; return MUS_VS_RIVAL; case TRAINER_CLASS_ELITE_FOUR: @@ -5687,7 +5688,7 @@ const u8 *GetTrainerPartnerName(void) { if (gPartnerTrainerId == TRAINER_PARTNER(PARTNER_STEVEN)) { - return gTrainers[TRAINER_STEVEN].trainerName; + return GetTrainerNameFromId(TRAINER_STEVEN); } else { @@ -5906,26 +5907,6 @@ void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality) } } -const u8 *GetTrainerClassNameFromId(u16 trainerId) -{ - if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) - return gTrainerClasses[gBattlePartners[trainerId].trainerClass].name; - else if (trainerId < TRAINERS_COUNT) - return gTrainerClasses[gTrainers[trainerId].trainerClass].name; - - return gTrainerClasses[gTrainers[TRAINER_NONE].trainerClass].name; -} - -const u8 *GetTrainerNameFromId(u16 trainerId) -{ - if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) - return gBattlePartners[trainerId].trainerName; - else if (trainerId < TRAINERS_COUNT) - return gTrainers[trainerId].trainerName; - - return gTrainers[TRAINER_NONE].trainerName; -} - bool8 HasTwoFramesAnimation(u16 species) { return species != SPECIES_UNOWN; diff --git a/src/pokenav_match_call_data.c b/src/pokenav_match_call_data.c index 8494446fd2..ca027380d4 100644 --- a/src/pokenav_match_call_data.c +++ b/src/pokenav_match_call_data.c @@ -1097,7 +1097,7 @@ static void MatchCall_GetNameAndDesc_Birch(match_call_t matchCall, const u8 **de static void MatchCall_GetNameAndDescByRematchIdx(u32 idx, const u8 **desc, const u8 **name) { - const struct Trainer *trainer = gTrainers + GetTrainerIdxByRematchIdx(idx); + const struct Trainer *trainer = GetTrainerStructFromId(GetTrainerIdxByRematchIdx(idx)); *desc = gTrainerClasses[trainer->trainerClass].name; *name = trainer->trainerName; } diff --git a/src/pokenav_match_call_list.c b/src/pokenav_match_call_list.c index f0098e546d..43cd5220dd 100755 --- a/src/pokenav_match_call_list.c +++ b/src/pokenav_match_call_list.c @@ -337,7 +337,7 @@ int GetMatchCallTrainerPic(int index) if (!state->matchCallEntries[index].isSpecialTrainer) { index = GetTrainerIdxByRematchIdx(state->matchCallEntries[index].headerId); - return gTrainers[index].trainerPic; + return GetTrainerPicFromId(index); } headerId = state->matchCallEntries[index].headerId; @@ -345,7 +345,7 @@ int GetMatchCallTrainerPic(int index) if (index != REMATCH_TABLE_ENTRIES) { index = GetTrainerIdxByRematchIdx(index); - return gTrainers[index].trainerPic; + return GetTrainerPicFromId(index); } index = MatchCall_GetOverrideFacilityClass(headerId); @@ -407,7 +407,7 @@ void BufferMatchCallNameAndDesc(struct PokenavMatchCallEntry *matchCallEntry, u8 if (!matchCallEntry->isSpecialTrainer) { int index = GetTrainerIdxByRematchIdx(matchCallEntry->headerId); - const struct Trainer *trainer = &gTrainers[index]; + const struct Trainer *trainer = GetTrainerStructFromId(index); int class = trainer->trainerClass; className = gTrainerClasses[class].name; trainerName = trainer->trainerName;