summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_setup.c11
-rw-r--r--src/battle_tower.c853
-rw-r--r--src/record_mixing.c21
3 files changed, 800 insertions, 85 deletions
diff --git a/src/battle_setup.c b/src/battle_setup.c
index b5ae0d6ea..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.battledTrainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum * 2 + 0]
- + gSaveBlock2Ptr->frontier.battledTrainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum * 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_tower.c b/src/battle_tower.c
index 75253792e..25a46d073 100644
--- a/src/battle_tower.c
+++ b/src/battle_tower.c
@@ -18,6 +18,10 @@
#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"
@@ -44,21 +48,23 @@ extern const u8 gUnknown_085DF9EC[];
extern const u16 gBattleFrontierHeldItems[];
// This file's functions.
-void sub_8164ED8(void);
+void ValidateBattleTowerRecordChecksums(void);
void SaveCurrentWinStreak(void);
void sub_8165B20(void);
void sub_8165E18(void);
-void sub_816537C(void);
-void sub_8164FB8(struct EmeraldBattleTowerRecord *record);
+void CopyEReaderTrainerFarewellMessage(void);
+void ClearBattleTowerRecord(struct EmeraldBattleTowerRecord *record);
u16 GetCurrentBattleTowerWinStreak(u8 lvlMode, u8 battleMode);
-void sub_816534C(void *);
u16 sub_8162548(u8, u8);
-void sub_81630C4(u16 trainerId, u8 firstMonId, u8 monCount);
+static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount);
void sub_8165EA4(u16 trainerId, u8 firstMonId, u8 monCount);
void sub_81635D4(u16 trainerId, u8 firstMonId);
void sub_816379C(u16 trainerId, u8 firstMonId);
u8 GetFrontierTrainerFixedIvs(u16 trainerId);
void sub_8165404(u16 trainerId);
+void sub_8165B88(u8 *dst, u16 trainerId);
+void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer);
+void ClearEReaderTrainer(struct BattleTowerEReaderTrainer *ereaderTrainer);
// code
void sub_8161F74(void)
@@ -77,9 +83,9 @@ void sub_8161F94(void)
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;
}
@@ -115,7 +121,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)
@@ -132,7 +138,7 @@ void sub_81620F4(void)
void sub_81621C0(void)
{
if (gTrainerBattleOpponent_A == BATTLE_TOWER_EREADER_TRAINER_ID)
- sub_816534C(&gSaveBlock2Ptr->frontier.ereaderTrainer);
+ ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer);
if (gSaveBlock2Ptr->frontier.field_D04 < 9999)
gSaveBlock2Ptr->frontier.field_D04++;
@@ -227,15 +233,15 @@ void ChooseNextBattleTowerTrainer(void)
if (battleMode == FRONTIER_MODE_MULTIS || battleMode == FRONTIER_MODE_LINK_MULTIS)
{
id = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
- gTrainerBattleOpponent_A = gSaveBlock2Ptr->frontier.battledTrainerIds[id * 2];
- gTrainerBattleOpponent_B = gSaveBlock2Ptr->frontier.battledTrainerIds[id * 2 + 1];
+ 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.battledTrainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
+ gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
}
else
{
@@ -247,7 +253,7 @@ void ChooseNextBattleTowerTrainer(void)
// Ensure trainer wasn't previously fought in this challenge.
for (i = 0; i < gSaveBlock2Ptr->frontier.curChallengeBattleNum; i++)
{
- if (gSaveBlock2Ptr->frontier.battledTrainerIds[i] == id)
+ if (gSaveBlock2Ptr->frontier.field_CB4[i] == id)
break;
}
if (i == gSaveBlock2Ptr->frontier.curChallengeBattleNum)
@@ -257,7 +263,7 @@ void ChooseNextBattleTowerTrainer(void)
gTrainerBattleOpponent_A = id;
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < 7)
- gSaveBlock2Ptr->frontier.battledTrainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
+ gSaveBlock2Ptr->frontier.field_CB4[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
}
}
}
@@ -522,13 +528,13 @@ u8 GetBattleFacilityTrainerGfxId(u16 trainerId)
}
}
-void PutNewBattleTowerRecord(union BattleTowerRecord *newRecord)
+void PutNewBattleTowerRecord(struct EmeraldBattleTowerRecord *newRecordEm)
{
u16 slotValues[6];
u16 slotIds[6];
s32 i, j, k;
s32 slotsCount = 0;
- struct EmeraldBattleTowerRecord *newRecordEm = &newRecord->emerald;
+ struct EmeraldBattleTowerRecord *newRecord = newRecordEm; // Needed to match.
// Find a record slot of the same player and replace it.
for (i = 0; i < 5; i++)
@@ -536,7 +542,7 @@ void PutNewBattleTowerRecord(union BattleTowerRecord *newRecord)
k = 0;
for (j = 0; j < 4; j++)
{
- if (gSaveBlock2Ptr->frontier.towerRecords[i].trainerId[j] != newRecordEm->trainerId[j])
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].trainerId[j] != newRecord->trainerId[j])
break;
}
if (j == 4)
@@ -544,9 +550,9 @@ void PutNewBattleTowerRecord(union BattleTowerRecord *newRecord)
for (k = 0; k < PLAYER_NAME_LENGTH; k++)
{
// BUG: Wrong variable used, 'j' instead of 'k'.
- if (gSaveBlock2Ptr->frontier.towerRecords[i].name[j] != newRecordEm->name[j])
+ if (gSaveBlock2Ptr->frontier.towerRecords[i].name[j] != newRecord->name[j])
break;
- if (newRecordEm->name[j] == EOS)
+ if (newRecord->name[j] == EOS)
{
k = PLAYER_NAME_LENGTH;
break;
@@ -559,7 +565,7 @@ void PutNewBattleTowerRecord(union BattleTowerRecord *newRecord)
}
if (i < 5)
{
- gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecordEm;
+ gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecord;
return;
}
@@ -571,7 +577,7 @@ void PutNewBattleTowerRecord(union BattleTowerRecord *newRecord)
}
if (i < 5)
{
- gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecordEm;
+ gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecord;
return;
}
@@ -607,7 +613,7 @@ void PutNewBattleTowerRecord(union BattleTowerRecord *newRecord)
}
i = Random() % slotsCount;
- gSaveBlock2Ptr->frontier.towerRecords[slotIds[i]] = *newRecordEm;
+ gSaveBlock2Ptr->frontier.towerRecords[slotIds[i]] = *newRecord;
}
u8 GetFrontierTrainerFrontSpriteId(u16 trainerId)
@@ -822,17 +828,17 @@ bool8 IsFrontierTrainerFemale(u16 trainerId)
return FALSE;
}
-void sub_8163048(u8 monsCount)
+void FillFrontierTrainerParty(u8 monsCount)
{
ZeroEnemyPartyMons();
- sub_81630C4(gTrainerBattleOpponent_A, 0, monsCount);
+ FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount);
}
-void sub_816306C(u8 monsCount)
+void FillFrontierTrainersParties(u8 monsCount)
{
ZeroEnemyPartyMons();
- sub_81630C4(gTrainerBattleOpponent_A, 0, monsCount);
- sub_81630C4(gTrainerBattleOpponent_B, 3, monsCount);
+ FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount);
+ FillTrainerParty(gTrainerBattleOpponent_B, 3, monsCount);
}
void sub_81630A0(u8 monsCount)
@@ -841,7 +847,7 @@ void sub_81630A0(u8 monsCount)
sub_8165EA4(gTrainerBattleOpponent_A, 0, monsCount);
}
-void sub_81630C4(u16 trainerId, u8 firstMonId, u8 monCount)
+static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount)
{
s32 i, j;
u16 chosenMonIndices[4];
@@ -983,15 +989,15 @@ void Unused_CreateApprenticeMons(u16 trainerId, u8 firstMonId)
for (i = 0; i != 3; i++)
{
- CreateMonWithEVSpread(&gEnemyParty[firstMonId + i], apprentice->monData[i].species, level, fixedIV, 8);
+ CreateMonWithEVSpread(&gEnemyParty[firstMonId + i], apprentice->party[i].species, level, fixedIV, 8);
friendship = 0xFF;
for (j = 0; j < 4; j++)
{
- if (apprentice->monData[i].moves[j] == MOVE_FRUSTRATION)
+ 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->monData[i].item);
+ SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_HELD_ITEM, &apprentice->party[i].item);
}
}
@@ -1053,7 +1059,7 @@ void sub_81635D4(u16 trainerId, u8 firstMonId)
{
u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode; // Unused variable.
u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
- u8 challengeNum = gSaveBlock2Ptr->frontier.field_CE0[battleMode][0] / 7;
+ u8 challengeNum = gSaveBlock2Ptr->frontier.winStreaks[battleMode][0] / 7;
if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < 6)
fixedIV = sub_81A6CA8(challengeNum, 0);
else
@@ -1201,7 +1207,7 @@ static void HandleSpecialTrainerBattleEnd(void)
}
break;
case SPECIAL_BATTLE_EREADER:
- sub_816537C();
+ CopyEReaderTrainerFarewellMessage();
break;
}
@@ -1233,21 +1239,21 @@ void DoSpecialTrainerBattle(void)
switch (VarGet(VAR_FRONTIER_BATTLE_MODE))
{
case FRONTIER_MODE_SINGLES:
- sub_8163048(3);
+ FillFrontierTrainerParty(3);
break;
case FRONTIER_MODE_DOUBLES:
- sub_8163048(4);
+ FillFrontierTrainerParty(4);
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
break;
case FRONTIER_MODE_MULTIS:
- sub_816306C(2);
- gPartnerTrainerId = gSaveBlock2Ptr->frontier.field_CD6;
+ FillFrontierTrainersParties(2);
+ gPartnerTrainerId = gSaveBlock2Ptr->frontier.field_CB4[17];
sub_8165404(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;
- sub_816306C(2);
+ FillFrontierTrainersParties(2);
break;
}
CreateTask(Task_StartBattleAfterTransition, 1);
@@ -1279,7 +1285,7 @@ void DoSpecialTrainerBattle(void)
if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
if (gTrainerBattleOpponent_A == TRAINER_FRONTIER_BRAIN)
- sub_8163048(2);
+ FillFrontierTrainerParty(2);
CreateTask(Task_StartBattleAfterTransition, 1);
sub_806E694(0);
BattleTransition_StartOnField(sub_80B100C(3));
@@ -1289,7 +1295,7 @@ void DoSpecialTrainerBattle(void)
if (VarGet(VAR_FRONTIER_BATTLE_MODE) == FRONTIER_MODE_DOUBLES)
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
- sub_8163048(3);
+ FillFrontierTrainerParty(3);
else
sub_81630A0(3);
CreateTask(Task_StartBattleAfterTransition, 1);
@@ -1299,7 +1305,7 @@ void DoSpecialTrainerBattle(void)
case SPECIAL_BATTLE_ARENA:
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_ARENA;
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
- sub_8163048(3);
+ FillFrontierTrainerParty(3);
else
sub_81630A0(3);
CreateTask(Task_StartBattleAfterTransition, 1);
@@ -1317,21 +1323,21 @@ void DoSpecialTrainerBattle(void)
break;
case SPECIAL_BATTLE_PIKE_SINGLE:
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER;
- sub_8163048(3);
+ 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;
- sub_8163048(3);
+ 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;
- sub_816306C(1);
+ FillFrontierTrainersParties(1);
CreateTask(Task_StartBattleAfterTransition, 1);
PlayMapChosenOrBattleBGM(0);
BattleTransition_StartOnField(sub_80B100C(7));
@@ -1357,8 +1363,8 @@ void SaveCurrentWinStreak(void)
u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
u16 winStreak = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
- if (gSaveBlock2Ptr->frontier.field_CE0[battleMode][lvlMode] < winStreak)
- gSaveBlock2Ptr->frontier.field_CE0[battleMode][lvlMode] = winStreak;
+ if (gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] < winStreak)
+ gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] = winStreak;
}
void sub_8163EE4(void)
@@ -1367,7 +1373,7 @@ void sub_8163EE4(void)
u8 lvlMode, battleMode, class;
struct EmeraldBattleTowerRecord *playerRecord = &gSaveBlock2Ptr->frontier.towerPlayer;
- sub_8164FB8(playerRecord);
+ ClearBattleTowerRecord(playerRecord);
lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
if (gSaveBlock2Ptr->playerGender != MALE)
@@ -1399,8 +1405,8 @@ void sub_8163EE4(void)
for (i = 0; i < 4; i++)
{
- if (gSaveBlock2Ptr->frontier.field_CAA[i] != 0)
- sub_80686FC(&gPlayerParty[gSaveBlock2Ptr->frontier.field_CAA[i] - 1], &playerRecord->party[i]);
+ if (gSaveBlock2Ptr->frontier.selectedPartyMons[i] != 0)
+ sub_80686FC(&gPlayerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1], &playerRecord->party[i]);
}
playerRecord->language = gGameLanguage;
@@ -1412,7 +1418,7 @@ void SaveBattleTowerProgress(void)
{
u16 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
u16 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
- s32 challengeNum = (signed)(gSaveBlock2Ptr->frontier.field_CE0[battleMode][lvlMode] / 7);
+ s32 challengeNum = (signed)(gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] / 7);
if (gSpecialVar_0x8005 == 0 && (challengeNum > 1 || gSaveBlock2Ptr->frontier.curChallengeBattleNum != 0))
sub_8163EE4();
@@ -1443,7 +1449,7 @@ void sub_81640E0(u16 trainerId)
count = 0;
for (i = 0; i < 3; i++)
{
- u16 apprenticeSpecies = gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].monData[i].species;
+ u16 apprenticeSpecies = gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].party[i].species;
if (apprenticeSpecies != species1 && apprenticeSpecies != species2)
{
validSpecies[count] = i;
@@ -1502,43 +1508,45 @@ void sub_81642A0(void)
eventObjTemplates = gSaveBlock1Ptr->eventObjectTemplates;
lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
- challengeNum = gSaveBlock2Ptr->frontier.field_CE0[battleMode][lvlMode] / 7;
+ challengeNum = gSaveBlock2Ptr->frontier.winStreaks[battleMode][lvlMode] / 7;
species1 = GetMonData(&gPlayerParty[0], MON_DATA_SPECIES, NULL);
species2 = GetMonData(&gPlayerParty[1], MON_DATA_SPECIES, NULL);
level = GetFacilityEnemyMonLevel();
- for (j = 0; j < 6; j++)
+ j = 0;
+ do
{
do
{
trainerId = sub_8162548(challengeNum, 0);
for (i = 0; i < j; i++)
{
- if (gSaveBlock2Ptr->frontier.battledTrainerIds[i] == trainerId)
+ if (gSaveBlock2Ptr->frontier.field_CB4[i] == trainerId)
break;
- if (gFacilityTrainers[gSaveBlock2Ptr->frontier.battledTrainerIds[i]].facilityClass == gFacilityTrainers[trainerId].facilityClass)
+ if (gFacilityTrainers[gSaveBlock2Ptr->frontier.field_CB4[i]].facilityClass == gFacilityTrainers[trainerId].facilityClass)
break;
}
} while (i != j);
- gSaveBlock2Ptr->frontier.battledTrainerIds[j] = trainerId;
- }
+ gSaveBlock2Ptr->frontier.field_CB4[j] = trainerId;
+ j++;
+ } while (j < 6);
r10 = 8;
for (i = 0; i < 6; i++)
{
- trainerId = gSaveBlock2Ptr->frontier.battledTrainerIds[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.battledTrainerIds[r10 - 1]].itemTableId == gFacilityTrainerMons[monPoolId].itemTableId)
+ 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.battledTrainerIds[k]].species == gFacilityTrainerMons[monPoolId].species)
+ if (gFacilityTrainerMons[gSaveBlock2Ptr->frontier.field_CB4[k]].species == gFacilityTrainerMons[monPoolId].species)
break;
if (species1 == gFacilityTrainerMons[monPoolId].species)
break;
@@ -1549,7 +1557,7 @@ void sub_81642A0(void)
break;
}
- gSaveBlock2Ptr->frontier.battledTrainerIds[r10] = monPoolId;
+ gSaveBlock2Ptr->frontier.field_CB4[r10] = monPoolId;
r10++;
}
}
@@ -1565,8 +1573,8 @@ void sub_81642A0(void)
k = 0;
for (j = 0; j < 3; j++)
{
- if (species1 != gSaveBlock2Ptr->apprentices[i].monData[j].species
- && species2 != gSaveBlock2Ptr->apprentices[i].monData[j].species)
+ if (species1 != gSaveBlock2Ptr->apprentices[i].party[j].species
+ && species2 != gSaveBlock2Ptr->apprentices[i].party[j].species)
{
k++;
}
@@ -1580,10 +1588,10 @@ void sub_81642A0(void)
}
if (r10 != 0)
{
- gSaveBlock2Ptr->frontier.battledTrainerIds[6] = spArray[Random() % r10];
- eventObjTemplates[7].graphicsId = GetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.battledTrainerIds[6]);
+ 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.battledTrainerIds[6]);
+ sub_81640E0(gSaveBlock2Ptr->frontier.field_CB4[6]);
}
r10 = 0;
@@ -1623,9 +1631,716 @@ void sub_81642A0(void)
}
if (r10 != 0)
{
- gSaveBlock2Ptr->frontier.battledTrainerIds[7] = spArray[Random() % r10];
- eventObjTemplates[8].graphicsId = GetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.battledTrainerIds[7]);
+ 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.battledTrainerIds[7]);
+ sub_8164188(gSaveBlock2Ptr->frontier.field_CB4[7]);
+ }
+}
+
+void sub_81646BC(u16 trainerId, u16 monPoolId)
+{
+ u16 move = 0;
+ u16 species = 0;
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+
+ if (trainerId != BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ move = gFacilityTrainerMons[monPoolId].moves[0];
+ species = gFacilityTrainerMons[monPoolId].species;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ move = gSaveBlock2Ptr->frontier.towerRecords[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].party[gUnknown_03006298[gSpecialVar_0x8005 + 1]].moves[0];
+ species = gSaveBlock2Ptr->frontier.towerRecords[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].party[gUnknown_03006298[gSpecialVar_0x8005 + 1]].species;
+ }
+ else
+ {
+ s32 i;
+
+ move = gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].party[gUnknown_03006298[gSpecialVar_0x8005 - 1]].moves[0];
+ species = gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].party[gUnknown_03006298[gSpecialVar_0x8005 - 1]].species;
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ gStringVar3[i] = gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].playerName[i];
+ gStringVar3[i] = EOS;
+ ConvertInternationalString(gStringVar3, gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].language);
+ }
+ }
+
+ StringCopy(gStringVar1, gMoveNames[move]);
+ StringCopy(gStringVar2, gSpeciesNames[species]);
+}
+
+struct
+{
+ u32 facilityClass;
+ const u8 *const *strings;
+} extern const gUnknown_085DD500[50];
+
+extern const u8 *const *const gUnknown_085DD690[];
+extern const u8 gUnknown_085DFA42[4];
+
+void sub_8164828(void)
+{
+ s32 i, j, arrId;
+ s32 monPoolId;
+ s32 level = GetFacilityEnemyMonLevel(); // Unused variable.
+ 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 == BATTLE_TOWER_EREADER_TRAINER_ID)
+ return;
+ if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ GetFrontierTrainerName(gStringVar1, trainerId);
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ GetFrontierTrainerName(gStringVar1, trainerId);
+ }
+ else
+ {
+ s32 i;
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ gStringVar1[i] = gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].playerName[i];
+ gStringVar1[i] = EOS;
+ ConvertInternationalString(gStringVar1, gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].language);
+ ConvertIntToDecimalStringN(gStringVar2, gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].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 < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ 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 < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ 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 == BATTLE_TOWER_EREADER_TRAINER_ID)
+ return;
+
+ if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ ShowFieldMessage(gUnknown_085DD500[arrId].strings[gSpecialVar_0x8005]);
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ ShowFieldMessage(gUnknown_085DD500[arrId].strings[gSpecialVar_0x8005]);
+ }
+ else
+ {
+ u8 id = gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].id;
+ ShowFieldMessage(gUnknown_085DD690[id][gSpecialVar_0x8005]);
+ }
+}
+
+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;
+ }
+}
+
+void sub_8164DCC(void)
+{
+ if (gWirelessCommType != 0)
+ sub_800AC34();
+}
+
+void sub_8164DE4(void)
+{
+ SetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.field_CB4[17], 0xF);
+}
+
+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);
+ sub_8165B88(&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;
+}
+
+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];
+}
+
+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;
+}
+
+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;
+};
+
+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.
+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 *trainerName)
+{
+ s32 i;
+
+ for (i = 0; i < 5; i++)
+ trainerName[i] = gSaveBlock2Ptr->frontier.ereaderTrainer.name[i];
+
+ trainerName[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;
+ }
+}
+
+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);
+}
+
+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);
+ }
+}
+
+struct StevenMon
+{
+ u16 species;
+ u8 fixedIV;
+ u8 level;
+ u8 nature;
+ u8 evs[6];
+ u16 moves[4];
+};
+
+extern const struct StevenMon sStevenMons[3];
+
+#define STEVEN_OTID 61226
+
+void sub_8165404(u16 trainerId)
+{
+ s32 i, j;
+ u32 ivs, level;
+ u32 friendship;
+ u16 monPoolId;
+ u32 otID;
+ u8 trainerName[PLAYER_NAME_LENGTH + 1];
+ GetFacilityEnemyMonLevel(); // Unused return variable.
+
+ 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 == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ // Scrapped, lol.
+ trainerName[0] = gGameLanguage;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ level = GetFacilityEnemyMonLevel();
+ 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 < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ trainerId -= BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID;
+ 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 + BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_GENDER, &j);
+ }
+ }
+ else
+ {
+ trainerId -= BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID;
+ for (i = 0; i < 2; i++)
+ {
+ CreateApprenticeMon(&gPlayerParty[3 + i], &gSaveBlock2Ptr->apprentices[trainerId], gSaveBlock2Ptr->frontier.field_CB4[18 + i]);
+ j = IsFrontierTrainerFemale(trainerId + BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID);
+ SetMonData(&gPlayerParty[3 + i], MON_DATA_OT_GENDER, &j);
+ }
+ }
+}
+
+extern const u8 sRubyFacilityClassToEmerald[82][2];
+extern const u16 gUnknown_085DFA46[];
+extern const u16 gUnknown_085DFA52[];
+
+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;
}
}
diff --git a/src/record_mixing.c b/src/record_mixing.c
index c9fe3fd47..11c3f2fef 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);
@@ -215,7 +216,7 @@ static void PrepareUnknownExchangePacket(struct PlayerRecordsRS *dest)
sub_81659DC(sBattleTowerSave, &dest->battleTowerRecord);
if (GetMultiplayerId() == 0)
- dest->battleTowerRecord.unk_11c8 = GetRecordMixingGift();
+ dest->giftItem = GetRecordMixingGift();
}
static void PrepareExchangePacketForRubySapphire(struct PlayerRecordsRS *dest)
@@ -234,7 +235,7 @@ static void PrepareExchangePacketForRubySapphire(struct PlayerRecordsRS *dest)
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 ++)
{
@@ -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)
{