summaryrefslogtreecommitdiff
path: root/src/battle_tower.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/battle_tower.c')
-rw-r--r--src/battle_tower.c977
1 files changed, 971 insertions, 6 deletions
diff --git a/src/battle_tower.c b/src/battle_tower.c
index a6983897f..b9451aecd 100644
--- a/src/battle_tower.c
+++ b/src/battle_tower.c
@@ -1,27 +1,55 @@
#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 "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 "constants/battle_frontier.h"
+#include "constants/trainers.h"
+#include "constants/event_objects.h"
+#include "constants/moves.h"
extern void sub_81A3ACC(void);
+extern void CreateFrontierBrainPokemon(void);
+extern void sub_81A6CD0(void);
extern u8 GetFrontierEnemyMonLevel(u8);
+extern u8 GetFacilityEnemyMonLevel(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 u32 gUnknown_085DF9AC[][2];
extern const u32 gUnknown_085DF9CC[][2];
extern void (* const gUnknown_085DF96C[])(void);
extern const u8 gUnknown_085DF9F6[];
extern const u8 gUnknown_085DF9EC[];
+extern const u16 gBattleFrontierHeldItems[];
// This file's functions.
void sub_8164ED8(void);
void sub_8163E90(void);
void sub_8165B20(void);
+void sub_8165E18(void);
u16 GetCurrentBattleTowerWinStreak(u8 lvlMode, u8 battleMode);
void sub_816534C(void *);
+u16 sub_8162548(u8, u8);
+void sub_81630C4(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);
// code
void sub_8161F74(void)
@@ -35,7 +63,7 @@ void sub_8161F94(void)
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();
@@ -94,15 +122,15 @@ void sub_81620F4(void)
void sub_81621C0(void)
{
- if (gTrainerBattleOpponent_A == 500)
- sub_816534C(&gSaveBlock2Ptr->frontier.filler_BEC);
+ if (gTrainerBattleOpponent_A == BATTLE_TOWER_EREADER_TRAINER_ID)
+ sub_816534C(&gSaveBlock2Ptr->frontier.ereaderTrainer);
if (gSaveBlock2Ptr->frontier.field_D04 < 9999)
gSaveBlock2Ptr->frontier.field_D04++;
- gSaveBlock2Ptr->frontier.field_CB2++;
+ gSaveBlock2Ptr->frontier.curChallengeBattleNum++;
sub_8163E90();
- gSpecialVar_Result = gSaveBlock2Ptr->frontier.field_CB2;
+ gSpecialVar_Result = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
}
bool8 ChooseSpecialBattleTowerTrainer(void)
@@ -172,3 +200,940 @@ bool8 ChooseSpecialBattleTowerTrainer(void)
return FALSE;
}
}
+
+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;
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+
+ 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];
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1);
+ }
+ else if (ChooseSpecialBattleTowerTrainer())
+ {
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ gSaveBlock2Ptr->frontier.battledTrainerIds[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.battledTrainerIds[i] == id)
+ break;
+ }
+ if (i == gSaveBlock2Ptr->frontier.curChallengeBattleNum)
+ break;
+ }
+
+ gTrainerBattleOpponent_A = id;
+ SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < 7)
+ gSaveBlock2Ptr->frontier.battledTrainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
+ }
+ }
+}
+
+extern const u16 gUnknown_085DFA1A[][2];
+extern const u16 gUnknown_085DF9FA[][2];
+
+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
+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
+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;
+
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+ if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ SetFrontierBrainTrainerGfxId();
+ return;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].facilityClass;
+ }
+ else
+ {
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].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(BATTLE_TOWER_EREADER_TRAINER_ID, 0);
+}
+
+u8 GetBattleFacilityTrainerGfxId(u16 trainerId)
+{
+ u32 i;
+ u8 facilityClass;
+ u8 trainerObjectGfxId;
+
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+ if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].facilityClass;
+ }
+ else
+ {
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].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(union BattleTowerRecord *newRecord)
+{
+ u16 slotValues[6];
+ u16 slotIds[6];
+ s32 i, j, k;
+ s32 slotsCount = 0;
+ struct EmeraldBattleTowerRecord *newRecordEm = &newRecord->emerald;
+
+ // 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.records[i].trainerId[j] != newRecordEm->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.records[i].name[j] != newRecordEm->name[j])
+ break;
+ if (newRecordEm->name[j] == EOS)
+ {
+ k = PLAYER_NAME_LENGTH;
+ break;
+ }
+ }
+ }
+
+ if (k == PLAYER_NAME_LENGTH)
+ break;
+ }
+ if (i < 5)
+ {
+ gSaveBlock2Ptr->frontier.records[i] = *newRecordEm;
+ return;
+ }
+
+ // Find an empty record slot.
+ for (i = 0; i < 5; i++)
+ {
+ if (gSaveBlock2Ptr->frontier.records[i].winStreak == 0)
+ break;
+ }
+ if (i < 5)
+ {
+ gSaveBlock2Ptr->frontier.records[i] = *newRecordEm;
+ return;
+ }
+
+ // Find possible slots to replace the record.
+ slotValues[0] = gSaveBlock2Ptr->frontier.records[0].winStreak;
+ slotIds[0] = 0;
+ slotsCount++;
+
+ for (i = 1; i < 5; i++)
+ {
+ for (j = 0; j < slotsCount; j++)
+ {
+ if (gSaveBlock2Ptr->frontier.records[i].winStreak < slotValues[j])
+ {
+ j = 0;
+ slotsCount = 1;
+ slotValues[0] = gSaveBlock2Ptr->frontier.records[i].winStreak;
+ slotIds[0] = i;
+ break;
+ }
+ else if (gSaveBlock2Ptr->frontier.records[i].winStreak > slotValues[j])
+ {
+ break;
+ }
+ }
+
+ if (j == slotsCount)
+ {
+ slotValues[slotsCount] = gSaveBlock2Ptr->frontier.records[i].winStreak;
+ slotIds[slotsCount] = i;
+ slotsCount++;
+ }
+ }
+
+ i = Random() % slotsCount;
+ gSaveBlock2Ptr->frontier.records[slotIds[i]] = *newRecordEm;
+}
+
+u8 GetFrontierTrainerFrontSpriteId(u16 trainerId)
+{
+ GetFacilityEnemyMonLevel(); // Pointless function call
+
+ if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ return GetFrontierBrainTrainerPicIndex();
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ return gFacilityClassToPicIndex[gFacilityTrainers[trainerId].facilityClass];
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ return gFacilityClassToPicIndex[sub_818649C()];
+ else
+ return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].facilityClass];
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ return gFacilityClassToPicIndex[gApprentices[sub_81864A8()].facilityClass];
+ else
+ return gFacilityClassToPicIndex[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].id].facilityClass];
+ }
+}
+
+u8 GetFrontierOpponentClass(u16 trainerId)
+{
+ u8 trainerClass = 0;
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+
+ if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ 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 < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ trainerClass = gFacilityClassToTrainerClass[gFacilityTrainers[trainerId].facilityClass];
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ trainerClass = gFacilityClassToTrainerClass[sub_818649C()];
+ }
+ else
+ {
+ trainerClass = gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].facilityClass];
+ asm("");
+ }
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ trainerClass = gFacilityClassToTrainerClass[gApprentices[sub_81864A8()].facilityClass];
+ }
+ else
+ {
+ trainerClass = gFacilityClassToTrainerClass[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].id].facilityClass];
+ asm("");
+ }
+ }
+
+ return trainerClass;
+}
+
+u8 GetFrontierTrainerFacilityClass(u16 trainerId)
+{
+ u8 facilityClass;
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+
+ if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ facilityClass = sub_818649C();
+ else
+ facilityClass = gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].facilityClass;
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ facilityClass = gApprentices[sub_81864A8()].facilityClass;
+ else
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].id].facilityClass;
+ }
+
+ return facilityClass;
+}
+
+void GetFrontierTrainerName(u8 *dst, u16 trainerId)
+{
+ s32 i = 0;
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+
+ if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ 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 < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ for (i = 0; i < PLAYER_NAME_LENGTH; i++)
+ dst[i] = gFacilityTrainers[trainerId].trainerName[i];
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ {
+ sub_8186468(dst);
+ return;
+ }
+ else
+ {
+ struct EmeraldBattleTowerRecord *record = &gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID];
+ 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 - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID];
+ id = apprentice->id;
+ language = apprentice->language;
+ }
+ TVShowConvertInternationalString(dst, GetApprenticeNameInLanguage(id, language), language);
+ return;
+ }
+
+ dst[i] = EOS;
+}
+
+bool8 IsFrontierTrainerFemale(u16 trainerId)
+{
+ u32 i;
+ u8 facilityClass;
+
+ GetFacilityEnemyMonLevel(); // Pointless function call.
+ if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
+ }
+ else if (trainerId == TRAINER_FRONTIER_BRAIN)
+ {
+ return IsFrontierBrainFemale();
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ facilityClass = gFacilityTrainers[trainerId].facilityClass;
+ }
+ else if (trainerId < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ facilityClass = gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].facilityClass;
+ }
+ else
+ {
+ facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID].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 sub_8163048(u8 monsCount)
+{
+ ZeroEnemyPartyMons();
+ sub_81630C4(gTrainerBattleOpponent_A, 0, monsCount);
+}
+
+void sub_816306C(u8 monsCount)
+{
+ ZeroEnemyPartyMons();
+ sub_81630C4(gTrainerBattleOpponent_A, 0, monsCount);
+ sub_81630C4(gTrainerBattleOpponent_B, 3, monsCount);
+}
+
+void sub_81630A0(u8 monsCount)
+{
+ ZeroEnemyPartyMons();
+ sub_8165EA4(gTrainerBattleOpponent_A, 0, monsCount);
+}
+
+void sub_81630C4(u16 trainerId, u8 firstMonId, u8 monCount)
+{
+ s32 i, j;
+ u16 chosenMonIndices[4];
+ u8 friendship = 0xFF;
+ u8 level = GetFacilityEnemyMonLevel();
+ u8 fixedIV = 0;
+ u8 bfMonCount;
+ const u16 *bfMonPool = NULL;
+ u32 otID = 0;
+
+ if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ // Normal battle frontier trainer.
+ fixedIV = GetFrontierTrainerFixedIvs(trainerId);
+ bfMonPool = gFacilityTrainers[gTrainerBattleOpponent_A].bfMonPool;
+ }
+ else if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ 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 < BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID)
+ {
+ // Record mixed player.
+ for (j = 0, i = firstMonId; i < firstMonId + monCount; j++, i++)
+ {
+ if (gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].party[j].species != 0
+ && gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].party[j].level <= level)
+ {
+ sub_8068338(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.records[trainerId - BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID].party[j], FALSE);
+ }
+ }
+ return;
+ }
+ else
+ {
+ // Apprentice.
+ for (i = firstMonId; i < firstMonId + 3; i++)
+ CreateApprenticeMon(&gEnemyParty[i], &gSaveBlock2Ptr->apprentices[trainerId - BATTLE_TOWER_RECORD_APPRENTICE_BASE_ID], 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.
+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->monData[i].species, level, fixedIV, 8);
+ friendship = 0xFF;
+ for (j = 0; j < 4; j++)
+ {
+ if (apprentice->monData[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);
+ }
+}
+
+u16 RandomizeFacilityTrainerMonId(u16 trainerId)
+{
+ u32 monPoolId;
+ u8 level = GetFacilityEnemyMonLevel();
+ const u16 *bfMonPool = gFacilityTrainers[trainerId].bfMonPool;
+ u8 bfMonCount = 0;
+
+ /*
+ I had to use ugly C tricks to get this part to match.
+ A cleaner version would look like this
+
+ for (bfMonCount = 0; bfMonPool[bfMonCount] != 0xFFFF; bfMonCount++)
+ ;
+
+ */
+
+ monPoolId = bfMonPool[bfMonCount];
+ goto COMPARE;
+ while (1)
+ {
+ bfMonCount++;
+ monPoolId = bfMonPool[bfMonCount];
+ COMPARE:
+ if (monPoolId == 0xFFFF)
+ break;
+ }
+
+ do
+ {
+ monPoolId = bfMonPool[Random() % bfMonCount];
+ } while((level == 50 || level == 20) && monPoolId > 849);
+
+ return monPoolId;
+}
+
+void sub_8163590(void)
+{
+ ZeroEnemyPartyMons();
+ if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
+ sub_81635D4(gTrainerBattleOpponent_A, 0);
+ else
+ sub_816379C(gTrainerBattleOpponent_A, 0);
+}
+
+extern u16 gUnknown_03006298[];
+
+void sub_81635D4(u16 trainerId, u8 firstMonId)
+{
+ u8 i, j;
+ u8 friendship;
+ u8 level;
+ u8 fixedIV;
+ u32 otID;
+
+ if (trainerId < BATTLE_TOWER_RECORD_MIXING_TRAINER_BASE_ID)
+ {
+ u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode; // Unused variable.
+ u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
+ u8 r1 = gSaveBlock2Ptr->frontier.field_CE0[battleMode][0] / 7;
+ if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < 6)
+ fixedIV = sub_81A6CA8(r1, 0);
+ else
+ fixedIV = sub_81A6CA8(r1, 1);
+ }
+ else if (trainerId == BATTLE_TOWER_EREADER_TRAINER_ID)
+ {
+ 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 = GetFacilityEnemyMonLevel();
+ 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]);
+ }
+}
+
+void sub_816379C(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 ConvertBattleFrontierTrainerSpeechToString(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;
+ }
+}