summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/apprentice.c74
-rw-r--r--src/battle_dome.c88
-rw-r--r--src/battle_frontier_1.c8
-rw-r--r--src/battle_main.c8
-rw-r--r--src/battle_message.c7
-rw-r--r--src/battle_setup.c11
-rw-r--r--src/battle_tent.c22
-rw-r--r--src/battle_tower.c2798
-rw-r--r--src/field_specials.c84
-rw-r--r--src/map_name_popup.c2
-rw-r--r--src/pokemon.c8
-rw-r--r--src/record_mixing.c31
-rw-r--r--src/recorded_battle.c30
-rw-r--r--src/secret_base.c3
-rw-r--r--src/start_menu.c4
-rw-r--r--src/tv.c6
-rw-r--r--src/wild_encounter.c4
17 files changed, 2936 insertions, 252 deletions
diff --git a/src/apprentice.c b/src/apprentice.c
index f2a8aa9c0..065d9cf16 100644
--- a/src/apprentice.c
+++ b/src/apprentice.c
@@ -344,13 +344,6 @@ extern struct Unk030062ECStruct *gUnknown_030062EC;
extern struct Unk030062F0Struct *gUnknown_030062F0;
extern void (*gUnknown_030062F4)(void);
-extern void sub_8165AE8(struct Apprentice *);
-
-extern const u8 gUnknown_085DCEDC[];
-extern const u8 gUnknown_085DCF0E[];
-extern const u8 gUnknown_085DCEFA[];
-extern const u8 gUnknown_085DCF2C[];
-
// This file's functions.
static u16 sub_819FF98(u8 arg0);
static bool8 sub_81A0194(u8 arg0, u16 moveId);
@@ -382,7 +375,7 @@ static void sub_81A1218(void);
static void sub_81A1224(void);
static void sub_81A1438(void);
static void sub_81A150C(void);
-static void sub_81A15A4(void);
+static void Script_SetPlayerApprenticeTrainerGfxId(void);
static void sub_81A1644(void);
static void sub_81A1370(void);
@@ -1030,7 +1023,7 @@ static void (* const sApprenticeFunctions[])(void) =
sub_81A1224,
sub_81A1438,
sub_81A150C,
- sub_81A15A4,
+ Script_SetPlayerApprenticeTrainerGfxId,
sub_81A1644,
sub_81A1370,
};
@@ -1092,7 +1085,7 @@ void ResetAllApprenticeData(void)
for (j = 0; j < 4; j++)
gSaveBlock2Ptr->apprentices[i].playerId[j] = 0;
gSaveBlock2Ptr->apprentices[i].language = gGameLanguage;
- gSaveBlock2Ptr->apprentices[i].unk40 = 0;
+ gSaveBlock2Ptr->apprentices[i].checksum = 0;
}
Script_ResetPlayerApprentice();
@@ -1435,16 +1428,16 @@ static void sub_81A0390(u8 arg0)
for (i = 0; i < 3; i++)
{
- gSaveBlock2Ptr->apprentices[0].monData[i].species = 0;
- gSaveBlock2Ptr->apprentices[0].monData[i].item = 0;
+ gSaveBlock2Ptr->apprentices[0].party[i].species = 0;
+ gSaveBlock2Ptr->apprentices[0].party[i].item = 0;
for (j = 0; j < 4; j++)
- gSaveBlock2Ptr->apprentices[0].monData[i].moves[j] = 0;
+ gSaveBlock2Ptr->apprentices[0].party[i].moves[j] = 0;
}
j = PLAYER_APPRENTICE.field_B1_2;
for (i = 0; i < 3; i++)
{
- apprenticeMons[j] = &gSaveBlock2Ptr->apprentices[0].monData[i];
+ apprenticeMons[j] = &gSaveBlock2Ptr->apprentices[0].party[i];
j = (j + 1) % 3;
}
@@ -1975,7 +1968,7 @@ static void sub_81A0FFC(void)
StringCopy(stringDst, gText_OpenLevel);
break;
case APPRENTICE_BUFF_EASY_CHAT:
- ConvertBattleFrontierTrainerSpeechToString(gSaveBlock2Ptr->apprentices[0].easyChatWords);
+ FrontierSpeechToString(gSaveBlock2Ptr->apprentices[0].easyChatWords);
StringCopy(stringDst, gStringVar4);
break;
case APPRENTICE_BUFF_SPECIES4:
@@ -2261,7 +2254,7 @@ static void sub_81A1438(void)
StringCopy(gSaveBlock2Ptr->apprentices[0].playerName, gSaveBlock2Ptr->playerName);
gSaveBlock2Ptr->apprentices[0].language = gGameLanguage;
- sub_8165AE8(&gSaveBlock2Ptr->apprentices[0]);
+ CalcApprenticeChecksum(&gSaveBlock2Ptr->apprentices[0]);
}
static void sub_81A150C(void)
@@ -2270,51 +2263,46 @@ static void sub_81A150C(void)
u8 mapObjectGfxId;
u8 class = gApprentices[gSaveBlock2Ptr->apprentices[0].id].facilityClass;
- for (i = 0; i < 30 && gUnknown_085DCEDC[i] != class; i++)
+ // Search male classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses) && gTowerMaleFacilityClasses[i] != class; i++)
;
-
- if (i != 30)
+ if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
{
- mapObjectGfxId = gUnknown_085DCF0E[i];
+ mapObjectGfxId = gTowerMaleTrainerGfxIds[i];
VarSet(VAR_OBJ_GFX_ID_0, mapObjectGfxId);
+ return;
}
- else
- {
- for (i = 0; i < 20 && gUnknown_085DCEFA[i] != class; i++)
- ;
- if (i != 20)
- {
- mapObjectGfxId = gUnknown_085DCF2C[i];
- VarSet(VAR_OBJ_GFX_ID_0, mapObjectGfxId);
- }
+ for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses) && gTowerFemaleFacilityClasses[i] != class; i++)
+ ;
+ if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
+ {
+ mapObjectGfxId = gTowerFemaleTrainerGfxIds[i];
+ VarSet(VAR_OBJ_GFX_ID_0, mapObjectGfxId);
}
}
-static void sub_81A15A4(void)
+static void Script_SetPlayerApprenticeTrainerGfxId(void)
{
u8 i;
u8 mapObjectGfxId;
u8 class = gApprentices[PLAYER_APPRENTICE.id].facilityClass;
- for (i = 0; i < 30 && gUnknown_085DCEDC[i] != class; i++)
+ for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses) && gTowerMaleFacilityClasses[i] != class; i++)
;
-
- if (i != 30)
+ if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
{
- mapObjectGfxId = gUnknown_085DCF0E[i];
+ mapObjectGfxId = gTowerMaleTrainerGfxIds[i];
VarSet(VAR_OBJ_GFX_ID_0, mapObjectGfxId);
+ return;
}
- else
- {
- for (i = 0; i < 20 && gUnknown_085DCEFA[i] != class; i++)
- ;
- if (i != 20)
- {
- mapObjectGfxId = gUnknown_085DCF2C[i];
- VarSet(VAR_OBJ_GFX_ID_0, mapObjectGfxId);
- }
+ for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses) && gTowerFemaleFacilityClasses[i] != class; i++)
+ ;
+ if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
+ {
+ mapObjectGfxId = gTowerFemaleTrainerGfxIds[i];
+ VarSet(VAR_OBJ_GFX_ID_0, mapObjectGfxId);
}
}
diff --git a/src/battle_dome.c b/src/battle_dome.c
index 4aec0a336..15348e458 100644
--- a/src/battle_dome.c
+++ b/src/battle_dome.c
@@ -57,18 +57,12 @@ struct UnkStruct_860DD10
extern void sub_81B8558(void);
extern u32 sub_81A39C4(void);
-extern u16 sub_8162548(u8, u8);
-extern u16 RandomizeFacilityTrainerMonId(u16);
-extern u8 GetFacilityEnemyMonLevel(void);
extern u16 sub_81A5060(u8 monId, u8 moveSlotId);
extern u8 sub_81A50F0(u8, u8);
extern u8 sub_81A50B0(u8);
-extern void sub_8162614(u16, u8);
extern void sub_81A4C30(void);
extern bool8 sub_81A3610(void);
extern u16 sub_81A4FF0(u8);
-extern u8 GetFrontierTrainerFrontSpriteId(u16);
-extern u8 GetFrontierOpponentClass(u16);
extern void ReducePlayerPartyToThree(void);
extern u8 gUnknown_0203CEF8[];
@@ -2410,7 +2404,7 @@ static void sub_818E9CC(void)
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
gSaveBlock2Ptr->frontier.field_CA8 = 0;
- gSaveBlock2Ptr->frontier.field_CB2 = 0;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
gSaveBlock2Ptr->frontier.field_CA9_a = 0;
gSaveBlock2Ptr->frontier.field_CA9_b = 0;
if (!(gSaveBlock2Ptr->frontier.field_CDC & gUnknown_0860D0EC[battleMode][lvlMode]))
@@ -2581,13 +2575,13 @@ static void InitDomeTrainers(void)
for (i = 0; i < 3; i++)
{
- gSaveBlock2Ptr->frontier.domeMonId[0][i] = GetMonData(&gPlayerParty[gSaveBlock2Ptr->frontier.field_CAA[i] - 1], MON_DATA_SPECIES, NULL);
+ gSaveBlock2Ptr->frontier.domeMonId[0][i] = GetMonData(&gPlayerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1], MON_DATA_SPECIES, NULL);
for (j = 0; j < 4; j++)
- gSaveBlock2Ptr->frontier.field_EFC[i].moves[j] = GetMonData(&gPlayerParty[gSaveBlock2Ptr->frontier.field_CAA[i] - 1], MON_DATA_MOVE1 + j, NULL);
+ gSaveBlock2Ptr->frontier.field_EFC[i].moves[j] = GetMonData(&gPlayerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1], MON_DATA_MOVE1 + j, NULL);
for (j = 0; j < 6; j++)
- gSaveBlock2Ptr->frontier.field_EFC[i].evs[j] = GetMonData(&gPlayerParty[gSaveBlock2Ptr->frontier.field_CAA[i] - 1], MON_DATA_HP_EV + j, NULL);
+ gSaveBlock2Ptr->frontier.field_EFC[i].evs[j] = GetMonData(&gPlayerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1], MON_DATA_HP_EV + j, NULL);
- gSaveBlock2Ptr->frontier.field_EFC[i].nature = GetNature(&gPlayerParty[gSaveBlock2Ptr->frontier.field_CAA[i] - 1]);
+ gSaveBlock2Ptr->frontier.field_EFC[i].nature = GetNature(&gPlayerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1]);
}
for (i = 1; i < DOME_TOURNAMENT_TRAINERS_COUNT; i++)
@@ -2649,7 +2643,7 @@ static void InitDomeTrainers(void)
statSums[0] = 0;
for (i = 0; i < 3; i++)
{
- trainerId = gSaveBlock2Ptr->frontier.field_CAA[i] - 1; // Great variable choice, gamefreak.
+ trainerId = gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1; // Great variable choice, gamefreak.
statSums[0] += GetMonData(&gPlayerParty[trainerId], MON_DATA_ATK, NULL);
statSums[0] += GetMonData(&gPlayerParty[trainerId], MON_DATA_DEF, NULL);
statSums[0] += GetMonData(&gPlayerParty[trainerId], MON_DATA_SPATK, NULL);
@@ -2667,7 +2661,7 @@ static void InitDomeTrainers(void)
monTypesBits >>= 1;
}
- monLevel = GetFacilityEnemyMonLevel();
+ monLevel = SetFacilityPtrsGetLevel();
statSums[0] += (monTypesCount * monLevel) / 20;
for (i = 1; i < DOME_TOURNAMENT_TRAINERS_COUNT; i++)
@@ -2810,12 +2804,12 @@ static void SwapDomeTrainers(s32 id1, s32 id2, u16 *statsArray)
static void sub_818F9B0(void)
{
- StringCopy(gStringVar1, gRoundsStringTable[gSaveBlock2Ptr->frontier.field_CB2]);
+ StringCopy(gStringVar1, gRoundsStringTable[gSaveBlock2Ptr->frontier.curChallengeBattleNum]);
}
static void sub_818F9E0(void)
{
- StringCopy(gStringVar1, gRoundsStringTable[gSaveBlock2Ptr->frontier.field_CB2]);
+ StringCopy(gStringVar1, gRoundsStringTable[gSaveBlock2Ptr->frontier.curChallengeBattleNum]);
CopyDomeTrainerName(gStringVar2, gTrainerBattleOpponent_A);
}
@@ -2833,7 +2827,7 @@ static void CreateDomeMon(u8 monPartyId, u16 tournamentTrainerId, u8 tournamentM
s32 i;
u8 happiness = 0xFF;
u8 fixedIv = GetDomeTrainerMonIvs(tournamentTrainerId); // BUG: Should be using trainerId instead of tournamentTrainerId. As a result, all Pokemon have ivs of 3.
- u8 level = GetFacilityEnemyMonLevel();
+ u8 level = SetFacilityPtrsGetLevel();
CreateMonWithEVSpreadPersonalityOTID(&gEnemyParty[monPartyId],
gFacilityTrainerMons[gSaveBlock2Ptr->frontier.domeMonId[tournamentTrainerId][tournamentMonId]].species,
level,
@@ -3466,12 +3460,12 @@ static void sub_8190298(void)
static u16 TrainerIdOfPlayerOpponent(void)
{
- return gSaveBlock2Ptr->frontier.domeTrainers[TournamentIdOfOpponent(gSaveBlock2Ptr->frontier.field_CB2, TRAINER_PLAYER)].trainerId;
+ return gSaveBlock2Ptr->frontier.domeTrainers[TournamentIdOfOpponent(gSaveBlock2Ptr->frontier.curChallengeBattleNum, TRAINER_PLAYER)].trainerId;
}
static void sub_81902E4(void)
{
- sub_8162614(gTrainerBattleOpponent_A, 0);
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
}
static void sub_81902F8(void)
@@ -3805,7 +3799,7 @@ static void sub_8190B40(struct Sprite *sprite)
s32 taskId1 = sprite->data[0];
s32 arrId = gTasks[gTasks[taskId1].data[4]].data[1];
s32 tournmanetTrainerId = gUnknown_0860D080[arrId];
- s32 r12 = gSaveBlock2Ptr->frontier.field_CB2;
+ s32 roundId = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
if (gTasks[taskId1].data[3] == 1)
{
@@ -3817,7 +3811,7 @@ static void sub_8190B40(struct Sprite *sprite)
sprite->invisible = FALSE;
}
else if (!gSaveBlock2Ptr->frontier.domeTrainers[tournmanetTrainerId].isEliminated
- && sBattleDomeStruct->unk_10 - 1 < r12)
+ && sBattleDomeStruct->unk_10 - 1 < roundId)
{
sprite->invisible = FALSE;
}
@@ -4621,7 +4615,7 @@ static u8 sub_819221C(u8 taskId)
s32 taskId2 = gTasks[taskId].data[4];
s32 r5 = gTasks[taskId2].data[1];
u8 r10 = gUnknown_0860D080[r5];
- u16 roundId = gSaveBlock2Ptr->frontier.field_CB2;
+ u16 roundId = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
if (gMain.newKeys & (A_BUTTON | B_BUTTON))
retVal = 9;
@@ -5373,7 +5367,7 @@ static void sub_81938E0(void)
sub_8194D48();
gSaveBlock2Ptr->frontier.lvlMode = gSaveBlock2Ptr->frontier.field_D0A - 1;
- gSaveBlock2Ptr->frontier.field_CB2 = 3;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum = 3;
taskId = CreateTask(sub_8194220, 0);
gTasks[taskId].data[0] = 0;
gTasks[taskId].data[1] = 0;
@@ -5475,7 +5469,7 @@ static u8 sub_8193BDC(u8 taskId)
u8 retVal = 1;
s32 arrId = 4;
s32 spriteId = gTasks[taskId].data[1];
- s32 roundId = gSaveBlock2Ptr->frontier.field_CB2;
+ s32 roundId = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
if (gMain.newKeys == B_BUTTON || (gMain.newKeys & A_BUTTON && spriteId == 31))
{
@@ -5536,19 +5530,19 @@ static void sub_8193D7C(void)
if (gSpecialVar_0x8005 == 1)
{
gSaveBlock2Ptr->frontier.domeTrainers[TrainerIdToTournamentId(gTrainerBattleOpponent_A)].isEliminated = 1;
- gSaveBlock2Ptr->frontier.domeTrainers[TrainerIdToTournamentId(gTrainerBattleOpponent_A)].eliminatedAt = gSaveBlock2Ptr->frontier.field_CB2;
+ gSaveBlock2Ptr->frontier.domeTrainers[TrainerIdToTournamentId(gTrainerBattleOpponent_A)].eliminatedAt = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
gSaveBlock2Ptr->frontier.field_EC0[TrainerIdToTournamentId(gTrainerBattleOpponent_A)] = gBattleResults.lastUsedMovePlayer;
- if (gSaveBlock2Ptr->frontier.field_CB2 < DOME_FINAL)
- DecideRoundWinners(gSaveBlock2Ptr->frontier.field_CB2);
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < DOME_FINAL)
+ DecideRoundWinners(gSaveBlock2Ptr->frontier.curChallengeBattleNum);
}
else
{
gSaveBlock2Ptr->frontier.domeTrainers[TrainerIdToTournamentId(TRAINER_PLAYER)].isEliminated = 1;
- gSaveBlock2Ptr->frontier.domeTrainers[TrainerIdToTournamentId(TRAINER_PLAYER)].eliminatedAt = gSaveBlock2Ptr->frontier.field_CB2;
+ gSaveBlock2Ptr->frontier.domeTrainers[TrainerIdToTournamentId(TRAINER_PLAYER)].eliminatedAt = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
gSaveBlock2Ptr->frontier.field_EC0[TrainerIdToTournamentId(TRAINER_PLAYER)] = gBattleResults.lastUsedMoveOpponent;
if (gBattleOutcome == B_OUTCOME_FORFEITED || gSpecialVar_0x8005 == 9)
gSaveBlock2Ptr->frontier.domeTrainers[TrainerIdToTournamentId(TRAINER_PLAYER)].unk3 = 1;
- for (i = gSaveBlock2Ptr->frontier.field_CB2; i < DOME_ROUNDS_COUNT; i++)
+ for (i = gSaveBlock2Ptr->frontier.curChallengeBattleNum; i < DOME_ROUNDS_COUNT; i++)
DecideRoundWinners(i);
}
}
@@ -5561,7 +5555,7 @@ static u16 GetWinningMove(s32 winnerTournamentId, s32 loserTournamentId, u8 roun
u16 bestScore = 0;
u16 bestId = 0;
s32 movePower = 0;
- GetFacilityEnemyMonLevel(); // Unused return variable.
+ SetFacilityPtrsGetLevel();
// Calc move points of all 4 moves for all 3 pokemon hitting all 3 target mons.
for (i = 0; i < 3; i++)
@@ -5761,7 +5755,7 @@ static void sub_8194220(u8 taskId)
AddTextPrinter(&textPrinter, 0, NULL);
for (i = 0; i < DOME_TOURNAMENT_TRAINERS_COUNT; i++)
{
- s32 var, var2;
+ s32 roundId, var2;
CopyDomeTrainerName(gDisplayedStringBattle, gSaveBlock2Ptr->frontier.domeTrainers[i].trainerId);
if (r10 == 1)
@@ -5774,9 +5768,9 @@ static void sub_8194220(u8 taskId)
sub_81948EC(i, var2);
}
}
- else if (gSaveBlock2Ptr->frontier.field_CB2 != DOME_ROUND2)
+ else if (gSaveBlock2Ptr->frontier.curChallengeBattleNum != DOME_ROUND2)
{
- sub_81948EC(i, gSaveBlock2Ptr->frontier.field_CB2 - 2);
+ sub_81948EC(i, gSaveBlock2Ptr->frontier.curChallengeBattleNum - 2);
}
}
else if (r10 == 0)
@@ -5789,23 +5783,23 @@ static void sub_8194220(u8 taskId)
sub_81948EC(i, var2);
}
}
- else if (gSaveBlock2Ptr->frontier.field_CB2 != DOME_ROUND1)
+ else if (gSaveBlock2Ptr->frontier.curChallengeBattleNum != DOME_ROUND1)
{
if (gTasks[taskId].data[4])
- var2 = gSaveBlock2Ptr->frontier.field_CB2;
+ var2 = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
else
- var2 = gSaveBlock2Ptr->frontier.field_CB2 - 1;
+ var2 = gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1;
sub_81948EC(i, var2);
}
}
if (gTasks[taskId].data[4])
- var = gSaveBlock2Ptr->frontier.field_CB2;
+ roundId = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
else
- var = gSaveBlock2Ptr->frontier.field_CB2 - 1;
+ roundId = gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1;
- if ( ((r10 == 1 && gSaveBlock2Ptr->frontier.domeTrainers[i].eliminatedAt < gSaveBlock2Ptr->frontier.field_CB2 - 1)
- || (r10 == 0 && gSaveBlock2Ptr->frontier.domeTrainers[i].eliminatedAt <= var))
+ if ( ((r10 == 1 && gSaveBlock2Ptr->frontier.domeTrainers[i].eliminatedAt < gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1)
+ || (r10 == 0 && gSaveBlock2Ptr->frontier.domeTrainers[i].eliminatedAt <= roundId))
&& gSaveBlock2Ptr->frontier.domeTrainers[i].isEliminated)
{
if (gSaveBlock2Ptr->frontier.domeTrainers[i].trainerId == TRAINER_PLAYER)
@@ -5930,7 +5924,7 @@ static void sub_8194950(u8 taskId)
for (i = 0; i < DOME_TOURNAMENT_TRAINERS_COUNT; i++)
{
CopyDomeTrainerName(gDisplayedStringBattle, gSaveBlock2Ptr->frontier.domeTrainers[i].trainerId);
- if (gSaveBlock2Ptr->frontier.domeTrainers[i].eliminatedAt == gSaveBlock2Ptr->frontier.field_CB2 - 1
+ if (gSaveBlock2Ptr->frontier.domeTrainers[i].eliminatedAt == gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1
&& gSaveBlock2Ptr->frontier.domeTrainers[i].isEliminated)
{
if (gUnknown_0860D3F1[i][0] == 0)
@@ -5945,8 +5939,8 @@ static void sub_8194950(u8 taskId)
}
if (!gSaveBlock2Ptr->frontier.domeTrainers[i].isEliminated)
{
- s32 var = gSaveBlock2Ptr->frontier.field_CB2 - 1;
- sub_81948EC(i, var);
+ s32 roundId = gSaveBlock2Ptr->frontier.curChallengeBattleNum - 1;
+ sub_81948EC(i, roundId);
}
}
}
@@ -6084,7 +6078,7 @@ static void sub_8194D68(void)
for (i = 0; i < 2; i++)
{
- s32 playerMonId = gSaveBlock2Ptr->frontier.field_CAA[gUnknown_0203CEF8[i] - 1] - 1;
+ s32 playerMonId = gSaveBlock2Ptr->frontier.selectedPartyMons[gUnknown_0203CEF8[i] - 1] - 1;
s32 count;
for (moveSlot = 0; moveSlot < 4; moveSlot++)
@@ -6110,7 +6104,7 @@ static void sub_8194E44(void)
for (i = 0; i < 2; i++)
{
- s32 playerMonId = gSaveBlock2Ptr->frontier.field_CAA[gUnknown_0203CEF8[i] - 1] - 1;
+ s32 playerMonId = gSaveBlock2Ptr->frontier.selectedPartyMons[gUnknown_0203CEF8[i] - 1] - 1;
u16 item = GetMonData(&gSaveBlock1Ptr->playerParty[playerMonId], MON_DATA_HELD_ITEM, NULL);
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &item);
}
@@ -6425,7 +6419,7 @@ static void DecideRoundWinners(u8 roundId)
static void CopyDomeTrainerName(u8 *dst, u16 trainerId)
{
s32 i = 0;
- GetFacilityEnemyMonLevel(); // Unused return value.
+ SetFacilityPtrsGetLevel();
if (trainerId == TRAINER_FRONTIER_BRAIN)
{
@@ -6440,7 +6434,7 @@ static void CopyDomeTrainerName(u8 *dst, u16 trainerId)
}
else if (trainerId < 300)
{
- for (i = 0; i < FRONTIER_TRAINER_NAME_LENGTH; i++)
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
dst[i] = gFacilityTrainers[trainerId].trainerName[i];
}
dst[i] = EOS;
@@ -6461,7 +6455,7 @@ static void CopyDomeBrainTrainerName(u8 *dst)
{
s32 i;
- for (i = 0; i < FRONTIER_TRAINER_NAME_LENGTH; i++)
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
dst[i] = gTrainers[TRAINER_TUCKER].trainerName[i];
dst[i] = EOS;
}
diff --git a/src/battle_frontier_1.c b/src/battle_frontier_1.c
index ee8a42954..9ec9f8520 100644
--- a/src/battle_frontier_1.c
+++ b/src/battle_frontier_1.c
@@ -5,7 +5,7 @@
#include "random.h"
#include "battle_tower.h"
-extern void sub_8162614(u16, u8);
+extern void SetBattleFacilityTrainerGfxId(u16, u8);
extern void (* const gUnknown_0860DE50[])(void);
extern const u32 gUnknown_0860DE98[][2];
@@ -23,7 +23,7 @@ void sub_8195980(void)
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
gSaveBlock2Ptr->frontier.field_CA8 = 0;
- gSaveBlock2Ptr->frontier.field_CB2 = 0;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
gSaveBlock2Ptr->frontier.field_CA9_a = 0;
gSaveBlock2Ptr->frontier.field_CA9_b = 0;
if (!(gSaveBlock2Ptr->frontier.field_CDC & gUnknown_0860DE98[battleMode][lvlMode]))
@@ -90,13 +90,13 @@ void sub_8195BB0(void)
void sub_8195C20(void)
{
gTrainerBattleOpponent_A = 5 *(Random() % 255) / 64u;
- sub_8162614(gTrainerBattleOpponent_A, 0);
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
}
void sub_8195C50(void)
{
if (gTrainerBattleOpponent_A < 300)
- ConvertBattleFrontierTrainerSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore);
+ FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore);
}
/*
diff --git a/src/battle_main.c b/src/battle_main.c
index 80ee5c425..9f1ea3c01 100644
--- a/src/battle_main.c
+++ b/src/battle_main.c
@@ -52,6 +52,7 @@
#include "international_string_util.h"
#include "pokeball.h"
#include "party_menu.h"
+#include "battle_tower.h"
struct UnknownPokemonStruct4
{
@@ -106,9 +107,6 @@ extern const u8 gText_Confusion[];
extern const u8 gText_Love[];
// functions
-extern void GetFrontierTrainerName(u8* dst, u16 trainerId); // battle tower
-extern void sub_8166188(void); // battle tower, sets link battle mons level but why?
-extern void sub_8165B88(u8* dst, u16 trainerId); // battle tower, gets language
extern void sub_81B9150(void);
extern void sub_80B3AF8(u8 taskId); // cable club
extern void sub_81A56B4(void); // battle frontier 2
@@ -1159,9 +1157,9 @@ static void CB2_HandleStartMultiPartnerBattle(void)
gLinkPlayers[3].id = 3;
GetFrontierTrainerName(gLinkPlayers[2].name, gTrainerBattleOpponent_A);
GetFrontierTrainerName(gLinkPlayers[3].name, gTrainerBattleOpponent_B);
- sub_8165B88(&language, gTrainerBattleOpponent_A);
+ GetBattleTowerTrainerLanguage(&language, gTrainerBattleOpponent_A);
gLinkPlayers[2].language = language;
- sub_8165B88(&language, gTrainerBattleOpponent_B);
+ GetBattleTowerTrainerLanguage(&language, gTrainerBattleOpponent_B);
gLinkPlayers[3].language = language;
if (sub_800A520())
diff --git a/src/battle_message.c b/src/battle_message.c
index a5f549733..99ab8bbd6 100644
--- a/src/battle_message.c
+++ b/src/battle_message.c
@@ -18,6 +18,8 @@
#include "recorded_battle.h"
#include "international_string_util.h"
#include "battle_frontier_2.h"
+#include "battle_tower.h"
+#include "data2.h"
struct BattleWindowText
{
@@ -35,7 +37,6 @@ struct BattleWindowText
extern u8 gUnknown_0203C7B4;
-extern const u8 gMoveNames[MOVES_COUNT][13];
extern const u8 gTrainerClassNames[][13];
extern const u16 gUnknown_08D85620[];
@@ -46,14 +47,10 @@ extern const u8 gText_PkmnTransferredSomeonesPC[];
extern const u8 gText_PkmnTransferredLanettesPC[];
extern u8 GetFrontierBrainTrainerClass(void); // battle_frontier_2
-extern u8 GetFrontierOpponentClass(u16 trainerId); // battle_tower
extern u8 GetTrainerHillOpponentClass(u16 trainerId); // pokenav
-extern u8 GetEreaderTrainerClassId(void); // battle_tower
extern void CopyFrontierBrainTrainerName(u8 *txtPtr); // battle_frontier_2
extern void GetTrainerHillTrainerName(u8 *txtPtr, u16 trainerId); // pokenav
-extern void GetEreaderTrainerName(u8 *txtPtr);
extern void CopyTrainerHillTrainerText(u8 arg0, u16 trainerId); // pokenav
-extern void GetFrontierTrainerName(u8 *dst, u16 trainerId);
// this file's functions
static void ChooseMoveUsedParticle(u8 *textPtr);
diff --git a/src/battle_setup.c b/src/battle_setup.c
index db173a38e..c18176706 100644
--- a/src/battle_setup.c
+++ b/src/battle_setup.c
@@ -31,6 +31,7 @@
#include "string_util.h"
#include "overworld.h"
#include "field_weather.h"
+#include "battle_tower.h"
#include "gym_leader_rematch.h"
#include "constants/map_types.h"
#include "constants/battle_frontier.h"
@@ -67,8 +68,6 @@ extern u16 sub_81D6180(u8 localId);
extern bool8 GetBattlePyramidTrainerFlag(u8 eventObjId);
extern bool8 GetTrainerHillTrainerFlag(u8 eventObjId);
extern bool8 sub_81D5C18(void);
-extern void sub_816306C(u8 a0);
-extern void sub_8163048(u8 a0);
extern void sub_81A9B04(void);
extern void sub_81D639C(void);
extern void sub_81D6384(void);
@@ -885,8 +884,8 @@ u8 sub_80B100C(s32 arg0)
return sUnknown_0854FE98[Random() % ARRAY_COUNT(sUnknown_0854FE98)];
}
- var = gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.field_CB2 * 2 + 0]
- + gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.field_CB2 * 2 + 1];
+ var = gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum * 2 + 0]
+ + gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum * 2 + 1];
return sUnknown_0854FE98[var % ARRAY_COUNT(sUnknown_0854FE98)];
}
@@ -1264,7 +1263,7 @@ void BattleSetup_StartTrainerBattle(void)
if (gNoOfApproachingTrainers == 2)
{
- sub_816306C(1);
+ FillFrontierTrainersParties(1);
ZeroMonData(&gEnemyParty[1]);
ZeroMonData(&gEnemyParty[2]);
ZeroMonData(&gEnemyParty[4]);
@@ -1272,7 +1271,7 @@ void BattleSetup_StartTrainerBattle(void)
}
else
{
- sub_8163048(1);
+ FillFrontierTrainerParty(1);
ZeroMonData(&gEnemyParty[1]);
ZeroMonData(&gEnemyParty[2]);
}
diff --git a/src/battle_tent.c b/src/battle_tent.c
index e30cac386..4c4bd7fc3 100644
--- a/src/battle_tent.c
+++ b/src/battle_tent.c
@@ -102,7 +102,7 @@ void sub_81B99B4(void)
static void sub_81B99D4(void)
{
gSaveBlock2Ptr->frontier.field_CA8 = 0;
- gSaveBlock2Ptr->frontier.field_CB2 = 0;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
gSaveBlock2Ptr->frontier.field_CA9_a = FALSE;
saved_warp2_set(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
}
@@ -120,13 +120,13 @@ static void sub_81B9A44(void)
static void sub_81B9A60(void)
{
gTrainerBattleOpponent_A = (u32)((Random() % 255) * 5) / 64;
- sub_8162614(gTrainerBattleOpponent_A, 0);
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
}
static void sub_81B9A90(void)
{
if (gTrainerBattleOpponent_A < 300)
- ConvertBattleFrontierTrainerSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore);
+ FrontierSpeechToString(gFacilityTrainers[gTrainerBattleOpponent_A].speechBefore);
}
static void sub_81B9ABC(void)
@@ -164,7 +164,7 @@ void sub_81B9B80(void)
static void sub_81B9BA0(void)
{
gSaveBlock2Ptr->frontier.field_CA8 = 0;
- gSaveBlock2Ptr->frontier.field_CB2 = 0;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
gSaveBlock2Ptr->frontier.field_CA9_a = FALSE;
saved_warp2_set(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
}
@@ -219,7 +219,7 @@ void sub_81B9D08(void)
static void sub_81B9D28(void)
{
gSaveBlock2Ptr->frontier.field_CA8 = 0;
- gSaveBlock2Ptr->frontier.field_CB2 = 0;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
gSaveBlock2Ptr->frontier.field_CA9_a = FALSE;
saved_warp2_set(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
}
@@ -551,25 +551,25 @@ static void sub_81BA040(void)
do
{
trainerId = Random() % 30;
- for (i = 0; i < gSaveBlock2Ptr->frontier.field_CB2; i++)
+ for (i = 0; i < gSaveBlock2Ptr->frontier.curChallengeBattleNum; i++)
{
if (gSaveBlock2Ptr->frontier.field_CB4[i] == trainerId)
break;
}
- } while (i != gSaveBlock2Ptr->frontier.field_CB2);
+ } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum);
gTrainerBattleOpponent_A = trainerId;
- while (gFacilityTrainers[gTrainerBattleOpponent_A].btMonPool[monPoolCount] != 0xFFFF)
+ while (gFacilityTrainers[gTrainerBattleOpponent_A].bfMonPool[monPoolCount] != 0xFFFF)
monPoolCount++;
if (monPoolCount > 8)
break;
monPoolCount = 0;
}
- if (gSaveBlock2Ptr->frontier.field_CB2 < 2)
- gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.field_CB2] = gTrainerBattleOpponent_A;
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < 2)
+ gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
- monSetsPool = gFacilityTrainers[gTrainerBattleOpponent_A].btMonPool;
+ monSetsPool = gFacilityTrainers[gTrainerBattleOpponent_A].bfMonPool;
i = 0;
while (i != 3)
{
diff --git a/src/battle_tower.c b/src/battle_tower.c
index e70d4af91..4b63c2875 100644
--- a/src/battle_tower.c
+++ b/src/battle_tower.c
@@ -1,19 +1,207 @@
#include "global.h"
+#include "battle_tower.h"
+#include "apprentice.h"
#include "event_data.h"
#include "battle_setup.h"
#include "overworld.h"
#include "random.h"
-#include "battle_tower.h"
+#include "text.h"
+#include "main.h"
+#include "international_string_util.h"
+#include "battle.h"
+#include "battle_frontier_1.h"
+#include "battle_frontier_2.h"
+#include "recorded_battle.h"
+#include "easy_chat.h"
+#include "gym_leader_rematch.h"
+#include "battle_transition.h"
+#include "trainer_see.h"
+#include "new_game.h"
+#include "string_util.h"
+#include "data2.h"
+#include "link.h"
+#include "field_message_box.h"
+#include "tv.h"
+#include "constants/battle_frontier.h"
+#include "constants/trainers.h"
+#include "constants/event_objects.h"
+#include "constants/moves.h"
+#include "constants/species.h"
+
+extern u16 gUnknown_03006298[];
extern void sub_81A3ACC(void);
+extern void CreateFrontierBrainPokemon(void);
+extern void sub_81A6CD0(void);
+extern u16 sub_81A39C4(void);
+extern void SetFrontierBrainTrainerGfxId(void);
+extern u8 GetFrontierBrainTrainerPicIndex(void);
+extern u8 GetFrontierBrainTrainerClass(void);
+extern u8 IsFrontierBrainFemale(void);
+extern void CopyFrontierBrainTrainerName(u8 *dst);
+extern void SetMonMoveAvoidReturn(struct Pokemon *mon, u16 move, u8 moveSlot);
+
+extern const u8 *const *const gUnknown_085DD690[];
+extern const u16 gBattleFrontierHeldItems[];
+extern const u8 sRubyFacilityClassToEmerald[82][2];
+extern const u16 gUnknown_085DFA46[];
+extern const struct FacilityMon gBattleFrontierMons[];
+extern const struct FacilityMon gSlateportBattleTentMons[];
+extern const struct FacilityMon gVerdanturfBattleTentMons[];
+extern const struct FacilityMon gFallarborBattleTentMons[];
+extern const struct BattleFrontierTrainer gBattleFrontierTrainers[];
+extern const struct BattleFrontierTrainer gSlateportBattleTentTrainers[];
+extern const struct BattleFrontierTrainer gVerdanturfBattleTentTrainers[];
+extern const struct BattleFrontierTrainer gFallarborBattleTentTrainers[];
-extern const u32 gUnknown_085DF9AC[][2];
-extern const u32 gUnknown_085DF9CC[][2];
-extern void (* const gUnknown_085DF96C[])(void);
+struct
+{
+ u32 facilityClass;
+ const u8 *const *strings;
+} extern const gUnknown_085DD500[50];
+
+struct
+{
+ u16 species;
+ u8 fixedIV;
+ u8 level;
+ u8 nature;
+ u8 evs[6];
+ u16 moves[4];
+} extern const sStevenMons[3];
+
+extern const u8 MossdeepCity_SpaceCenter_2F_EventScript_224157[];
+extern const u8 MossdeepCity_SpaceCenter_2F_EventScript_224166[];
+
+// EWRAM vars.
+EWRAM_DATA const struct BattleFrontierTrainer *gFacilityTrainers = NULL;
+EWRAM_DATA const struct FacilityMon *gFacilityTrainerMons = NULL;
// This file's functions.
-void sub_8164ED8(void);
-u16 sub_8164FCC(u8, u8);
+static void sub_8161F94(void);
+static void sub_8162054(void);
+static void sub_81620F4(void);
+static void ChooseNextBattleTowerTrainer(void);
+static void sub_81621C0(void);
+static void AwardBattleTowerRibbons(void);
+static void SaveBattleTowerProgress(void);
+static void sub_8163914(void);
+static void nullsub_61(void);
+static void nullsub_116(void);
+static void sub_81642A0(void);
+static void sub_8164828(void);
+static void sub_8164B74(void);
+static void sub_8164DCC(void);
+static void sub_8164DE4(void);
+static void sub_8164E04(void);
+static void ValidateBattleTowerRecordChecksums(void);
+static void SaveCurrentWinStreak(void);
+static void ValidateApprenticesChecksums(void);
+static void sub_8165E18(void);
+static void CopyEReaderTrainerFarewellMessage(void);
+static void ClearBattleTowerRecord(struct EmeraldBattleTowerRecord *record);
+static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount);
+static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount);
+static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId);
+static void FillFactoryTentTrainerParty(u16 trainerId, u8 firstMonId);
+static u8 GetFrontierTrainerFixedIvs(u16 trainerId);
+static void FillPartnerParty(u16 trainerId);
+static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer);
+static u8 SetTentPtrsGetLevel(void);
+
+// Const rom data.
+static void (* const gUnknown_085DF96C[])(void) =
+{
+ sub_8161F94,
+ sub_8162054,
+ sub_81620F4,
+ ChooseNextBattleTowerTrainer,
+ sub_81621C0,
+ AwardBattleTowerRibbons,
+ SaveBattleTowerProgress,
+ sub_8163914,
+ nullsub_61,
+ nullsub_116,
+ sub_81642A0,
+ sub_8164828,
+ sub_8164B74,
+ sub_8164DCC,
+ sub_8164DE4,
+ sub_8164E04,
+};
+
+static const u32 gUnknown_085DF9AC[][2] =
+{
+ {0x00000001, 0x00000002},
+ {0x00004000, 0x00008000},
+ {0x00010000, 0x00020000},
+ {0x00040000, 0x00080000},
+};
+
+static const u32 gUnknown_085DF9CC[][2] =
+{
+ {0xfffffffe, 0xfffffffd},
+ {0xffffbfff, 0xffff7fff},
+ {0xfffeffff, 0xfffdffff},
+ {0xfffbffff, 0xfff7ffff},
+};
+
+static const u8 gUnknown_085DF9EC[] =
+{
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x08, 0x09, 0x0a, 0x0b, 0x0c
+};
+
+static const u8 gUnknown_085DF9F6[] =
+{
+ [FRONTIER_MODE_SINGLES] = 3,
+ [FRONTIER_MODE_DOUBLES] = 4,
+ [FRONTIER_MODE_MULTIS] = 2,
+ [FRONTIER_MODE_LINK_MULTIS] = 2,
+};
+
+static const u16 gUnknown_085DF9FA[][2] =
+{
+ {0x0000, 0x0063},
+ {0x0050, 0x0077},
+ {0x0064, 0x008b},
+ {0x0078, 0x009f},
+ {0x008c, 0x00b3},
+ {0x00a0, 0x00c7},
+ {0x00b4, 0x00db},
+ {0x00c8, 0x012b},
+};
+
+static const u16 gUnknown_085DFA1A[][2] =
+{
+ {0x0064, 0x0077},
+ {0x0078, 0x008b},
+ {0x008c, 0x009f},
+ {0x00a0, 0x00b3},
+ {0x00b4, 0x00c7},
+ {0x00c8, 0x00db},
+ {0x00dc, 0x00ef},
+ {0x00c8, 0x012b},
+ {0x00b3, 0x008d},
+ {0x00c8, 0x00b7},
+};
+
+static const u8 gUnknown_085DFA42[4] =
+{
+ [FRONTIER_MODE_SINGLES] = 3,
+ [FRONTIER_MODE_DOUBLES] = 4,
+ [FRONTIER_MODE_MULTIS] = 2,
+ [FRONTIER_MODE_LINK_MULTIS] = 2,
+};
+
+static const u16 gUnknown_085DFA46[] =
+{
+ 0x0c3a, 0x0c3a, 0x0c01, 0x0a2a, 0x0607, 0x0c01
+};
+
+static const u16 gUnknown_085DFA52[] =
+{
+ 0x1039, 0x122e, 0x0c04, 0x0a3d, 0x0630, 0x0c04
+};
// code
void sub_8161F74(void)
@@ -21,25 +209,25 @@ void sub_8161F74(void)
gUnknown_085DF96C[gSpecialVar_0x8004]();
}
-void sub_8161F94(void)
+static void sub_8161F94(void)
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
gSaveBlock2Ptr->frontier.field_CA8 = 1;
- gSaveBlock2Ptr->frontier.field_CB2 = 0;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
gSaveBlock2Ptr->frontier.field_CA9_a = 0;
gSaveBlock2Ptr->frontier.field_CA9_b = 0;
sub_81A3ACC();
if (!(gSaveBlock2Ptr->frontier.field_CDC & gUnknown_085DF9AC[battleMode][lvlMode]))
- gSaveBlock2Ptr->frontier.field_CE0[battleMode][lvlMode] = 0;
+ gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] = 0;
- sub_8164ED8();
+ ValidateBattleTowerRecordChecksums();
saved_warp2_set(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
gTrainerBattleOpponent_A = 0;
}
-void sub_8162054(void)
+static void sub_8162054(void)
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
@@ -49,7 +237,7 @@ void sub_8162054(void)
case 0:
break;
case 1:
- gSpecialVar_Result = sub_8164FCC(lvlMode, battleMode);
+ gSpecialVar_Result = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
break;
case 2:
gSpecialVar_Result = ((gSaveBlock2Ptr->frontier.field_CDC & gUnknown_085DF9AC[battleMode][lvlMode]) != 0);
@@ -60,7 +248,7 @@ void sub_8162054(void)
}
}
-void sub_81620F4(void)
+static void sub_81620F4(void)
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
@@ -70,7 +258,7 @@ void sub_81620F4(void)
case 0:
break;
case 1:
- gSaveBlock2Ptr->frontier.field_CE0[battleMode][lvlMode] = gSpecialVar_0x8006;
+ gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] = gSpecialVar_0x8006;
break;
case 2:
if (gSpecialVar_0x8006)
@@ -83,3 +271,2585 @@ void sub_81620F4(void)
break;
}
}
+
+static void sub_81621C0(void)
+{
+ if (gTrainerBattleOpponent_A == TRAINER_EREADER)
+ ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer);
+
+ if (gSaveBlock2Ptr->frontier.field_D04 < 9999)
+ gSaveBlock2Ptr->frontier.field_D04++;
+
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum++;
+ SaveCurrentWinStreak();
+ gSpecialVar_Result = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
+}
+
+static bool8 ChooseSpecialBattleTowerTrainer(void)
+{
+ s32 i, j, validMons;
+ s32 trainerIds[9];
+ s32 idsCount = 0;
+ s32 winStreak = 0;
+ u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+
+ if (VarGet(VAR_FRONTIER_FACILITY) != FRONTIER_FACILITY_TOWER)
+ return FALSE;
+
+ winStreak = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
+ for (i = 0; i < 5; i++)
+ {
+ u32 *record = (u32*)(&gSaveBlock2Ptr->frontier.towerRecords[i]);
+ u32 recordHasData = 0;
+ u32 checksum = 0;
+ for (j = 0; j < (sizeof(struct EmeraldBattleTowerRecord) - 4) / 4; j++) // - 4, because of the last field being the checksum itself.
+ {
+ recordHasData |= record[j];
+ checksum += record[j];
+ }
+ validMons = 0;
+ for (j = 0; j < 4; j++)
+ {
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].party[j].species != 0
+ && gSaveBlock2Ptr->frontier.towerRecords[i].party[j].level <= GetFrontierEnemyMonLevel(lvlMode))
+ validMons++;
+ }
+
+ if (validMons >= gUnknown_085DF9F6[battleMode]
+ && gSaveBlock2Ptr->frontier.towerRecords[i].winStreak == winStreak
+ && gSaveBlock2Ptr->frontier.towerRecords[i].lvlMode == lvlMode
+ && recordHasData
+ && gSaveBlock2Ptr->frontier.towerRecords[i].checksum == checksum)
+ {
+ trainerIds[idsCount] = i + TRAINER_RECORD_MIXING_FRIEND;
+ idsCount++;
+ }
+ }
+
+ if (battleMode == FRONTIER_MODE_SINGLES)
+ {
+ ValidateApprenticesChecksums();
+ for (i = 0; i < 4; i++)
+ {
+ if (gSaveBlock2Ptr->apprentices[i].lvlMode != 0
+ && gUnknown_085DF9EC[gSaveBlock2Ptr->apprentices[i].field_1] == winStreak
+ && gSaveBlock2Ptr->apprentices[i].lvlMode - 1 == lvlMode)
+ {
+ trainerIds[idsCount] = i + TRAINER_RECORD_MIXING_APPRENTICE;
+ idsCount++;
+ }
+ }
+ }
+
+ if (idsCount != 0)
+ {
+ gTrainerBattleOpponent_A = trainerIds[Random() % idsCount];
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static void ChooseNextBattleTowerTrainer(void)
+{
+ u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ if (lvlMode == FRONTIER_LVL_TENT)
+ {
+ sub_8165E18();
+ }
+ else
+ {
+ u16 id;
+ u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ u32 r5 = sub_81A39C4() / 7;
+ SetFacilityPtrsGetLevel();
+
+ if (battleMode == FRONTIER_MODE_MULTIS || battleMode == FRONTIER_MODE_LINK_MULTIS)
+ {
+ id = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
+ gTrainerBattleOpponent_A = gSaveBlock2Ptr->frontier.field_CB4[id * 2];
+ gTrainerBattleOpponent_B = gSaveBlock2Ptr->frontier.field_CB4[id * 2 + 1];
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1);
+ }
+ else if (ChooseSpecialBattleTowerTrainer())
+ {
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
+ }
+ else
+ {
+ s32 i;
+ while (1)
+ {
+ id = sub_8162548(r5, gSaveBlock2Ptr->frontier.curChallengeBattleNum);
+
+ // Ensure trainer wasn't previously fought in this challenge.
+ for (i = 0; i < gSaveBlock2Ptr->frontier.curChallengeBattleNum; i++)
+ {
+ if (gSaveBlock2Ptr->frontier.field_CB4[i] == id)
+ break;
+ }
+ if (i == gSaveBlock2Ptr->frontier.curChallengeBattleNum)
+ break;
+ }
+
+ gTrainerBattleOpponent_A = id;
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < 7)
+ gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
+ }
+ }
+}
+
+u16 sub_8162548(u8 challengeNum, u8 battleNum)
+{
+ u16 trainerId;
+
+ if (challengeNum <= 7)
+ {
+ if (battleNum == 6)
+ {
+ trainerId = (gUnknown_085DFA1A[challengeNum][1] - gUnknown_085DFA1A[challengeNum][0]) + 1;
+ trainerId = gUnknown_085DFA1A[challengeNum][0] + (Random() % trainerId);
+ }
+ else
+ {
+ trainerId = (gUnknown_085DF9FA[challengeNum][1] - gUnknown_085DF9FA[challengeNum][0]) + 1;
+ trainerId = gUnknown_085DF9FA[challengeNum][0] + (Random() % trainerId);
+ }
+ }
+ else
+ {
+ trainerId = (gUnknown_085DF9FA[7][1] - gUnknown_085DF9FA[7][0]) + 1;
+ trainerId = gUnknown_085DF9FA[7][0] + (Random() % trainerId);
+ }
+
+ return trainerId;
+}
+
+#ifdef NONMATCHING
+static u16 sub_81625B4(u8 challengeNum, u8 battleNum, u16 *trainerIdPtr, u8 *arg3) // Unused
+{
+ register u16 trainerId, count;
+
+ if (challengeNum <= 7)
+ {
+ if (battleNum == 6)
+ {
+ count = (gUnknown_085DFA1A[challengeNum][1] - gUnknown_085DFA1A[challengeNum][0]) + 1;
+ trainerId = gUnknown_085DFA1A[challengeNum][0];
+ }
+ else
+ {
+ count = (gUnknown_085DF9FA[challengeNum][1] - gUnknown_085DF9FA[challengeNum][0]) + 1;
+ trainerId = gUnknown_085DF9FA[challengeNum][0];
+ }
+ }
+ else
+ {
+ count = (gUnknown_085DF9FA[7][1] - gUnknown_085DF9FA[7][0]) + 1;
+ trainerId = gUnknown_085DF9FA[7][0];
+ }
+
+ *trainerIdPtr = trainerId;
+ *arg3 = count;
+}
+#else
+NAKED
+static u16 sub_81625B4(u8 challengeNum, u8 battleNum, u16 *trainerIdPtr, u8 *arg3)
+{
+ asm_unified(" push {r4,lr}\n\
+ adds r4, r2, 0\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ adds r2, r0, 0\n\
+ lsls r1, 24\n\
+ lsrs r1, 24\n\
+ cmp r0, 0x7\n\
+ bhi _081625F4\n\
+ cmp r1, 0x6\n\
+ bne _081625D4\n\
+ ldr r1, =gUnknown_085DFA1A\n\
+ lsls r2, r0, 2\n\
+ b _081625D8\n\
+ .pool\n\
+_081625D4:\n\
+ ldr r1, =gUnknown_085DF9FA\n\
+ lsls r2, 2\n\
+_081625D8:\n\
+ adds r0, r1, 0x2\n\
+ adds r0, r2, r0\n\
+ adds r2, r1\n\
+ ldrh r0, [r0]\n\
+ ldrh r1, [r2]\n\
+ subs r0, r1\n\
+ adds r0, 0x1\n\
+ lsls r0, 16\n\
+ lsrs r1, r0, 16\n\
+ ldrh r0, [r2]\n\
+ b _08162604\n\
+ .pool\n\
+_081625F4:\n\
+ ldr r0, =gUnknown_085DF9FA\n\
+ ldrh r1, [r0, 0x1E]\n\
+ ldrh r2, [r0, 0x1C]\n\
+ subs r1, r2\n\
+ adds r1, 0x1\n\
+ lsls r1, 16\n\
+ lsrs r1, 16\n\
+ ldrh r0, [r0, 0x1C]\n\
+_08162604:\n\
+ strh r0, [r4]\n\
+ strb r1, [r3]\n\
+ pop {r4}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .pool");
+}
+#endif
+
+void SetBattleFacilityTrainerGfxId(u16 trainerId, u8 tempVarId)
+{
+ u32 i;
+ u8 facilityClass;
+ u8 trainerObjectGfxId;
+
+ SetFacilityPtrsGetLevel();
+ if (trainerId == TRAINER_EREADER)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ SetFrontierBrainTrainerGfxId();
+ return;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
+ }
+ else
+ {
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
+ }
+
+ // Search male classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses); i++)
+ {
+ if (gTowerMaleFacilityClasses[i] == facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
+ {
+ trainerObjectGfxId = gTowerMaleTrainerGfxIds[i];
+ switch (tempVarId)
+ {
+ case 0:
+ default:
+ VarSet(VAR_OBJ_GFX_ID_0, trainerObjectGfxId);
+ return;
+ case 1:
+ VarSet(VAR_OBJ_GFX_ID_1, trainerObjectGfxId);
+ return;
+ case 15:
+ VarSet(VAR_OBJ_GFX_ID_E, trainerObjectGfxId);
+ return;
+ }
+ }
+
+ // Search female classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
+ {
+ if (gTowerFemaleFacilityClasses[i] == facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
+ {
+ trainerObjectGfxId = gTowerFemaleTrainerGfxIds[i];
+ switch (tempVarId)
+ {
+ case 0:
+ default:
+ VarSet(VAR_OBJ_GFX_ID_0, trainerObjectGfxId);
+ return;
+ case 1:
+ VarSet(VAR_OBJ_GFX_ID_1, trainerObjectGfxId);
+ return;
+ case 15:
+ VarSet(VAR_OBJ_GFX_ID_E, trainerObjectGfxId);
+ return;
+ }
+ }
+
+ switch (tempVarId)
+ {
+ case 0:
+ default:
+ VarSet(VAR_OBJ_GFX_ID_0, EVENT_OBJ_GFX_BOY_1);
+ return;
+ case 1:
+ VarSet(VAR_OBJ_GFX_ID_1, EVENT_OBJ_GFX_BOY_1);
+ return;
+ case 15:
+ VarSet(VAR_OBJ_GFX_ID_E, EVENT_OBJ_GFX_BOY_1);
+ return;
+ }
+}
+
+void SetEReaderTrainerGfxId(void)
+{
+ SetBattleFacilityTrainerGfxId(TRAINER_EREADER, 0);
+}
+
+u8 GetBattleFacilityTrainerGfxId(u16 trainerId)
+{
+ u32 i;
+ u8 facilityClass;
+ u8 trainerObjectGfxId;
+
+ SetFacilityPtrsGetLevel();
+ if (trainerId == TRAINER_EREADER)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
+ }
+ else
+ {
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
+ }
+
+ // Search male classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses); i++)
+ {
+ if (gTowerMaleFacilityClasses[i] == facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
+ {
+ trainerObjectGfxId = gTowerMaleTrainerGfxIds[i];
+ return trainerObjectGfxId;
+ }
+
+ // Search female classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
+ {
+ if (gTowerFemaleFacilityClasses[i] == facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
+ {
+ trainerObjectGfxId = gTowerFemaleTrainerGfxIds[i];
+ return trainerObjectGfxId;
+ }
+ else
+ {
+ return EVENT_OBJ_GFX_BOY_1;
+ }
+}
+
+void PutNewBattleTowerRecord(struct EmeraldBattleTowerRecord *newRecordEm)
+{
+ u16 slotValues[6];
+ u16 slotIds[6];
+ s32 i, j, k;
+ s32 slotsCount = 0;
+ struct EmeraldBattleTowerRecord *newRecord = newRecordEm; // Needed to match.
+
+ // Find a record slot of the same player and replace it.
+ for (i = 0; i < 5; i++)
+ {
+ k = 0;
+ for (j = 0; j < 4; j++)
+ {
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].trainerId[j] != newRecord->trainerId[j])
+ break;
+ }
+ if (j == 4)
+ {
+ for (k = 0; k < PLAYER_NAME_LENGTH; k++)
+ {
+ // BUG: Wrong variable used, 'j' instead of 'k'.
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].name[j] != newRecord->name[j])
+ break;
+ if (newRecord->name[j] == EOS)
+ {
+ k = PLAYER_NAME_LENGTH;
+ break;
+ }
+ }
+ }
+
+ if (k == PLAYER_NAME_LENGTH)
+ break;
+ }
+ if (i < 5)
+ {
+ gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecord;
+ return;
+ }
+
+ // Find an empty record slot.
+ for (i = 0; i < 5; i++)
+ {
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].winStreak == 0)
+ break;
+ }
+ if (i < 5)
+ {
+ gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecord;
+ return;
+ }
+
+ // Find possible slots to replace the record.
+ slotValues[0] = gSaveBlock2Ptr->frontier.towerRecords[0].winStreak;
+ slotIds[0] = 0;
+ slotsCount++;
+
+ for (i = 1; i < 5; i++)
+ {
+ for (j = 0; j < slotsCount; j++)
+ {
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].winStreak < slotValues[j])
+ {
+ j = 0;
+ slotsCount = 1;
+ slotValues[0] = gSaveBlock2Ptr->frontier.towerRecords[i].winStreak;
+ slotIds[0] = i;
+ break;
+ }
+ else if (gSaveBlock2Ptr->frontier.towerRecords[i].winStreak > slotValues[j])
+ {
+ break;
+ }
+ }
+
+ if (j == slotsCount)
+ {
+ slotValues[slotsCount] = gSaveBlock2Ptr->frontier.towerRecords[i].winStreak;
+ slotIds[slotsCount] = i;
+ slotsCount++;
+ }
+ }
+
+ i = Random() % slotsCount;
+ gSaveBlock2Ptr->frontier.towerRecords[slotIds[i]] = *newRecord;
+}
+
+u8 GetFrontierTrainerFrontSpriteId(u16 trainerId)
+{
+ SetFacilityPtrsGetLevel();
+
+ if (trainerId == TRAINER_EREADER)
+ {
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ return GetFrontierBrainTrainerPicIndex();
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ return gFacilityClassToPicIndex[gFacilityTrainers[trainerId].facilityClass];
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ return gFacilityClassToPicIndex[sub_818649C()];
+ else
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass];
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ return gFacilityClassToPicIndex[gApprentices[sub_81864A8()].facilityClass];
+ else
+ return gFacilityClassToPicIndex[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass];
+ }
+}
+
+u8 GetFrontierOpponentClass(u16 trainerId)
+{
+ u8 trainerClass = 0;
+ SetFacilityPtrsGetLevel();
+
+ if (trainerId == TRAINER_EREADER)
+ {
+ trainerClass = gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ trainerClass = GetFrontierBrainTrainerClass();
+ }
+ else if (trainerId == TRAINER_STEVEN_PARTNER)
+ {
+ trainerClass = gTrainers[TRAINER_STEVEN].trainerClass;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ trainerClass = gFacilityClassToTrainerClass[gFacilityTrainers[trainerId].facilityClass];
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ trainerClass = gFacilityClassToTrainerClass[sub_818649C()];
+ }
+ else
+ {
+ trainerClass = gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass];
+ asm("");
+ }
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ trainerClass = gFacilityClassToTrainerClass[gApprentices[sub_81864A8()].facilityClass];
+ }
+ else
+ {
+ trainerClass = gFacilityClassToTrainerClass[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass];
+ asm("");
+ }
+ }
+
+ return trainerClass;
+}
+
+static u8 GetFrontierTrainerFacilityClass(u16 trainerId)
+{
+ u8 facilityClass;
+ SetFacilityPtrsGetLevel();
+
+ if (trainerId == TRAINER_EREADER)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ facilityClass = sub_818649C();
+ else
+ facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ facilityClass = gApprentices[sub_81864A8()].facilityClass;
+ else
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
+ }
+
+ return facilityClass;
+}
+
+void GetFrontierTrainerName(u8 *dst, u16 trainerId)
+{
+ s32 i = 0;
+ SetFacilityPtrsGetLevel();
+
+ if (trainerId == TRAINER_EREADER)
+ {
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ dst[i] = gSaveBlock2Ptr->frontier.ereaderTrainer.name[i];
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ CopyFrontierBrainTrainerName(dst);
+ return;
+ }
+ else if (trainerId == TRAINER_STEVEN_PARTNER)
+ {
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ dst[i] = gTrainers[TRAINER_STEVEN].trainerName[i];
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ dst[i] = gFacilityTrainers[trainerId].trainerName[i];
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ sub_8186468(dst);
+ return;
+ }
+ else
+ {
+ struct EmeraldBattleTowerRecord *record = &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND];
+ TVShowConvertInternationalString(dst, record->name, record->language);
+ return;
+ }
+ }
+ else
+ {
+ u8 id, language;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ id = sub_81864A8();
+ language = sub_81864C0();
+ }
+ else
+ {
+ struct Apprentice *apprentice = &gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE];
+ id = apprentice->id;
+ language = apprentice->language;
+ }
+ TVShowConvertInternationalString(dst, GetApprenticeNameInLanguage(id, language), language);
+ return;
+ }
+
+ dst[i] = EOS;
+}
+
+static bool8 IsFrontierTrainerFemale(u16 trainerId)
+{
+ u32 i;
+ u8 facilityClass;
+
+ SetFacilityPtrsGetLevel();
+ if (trainerId == TRAINER_EREADER)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ return IsFrontierBrainFemale();
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
+ }
+ else
+ {
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
+ }
+
+ // Search female classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
+ {
+ if (gTowerFemaleFacilityClasses[i] == facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void FillFrontierTrainerParty(u8 monsCount)
+{
+ ZeroEnemyPartyMons();
+ FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount);
+}
+
+void FillFrontierTrainersParties(u8 monsCount)
+{
+ ZeroEnemyPartyMons();
+ FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount);
+ FillTrainerParty(gTrainerBattleOpponent_B, 3, monsCount);
+}
+
+static void FillTentTrainerParty(u8 monsCount)
+{
+ ZeroEnemyPartyMons();
+ FillTentTrainerParty_(gTrainerBattleOpponent_A, 0, monsCount);
+}
+
+static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount)
+{
+ s32 i, j;
+ u16 chosenMonIndices[4];
+ u8 friendship = 0xFF;
+ u8 level = SetFacilityPtrsGetLevel();
+ u8 fixedIV = 0;
+ u8 bfMonCount;
+ const u16 *bfMonPool = NULL;
+ u32 otID = 0;
+
+ if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ // Normal battle frontier trainer.
+ fixedIV = GetFrontierTrainerFixedIvs(trainerId);
+ bfMonPool = gFacilityTrainers[gTrainerBattleOpponent_A].bfMonPool;
+ }
+ else if (trainerId == TRAINER_EREADER)
+ {
+ for (i = firstMonId; i < firstMonId + 3; i++)
+ sub_806819C(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i - firstMonId]);
+ return;
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ CreateFrontierBrainPokemon();
+ return;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ // Record mixed player.
+ for (j = 0, i = firstMonId; i < firstMonId + monCount; j++, i++)
+ {
+ if (gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j].species != 0
+ && gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j].level <= level)
+ {
+ sub_8068338(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j], FALSE);
+ }
+ }
+ return;
+ }
+ else
+ {
+ // Apprentice.
+ for (i = firstMonId; i < firstMonId + 3; i++)
+ CreateApprenticeMon(&gEnemyParty[i], &gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE], i - firstMonId);
+ return;
+ }
+
+ // Regular battle frontier trainer.
+ // Attempt to fill the trainer's party with random Pokemon until 3 have been
+ // successfully chosen. The trainer's party may not have duplicate pokemon species
+ // or duplicate held items.
+ for (bfMonCount = 0; bfMonPool[bfMonCount] != 0xFFFF; bfMonCount++)
+ ;
+ i = 0;
+ otID = Random32();
+ while (i != monCount)
+ {
+ u16 monPoolId = bfMonPool[Random() % bfMonCount];
+ if ((level == 50 || level == 20) && monPoolId > 849)
+ continue;
+
+ // Ensure this pokemon species isn't a duplicate.
+ for (j = 0; j < i + firstMonId; j++)
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_SPECIES, NULL) == gFacilityTrainerMons[monPoolId].species)
+ break;
+ }
+ if (j != i + firstMonId)
+ continue;
+
+ // Ensure this Pokemon's held item isn't a duplicate.
+ for (j = 0; j < i + firstMonId; j++)
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) == gBattleFrontierHeldItems[gFacilityTrainerMons[monPoolId].itemTableId])
+ break;
+ }
+ if (j != i + firstMonId)
+ continue;
+
+ // Ensure this exact pokemon index isn't a duplicate. This check doesn't seem necessary
+ // because the species and held items were already checked directly above.
+ for (j = 0; j < i; j++)
+ {
+ if (chosenMonIndices[j] == monPoolId)
+ break;
+ }
+ if (j != i)
+ continue;
+
+ chosenMonIndices[i] = monPoolId;
+
+ // Place the chosen pokemon into the trainer's party.
+ CreateMonWithEVSpreadPersonalityOTID(&gEnemyParty[i + firstMonId],
+ gFacilityTrainerMons[monPoolId].species,
+ level,
+ gFacilityTrainerMons[monPoolId].nature,
+ fixedIV,
+ gFacilityTrainerMons[monPoolId].evSpread,
+ otID);
+
+ friendship = 255;
+ // Give the chosen pokemon its specified moves.
+ for (j = 0; j < 4; j++)
+ {
+ SetMonMoveSlot(&gEnemyParty[i + firstMonId], gFacilityTrainerMons[monPoolId].moves[j], j);
+ if (gFacilityTrainerMons[monPoolId].moves[j] == MOVE_FRUSTRATION)
+ friendship = 0; // Frustration is more powerful the lower the pokemon's friendship is.
+ }
+
+ SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monPoolId].itemTableId]);
+
+ // The pokemon was successfully added to the trainer's party, so it's safe to move on to
+ // the next party slot.
+ i++;
+ }
+}
+
+// Probably an early draft before the 'CreateApprenticeMon' was written.
+static void Unused_CreateApprenticeMons(u16 trainerId, u8 firstMonId)
+{
+ s32 i, j;
+ u8 friendship = 0xFF;
+ u8 level = 0;
+ u8 fixedIV = 0;
+ struct Apprentice *apprentice = &gSaveBlock2Ptr->apprentices[0];
+
+ if (apprentice->field_1 < 5)
+ fixedIV = 6;
+ else
+ fixedIV = 9;
+
+ if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_50)
+ level = 100;
+ else
+ level = 50;
+
+ for (i = 0; i != 3; i++)
+ {
+ CreateMonWithEVSpread(&gEnemyParty[firstMonId + i], apprentice->party[i].species, level, fixedIV, 8);
+ friendship = 0xFF;
+ for (j = 0; j < 4; j++)
+ {
+ if (apprentice->party[i].moves[j] == MOVE_FRUSTRATION)
+ friendship = 0;
+ }
+ SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_HELD_ITEM, &apprentice->party[i].item);
+ }
+}
+
+u16 RandomizeFacilityTrainerMonId(u16 trainerId)
+{
+ u8 level = SetFacilityPtrsGetLevel();
+ const u16 *bfMonPool = gFacilityTrainers[trainerId].bfMonPool;
+ u8 bfMonCount = 0;
+ u32 monPoolId = bfMonPool[bfMonCount];
+
+ while (monPoolId != 0xFFFF)
+ {
+ bfMonCount++;
+ monPoolId = bfMonPool[bfMonCount];
+ if (monPoolId == 0xFFFF)
+ break;
+ }
+
+ do
+ {
+ monPoolId = bfMonPool[Random() % bfMonCount];
+ } while((level == 50 || level == 20) && monPoolId > 849);
+
+ return monPoolId;
+}
+
+static void FillFactoryTrainerParty(void)
+{
+ ZeroEnemyPartyMons();
+ if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
+ FillFactoryFrontierTrainerParty(gTrainerBattleOpponent_A, 0);
+ else
+ FillFactoryTentTrainerParty(gTrainerBattleOpponent_A, 0);
+}
+
+static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId)
+{
+ u8 i, j;
+ u8 friendship;
+ u8 level;
+ u8 fixedIV;
+ u32 otID;
+
+ if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode; // Unused variable.
+ u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ u8 challengeNum = gSaveBlock2Ptr->frontier.winStreaks[battleMode][0] / 7;
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < 6)
+ fixedIV = sub_81A6CA8(challengeNum, 0);
+ else
+ fixedIV = sub_81A6CA8(challengeNum, 1);
+ }
+ else if (trainerId == TRAINER_EREADER)
+ {
+ for (i = firstMonId; i < firstMonId + 3; i++)
+ sub_806819C(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i - firstMonId]);
+ return;
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ sub_81A6CD0();
+ return;
+ }
+ else
+ {
+ fixedIV = 31;
+ }
+
+
+ level = SetFacilityPtrsGetLevel();
+ otID = T1_READ_32(gSaveBlock2Ptr->playerTrainerId);
+ for (i = 0; i < 3; i++)
+ {
+ u16 poolId = gUnknown_03006298[i];
+ CreateMonWithEVSpreadPersonalityOTID(&gEnemyParty[firstMonId + i],
+ gFacilityTrainerMons[poolId].species,
+ level,
+ gFacilityTrainerMons[poolId].nature,
+ fixedIV,
+ gFacilityTrainerMons[poolId].evSpread,
+ otID);
+
+ friendship = 0;
+ for (j = 0; j < 4; j++)
+ SetMonMoveAvoidReturn(&gEnemyParty[firstMonId + i], gFacilityTrainerMons[poolId].moves[j], j);
+
+ SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[poolId].itemTableId]);
+ }
+}
+
+static void FillFactoryTentTrainerParty(u16 trainerId, u8 firstMonId)
+{
+ u8 i, j;
+ u8 friendship;
+ u8 level = 30;
+ u8 fixedIV = 0;
+ u32 otID = T1_READ_32(gSaveBlock2Ptr->playerTrainerId);
+
+ for (i = 0; i < 3; i++)
+ {
+ u16 poolId = gUnknown_03006298[i];
+ CreateMonWithEVSpreadPersonalityOTID(&gEnemyParty[firstMonId + i],
+ gFacilityTrainerMons[poolId].species,
+ level,
+ gFacilityTrainerMons[poolId].nature,
+ fixedIV,
+ gFacilityTrainerMons[poolId].evSpread,
+ otID);
+
+ friendship = 0;
+ for (j = 0; j < 4; j++)
+ {
+ SetMonMoveAvoidReturn(&gEnemyParty[firstMonId + i], gFacilityTrainerMons[poolId].moves[j], j);
+ if (gFacilityTrainerMons[poolId].moves[j] == MOVE_FRUSTRATION)
+ friendship = 0;
+ }
+
+ SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[poolId].itemTableId]);
+ }
+}
+
+void FrontierSpeechToString(const u16 *words)
+{
+ ConvertEasyChatWordsToString(gStringVar4, words, 3, 2);
+ if (GetStringWidth(1, gStringVar4, -1) > 204)
+ {
+ s32 i = 0;
+
+ ConvertEasyChatWordsToString(gStringVar4, words, 2, 3);
+ while (gStringVar4[i++] != CHAR_NEWLINE)
+ ;
+ while (gStringVar4[i] != CHAR_NEWLINE)
+ i++;
+
+ gStringVar4[i] = CHAR_PROMPT_SCROLL;
+ }
+}
+
+static void sub_8163914(void)
+{
+ u16 trainerId;
+ SetFacilityPtrsGetLevel();
+
+ if (gSpecialVar_0x8005)
+ trainerId = gTrainerBattleOpponent_B;
+ else
+ trainerId = gTrainerBattleOpponent_A;
+
+ if (trainerId == TRAINER_EREADER)
+ FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.greeting);
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ FrontierSpeechToString(gFacilityTrainers[trainerId].speechBefore);
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ FrontierSpeechToString(gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].greeting);
+ else
+ CopyFriendsApprenticeChallengeText(trainerId - TRAINER_RECORD_MIXING_APPRENTICE);
+}
+
+static void HandleSpecialTrainerBattleEnd(void)
+{
+ s32 i;
+
+ sub_81864CC();
+ switch (gBattleScripting.specialTrainerBattleType)
+ {
+ case SPECIAL_BATTLE_TOWER:
+ case SPECIAL_BATTLE_DOME:
+ case SPECIAL_BATTLE_PALACE:
+ case SPECIAL_BATTLE_ARENA:
+ case SPECIAL_BATTLE_FACTORY:
+ case SPECIAL_BATTLE_PIKE_SINGLE:
+ case SPECIAL_BATTLE_PIKE_DOUBLE:
+ case SPECIAL_BATTLE_PYRAMID:
+ if (gSaveBlock2Ptr->frontier.battlesCount < 0xFFFFFF)
+ {
+ gSaveBlock2Ptr->frontier.battlesCount++;
+ if (gSaveBlock2Ptr->frontier.battlesCount % 20 == 0)
+ UpdateGymLeaderRematch();
+ }
+ else
+ {
+ gSaveBlock2Ptr->frontier.battlesCount = 0xFFFFFF;
+ }
+ break;
+ case SPECIAL_BATTLE_SECRET_BASE:
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ u16 itemBefore = GetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM);
+ SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &itemBefore);
+ }
+ break;
+ case SPECIAL_BATTLE_EREADER:
+ CopyEReaderTrainerFarewellMessage();
+ break;
+ }
+
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+}
+
+static void Task_StartBattleAfterTransition(u8 taskId)
+{
+ if (IsBattleTransitionDone() == TRUE)
+ {
+ gMain.savedCallback = HandleSpecialTrainerBattleEnd;
+ SetMainCallback2(CB2_InitBattle);
+ DestroyTask(taskId);
+ }
+}
+
+void DoSpecialTrainerBattle(void)
+{
+ s32 i;
+
+ gBattleScripting.specialTrainerBattleType = gSpecialVar_0x8004;
+ switch (gSpecialVar_0x8004)
+ {
+ case SPECIAL_BATTLE_TOWER:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER;
+ switch (VarGet(VAR_FRONTIER_BATTLE_MODE))
+ {
+ case FRONTIER_MODE_SINGLES:
+ FillFrontierTrainerParty(3);
+ break;
+ case FRONTIER_MODE_DOUBLES:
+ FillFrontierTrainerParty(4);
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
+ break;
+ case FRONTIER_MODE_MULTIS:
+ FillFrontierTrainersParties(2);
+ gPartnerTrainerId = gSaveBlock2Ptr->frontier.field_CB4[17];
+ FillPartnerParty(gPartnerTrainerId);
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE | BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS;
+ break;
+ case FRONTIER_MODE_LINK_MULTIS:
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_MULTI | BATTLE_TYPE_x800000;
+ FillFrontierTrainersParties(2);
+ break;
+ }
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(0));
+ break;
+ case SPECIAL_BATTLE_SECRET_BASE:
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ u16 itemBefore = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+ SetMonData(&gSaveBlock1Ptr->playerParty[i], MON_DATA_HELD_ITEM, &itemBefore);
+ }
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(12));
+ break;
+ case SPECIAL_BATTLE_EREADER:
+ ZeroEnemyPartyMons();
+ for (i = 0; i < 3; i++)
+ sub_806819C(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i]);
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_EREADER_TRAINER;
+ gTrainerBattleOpponent_A = 0;
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(13));
+ break;
+ case SPECIAL_BATTLE_DOME:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOME;
+ if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
+ if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN)
+ FillFrontierTrainerParty(2);
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ sub_806E694(0);
+ BattleTransition_StartOnField(sub_80B100C(3));
+ break;
+ case SPECIAL_BATTLE_PALACE:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_PALACE;
+ if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
+ if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
+ FillFrontierTrainerParty(3);
+ else
+ FillTentTrainerParty(3);
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(4));
+ break;
+ case SPECIAL_BATTLE_ARENA:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_ARENA;
+ if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
+ FillFrontierTrainerParty(3);
+ else
+ FillTentTrainerParty(3);
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(5));
+ break;
+ case SPECIAL_BATTLE_FACTORY:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_FACTORY;
+ if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
+ gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
+ FillFactoryTrainerParty();
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(6));
+ break;
+ case SPECIAL_BATTLE_PIKE_SINGLE:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER;
+ FillFrontierTrainerParty(3);
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(7));
+ break;
+ case SPECIAL_BATTLE_PYRAMID:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID;
+ FillFrontierTrainerParty(3);
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(10));
+ break;
+ case SPECIAL_BATTLE_PIKE_DOUBLE:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS;
+ FillFrontierTrainersParties(1);
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(sub_80B100C(7));
+ break;
+ case SPECIAL_BATTLE_STEVEN:
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
+ FillPartnerParty(TRAINER_STEVEN_PARTNER);
+ gApproachingTrainerId = 0;
+ BattleSetup_ConfigureTrainerBattle(MossdeepCity_SpaceCenter_2F_EventScript_224157 + 1);
+ gApproachingTrainerId = 1;
+ BattleSetup_ConfigureTrainerBattle(MossdeepCity_SpaceCenter_2F_EventScript_224166 + 1);
+ gPartnerTrainerId = TRAINER_STEVEN_PARTNER;
+ CreateTask(Task_StartBattleAfterTransition, 1);
+ PlayMapChosenOrBattleBGM(0);
+ BattleTransition_StartOnField(B_TRANSITION_MAGMA);
+ break;
+ }
+}
+
+static void SaveCurrentWinStreak(void)
+{
+ u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ u16 winStreak = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
+
+ if (gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] < winStreak)
+ gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] = winStreak;
+}
+
+static void sub_8163EE4(void)
+{
+ s32 i;
+ u8 lvlMode, battleMode, class;
+ struct EmeraldBattleTowerRecord *playerRecord = &gSaveBlock2Ptr->frontier.towerPlayer;
+
+ ClearBattleTowerRecord(playerRecord);
+ lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ if (gSaveBlock2Ptr->playerGender != MALE)
+ {
+ class = gTowerFemaleFacilityClasses[(gSaveBlock2Ptr->playerTrainerId[0] +
+ gSaveBlock2Ptr->playerTrainerId[1] +
+ gSaveBlock2Ptr->playerTrainerId[2] +
+ gSaveBlock2Ptr->playerTrainerId[3]) % ARRAY_COUNT(gTowerFemaleFacilityClasses)];
+ }
+ else
+ {
+ class = gTowerMaleFacilityClasses[(gSaveBlock2Ptr->playerTrainerId[0] +
+ gSaveBlock2Ptr->playerTrainerId[1] +
+ gSaveBlock2Ptr->playerTrainerId[2] +
+ gSaveBlock2Ptr->playerTrainerId[3]) % ARRAY_COUNT(gTowerMaleFacilityClasses)];
+ }
+ playerRecord->lvlMode = lvlMode;
+ playerRecord->facilityClass = class;
+ CopyUnalignedWord(playerRecord->trainerId, gSaveBlock2Ptr->playerTrainerId);
+ StringCopy7(playerRecord->name, gSaveBlock2Ptr->playerName);
+ playerRecord->winStreak = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
+
+ for (i = 0; i < 6; i++)
+ {
+ playerRecord->greeting[i] = gSaveBlock1Ptr->unk2BBC[i];
+ playerRecord->unk1C[i] = gSaveBlock1Ptr->unk2BC8[i];
+ playerRecord->unk28[i] = gSaveBlock1Ptr->unk2BD4[i];
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gSaveBlock2Ptr->frontier.selectedPartyMons[i] != 0)
+ sub_80686FC(&gPlayerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1], &playerRecord->party[i]);
+ }
+
+ playerRecord->language = gGameLanguage;
+ CalcEmeraldBattleTowerChecksum(&gSaveBlock2Ptr->frontier.towerPlayer);
+ SaveCurrentWinStreak();
+}
+
+static void SaveBattleTowerProgress(void)
+{
+ u16 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ u16 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ s32 challengeNum = (signed)(gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] / 7);
+
+ if (gSpecialVar_0x8005 == 0 && (challengeNum > 1 || gSaveBlock2Ptr->frontier.curChallengeBattleNum != 0))
+ sub_8163EE4();
+
+ gSaveBlock2Ptr->frontier.field_CA8 =gSpecialVar_0x8005;
+ VarSet(VAR_TEMP_0, 0);
+ gSaveBlock2Ptr->frontier.field_CA9_a = 1;
+ sub_81A4C30();
+}
+
+static void nullsub_61(void)
+{
+
+}
+
+static void nullsub_116(void)
+{
+
+}
+
+static void sub_81640E0(u16 trainerId)
+{
+ s32 i, count;
+ u32 validSpecies[3];
+ u16 species1 = GetMonData(&gPlayerParty[0], MON_DATA_SPECIES, NULL);
+ u16 species2 = GetMonData(&gPlayerParty[1], MON_DATA_SPECIES, NULL);
+
+ count = 0;
+ for (i = 0; i < 3; i++)
+ {
+ u16 apprenticeSpecies = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].party[i].species;
+ if (apprenticeSpecies != species1 && apprenticeSpecies != species2)
+ {
+ validSpecies[count] = i;
+ count++;
+ }
+ }
+
+ gUnknown_03006298[0] = validSpecies[Random() % count];
+ do
+ {
+ gUnknown_03006298[1] = validSpecies[Random() % count];
+ } while (gUnknown_03006298[0] == gUnknown_03006298[1]);
+}
+
+static void sub_8164188(u16 trainerId)
+{
+ s32 i, count;
+ u32 validSpecies[3];
+ u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ u16 species1 = GetMonData(&gPlayerParty[0], MON_DATA_SPECIES, NULL);
+ u16 species2 = GetMonData(&gPlayerParty[1], MON_DATA_SPECIES, NULL);
+
+ count = 0;
+ for (i = 0; i < 4; i++)
+ {
+ if (gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[i].species != species1
+ && gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[i].species != species2
+ && gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[i].level <= GetFrontierEnemyMonLevel(lvlMode)
+ && gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[i].species != 0)
+ {
+ validSpecies[count] = i;
+ count++;
+ }
+ }
+
+ gUnknown_03006298[2] = validSpecies[Random() % count];
+ do
+ {
+ gUnknown_03006298[3] = validSpecies[Random() % count];
+ } while (gUnknown_03006298[2] == gUnknown_03006298[3]);
+}
+
+static void sub_81642A0(void)
+{
+ s32 i, j, k;
+ u32 spArray[5];
+ s32 r10;
+ u16 trainerId;
+ u16 monPoolId;
+ u32 lvlMode, battleMode;
+ s32 challengeNum;
+ u32 species1, species2;
+ u32 level;
+ struct EventObjectTemplate *eventObjTemplates;
+
+ eventObjTemplates = gSaveBlock1Ptr->eventObjectTemplates;
+ lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ challengeNum = gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] / 7;
+ species1 = GetMonData(&gPlayerParty[0], MON_DATA_SPECIES, NULL);
+ species2 = GetMonData(&gPlayerParty[1], MON_DATA_SPECIES, NULL);
+ level = SetFacilityPtrsGetLevel();
+
+ j = 0;
+ do
+ {
+ do
+ {
+ trainerId = sub_8162548(challengeNum, 0);
+ for (i = 0; i < j; i++)
+ {
+ if (gSaveBlock2Ptr->frontier.field_CB4[i] == trainerId)
+ break;
+ if (gFacilityTrainers[gSaveBlock2Ptr->frontier.field_CB4[i]].facilityClass == gFacilityTrainers[trainerId].facilityClass)
+ break;
+ }
+ } while (i != j);
+ gSaveBlock2Ptr->frontier.field_CB4[j] = trainerId;
+ j++;
+ } while (j < 6);
+
+ r10 = 8;
+ for (i = 0; i < 6; i++)
+ {
+ trainerId = gSaveBlock2Ptr->frontier.field_CB4[i];
+ eventObjTemplates[i + 1].graphicsId = GetBattleFacilityTrainerGfxId(trainerId);
+ for (j = 0; j < 2; j++)
+ {
+ while (1)
+ {
+ monPoolId = RandomizeFacilityTrainerMonId(trainerId);
+ if (j % 2 != 0 && gFacilityTrainerMons[gSaveBlock2Ptr->frontier.field_CB4[r10 - 1]].itemTableId == gFacilityTrainerMons[monPoolId].itemTableId)
+ continue;
+
+ for (k = 8; k < r10; k++)
+ {
+ if (gFacilityTrainerMons[gSaveBlock2Ptr->frontier.field_CB4[k]].species == gFacilityTrainerMons[monPoolId].species)
+ break;
+ if (species1 == gFacilityTrainerMons[monPoolId].species)
+ break;
+ if (species2 == gFacilityTrainerMons[monPoolId].species)
+ break;
+ }
+ if (k == r10)
+ break;
+ }
+
+ gSaveBlock2Ptr->frontier.field_CB4[r10] = monPoolId;
+ r10++;
+ }
+ }
+
+ r10 = 0;
+ ValidateApprenticesChecksums();
+ for (i = 0; i < 4; i++)
+ {
+ if (gSaveBlock2Ptr->apprentices[i].lvlMode != 0
+ && gUnknown_085DF9EC[gSaveBlock2Ptr->apprentices[i].field_1] / 7 <= challengeNum
+ && gSaveBlock2Ptr->apprentices[i].lvlMode - 1 == lvlMode)
+ {
+ k = 0;
+ for (j = 0; j < 3; j++)
+ {
+ if (species1 != gSaveBlock2Ptr->apprentices[i].party[j].species
+ && species2 != gSaveBlock2Ptr->apprentices[i].party[j].species)
+ {
+ k++;
+ }
+ }
+ if (k > 2)
+ {
+ spArray[r10] = i + TRAINER_RECORD_MIXING_APPRENTICE;
+ r10++;
+ }
+ }
+ }
+ if (r10 != 0)
+ {
+ gSaveBlock2Ptr->frontier.field_CB4[6] = spArray[Random() % r10];
+ eventObjTemplates[7].graphicsId = GetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.field_CB4[6]);
+ FlagClear(FLAG_HIDE_BATTLE_TOWER_MULTI_BATTLE_PARTNER_ALT_1);
+ sub_81640E0(gSaveBlock2Ptr->frontier.field_CB4[6]);
+ }
+
+ r10 = 0;
+ for (i = 0; i < 5; i++)
+ {
+ u32 *record = (u32*)(&gSaveBlock2Ptr->frontier.towerRecords[i]);
+ u32 recordHasData = 0;
+ u32 checksum = 0;
+ for (j = 0; j < (sizeof(struct EmeraldBattleTowerRecord) - 4) / 4; j++) // - 4, because of the last field being the checksum itself.
+ {
+ recordHasData |= record[j];
+ checksum += record[j];
+ }
+
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].winStreak / 7 <= challengeNum
+ && gSaveBlock2Ptr->frontier.towerRecords[i].lvlMode == lvlMode
+ && recordHasData
+ && gSaveBlock2Ptr->frontier.towerRecords[i].checksum == checksum)
+ {
+ k = 0;
+ for (j = 0; j < 4; j++)
+ {
+ if (species1 != gSaveBlock2Ptr->frontier.towerRecords[i].party[j].species
+ && species2 != gSaveBlock2Ptr->frontier.towerRecords[i].party[j].species
+ && gSaveBlock2Ptr->frontier.towerRecords[i].party[j].level <= GetFrontierEnemyMonLevel(lvlMode)
+ && gSaveBlock2Ptr->frontier.towerRecords[i].party[j].species != 0)
+ {
+ k++;
+ }
+ }
+ if (k > 1)
+ {
+ spArray[r10] = i + TRAINER_RECORD_MIXING_FRIEND;
+ r10++;
+ }
+ }
+ }
+ if (r10 != 0)
+ {
+ gSaveBlock2Ptr->frontier.field_CB4[7] = spArray[Random() % r10];
+ eventObjTemplates[8].graphicsId = GetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.field_CB4[7]);
+ FlagClear(FLAG_HIDE_BATTLE_TOWER_MULTI_BATTLE_PARTNER_ALT_2);
+ sub_8164188(gSaveBlock2Ptr->frontier.field_CB4[7]);
+ }
+}
+
+static void sub_81646BC(u16 trainerId, u16 monPoolId)
+{
+ u16 move = 0;
+ u16 species = 0;
+ SetFacilityPtrsGetLevel();
+
+ if (trainerId != TRAINER_EREADER)
+ {
+ if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ move = gFacilityTrainerMons[monPoolId].moves[0];
+ species = gFacilityTrainerMons[monPoolId].species;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ move = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[gUnknown_03006298[gSpecialVar_0x8005 + 1]].moves[0];
+ species = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[gUnknown_03006298[gSpecialVar_0x8005 + 1]].species;
+ }
+ else
+ {
+ s32 i;
+
+ move = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].party[gUnknown_03006298[gSpecialVar_0x8005 - 1]].moves[0];
+ species = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].party[gUnknown_03006298[gSpecialVar_0x8005 - 1]].species;
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ gStringVar3[i] = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].playerName[i];
+ gStringVar3[i] = EOS;
+ ConvertInternationalString(gStringVar3, gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].language);
+ }
+ }
+
+ StringCopy(gStringVar1, gMoveNames[move]);
+ StringCopy(gStringVar2, gSpeciesNames[species]);
+}
+
+static void sub_8164828(void)
+{
+ s32 i, j, arrId;
+ s32 monPoolId;
+ s32 level = SetFacilityPtrsGetLevel();
+ s32 challengeNum = sub_81A39C4() / 7;
+ s32 k = gSpecialVar_LastTalked - 2;
+ s32 trainerId = gSaveBlock2Ptr->frontier.field_CB4[k];
+
+ for (arrId = 0; arrId < ARRAY_COUNT(gUnknown_085DD500); arrId++)
+ {
+ if (gUnknown_085DD500[arrId].facilityClass == GetFrontierTrainerFacilityClass(trainerId))
+ break;
+ }
+
+ switch (gSpecialVar_0x8005)
+ {
+ case 0:
+ if (trainerId == TRAINER_EREADER)
+ return;
+ if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ GetFrontierTrainerName(gStringVar1, trainerId);
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ GetFrontierTrainerName(gStringVar1, trainerId);
+ }
+ else
+ {
+ s32 i;
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ gStringVar1[i] = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].playerName[i];
+ gStringVar1[i] = EOS;
+ ConvertInternationalString(gStringVar1, gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].language);
+ ConvertIntToDecimalStringN(gStringVar2, gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].number, STR_CONV_MODE_LEFT_ALIGN, 3);
+ GetFrontierTrainerName(gStringVar3, trainerId);
+ }
+ break;
+ case 1:
+ monPoolId = gSaveBlock2Ptr->frontier.field_CB4[8 + k * 2];
+ sub_81646BC(trainerId, monPoolId);
+ break;
+ case 2:
+ monPoolId = gSaveBlock2Ptr->frontier.field_CB4[9 + k * 2];
+ sub_81646BC(trainerId, monPoolId);
+ break;
+ case 3:
+ gPartnerTrainerId = trainerId;
+ if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ gSaveBlock2Ptr->frontier.field_CB4[18] = gSaveBlock2Ptr->frontier.field_CB4[8 + k * 2];
+ gSaveBlock2Ptr->frontier.field_CB4[19] = gSaveBlock2Ptr->frontier.field_CB4[9 + k * 2];
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ gSaveBlock2Ptr->frontier.field_CB4[18] = gUnknown_03006298[2];
+ gSaveBlock2Ptr->frontier.field_CB4[19] = gUnknown_03006298[3];
+ }
+ else
+ {
+ gSaveBlock2Ptr->frontier.field_CB4[18] = gUnknown_03006298[0];
+ gSaveBlock2Ptr->frontier.field_CB4[19] = gUnknown_03006298[1];
+ }
+ for (k = 0; k < 14; k++)
+ {
+ while (1)
+ {
+ i = sub_8162548(challengeNum, k / 2);
+ if (gPartnerTrainerId == i)
+ continue;
+
+ for (j = 0; j < k; j++)
+ {
+ if (gSaveBlock2Ptr->frontier.field_CB4[j] == i)
+ break;
+ }
+ if (j == k)
+ break;
+ }
+ gSaveBlock2Ptr->frontier.field_CB4[k] = i;
+ }
+ gSaveBlock2Ptr->frontier.field_CB4[17] = trainerId;
+ break;
+ case 4:
+ break;
+ }
+
+ if (trainerId == TRAINER_EREADER)
+ return;
+
+ if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ ShowFieldMessage(gUnknown_085DD500[arrId].strings[gSpecialVar_0x8005]);
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ ShowFieldMessage(gUnknown_085DD500[arrId].strings[gSpecialVar_0x8005]);
+ }
+ else
+ {
+ u8 id = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id;
+ ShowFieldMessage(gUnknown_085DD690[id][gSpecialVar_0x8005]);
+ }
+}
+
+static void sub_8164B74(void)
+{
+ s32 challengeNum;
+ s32 i, j;
+ s32 trainerId = 0;
+ u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ u32 battleNum = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
+ GetMultiplayerId(); // Yet another pointless function call.
+
+ switch (gSpecialVar_Result)
+ {
+ case 0:
+ if (battleMode == FRONTIER_MODE_LINK_MULTIS)
+ {
+ challengeNum = gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] / 7;
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), &challengeNum, sizeof(challengeNum));
+ gSpecialVar_Result = 1;
+ }
+ }
+ else
+ {
+ gSpecialVar_Result = 6;
+ }
+ break;
+ case 1:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ if (gBlockRecvBuffer[0][0] > gBlockRecvBuffer[1][0])
+ challengeNum = gBlockRecvBuffer[0][0];
+ else
+ challengeNum = gBlockRecvBuffer[1][0];
+ for (i = 0; i < 14; i++)
+ {
+ do
+ {
+ trainerId = sub_8162548(challengeNum, i / 2);
+ for (j = 0; j < i; j++)
+ {
+ if (gSaveBlock2Ptr->frontier.field_CB4[j] == trainerId)
+ break;
+ }
+ } while (i != j);
+ if (i == j) // This condition is always true, because of the loop above.
+ gSaveBlock2Ptr->frontier.field_CB4[i] = trainerId;
+ }
+ gSpecialVar_Result = 2;
+ }
+ break;
+ case 2:
+ if (sub_800A520())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), &gSaveBlock2Ptr->frontier.field_CB4, sizeof(gSaveBlock2Ptr->frontier.field_CB4));
+ gSpecialVar_Result = 3;
+ }
+ break;
+ case 3:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ memcpy(&gSaveBlock2Ptr->frontier.field_CB4, gBlockRecvBuffer, sizeof(gSaveBlock2Ptr->frontier.field_CB4));
+ gTrainerBattleOpponent_A = gSaveBlock2Ptr->frontier.field_CB4[battleNum * 2];
+ gTrainerBattleOpponent_B = gSaveBlock2Ptr->frontier.field_CB4[battleNum * 2 + 1];
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1);
+ if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType == 0)
+ gSpecialVar_Result = 4;
+ else
+ gSpecialVar_Result = 6;
+ }
+ break;
+ case 4:
+ sub_800AC34();
+ gSpecialVar_Result = 5;
+ break;
+ case 5:
+ if (gReceivedRemoteLinkPlayers == 0)
+ {
+ gSpecialVar_Result = 6;
+ }
+ break;
+ case 6:
+ return;
+ }
+}
+
+static void sub_8164DCC(void)
+{
+ if (gWirelessCommType != 0)
+ sub_800AC34();
+}
+
+static void sub_8164DE4(void)
+{
+ SetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.field_CB4[17], 0xF);
+}
+
+static void sub_8164E04(void)
+{
+ s32 i;
+ u8 text[32];
+
+ if (VarGet(VAR_FRONTIER_BATTLE_MODE) != FRONTIER_MODE_SINGLES)
+ return;
+
+ GetFrontierTrainerName(text, gTrainerBattleOpponent_A);
+ StripExtCtrlCodes(text);
+ StringCopy(gSaveBlock2Ptr->frontier.field_BD8, text);
+ GetBattleTowerTrainerLanguage(&gSaveBlock2Ptr->frontier.field_BEB, gTrainerBattleOpponent_A);
+ gSaveBlock2Ptr->frontier.field_BD6 = GetMonData(&gEnemyParty[gBattlerPartyIndexes[1]], MON_DATA_SPECIES, NULL);
+ gSaveBlock2Ptr->frontier.field_BD4 = GetMonData(&gPlayerParty[gBattlerPartyIndexes[0]], MON_DATA_SPECIES, NULL);
+ for (i = 0; i < POKEMON_NAME_LENGTH + 1; i++)
+ gSaveBlock2Ptr->frontier.field_BE0[i] = gBattleMons[0].nickname[i];
+ gSaveBlock2Ptr->frontier.field_D06 = gBattleOutcome;
+}
+
+static void ValidateBattleTowerRecordChecksums(void)
+{
+ s32 i, j;
+ u32 *record = (u32*)(&gSaveBlock2Ptr->frontier.towerPlayer);
+ u32 checksum = 0;
+
+ for (j = 0; j < (sizeof(struct EmeraldBattleTowerRecord) - 4) / 4; j++) // - 4, because of the last field being the checksum itself.
+ {
+ checksum += record[j];
+ }
+ if (gSaveBlock2Ptr->frontier.towerPlayer.checksum != checksum)
+ ClearBattleTowerRecord(&gSaveBlock2Ptr->frontier.towerPlayer);
+
+ for (i = 0; i < 5; i++)
+ {
+ record = (u32*)(&gSaveBlock2Ptr->frontier.towerRecords[i]);
+ checksum = 0;
+ for (j = 0; j < (sizeof(struct EmeraldBattleTowerRecord) - 4) / 4; j++) // - 4, because of the last field being the checksum itself.
+ {
+ checksum += record[j];
+ }
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].checksum != checksum)
+ ClearBattleTowerRecord(&gSaveBlock2Ptr->frontier.towerRecords[i]);
+ }
+}
+
+void CalcEmeraldBattleTowerChecksum(struct EmeraldBattleTowerRecord *record)
+{
+ u32 i;
+
+ record->checksum = 0;
+ for (i = 0; i < (sizeof(struct EmeraldBattleTowerRecord) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
+ record->checksum += ((u32 *)record)[i];
+}
+
+void CalcRubyBattleTowerChecksum(struct RSBattleTowerRecord *record)
+{
+ u32 i;
+
+ record->checksum = 0;
+ for (i = 0; i < (sizeof(struct RSBattleTowerRecord) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
+ record->checksum += ((u32 *)record)[i];
+}
+
+static void ClearBattleTowerRecord(struct EmeraldBattleTowerRecord *record)
+{
+ u32 i;
+
+ for (i = 0; i < sizeof(struct EmeraldBattleTowerRecord) / 4; i++)
+ ((u32 *)record)[i] = 0;
+}
+
+u16 GetCurrentBattleTowerWinStreak(u8 lvlMode, u8 battleMode)
+{
+ u16 winStreak = gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode];
+
+ if (winStreak > 9999)
+ return 9999;
+ else
+ return winStreak;
+}
+
+static u8 GetMonCountForBattleMode(u8 battleMode)
+{
+ u8 sp[ARRAY_COUNT(gUnknown_085DFA42)];
+ memcpy(sp, gUnknown_085DFA42, sizeof(gUnknown_085DFA42));
+
+ if (battleMode < ARRAY_COUNT(gUnknown_085DFA42))
+ return sp[battleMode];
+ else
+ return 3;
+}
+
+struct RibbonCounter
+{
+ u8 partyIndex;
+ u8 count;
+};
+
+static void AwardBattleTowerRibbons(void)
+{
+ s32 i;
+ u32 partyIndex;
+ struct RibbonCounter ribbons[3]; // BUG: 4 Pokemon can receive ribbons in a double battle mode.
+ u8 ribbonType = 0;
+ u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
+ u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ u8 monCount = GetMonCountForBattleMode(battleMode);
+
+ if (lvlMode != FRONTIER_LVL_50)
+ ribbonType = MON_DATA_VICTORY_RIBBON;
+ else
+ ribbonType = MON_DATA_WINNING_RIBBON;
+
+ gSpecialVar_Result = FALSE;
+
+ if (GetCurrentBattleTowerWinStreak(lvlMode, battleMode) > 55)
+ {
+ for (i = 0; i < monCount; i++)
+ {
+ partyIndex = gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1;
+ ribbons[i].partyIndex = partyIndex;
+ ribbons[i].count = 0;
+ if (!GetMonData(&gSaveBlock1Ptr->playerParty[partyIndex], ribbonType))
+ {
+ gSpecialVar_Result = TRUE;
+ SetMonData(&gSaveBlock1Ptr->playerParty[partyIndex], ribbonType, &gSpecialVar_Result);
+ ribbons[i].count = GetRibbonCount(&gSaveBlock1Ptr->playerParty[partyIndex]);
+ }
+ }
+ }
+
+ if (gSpecialVar_Result)
+ {
+ IncrementGameStat(GAME_STAT_RECEIVED_RIBBONS);
+ for (i = 1; i < monCount; i++)
+ {
+ if (ribbons[i].count > ribbons[0].count)
+ {
+ struct RibbonCounter prevBest = ribbons[0];
+ ribbons[0] = ribbons[i];
+ ribbons[i] = prevBest;
+ }
+ }
+ if (ribbons[0].count > 4)
+ {
+ sub_80EE4DC(&gSaveBlock1Ptr->playerParty[ribbons[0].partyIndex], ribbonType);
+ }
+ }
+}
+
+// This is a leftover debugging function that is used to populate the E-Reader
+// trainer with the player's current data.
+static void FillEReaderTrainerWithPlayerData(void)
+{
+ struct BattleTowerEReaderTrainer *ereaderTrainer = &gSaveBlock2Ptr->frontier.ereaderTrainer;
+ s32 i, j;
+
+ if (gSaveBlock2Ptr->playerGender != MALE)
+ {
+ ereaderTrainer->facilityClass = gTowerFemaleFacilityClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
+ + gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % ARRAY_COUNT(gTowerFemaleFacilityClasses)];
+ }
+ else
+ {
+ ereaderTrainer->facilityClass = gTowerMaleFacilityClasses[(gSaveBlock2Ptr->playerTrainerId[0] + gSaveBlock2Ptr->playerTrainerId[1]
+ + gSaveBlock2Ptr->playerTrainerId[2] + gSaveBlock2Ptr->playerTrainerId[3]) % ARRAY_COUNT(gTowerMaleFacilityClasses)];
+ }
+
+ CopyUnalignedWord(ereaderTrainer->trainerId, gSaveBlock2Ptr->playerTrainerId);
+ StringCopy7(ereaderTrainer->name, gSaveBlock2Ptr->playerName);
+
+ ereaderTrainer->winStreak = 1;
+
+ j = 7;
+ for (i = 0; i < 6; i++)
+ {
+ ereaderTrainer->greeting[i] = gSaveBlock1Ptr->unk2BBC[i];
+ ereaderTrainer->farewellPlayerLost[i] = j;
+ ereaderTrainer->farewellPlayerWon[i] = j + 6;
+ j++;
+ }
+
+ for (i = 0; i < 3; i++)
+ sub_80686FC(&gPlayerParty[i], &ereaderTrainer->party[i]);
+
+ SetEReaderTrainerChecksum(ereaderTrainer);
+}
+
+u8 GetEreaderTrainerFrontSpriteId(void)
+{
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
+}
+
+u8 GetEreaderTrainerClassId(void)
+{
+ return gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
+}
+
+void GetEreaderTrainerName(u8 *dst)
+{
+ s32 i;
+
+ for (i = 0; i < 5; i++)
+ dst[i] = gSaveBlock2Ptr->frontier.ereaderTrainer.name[i];
+
+ dst[i] = EOS;
+}
+
+// Checks if the saved E-Reader trainer is valid.
+void ValidateEReaderTrainer(void)
+{
+ u32 i;
+ u32 checksum;
+ struct BattleTowerEReaderTrainer *ereaderTrainer;
+
+ gSpecialVar_Result = FALSE;
+ ereaderTrainer = &gSaveBlock2Ptr->frontier.ereaderTrainer;
+
+ checksum = 0;
+ for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
+ checksum |= ((u32 *)ereaderTrainer)[i];
+
+ if (checksum == 0)
+ {
+ gSpecialVar_Result = TRUE;
+ return;
+ }
+
+ checksum = 0;
+ for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
+ checksum += ((u32 *)ereaderTrainer)[i];
+
+ if (gSaveBlock2Ptr->frontier.ereaderTrainer.checksum != checksum)
+ {
+ ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer);
+ gSpecialVar_Result = TRUE;
+ }
+}
+
+static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer)
+{
+ s32 i;
+
+ ereaderTrainer->checksum = 0;
+ for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer) - 4) / 4; i++) // - 4, because of the last field being the checksum itself.
+ ereaderTrainer->checksum += ((u32 *)ereaderTrainer)[i];
+}
+
+void ClearEReaderTrainer(struct BattleTowerEReaderTrainer *ereaderTrainer)
+{
+ u32 i;
+
+ for (i = 0; i < (sizeof(struct BattleTowerEReaderTrainer)) / 4; i++)
+ ((u32 *)ereaderTrainer)[i] = 0;
+}
+
+void CopyEReaderTrainerGreeting(void)
+{
+ FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.greeting);
+}
+
+static void CopyEReaderTrainerFarewellMessage(void)
+{
+ if (gBattleOutcome == B_OUTCOME_DREW)
+ gStringVar4[0] = EOS;
+ else if (gBattleOutcome == B_OUTCOME_WON)
+ FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.farewellPlayerWon);
+ else
+ FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.farewellPlayerLost);
+}
+
+void sub_81653CC(void)
+{
+ if (gSaveBlock2Ptr->frontier.field_CA8 == 1)
+ sub_80F01B8();
+ if (FlagGet(FLAG_0x077) == TRUE)
+ {
+ sub_80F01B8();
+ FlagClear(FLAG_0x077);
+ }
+}
+
+#define STEVEN_OTID 61226
+
+static void FillPartnerParty(u16 trainerId)
+{
+ s32 i, j;
+ u32 ivs, level;
+ u32 friendship;
+ u16 monPoolId;
+ u32 otID;
+ u8 trainerName[PLAYER_NAME_LENGTH + 1];
+ SetFacilityPtrsGetLevel();
+
+ if (trainerId == TRAINER_STEVEN_PARTNER)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ do
+ {
+ j = Random32();
+ } while (IsShinyOtIdPersonality(STEVEN_OTID, j) || sStevenMons[i].nature != GetNatureFromPersonality(j));
+ CreateMon(&gPlayerParty[3 + i],
+ sStevenMons[i].species,
+ sStevenMons[i].level,
+ sStevenMons[i].fixedIV,
+ TRUE, i, // BUG: personality was stored in the 'j' variable. As a result, Steven's pokemon do not have the intended natures.
+ TRUE, STEVEN_OTID);
+ for (j = 0; j < 6; j++)
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_HP_EV + j, &sStevenMons[i].evs[j]);
+ for (j = 0; j < 4; j++)
+ SetMonMoveSlot(&gPlayerParty[3 + i], sStevenMons[i].moves[j], j);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_NAME, gTrainers[TRAINER_STEVEN].trainerName);
+ j = MALE;
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_GENDER, &j);
+ CalculateMonStats(&gPlayerParty[3 + i]);
+ }
+ }
+ else if (trainerId == TRAINER_EREADER)
+ {
+ // Scrapped, lol.
+ trainerName[0] = gGameLanguage;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ level = SetFacilityPtrsGetLevel();
+ ivs = GetFrontierTrainerFixedIvs(trainerId);
+ otID = Random32();
+ for (i = 0; i < 2; i++)
+ {
+ monPoolId = gSaveBlock2Ptr->frontier.field_CB4[i + 18];
+ CreateMonWithEVSpreadPersonalityOTID(&gPlayerParty[3 + i],
+ gFacilityTrainerMons[monPoolId].species,
+ level,
+ gFacilityTrainerMons[monPoolId].nature,
+ ivs,
+ gFacilityTrainerMons[monPoolId].evSpread,
+ otID);
+ friendship = 0xFF;
+ for (j = 0; j < 4; j++)
+ {
+ SetMonMoveSlot(&gPlayerParty[3 + i], gFacilityTrainerMons[monPoolId].moves[j], j);
+ if (gFacilityTrainerMons[monPoolId].moves[j] == MOVE_FRUSTRATION)
+ friendship = 0;
+ }
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monPoolId].itemTableId]);
+ for (j = 0; j < PLAYER_NAME_LENGTH + 1; j++)
+ trainerName[j] = gFacilityTrainers[trainerId].trainerName[j];
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_NAME, &trainerName);
+ j = IsFrontierTrainerFemale(trainerId);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_GENDER, &j);
+ }
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ trainerId -= TRAINER_RECORD_MIXING_FRIEND;
+ for (i = 0; i < 2; i++)
+ {
+ struct EmeraldBattleTowerRecord *record = &gSaveBlock2Ptr->frontier.towerRecords[trainerId];
+ struct UnknownPokemonStruct monData = record->party[gSaveBlock2Ptr->frontier.field_CB4[18 + i]];
+ StringCopy(trainerName, record->name);
+ if (record->language == LANGUAGE_JAPANESE)
+ {
+ if (monData.nickname[0] != EXT_CTRL_CODE_BEGIN || monData.nickname[1] != EXT_CTRL_CODE_JPN)
+ {
+ monData.nickname[5] = EOS;
+ ConvertInternationalString(monData.nickname, LANGUAGE_JAPANESE);
+ }
+ }
+ else
+ {
+ if (monData.nickname[0] == EXT_CTRL_CODE_BEGIN && monData.nickname[1] == EXT_CTRL_CODE_JPN)
+ trainerName[5] = EOS;
+ }
+ sub_8068338(&gPlayerParty[3 + i], &monData, TRUE);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_NAME, trainerName);
+ j = IsFrontierTrainerFemale(trainerId + TRAINER_RECORD_MIXING_FRIEND);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_GENDER, &j);
+ }
+ }
+ else
+ {
+ trainerId -= TRAINER_RECORD_MIXING_APPRENTICE;
+ for (i = 0; i < 2; i++)
+ {
+ CreateApprenticeMon(&gPlayerParty[3 + i], &gSaveBlock2Ptr->apprentices[trainerId], gSaveBlock2Ptr->frontier.field_CB4[18 + i]);
+ j = IsFrontierTrainerFemale(trainerId + TRAINER_RECORD_MIXING_APPRENTICE);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_GENDER, &j);
+ }
+ }
+}
+
+bool32 RubyBattleTowerRecordToEmerald(struct RSBattleTowerRecord *src, struct EmeraldBattleTowerRecord *dst)
+{
+ s32 i, validMons = 0;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (src->party[i].species)
+ validMons++;
+ }
+
+ if (validMons != 3)
+ {
+ memset(dst, 0, sizeof(*dst));
+ return FALSE;
+ }
+ else
+ {
+ dst->lvlMode = src->lvlMode;
+ dst->winStreak = src->winStreak;
+ for (i = 0; i < (signed) ARRAY_COUNT(sRubyFacilityClassToEmerald); i++)
+ {
+ if (sRubyFacilityClassToEmerald[i][0] == src->facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(sRubyFacilityClassToEmerald))
+ dst->facilityClass = sRubyFacilityClassToEmerald[i][1];
+ else
+ dst->facilityClass = FACILITY_CLASS_YOUNGSTER;
+
+ for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
+ dst->name[i] = src->name[i];
+ for (i = 0; i < 4; i++)
+ dst->trainerId[i] = src->trainerId[i];
+ for (i = 0; i < 6; i++)
+ dst->greeting[i] = src->greeting[i];
+ for (i = 0; i < 6; i++)
+ dst->unk1C[i] = gUnknown_085DFA46[i];
+ for (i = 0; i < 6; i++)
+ dst->unk28[i] = gUnknown_085DFA52[i];
+ for (i = 0; i < 3; i++)
+ dst->party[i] = src->party[i];
+
+ CpuFill32(0, &dst->party[3], sizeof(dst->party[3]));
+ CalcEmeraldBattleTowerChecksum(dst);
+ return TRUE;
+ }
+}
+
+bool32 EmeraldBattleTowerRecordToRuby(struct EmeraldBattleTowerRecord *src, struct RSBattleTowerRecord *dst)
+{
+ s32 i, validMons = 0;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (src->party[i].species)
+ validMons++;
+ }
+
+ if (validMons != 3)
+ {
+ memset(dst, 0, sizeof(*dst));
+ return FALSE;
+ }
+ else
+ {
+ dst->lvlMode = src->lvlMode;
+ dst->winStreak = src->winStreak;
+ for (i = 0; i < (signed) ARRAY_COUNT(sRubyFacilityClassToEmerald); i++)
+ {
+ if (sRubyFacilityClassToEmerald[i][1] == src->facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(sRubyFacilityClassToEmerald))
+ dst->facilityClass = sRubyFacilityClassToEmerald[i][0];
+ else
+ dst->facilityClass = 0x24; // FACILITY_CLASS_YOUNGSTER in Ruby/Sapphire.
+
+ for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
+ dst->name[i] = src->name[i];
+ for (i = 0; i < 4; i++)
+ dst->trainerId[i] = src->trainerId[i];
+ for (i = 0; i < 6; i++)
+ dst->greeting[i] = src->greeting[i];
+ for (i = 0; i < 3; i++)
+ dst->party[i] = src->party[i];
+
+ CalcRubyBattleTowerChecksum(dst);
+ return TRUE;
+ }
+}
+
+void CalcApprenticeChecksum(struct Apprentice *apprentice)
+{
+ s32 i;
+
+ apprentice->checksum = 0;
+ for (i = 0; i < (sizeof(struct Apprentice) - 4) / 4; i++)
+ apprentice->checksum += ((u32 *)apprentice)[i];
+}
+
+static void ClearApprentice(struct Apprentice *apprentice)
+{
+ s32 i;
+
+ for (i = 0; i < (sizeof(struct Apprentice)) / 4; i++)
+ ((u32 *)apprentice)[i] = 0;
+ ResetApprenticeStruct(apprentice);
+}
+
+static void ValidateApprenticesChecksums(void)
+{
+ s32 i, j;
+
+ for (i = 0; i < 4; i++)
+ {
+ u32 *data = (u32*) &gSaveBlock2Ptr->apprentices[i];
+ u32 checksum = 0;
+ for (j = 0; j < (sizeof(struct Apprentice) - 4) / 4; j++)
+ checksum += data[j];
+ if (gSaveBlock2Ptr->apprentices[i].checksum != checksum)
+ ClearApprentice(&gSaveBlock2Ptr->apprentices[i]);
+ }
+}
+
+void GetBattleTowerTrainerLanguage(u8 *dst, u16 trainerId)
+{
+ if (trainerId == TRAINER_EREADER)
+ {
+ *dst = gGameLanguage;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_FRIEND)
+ {
+ *dst = gGameLanguage;
+ }
+ else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ *dst = sub_81864B4();
+ else
+ *dst = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].language;
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ *dst = sub_81864C0();
+ else
+ *dst = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].language;
+ }
+}
+
+u8 SetFacilityPtrsGetLevel(void)
+{
+ if (gSaveBlock2Ptr->frontier.lvlMode == FRONTIER_LVL_TENT)
+ {
+ return SetTentPtrsGetLevel();
+ }
+ else
+ {
+ gFacilityTrainers = gBattleFrontierTrainers;
+ gFacilityTrainerMons = gBattleFrontierMons;
+ return GetFrontierEnemyMonLevel(gSaveBlock2Ptr->frontier.lvlMode);
+ }
+}
+
+u8 GetFrontierEnemyMonLevel(u8 lvlMode)
+{
+ u8 level;
+
+ switch (lvlMode)
+ {
+ default:
+ case FRONTIER_LVL_50:
+ level = 50;
+ break;
+ case FRONTIER_LVL_OPEN:
+ level = GetHighestLevelInPlayerParty();
+ if (level < 60)
+ level = 60;
+ break;
+ }
+
+ return level;
+}
+
+s32 GetHighestLevelInPlayerParty(void)
+{
+ s32 highestLevel = 0;
+ s32 i;
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL)
+ && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG)
+ {
+ s32 level = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL, NULL);
+ if (level > highestLevel)
+ highestLevel = level;
+ }
+ }
+
+ return highestLevel;
+}
+
+static u8 GetFrontierTrainerFixedIvs(u16 trainerId)
+{
+ u8 fixedIV = 0;
+
+ if (trainerId < 100)
+ fixedIV = 3;
+ else if (trainerId < 120)
+ fixedIV = 6;
+ else if (trainerId < 140)
+ fixedIV = 9;
+ else if (trainerId < 160)
+ fixedIV = 12;
+ else if (trainerId < 180)
+ fixedIV = 15;
+ else if (trainerId < 200)
+ fixedIV = 18;
+ else if (trainerId < 220)
+ fixedIV = 21;
+ else
+ fixedIV = 31;
+
+ return fixedIV;
+}
+
+static u16 sub_8165D40(void)
+{
+ u32 facility = VarGet(VAR_FRONTIER_FACILITY);
+
+ if (facility == FRONTIER_FACILITY_PALACE)
+ return Random() % 30;
+ else if (facility == FRONTIER_FACILITY_ARENA)
+ return Random() % 30;
+ else if (facility == FRONTIER_FACILITY_FACTORY)
+ return Random() % 30;
+ else if (facility == FRONTIER_FACILITY_TOWER)
+ return 0;
+ else
+ return 0;
+}
+
+static u8 SetTentPtrsGetLevel(void)
+{
+ u8 level = 30;
+ u32 tentFacility = VarGet(VAR_FRONTIER_FACILITY);
+
+ if (tentFacility == TENT_SLATEPORT)
+ {
+ gFacilityTrainers = gSlateportBattleTentTrainers;
+ gFacilityTrainerMons = gSlateportBattleTentMons;
+ }
+ else if (tentFacility == TENT_VERDANTURF)
+ {
+ gFacilityTrainers = gVerdanturfBattleTentTrainers;
+ gFacilityTrainerMons = gVerdanturfBattleTentMons;
+ }
+ else if (tentFacility == TENT_FALLARBOR)
+ {
+ gFacilityTrainers = gFallarborBattleTentTrainers;
+ gFacilityTrainerMons = gFallarborBattleTentMons;
+ }
+ else
+ {
+ gFacilityTrainers = gBattleFrontierTrainers;
+ gFacilityTrainerMons = gBattleFrontierMons;
+ }
+
+ level = GetHighestLevelInPlayerParty();
+ if (level < 30)
+ level = 30;
+
+ return level;
+}
+
+static void sub_8165E18(void)
+{
+ s32 i;
+ u16 trainerId;
+
+ do
+ {
+ trainerId = sub_8165D40();
+ for (i = 0; i < gSaveBlock2Ptr->frontier.curChallengeBattleNum; i++)
+ {
+ if (gSaveBlock2Ptr->frontier.field_CB4[i] == trainerId)
+ break;
+ }
+ } while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum);
+
+ gTrainerBattleOpponent_A = trainerId;
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < 3)
+ gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
+}
+
+static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount)
+{
+ s32 i, j;
+ u16 chosenMonIndices[4];
+ u8 friendship;
+ u8 level = SetTentPtrsGetLevel();
+ u8 fixedIV = 0;
+ u8 bfMonCount;
+ const u16 *bfMonPool = NULL;
+ u32 otID = 0;
+ u16 monPoolId;
+
+ bfMonPool = gFacilityTrainers[gTrainerBattleOpponent_A].bfMonPool;
+
+ bfMonCount = 0;
+ monPoolId = bfMonPool[bfMonCount];
+ while (monPoolId != 0xFFFF)
+ {
+ bfMonCount++;
+ monPoolId = bfMonPool[bfMonCount];
+ if (monPoolId == 0xFFFF)
+ break;
+ }
+
+ i = 0;
+ otID = Random32();
+ while (i != monCount)
+ {
+ u16 monPoolId = bfMonPool[Random() % bfMonCount];
+
+ // Ensure this pokemon species isn't a duplicate.
+ for (j = 0; j < i + firstMonId; j++)
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_SPECIES, NULL) == gFacilityTrainerMons[monPoolId].species)
+ break;
+ }
+ if (j != i + firstMonId)
+ continue;
+
+ // Ensure this Pokemon's held item isn't a duplicate.
+ for (j = 0; j < i + firstMonId; j++)
+ {
+ if (GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) != 0
+ && GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) == gBattleFrontierHeldItems[gFacilityTrainerMons[monPoolId].itemTableId])
+ break;
+ }
+ if (j != i + firstMonId)
+ continue;
+
+ // Ensure this exact pokemon index isn't a duplicate. This check doesn't seem necessary
+ // because the species and held items were already checked directly above.
+ for (j = 0; j < i; j++)
+ {
+ if (chosenMonIndices[j] == monPoolId)
+ break;
+ }
+ if (j != i)
+ continue;
+
+ chosenMonIndices[i] = monPoolId;
+
+ // Place the chosen pokemon into the trainer's party.
+ CreateMonWithEVSpreadPersonalityOTID(&gEnemyParty[i + firstMonId],
+ gFacilityTrainerMons[monPoolId].species,
+ level,
+ gFacilityTrainerMons[monPoolId].nature,
+ fixedIV,
+ gFacilityTrainerMons[monPoolId].evSpread,
+ otID);
+
+ friendship = 255;
+ // Give the chosen pokemon its specified moves.
+ for (j = 0; j < 4; j++)
+ {
+ SetMonMoveSlot(&gEnemyParty[i + firstMonId], gFacilityTrainerMons[monPoolId].moves[j], j);
+ if (gFacilityTrainerMons[monPoolId].moves[j] == MOVE_FRUSTRATION)
+ friendship = 0; // Frustration is more powerful the lower the pokemon's friendship is.
+ }
+
+ SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monPoolId].itemTableId]);
+
+ // The pokemon was successfully added to the trainer's party, so it's safe to move on to
+ // the next party slot.
+ i++;
+ }
+}
+
+u8 sub_81660B8(u8 facilityClass)
+{
+ u8 trainerObjectGfxId;
+ u8 i;
+
+ // Search male classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerMaleFacilityClasses); i++)
+ {
+ if (gTowerMaleFacilityClasses[i] == facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(gTowerMaleFacilityClasses))
+ {
+ trainerObjectGfxId = gTowerMaleTrainerGfxIds[i];
+ return trainerObjectGfxId;
+ }
+
+ // Search female classes.
+ for (i = 0; i < ARRAY_COUNT(gTowerFemaleFacilityClasses); i++)
+ {
+ if (gTowerFemaleFacilityClasses[i] == facilityClass)
+ break;
+ }
+ if (i != ARRAY_COUNT(gTowerFemaleFacilityClasses))
+ {
+ trainerObjectGfxId = gTowerFemaleTrainerGfxIds[i];
+ return trainerObjectGfxId;
+ }
+ else
+ {
+ return EVENT_OBJ_GFX_BOY_1;
+ }
+}
+
+bool32 ValidateBattleTowerRecord(u8 recordId) // unused
+{
+ s32 i;
+ u32 *record = (u32*)(&gSaveBlock2Ptr->frontier.towerRecords[recordId]);
+ u32 checksum = 0;
+ u32 hasData = 0;
+ for (i = 0; i < (sizeof(struct EmeraldBattleTowerRecord) - 4) / 4; i++) // - 4, because of the last fjeld bejng the checksum jtself.
+ {
+ checksum += record[i];
+ hasData |= record[i];
+ }
+
+ if (checksum == 0 && hasData == 0)
+ {
+ return FALSE;
+ }
+ else if (gSaveBlock2Ptr->frontier.towerRecords[recordId].checksum != checksum)
+ {
+ ClearBattleTowerRecord(&gSaveBlock2Ptr->frontier.towerRecords[recordId]);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void sub_8166188(void)
+{
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ {
+ s32 i;
+ u8 enemyLevel = SetFacilityPtrsGetLevel();
+
+ for (i = 0; i < PARTY_SIZE; i++)
+ {
+ u32 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, NULL);
+ if (species)
+ {
+ SetMonData(&gEnemyParty[i], MON_DATA_EXP, &gExperienceTables[gBaseStats[species].growthRate][enemyLevel]);
+ CalculateMonStats(&gEnemyParty[i]);
+ }
+ }
+ }
+}
diff --git a/src/field_specials.c b/src/field_specials.c
index 4b6ac47d0..e2e069d28 100644
--- a/src/field_specials.c
+++ b/src/field_specials.c
@@ -2158,13 +2158,13 @@ void sub_8139F20(void)
case 1:
case 2:
case 3:
- if (gSaveBlock2Ptr->frontier.field_CE0[var][0] >= gSaveBlock2Ptr->frontier.field_CE0[var][1])
+ if (gSaveBlock2Ptr->frontier.winStreaks[var][0] >= gSaveBlock2Ptr->frontier.winStreaks[var][1])
{
- unk = gSaveBlock2Ptr->frontier.field_CE0[var][0];
+ unk = gSaveBlock2Ptr->frontier.winStreaks[var][0];
}
else
{
- unk = gSaveBlock2Ptr->frontier.field_CE0[var][1];
+ unk = gSaveBlock2Ptr->frontier.winStreaks[var][1];
}
break;
case 4:
@@ -2244,7 +2244,7 @@ void sub_813A080(void)
u16 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
- if (battleMode == 2 && !FlagGet(FLAG_0x152))
+ if (battleMode == FRONTIER_MODE_MULTIS && !FlagGet(FLAG_0x152))
{
gSpecialVar_0x8005 = 5;
gSpecialVar_0x8006 = 4;
@@ -2253,7 +2253,7 @@ void sub_813A080(void)
for (i = 0; i < 9; i++)
{
- if (gUnknown_085B2CDC[i] > gSaveBlock2Ptr->frontier.field_CE0[battleMode][lvlMode])
+ if (gUnknown_085B2CDC[i] > gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode])
{
gSpecialVar_0x8005 = 4;
gSpecialVar_0x8006 = i + 5;
@@ -2733,8 +2733,6 @@ static void sub_813A46C(s32 itemIndex, bool8 onInit, struct ListMenu *list)
}
}
-// stupid r5<->r6 swap
-#ifdef NONMATCHING
static void sub_813A4EC(u8 taskId)
{
struct Task *task = &gTasks[taskId];
@@ -2752,7 +2750,11 @@ static void sub_813A4EC(u8 taskId)
default:
gSpecialVar_Result = itemId;
PlaySE(SE_SELECT);
- if (!task->data[6] || itemId == task->data[1] - 1)
+ if (!task->data[6])
+ {
+ sub_813A570(taskId);
+ }
+ else if (itemId == task->data[1] - 1)
{
sub_813A570(taskId);
}
@@ -2765,72 +2767,6 @@ static void sub_813A4EC(u8 taskId)
break;
}
}
-#else
-NAKED
-static void sub_813A4EC(u8 taskId)
-{
- asm_unified("push {r4-r6,lr}\n\
- lsls r0, 24\n\
- lsrs r5, r0, 24\n\
- lsls r0, r5, 2\n\
- adds r0, r5\n\
- lsls r0, 3\n\
- ldr r1, =gTasks\n\
- adds r6, r0, r1\n\
- ldrh r0, [r6, 0x24]\n\
- lsls r0, 24\n\
- lsrs r0, 24\n\
- bl ListMenuHandleInputGetItemId\n\
- adds r4, r0, 0\n\
- movs r0, 0x2\n\
- negs r0, r0\n\
- cmp r4, r0\n\
- beq _0813A51C\n\
- adds r0, 0x1\n\
- cmp r4, r0\n\
- bne _0813A530\n\
- b _0813A566\n\
- .pool\n\
-_0813A51C:\n\
- ldr r1, =gSpecialVar_Result\n\
- movs r0, 0x7F\n\
- strh r0, [r1]\n\
- movs r0, 0x5\n\
- bl PlaySE\n\
- b _0813A54C\n\
- .pool\n\
-_0813A530:\n\
- ldr r0, =gSpecialVar_Result\n\
- strh r4, [r0]\n\
- movs r0, 0x5\n\
- bl PlaySE\n\
- movs r1, 0x14\n\
- ldrsh r0, [r6, r1]\n\
- cmp r0, 0\n\
- beq _0813A54C\n\
- movs r1, 0xA\n\
- ldrsh r0, [r6, r1]\n\
- subs r0, 0x1\n\
- cmp r4, r0\n\
- bne _0813A558\n\
-_0813A54C:\n\
- adds r0, r5, 0\n\
- bl sub_813A570\n\
- b _0813A566\n\
- .pool\n\
-_0813A558:\n\
- adds r0, r5, 0\n\
- bl sub_813A738\n\
- ldr r0, =sub_813A600\n\
- str r0, [r6]\n\
- bl EnableBothScriptContexts\n\
-_0813A566:\n\
- pop {r4-r6}\n\
- pop {r0}\n\
- bx r0\n\
- .pool");
-}
-#endif // NONMATCHING
static void sub_813A570(u8 taskId)
{
diff --git a/src/map_name_popup.c b/src/map_name_popup.c
index 1e4ba5e1e..172fcc723 100644
--- a/src/map_name_popup.c
+++ b/src/map_name_popup.c
@@ -314,7 +314,7 @@ static void ShowMapNamePopUpWindow(void)
else
{
withoutPrefixPtr = &(mapDisplayHeader[3]);
- mapDisplayHeaderSource = gBattlePyramid_MapHeaderStrings[gSaveBlock2Ptr->frontier.field_CB2];
+ mapDisplayHeaderSource = gBattlePyramid_MapHeaderStrings[gSaveBlock2Ptr->frontier.curChallengeBattleNum];
}
StringCopy(withoutPrefixPtr, mapDisplayHeaderSource);
}
diff --git a/src/pokemon.c b/src/pokemon.c
index a7a91a630..b858ee925 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -2879,10 +2879,10 @@ void CreateApprenticeMon(struct Pokemon *mon, const struct Apprentice *src, u8 m
u8 language;
u32 otId = gApprentices[src->id].otId;
u32 personality = ((gApprentices[src->id].otId >> 8) | ((gApprentices[src->id].otId & 0xFF) << 8))
- + src->monData[monId].species + src->number;
+ + src->party[monId].species + src->number;
CreateMon(mon,
- src->monData[monId].species,
+ src->party[monId].species,
GetFrontierEnemyMonLevel(src->lvlMode - 1),
0x1F,
TRUE,
@@ -2890,9 +2890,9 @@ void CreateApprenticeMon(struct Pokemon *mon, const struct Apprentice *src, u8 m
TRUE,
otId);
- SetMonData(mon, MON_DATA_HELD_ITEM, &src->monData[monId].item);
+ SetMonData(mon, MON_DATA_HELD_ITEM, &src->party[monId].item);
for (i = 0; i < 4; i++)
- SetMonMoveSlot(mon, src->monData[monId].moves[i], i);
+ SetMonMoveSlot(mon, src->party[monId].moves[i], i);
evAmount = MAX_TOTAL_EVS / NUM_STATS;
for (i = 0; i < NUM_STATS; i++)
diff --git a/src/record_mixing.c b/src/record_mixing.c
index 4c3c3d03c..4bb97cf1d 100644
--- a/src/record_mixing.c
+++ b/src/record_mixing.c
@@ -69,6 +69,7 @@ struct PlayerRecordsRS
struct EasyChatPair easyChatPairs[5];
struct RecordMixingDayCareMail dayCareMail;
struct RSBattleTowerRecord battleTowerRecord;
+ u16 giftItem;
u16 filler11C8[0x32];
};
@@ -81,7 +82,7 @@ struct PlayerRecordsEmerald
/* 0x1084 */ struct EasyChatPair easyChatPairs[5];
/* 0x10ac */ struct RecordMixingDayCareMail dayCareMail;
/* 0x1124 */ struct EmeraldBattleTowerRecord battleTowerRecord;
- /* 0x1210 */ u16 unk_1210;
+ /* 0x1210 */ u16 giftItem;
/* 0x1214 */ LilycoveLady lilycoveLady;
/* 0x1254 */ struct Apprentice apprentice[2];
/* 0x12dc */ struct UnkRecordMixingStruct2 unk_12dc;
@@ -132,7 +133,7 @@ static void ReceiveBattleTowerData(void *battleTowerRecord, size_t, u8);
static void ReceiveLilycoveLadyData(LilycoveLady *, size_t, u8);
static void sub_80E7B2C(const u8 *);
static void ReceiveDaycareMailData(struct RecordMixingDayCareMail *, size_t, u8, TVShow *);
-static void sub_80E7F68(u16 *item, u8 which);
+static void ReceiveGiftItem(u16 *item, u8 which);
static void sub_80E7FF8(u8 taskId);
static void sub_80E8110(struct Apprentice *arg0, struct Apprentice *arg1);
static void ReceiveApprenticeData(struct Apprentice *arg0, size_t arg1, u32 arg2);
@@ -197,10 +198,10 @@ static void SetSrcLookupPointers(void)
sOldManSave = &gSaveBlock1Ptr->oldMan;
sEasyChatPairsSave = gSaveBlock1Ptr->easyChatPairs;
gUnknown_03001148 = &gUnknown_02039F9C;
- sBattleTowerSave = &gSaveBlock2Ptr->frontier.battleTower;
+ sBattleTowerSave = &gSaveBlock2Ptr->frontier.towerPlayer;
sLilycoveLadySave = &gSaveBlock1Ptr->lilycoveLady;
gUnknown_03001154 = gSaveBlock2Ptr->apprentices;
- sBattleTowerSave_Duplicate = &gSaveBlock2Ptr->frontier.battleTower;
+ sBattleTowerSave_Duplicate = &gSaveBlock2Ptr->frontier.towerPlayer;
}
static void PrepareUnknownExchangePacket(struct PlayerRecordsRS *dest)
@@ -212,10 +213,10 @@ static void PrepareUnknownExchangePacket(struct PlayerRecordsRS *dest)
memcpy(&dest->oldMan, sOldManSave, sizeof(dest->oldMan));
memcpy(dest->easyChatPairs, sEasyChatPairsSave, sizeof(dest->easyChatPairs));
sub_80E89F8(&dest->dayCareMail);
- sub_81659DC(sBattleTowerSave, &dest->battleTowerRecord);
+ EmeraldBattleTowerRecordToRuby(sBattleTowerSave, &dest->battleTowerRecord);
if (GetMultiplayerId() == 0)
- dest->battleTowerRecord.unk_11c8 = GetRecordMixingGift();
+ dest->giftItem = GetRecordMixingGift();
}
static void PrepareExchangePacketForRubySapphire(struct PlayerRecordsRS *dest)
@@ -230,11 +231,11 @@ static void PrepareExchangePacketForRubySapphire(struct PlayerRecordsRS *dest)
memcpy(dest->easyChatPairs, sEasyChatPairsSave, sizeof(dest->easyChatPairs));
sub_80E89F8(&dest->dayCareMail);
SanitizeDayCareMailForRuby(&dest->dayCareMail);
- sub_81659DC(sBattleTowerSave, &dest->battleTowerRecord);
+ EmeraldBattleTowerRecordToRuby(sBattleTowerSave, &dest->battleTowerRecord);
SanitizeRubyBattleTowerRecord(&dest->battleTowerRecord);
if (GetMultiplayerId() == 0)
- dest->battleTowerRecord.unk_11c8 = GetRecordMixingGift();
+ dest->giftItem = GetRecordMixingGift();
}
static void PrepareExchangePacket(void)
@@ -263,7 +264,7 @@ static void PrepareExchangePacket(void)
SanitizeEmeraldBattleTowerRecord(&sSentRecord->emerald.battleTowerRecord);
if (GetMultiplayerId() == 0)
- sSentRecord->emerald.unk_1210 = GetRecordMixingGift();
+ sSentRecord->emerald.giftItem = GetRecordMixingGift();
sub_80E8110(sSentRecord->emerald.apprentice, gUnknown_03001154);
sub_80E8260(&sSentRecord->emerald.unk_12dc);
@@ -283,7 +284,7 @@ static void ReceiveExchangePacket(u32 which)
ReceivePokeNewsData(sReceivedRecords->ruby.pokeNews, sizeof(struct PlayerRecordsRS), which);
ReceiveOldManData(&sReceivedRecords->ruby.oldMan, sizeof(struct PlayerRecordsRS), which);
ReceiveEasyChatPairsData(sReceivedRecords->ruby.easyChatPairs, sizeof(struct PlayerRecordsRS), which);
- sub_80E7F68(&sReceivedRecords->ruby.battleTowerRecord.unk_11c8, which);
+ ReceiveGiftItem(&sReceivedRecords->ruby.giftItem, which);
}
else
{
@@ -296,7 +297,7 @@ static void ReceiveExchangePacket(u32 which)
ReceiveEasyChatPairsData(sReceivedRecords->emerald.easyChatPairs, sizeof(struct PlayerRecordsEmerald), which);
ReceiveDaycareMailData(&sReceivedRecords->emerald.dayCareMail, sizeof(struct PlayerRecordsEmerald), which, sReceivedRecords->emerald.tvShows);
ReceiveBattleTowerData(&sReceivedRecords->emerald.battleTowerRecord, sizeof(struct PlayerRecordsEmerald), which);
- sub_80E7F68(&sReceivedRecords->emerald.unk_1210, which);
+ ReceiveGiftItem(&sReceivedRecords->emerald.giftItem, which);
ReceiveLilycoveLadyData(&sReceivedRecords->emerald.lilycoveLady, sizeof(struct PlayerRecordsEmerald), which);
ReceiveApprenticeData(sReceivedRecords->emerald.apprentice, sizeof(struct PlayerRecordsEmerald), (u8) which);
sub_80E89AC(&sReceivedRecords->emerald.unk_12dc, sizeof(struct PlayerRecordsEmerald), (u8) which);
@@ -667,7 +668,7 @@ static void ReceiveBattleTowerData(void *battleTowerRecord, size_t recordSize, u
ShufflePlayerIndices(mixIndices);
if (Link_AnyPartnersPlayingRubyOrSapphire())
{
- if (sub_816587C((void *)battleTowerRecord + recordSize * mixIndices[which], (void *)battleTowerRecord + recordSize * which) == TRUE)
+ if (RubyBattleTowerRecordToEmerald((void *)battleTowerRecord + recordSize * mixIndices[which], (void *)battleTowerRecord + recordSize * which) == TRUE)
{
dest = (void *)battleTowerRecord + recordSize * which;
dest->language = gLinkPlayers[mixIndices[which]].language;
@@ -676,7 +677,7 @@ static void ReceiveBattleTowerData(void *battleTowerRecord, size_t recordSize, u
}
else
{
- memcpy((void *)battleTowerRecord + recordSize * which, (void *)battleTowerRecord + recordSize * mixIndices[which], sizeof(union BattleTowerRecord));
+ memcpy((void *)battleTowerRecord + recordSize * which, (void *)battleTowerRecord + recordSize * mixIndices[which], sizeof(struct EmeraldBattleTowerRecord));
dest = (void *)battleTowerRecord + recordSize * which;
for (i = 0; i < 4; i ++)
{
@@ -686,7 +687,7 @@ static void ReceiveBattleTowerData(void *battleTowerRecord, size_t recordSize, u
}
CalcEmeraldBattleTowerChecksum(dest);
}
- sub_81628A0((void *)battleTowerRecord + recordSize * which);
+ PutNewBattleTowerRecord((void *)battleTowerRecord + recordSize * which);
}
static void ReceiveLilycoveLadyData(LilycoveLady *lilycoveLady, size_t recordSize, u8 which)
@@ -1460,7 +1461,7 @@ static void ReceiveDaycareMailData(struct RecordMixingDayCareMail *src, size_t r
}
#endif // NONMATCHING
-static void sub_80E7F68(u16 *item, u8 which)
+static void ReceiveGiftItem(u16 *item, u8 which)
{
if (which != 0 && *item != ITEM_NONE && GetPocketByItemId(*item) == POCKET_KEY_ITEMS)
{
diff --git a/src/recorded_battle.c b/src/recorded_battle.c
index 355ed5e07..0a199f289 100644
--- a/src/recorded_battle.c
+++ b/src/recorded_battle.c
@@ -402,73 +402,73 @@ u32 MoveRecordedBattleToSaveData(void)
{
for (i = 0; i < 8; i++)
{
- battleSave->field_504[i] = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_A - 300].field_4[i];
+ battleSave->field_504[i] = gSaveBlock2Ptr->records[gTrainerBattleOpponent_A - 300].field_4[i];
}
- battleSave->field_50C = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_A - 300].field_1;
+ battleSave->field_50C = gSaveBlock2Ptr->records[gTrainerBattleOpponent_A - 300].field_1;
if (sUnknown_0203CCE8 == 1)
{
for (i = 0; i < 6; i++)
{
- battleSave->field_50E[i] = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_A - 300].field_28[i];
+ battleSave->field_50E[i] = gSaveBlock2Ptr->records[gTrainerBattleOpponent_A - 300].field_28[i];
}
}
else
{
for (i = 0; i < 6; i++)
{
- battleSave->field_50E[i] = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_A - 300].field_1C[i];
+ battleSave->field_50E[i] = gSaveBlock2Ptr->records[gTrainerBattleOpponent_A - 300].field_1C[i];
}
}
- battleSave->field_51A = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_A - 300].field_E4;
+ battleSave->field_51A = gSaveBlock2Ptr->records[gTrainerBattleOpponent_A - 300].field_E4;
}
else if (gTrainerBattleOpponent_B >= 300 && gTrainerBattleOpponent_B <= 399)
{
for (i = 0; i < 8; i++)
{
- battleSave->field_504[i] = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_B - 300].field_4[i];
+ battleSave->field_504[i] = gSaveBlock2Ptr->records[gTrainerBattleOpponent_B - 300].field_4[i];
}
- battleSave->field_50C = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_B - 300].field_1;
+ battleSave->field_50C = gSaveBlock2Ptr->records[gTrainerBattleOpponent_B - 300].field_1;
if (sUnknown_0203CCE8 == 1)
{
for (i = 0; i < 6; i++)
{
- battleSave->field_50E[i] = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_B - 300].field_28[i];
+ battleSave->field_50E[i] = gSaveBlock2Ptr->records[gTrainerBattleOpponent_B - 300].field_28[i];
}
}
else
{
for (i = 0; i < 6; i++)
{
- battleSave->field_50E[i] = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_B - 300].field_1C[i];
+ battleSave->field_50E[i] = gSaveBlock2Ptr->records[gTrainerBattleOpponent_B - 300].field_1C[i];
}
}
- battleSave->field_51A = gSaveBlock2Ptr->field_738[gTrainerBattleOpponent_B - 300].field_E4;
+ battleSave->field_51A = gSaveBlock2Ptr->records[gTrainerBattleOpponent_B - 300].field_E4;
}
else if (gPartnerTrainerId >= 300 && gPartnerTrainerId <= 399)
{
for (i = 0; i < 8; i++)
{
- battleSave->field_504[i] = gSaveBlock2Ptr->field_738[gPartnerTrainerId - 300].field_4[i];
+ battleSave->field_504[i] = gSaveBlock2Ptr->records[gPartnerTrainerId - 300].field_4[i];
}
- battleSave->field_50C = gSaveBlock2Ptr->field_738[gPartnerTrainerId - 300].field_1;
+ battleSave->field_50C = gSaveBlock2Ptr->records[gPartnerTrainerId - 300].field_1;
if (sUnknown_0203CCE8 == 1)
{
for (i = 0; i < 6; i++)
{
- battleSave->field_50E[i] = gSaveBlock2Ptr->field_738[gPartnerTrainerId - 300].field_28[i];
+ battleSave->field_50E[i] = gSaveBlock2Ptr->records[gPartnerTrainerId - 300].field_28[i];
}
}
else
{
for (i = 0; i < 6; i++)
{
- battleSave->field_50E[i] = gSaveBlock2Ptr->field_738[gPartnerTrainerId - 300].field_1C[i];
+ battleSave->field_50E[i] = gSaveBlock2Ptr->records[gPartnerTrainerId - 300].field_1C[i];
}
}
- battleSave->field_51A = gSaveBlock2Ptr->field_738[gPartnerTrainerId - 300].field_E4;
+ battleSave->field_51A = gSaveBlock2Ptr->records[gPartnerTrainerId - 300].field_E4;
}
*/
diff --git a/src/secret_base.c b/src/secret_base.c
index a684f3982..87d44fb17 100644
--- a/src/secret_base.c
+++ b/src/secret_base.c
@@ -40,6 +40,7 @@
#include "tv.h"
#include "secret_base.h"
#include "constants/map_types.h"
+#include "constants/trainers.h"
extern void mapldr_default(void);
@@ -1143,7 +1144,7 @@ const u8 *GetSecretBaseTrainerLoseText(void)
void sub_80EA2E4(void)
{
sub_813BADC(TRUE);
- gTrainerBattleOpponent_A = 0x400;
+ gTrainerBattleOpponent_A = TRAINER_SECRET_BASE;
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_SECRET_BASE;
}
diff --git a/src/start_menu.c b/src/start_menu.c
index dcb2c4154..aaa9fec2c 100644
--- a/src/start_menu.c
+++ b/src/start_menu.c
@@ -383,14 +383,14 @@ static void ShowSafariBallsWindow(void)
static void ShowPyramidFloorWindow(void)
{
- if (gSaveBlock2Ptr->frontier.field_CB2 == 7)
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum == 7)
sBattlePyramidFloorWindowId = AddWindow(&sPyramidFloorWindowTemplate_1);
else
sBattlePyramidFloorWindowId = AddWindow(&sPyramidFloorWindowTemplate_2);
PutWindowTilemap(sBattlePyramidFloorWindowId);
NewMenuHelpers_DrawStdWindowFrame(sBattlePyramidFloorWindowId, FALSE);
- StringCopy(gStringVar1, sPyramindFloorNames[gSaveBlock2Ptr->frontier.field_CB2]);
+ StringCopy(gStringVar1, sPyramindFloorNames[gSaveBlock2Ptr->frontier.curChallengeBattleNum]);
StringExpandPlaceholders(gStringVar4, gText_BattlePyramidFloor);
AddTextPrinterParameterized(sBattlePyramidFloorWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL);
CopyWindowToVram(sBattlePyramidFloorWindowId, 2);
diff --git a/src/tv.c b/src/tv.c
index fb309f6e3..897f9950b 100644
--- a/src/tv.c
+++ b/src/tv.c
@@ -1544,7 +1544,7 @@ static void InterviewAfter_BravoTrainerBattleTowerProfile(void)
StringCopy(show->bravoTrainerTower.pokemonName, gSaveBlock2Ptr->frontier.field_BD8);
show->bravoTrainerTower.species = gSaveBlock2Ptr->frontier.field_BD4;
show->bravoTrainerTower.defeatedSpecies = gSaveBlock2Ptr->frontier.field_BD6;
- show->bravoTrainerTower.numFights = sub_8164FCC(gSaveBlock2Ptr->frontier.field_D07, 0);
+ show->bravoTrainerTower.numFights = GetCurrentBattleTowerWinStreak(gSaveBlock2Ptr->frontier.field_D07, 0);
show->bravoTrainerTower.wonTheChallenge = gSaveBlock2Ptr->frontier.field_D06;
if (gSaveBlock2Ptr->frontier.field_D07 == 0)
{
@@ -2540,8 +2540,8 @@ void sub_80EE8C8(u16 winStreak, u8 facility)
show->frontier.species2 = GetMonData(&gPlayerParty[1], MON_DATA_SPECIES, NULL);
break;
case 4:
- show->frontier.species1 = GetMonData(&gSaveBlock1Ptr->playerParty[gSaveBlock2Ptr->frontier.field_CAA[0] - 1], MON_DATA_SPECIES, NULL);
- show->frontier.species2 = GetMonData(&gSaveBlock1Ptr->playerParty[gSaveBlock2Ptr->frontier.field_CAA[1] - 1], MON_DATA_SPECIES, NULL);
+ show->frontier.species1 = GetMonData(&gSaveBlock1Ptr->playerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[0] - 1], MON_DATA_SPECIES, NULL);
+ show->frontier.species2 = GetMonData(&gSaveBlock1Ptr->playerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[1] - 1], MON_DATA_SPECIES, NULL);
break;
}
tv_store_id_3x(show);
diff --git a/src/wild_encounter.c b/src/wild_encounter.c
index 9a22323ff..ec69ad2b5 100644
--- a/src/wild_encounter.c
+++ b/src/wild_encounter.c
@@ -5102,7 +5102,7 @@ bool8 StandardWildEncounter(u16 currMetaTileBehavior, u16 previousMetaTileBehavi
}
if (gMapHeader.mapLayoutId == 0x169)
{
- headerId = gSaveBlock2Ptr->frontier.field_CB2;
+ headerId = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
if (previousMetaTileBehavior != currMetaTileBehavior && !DoGlobalWildEncounterDiceRoll())
return FALSE;
else if (DoWildEncounterRateTest(gBattlePyramidWildMonHeaders[headerId].landMonsInfo->encounterRate, FALSE) != TRUE)
@@ -5240,7 +5240,7 @@ bool8 SweetScentWildEncounter(void)
}
if (gMapHeader.mapLayoutId == 0x169)
{
- headerId = gSaveBlock2Ptr->frontier.field_CB2;
+ headerId = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
if (TryGenerateWildMon(gBattlePyramidWildMonHeaders[headerId].landMonsInfo, WILD_AREA_LAND, 0) != TRUE)
return FALSE;