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
This commit is contained in:
parent
5e79fcd5b4
commit
0522ec0247
18 changed files with 167 additions and 124 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue