2018-08-26 17:54:58 +02:00
|
|
|
#include "global.h"
|
2018-10-21 00:06:42 +02:00
|
|
|
#include "battle_tower.h"
|
|
|
|
#include "apprentice.h"
|
2018-08-26 17:54:58 +02:00
|
|
|
#include "event_data.h"
|
|
|
|
#include "battle_setup.h"
|
|
|
|
#include "overworld.h"
|
|
|
|
#include "random.h"
|
2018-10-21 00:06:42 +02:00
|
|
|
#include "text.h"
|
2018-10-21 20:13:12 +02:00
|
|
|
#include "main.h"
|
2018-10-21 00:06:42 +02:00
|
|
|
#include "international_string_util.h"
|
|
|
|
#include "battle.h"
|
2018-10-30 21:45:26 +01:00
|
|
|
#include "frontier_util.h"
|
2018-12-05 22:21:26 +01:00
|
|
|
#include "strings.h"
|
2018-10-21 00:06:42 +02:00
|
|
|
#include "recorded_battle.h"
|
|
|
|
#include "easy_chat.h"
|
2018-10-21 20:13:12 +02:00
|
|
|
#include "gym_leader_rematch.h"
|
|
|
|
#include "battle_transition.h"
|
|
|
|
#include "trainer_see.h"
|
|
|
|
#include "new_game.h"
|
|
|
|
#include "string_util.h"
|
2019-04-04 23:53:06 +02:00
|
|
|
#include "data.h"
|
2018-10-22 19:22:57 +02:00
|
|
|
#include "link.h"
|
|
|
|
#include "field_message_box.h"
|
|
|
|
#include "tv.h"
|
2018-11-11 16:44:27 +01:00
|
|
|
#include "battle_factory.h"
|
2020-01-08 05:43:06 -05:00
|
|
|
#include "constants/apprentice.h"
|
2020-04-09 15:18:53 -04:00
|
|
|
#include "constants/battle_dome.h"
|
2018-10-20 00:33:51 +02:00
|
|
|
#include "constants/battle_frontier.h"
|
2019-12-27 02:26:27 -08:00
|
|
|
#include "constants/battle_frontier_mons.h"
|
2020-01-08 01:07:53 -05:00
|
|
|
#include "constants/battle_tent_mons.h"
|
|
|
|
#include "constants/battle_tent_trainers.h"
|
2019-11-16 18:11:27 -05:00
|
|
|
#include "constants/battle_tower.h"
|
2019-11-24 16:58:40 -05:00
|
|
|
#include "constants/frontier_util.h"
|
2018-12-05 22:21:26 +01:00
|
|
|
#include "constants/items.h"
|
2018-10-21 00:06:42 +02:00
|
|
|
#include "constants/trainers.h"
|
|
|
|
#include "constants/event_objects.h"
|
|
|
|
#include "constants/moves.h"
|
2018-10-24 23:14:45 +02:00
|
|
|
#include "constants/species.h"
|
2018-12-02 23:22:42 -05:00
|
|
|
#include "constants/easy_chat.h"
|
2019-11-10 21:54:00 -05:00
|
|
|
#include "constants/tv.h"
|
2018-08-26 17:54:58 +02:00
|
|
|
|
2019-11-01 17:50:54 -04:00
|
|
|
extern const u8 MossdeepCity_SpaceCenter_2F_EventScript_MaxieTrainer[];
|
|
|
|
extern const u8 MossdeepCity_SpaceCenter_2F_EventScript_TabithaTrainer[];
|
2018-08-26 17:54:58 +02:00
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
// EWRAM vars.
|
|
|
|
EWRAM_DATA const struct BattleFrontierTrainer *gFacilityTrainers = NULL;
|
|
|
|
EWRAM_DATA const struct FacilityMon *gFacilityTrainerMons = NULL;
|
|
|
|
|
2018-11-19 01:03:14 +01:00
|
|
|
// IWRAM common
|
2019-12-02 08:44:34 -05:00
|
|
|
u16 gUnknown_03006298[MAX_FRONTIER_PARTY_SIZE];
|
2018-11-19 01:03:14 +01:00
|
|
|
|
2018-08-26 17:54:58 +02:00
|
|
|
// This file's functions.
|
2019-11-28 21:09:35 -05:00
|
|
|
static void InitTowerChallenge(void);
|
|
|
|
static void GetTowerData(void);
|
|
|
|
static void SetTowerData(void);
|
2019-11-28 22:46:39 -05:00
|
|
|
static void SetNextFacilityOpponent(void);
|
|
|
|
static void SetTowerBattleWon(void);
|
2018-10-25 21:27:10 +02:00
|
|
|
static void AwardBattleTowerRibbons(void);
|
2019-11-28 21:09:35 -05:00
|
|
|
static void SaveTowerChallenge(void);
|
2019-11-28 22:46:39 -05:00
|
|
|
static void GetOpponentIntroSpeech(void);
|
2018-10-25 21:27:10 +02:00
|
|
|
static void nullsub_61(void);
|
2019-11-16 20:50:52 -05:00
|
|
|
static void nullsub_116(void);
|
2020-01-08 05:43:06 -05:00
|
|
|
static void LoadMultiPartnerCandidatesData(void);
|
|
|
|
static void ShowPartnerCandidateMessage(void);
|
|
|
|
static void LoadLinkMultiOpponentsData(void);
|
2018-10-25 21:27:10 +02:00
|
|
|
static void sub_8164DCC(void);
|
2020-01-08 05:43:06 -05:00
|
|
|
static void SetMultiPartnerGfx(void);
|
2019-11-28 22:46:39 -05:00
|
|
|
static void SetTowerInterviewData(void);
|
2018-10-25 21:27:10 +02:00
|
|
|
static void ValidateBattleTowerRecordChecksums(void);
|
|
|
|
static void SaveCurrentWinStreak(void);
|
|
|
|
static void ValidateApprenticesChecksums(void);
|
2019-11-28 22:46:39 -05:00
|
|
|
static void SetNextBattleTentOpponent(void);
|
2018-10-25 21:27:10 +02:00
|
|
|
static void CopyEReaderTrainerFarewellMessage(void);
|
|
|
|
static void ClearBattleTowerRecord(struct EmeraldBattleTowerRecord *record);
|
2018-10-22 19:22:57 +02:00
|
|
|
static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount);
|
2018-10-25 21:27:10 +02:00
|
|
|
static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount);
|
2018-10-26 23:54:41 +02:00
|
|
|
static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId);
|
|
|
|
static void FillFactoryTentTrainerParty(u16 trainerId, u8 firstMonId);
|
2018-10-25 21:27:10 +02:00
|
|
|
static u8 GetFrontierTrainerFixedIvs(u16 trainerId);
|
|
|
|
static void FillPartnerParty(u16 trainerId);
|
|
|
|
static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer);
|
|
|
|
static u8 SetTentPtrsGetLevel(void);
|
|
|
|
|
|
|
|
// Const rom data.
|
2018-12-05 22:21:26 +01:00
|
|
|
const u16 gBattleFrontierHeldItems[] =
|
2018-12-04 12:09:35 -05:00
|
|
|
{
|
|
|
|
ITEM_NONE,
|
|
|
|
ITEM_KINGS_ROCK,
|
|
|
|
ITEM_SITRUS_BERRY,
|
|
|
|
ITEM_ORAN_BERRY,
|
|
|
|
ITEM_CHESTO_BERRY,
|
|
|
|
ITEM_HARD_STONE,
|
|
|
|
ITEM_FOCUS_BAND,
|
|
|
|
ITEM_PERSIM_BERRY,
|
|
|
|
ITEM_MIRACLE_SEED,
|
|
|
|
ITEM_BERRY_JUICE,
|
|
|
|
ITEM_MACHO_BRACE,
|
|
|
|
ITEM_SILVER_POWDER,
|
|
|
|
ITEM_CHERI_BERRY,
|
|
|
|
ITEM_BLACK_GLASSES,
|
|
|
|
ITEM_BLACK_BELT,
|
|
|
|
ITEM_SOUL_DEW,
|
|
|
|
ITEM_CHOICE_BAND,
|
|
|
|
ITEM_MAGNET,
|
|
|
|
ITEM_SILK_SCARF,
|
|
|
|
ITEM_WHITE_HERB,
|
|
|
|
ITEM_DEEP_SEA_SCALE,
|
|
|
|
ITEM_DEEP_SEA_TOOTH,
|
|
|
|
ITEM_MYSTIC_WATER,
|
|
|
|
ITEM_SHARP_BEAK,
|
|
|
|
ITEM_QUICK_CLAW,
|
|
|
|
ITEM_LEFTOVERS,
|
|
|
|
ITEM_RAWST_BERRY,
|
|
|
|
ITEM_LIGHT_BALL,
|
|
|
|
ITEM_POISON_BARB,
|
|
|
|
ITEM_NEVER_MELT_ICE,
|
|
|
|
ITEM_ASPEAR_BERRY,
|
|
|
|
ITEM_SPELL_TAG,
|
|
|
|
ITEM_BRIGHT_POWDER,
|
|
|
|
ITEM_LEPPA_BERRY,
|
|
|
|
ITEM_SCOPE_LENS,
|
|
|
|
ITEM_TWISTED_SPOON,
|
|
|
|
ITEM_METAL_COAT,
|
|
|
|
ITEM_MENTAL_HERB,
|
|
|
|
ITEM_CHARCOAL,
|
|
|
|
ITEM_PECHA_BERRY,
|
|
|
|
ITEM_SOFT_SAND,
|
|
|
|
ITEM_LUM_BERRY,
|
|
|
|
ITEM_DRAGON_SCALE,
|
|
|
|
ITEM_DRAGON_FANG,
|
|
|
|
ITEM_IAPAPA_BERRY,
|
|
|
|
ITEM_WIKI_BERRY,
|
|
|
|
ITEM_SEA_INCENSE,
|
|
|
|
ITEM_SHELL_BELL,
|
|
|
|
ITEM_SALAC_BERRY,
|
|
|
|
ITEM_LANSAT_BERRY,
|
|
|
|
ITEM_APICOT_BERRY,
|
|
|
|
ITEM_STARF_BERRY,
|
|
|
|
ITEM_LIECHI_BERRY,
|
|
|
|
ITEM_STICK,
|
|
|
|
ITEM_LAX_INCENSE,
|
|
|
|
ITEM_AGUAV_BERRY,
|
|
|
|
ITEM_FIGY_BERRY,
|
|
|
|
ITEM_THICK_CLUB,
|
|
|
|
ITEM_MAGO_BERRY,
|
|
|
|
ITEM_METAL_POWDER,
|
|
|
|
ITEM_PETAYA_BERRY,
|
|
|
|
ITEM_LUCKY_PUNCH,
|
|
|
|
ITEM_GANLON_BERRY
|
|
|
|
};
|
2018-12-02 23:22:42 -05:00
|
|
|
|
2018-12-04 12:09:35 -05:00
|
|
|
#include "data/battle_frontier/battle_frontier_trainer_mons.h"
|
|
|
|
#include "data/battle_frontier/battle_frontier_trainers.h"
|
|
|
|
#include "data/battle_frontier/battle_frontier_mons.h"
|
2018-12-02 23:22:42 -05:00
|
|
|
|
2018-12-10 10:33:51 -05:00
|
|
|
const u8 gTowerMaleFacilityClasses[30] =
|
2018-12-04 12:09:35 -05:00
|
|
|
{
|
|
|
|
FACILITY_CLASS_RUIN_MANIAC,
|
|
|
|
FACILITY_CLASS_TUBER_M,
|
|
|
|
FACILITY_CLASS_COOLTRAINER_M,
|
|
|
|
FACILITY_CLASS_RICH_BOY,
|
|
|
|
FACILITY_CLASS_POKEMANIAC,
|
|
|
|
FACILITY_CLASS_SWIMMER_M,
|
|
|
|
FACILITY_CLASS_BLACK_BELT,
|
|
|
|
FACILITY_CLASS_GUITARIST,
|
|
|
|
FACILITY_CLASS_KINDLER,
|
|
|
|
FACILITY_CLASS_CAMPER,
|
|
|
|
FACILITY_CLASS_BUG_MANIAC,
|
|
|
|
FACILITY_CLASS_PSYCHIC_M,
|
|
|
|
FACILITY_CLASS_GENTLEMAN,
|
|
|
|
FACILITY_CLASS_SCHOOL_KID_M,
|
|
|
|
FACILITY_CLASS_POKEFAN_M,
|
|
|
|
FACILITY_CLASS_EXPERT_M,
|
|
|
|
FACILITY_CLASS_YOUNGSTER,
|
|
|
|
FACILITY_CLASS_FISHERMAN,
|
|
|
|
FACILITY_CLASS_CYCLING_TRIATHLETE_M,
|
|
|
|
FACILITY_CLASS_RUNNING_TRIATHLETE_M,
|
|
|
|
FACILITY_CLASS_SWIMMING_TRIATHLETE_M,
|
|
|
|
FACILITY_CLASS_DRAGON_TAMER,
|
|
|
|
FACILITY_CLASS_BIRD_KEEPER,
|
|
|
|
FACILITY_CLASS_NINJA_BOY,
|
|
|
|
FACILITY_CLASS_SAILOR,
|
|
|
|
FACILITY_CLASS_COLLECTOR,
|
|
|
|
FACILITY_CLASS_PKMN_BREEDER_M,
|
|
|
|
FACILITY_CLASS_PKMN_RANGER_M,
|
|
|
|
FACILITY_CLASS_BUG_CATCHER,
|
|
|
|
FACILITY_CLASS_HIKER
|
|
|
|
};
|
2018-12-02 23:22:42 -05:00
|
|
|
|
2018-12-10 10:33:51 -05:00
|
|
|
const u8 gTowerFemaleFacilityClasses[20] =
|
2018-12-04 12:09:35 -05:00
|
|
|
{
|
|
|
|
FACILITY_CLASS_AROMA_LADY,
|
|
|
|
FACILITY_CLASS_TUBER_F,
|
|
|
|
FACILITY_CLASS_COOLTRAINER_F,
|
|
|
|
FACILITY_CLASS_HEX_MANIAC,
|
|
|
|
FACILITY_CLASS_LADY,
|
|
|
|
FACILITY_CLASS_BEAUTY,
|
|
|
|
FACILITY_CLASS_PSYCHIC_F,
|
|
|
|
FACILITY_CLASS_SCHOOL_KID_F,
|
|
|
|
FACILITY_CLASS_POKEFAN_F,
|
|
|
|
FACILITY_CLASS_EXPERT_F,
|
|
|
|
FACILITY_CLASS_CYCLING_TRIATHLETE_F,
|
|
|
|
FACILITY_CLASS_RUNNING_TRIATHLETE_F,
|
|
|
|
FACILITY_CLASS_SWIMMING_TRIATHLETE_F,
|
|
|
|
FACILITY_CLASS_BATTLE_GIRL,
|
|
|
|
FACILITY_CLASS_PARASOL_LADY,
|
|
|
|
FACILITY_CLASS_SWIMMER_F,
|
|
|
|
FACILITY_CLASS_PICNICKER,
|
2019-11-24 16:58:40 -05:00
|
|
|
FACILITY_CLASS_PKMN_BREEDER_F,
|
2018-12-04 12:09:35 -05:00
|
|
|
FACILITY_CLASS_PKMN_RANGER_F,
|
|
|
|
FACILITY_CLASS_LASS
|
|
|
|
};
|
2018-12-02 23:22:42 -05:00
|
|
|
|
2018-12-10 10:33:51 -05:00
|
|
|
const u8 gTowerMaleTrainerGfxIds[30] =
|
2018-12-04 12:09:35 -05:00
|
|
|
{
|
2019-11-20 23:12:51 -05:00
|
|
|
OBJ_EVENT_GFX_HIKER,
|
|
|
|
OBJ_EVENT_GFX_TUBER_M,
|
|
|
|
OBJ_EVENT_GFX_MAN_3,
|
|
|
|
OBJ_EVENT_GFX_RICH_BOY,
|
|
|
|
OBJ_EVENT_GFX_MANIAC,
|
|
|
|
OBJ_EVENT_GFX_RUNNING_TRIATHLETE_M,
|
|
|
|
OBJ_EVENT_GFX_BLACK_BELT,
|
|
|
|
OBJ_EVENT_GFX_MAN_5,
|
|
|
|
OBJ_EVENT_GFX_MAN_5,
|
|
|
|
OBJ_EVENT_GFX_CAMPER,
|
|
|
|
OBJ_EVENT_GFX_MANIAC,
|
|
|
|
OBJ_EVENT_GFX_PSYCHIC_M,
|
|
|
|
OBJ_EVENT_GFX_GENTLEMAN,
|
|
|
|
OBJ_EVENT_GFX_SCHOOL_KID_M,
|
|
|
|
OBJ_EVENT_GFX_POKEFAN_M,
|
|
|
|
OBJ_EVENT_GFX_EXPERT_M,
|
|
|
|
OBJ_EVENT_GFX_YOUNGSTER,
|
|
|
|
OBJ_EVENT_GFX_FISHERMAN,
|
|
|
|
OBJ_EVENT_GFX_CYCLING_TRIATHLETE_M,
|
|
|
|
OBJ_EVENT_GFX_RUNNING_TRIATHLETE_M,
|
|
|
|
OBJ_EVENT_GFX_RUNNING_TRIATHLETE_M,
|
|
|
|
OBJ_EVENT_GFX_MAN_3,
|
|
|
|
OBJ_EVENT_GFX_MAN_5,
|
|
|
|
OBJ_EVENT_GFX_NINJA_BOY,
|
|
|
|
OBJ_EVENT_GFX_SAILOR,
|
|
|
|
OBJ_EVENT_GFX_MANIAC,
|
|
|
|
OBJ_EVENT_GFX_MAN_4,
|
|
|
|
OBJ_EVENT_GFX_CAMPER,
|
|
|
|
OBJ_EVENT_GFX_BUG_CATCHER,
|
|
|
|
OBJ_EVENT_GFX_HIKER
|
2018-12-04 12:09:35 -05:00
|
|
|
};
|
2018-12-02 23:22:42 -05:00
|
|
|
|
2018-12-10 10:33:51 -05:00
|
|
|
const u8 gTowerFemaleTrainerGfxIds[20] =
|
2018-12-04 12:09:35 -05:00
|
|
|
{
|
2019-11-20 23:12:51 -05:00
|
|
|
OBJ_EVENT_GFX_WOMAN_2,
|
|
|
|
OBJ_EVENT_GFX_TUBER_F,
|
|
|
|
OBJ_EVENT_GFX_WOMAN_5,
|
|
|
|
OBJ_EVENT_GFX_HEX_MANIAC,
|
|
|
|
OBJ_EVENT_GFX_WOMAN_2,
|
|
|
|
OBJ_EVENT_GFX_BEAUTY,
|
|
|
|
OBJ_EVENT_GFX_LASS,
|
|
|
|
OBJ_EVENT_GFX_GIRL_3,
|
|
|
|
OBJ_EVENT_GFX_POKEFAN_F,
|
|
|
|
OBJ_EVENT_GFX_EXPERT_F,
|
|
|
|
OBJ_EVENT_GFX_CYCLING_TRIATHLETE_F,
|
|
|
|
OBJ_EVENT_GFX_RUNNING_TRIATHLETE_F,
|
|
|
|
OBJ_EVENT_GFX_RUNNING_TRIATHLETE_F,
|
|
|
|
OBJ_EVENT_GFX_GIRL_3,
|
|
|
|
OBJ_EVENT_GFX_WOMAN_5,
|
|
|
|
OBJ_EVENT_GFX_RUNNING_TRIATHLETE_F,
|
|
|
|
OBJ_EVENT_GFX_PICNICKER,
|
|
|
|
OBJ_EVENT_GFX_WOMAN_2,
|
|
|
|
OBJ_EVENT_GFX_PICNICKER,
|
|
|
|
OBJ_EVENT_GFX_LASS
|
2018-12-04 12:09:35 -05:00
|
|
|
};
|
2018-12-02 23:22:42 -05:00
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
// Excludes the unused RS_FACILITY_CLASS_BOARDER_1 and _2
|
|
|
|
static const u8 sRubyFacilityClassToEmerald[RS_FACILITY_CLASSES_COUNT - 2][2] =
|
|
|
|
{
|
|
|
|
{RS_FACILITY_CLASS_AQUA_LEADER_ARCHIE, FACILITY_CLASS_AQUA_LEADER_ARCHIE},
|
|
|
|
{RS_FACILITY_CLASS_AQUA_GRUNT_M, FACILITY_CLASS_AQUA_GRUNT_M},
|
|
|
|
{RS_FACILITY_CLASS_AQUA_GRUNT_F, FACILITY_CLASS_AQUA_GRUNT_F},
|
|
|
|
{RS_FACILITY_CLASS_AROMA_LADY, FACILITY_CLASS_AROMA_LADY},
|
|
|
|
{RS_FACILITY_CLASS_RUIN_MANIAC, FACILITY_CLASS_RUIN_MANIAC},
|
|
|
|
{RS_FACILITY_CLASS_INTERVIEWER, FACILITY_CLASS_INTERVIEWER},
|
|
|
|
{RS_FACILITY_CLASS_TUBER_F, FACILITY_CLASS_TUBER_F},
|
|
|
|
{RS_FACILITY_CLASS_TUBER_M, FACILITY_CLASS_TUBER_M},
|
|
|
|
{RS_FACILITY_CLASS_COOLTRAINER_M, FACILITY_CLASS_COOLTRAINER_M},
|
|
|
|
{RS_FACILITY_CLASS_COOLTRAINER_F, FACILITY_CLASS_COOLTRAINER_F},
|
|
|
|
{RS_FACILITY_CLASS_HEX_MANIAC, FACILITY_CLASS_HEX_MANIAC},
|
|
|
|
{RS_FACILITY_CLASS_LADY, FACILITY_CLASS_LADY},
|
|
|
|
{RS_FACILITY_CLASS_BEAUTY, FACILITY_CLASS_BEAUTY},
|
|
|
|
{RS_FACILITY_CLASS_RICH_BOY, FACILITY_CLASS_RICH_BOY},
|
|
|
|
{RS_FACILITY_CLASS_POKEMANIAC, FACILITY_CLASS_POKEMANIAC},
|
|
|
|
{RS_FACILITY_CLASS_SWIMMER_M, FACILITY_CLASS_SWIMMER_M},
|
|
|
|
{RS_FACILITY_CLASS_BLACK_BELT, FACILITY_CLASS_BLACK_BELT},
|
|
|
|
{RS_FACILITY_CLASS_GUITARIST, FACILITY_CLASS_GUITARIST},
|
|
|
|
{RS_FACILITY_CLASS_KINDLER, FACILITY_CLASS_KINDLER},
|
|
|
|
{RS_FACILITY_CLASS_CAMPER, FACILITY_CLASS_CAMPER},
|
|
|
|
{RS_FACILITY_CLASS_BUG_MANIAC, FACILITY_CLASS_BUG_MANIAC},
|
|
|
|
{RS_FACILITY_CLASS_PSYCHIC_M, FACILITY_CLASS_PSYCHIC_M},
|
|
|
|
{RS_FACILITY_CLASS_PSYCHIC_F, FACILITY_CLASS_PSYCHIC_F},
|
|
|
|
{RS_FACILITY_CLASS_GENTLEMAN, FACILITY_CLASS_GENTLEMAN},
|
|
|
|
{RS_FACILITY_CLASS_ELITE_FOUR_M, FACILITY_CLASS_ELITE_FOUR_SIDNEY},
|
|
|
|
{RS_FACILITY_CLASS_ELITE_FOUR_F, FACILITY_CLASS_ELITE_FOUR_PHOEBE},
|
|
|
|
{RS_FACILITY_CLASS_LEADER_F, FACILITY_CLASS_LEADER_ROXANNE},
|
|
|
|
{RS_FACILITY_CLASS_LEADER_M, FACILITY_CLASS_LEADER_BRAWLY},
|
|
|
|
{RS_FACILITY_CLASS_LEADER_MF, FACILITY_CLASS_LEADER_TATE_AND_LIZA},
|
|
|
|
{RS_FACILITY_CLASS_SCHOOL_KID_M, FACILITY_CLASS_SCHOOL_KID_M},
|
|
|
|
{RS_FACILITY_CLASS_SCHOOL_KID_F, FACILITY_CLASS_SCHOOL_KID_F},
|
|
|
|
{RS_FACILITY_CLASS_SR_AND_JR, FACILITY_CLASS_SR_AND_JR},
|
|
|
|
{RS_FACILITY_CLASS_POKEFAN_M, FACILITY_CLASS_POKEFAN_M},
|
|
|
|
{RS_FACILITY_CLASS_POKEFAN_F, FACILITY_CLASS_POKEFAN_F},
|
|
|
|
{RS_FACILITY_CLASS_EXPERT_M, FACILITY_CLASS_EXPERT_M},
|
|
|
|
{RS_FACILITY_CLASS_EXPERT_F, FACILITY_CLASS_EXPERT_F},
|
|
|
|
{RS_FACILITY_CLASS_YOUNGSTER, FACILITY_CLASS_YOUNGSTER},
|
|
|
|
{RS_FACILITY_CLASS_CHAMPION, FACILITY_CLASS_CHAMPION_WALLACE},
|
|
|
|
{RS_FACILITY_CLASS_FISHERMAN, FACILITY_CLASS_FISHERMAN},
|
|
|
|
{RS_FACILITY_CLASS_CYCLING_TRIATHLETE_M, FACILITY_CLASS_CYCLING_TRIATHLETE_M},
|
|
|
|
{RS_FACILITY_CLASS_CYCLING_TRIATHLETE_F, FACILITY_CLASS_CYCLING_TRIATHLETE_F},
|
|
|
|
{RS_FACILITY_CLASS_RUNNING_TRIATHLETE_M, FACILITY_CLASS_RUNNING_TRIATHLETE_M},
|
|
|
|
{RS_FACILITY_CLASS_RUNNING_TRIATHLETE_F, FACILITY_CLASS_RUNNING_TRIATHLETE_F},
|
|
|
|
{RS_FACILITY_CLASS_SWIMMING_TRIATHLETE_M, FACILITY_CLASS_SWIMMING_TRIATHLETE_M},
|
|
|
|
{RS_FACILITY_CLASS_SWIMMING_TRIATHLETE_F, FACILITY_CLASS_SWIMMING_TRIATHLETE_F},
|
|
|
|
{RS_FACILITY_CLASS_DRAGON_TAMER, FACILITY_CLASS_DRAGON_TAMER},
|
|
|
|
{RS_FACILITY_CLASS_BIRD_KEEPER, FACILITY_CLASS_BIRD_KEEPER},
|
|
|
|
{RS_FACILITY_CLASS_NINJA_BOY, FACILITY_CLASS_NINJA_BOY},
|
|
|
|
{RS_FACILITY_CLASS_BATTLE_GIRL, FACILITY_CLASS_BATTLE_GIRL},
|
|
|
|
{RS_FACILITY_CLASS_PARASOL_LADY, FACILITY_CLASS_PARASOL_LADY},
|
|
|
|
{RS_FACILITY_CLASS_SWIMMER_F, FACILITY_CLASS_SWIMMER_F},
|
|
|
|
{RS_FACILITY_CLASS_PICNICKER, FACILITY_CLASS_PICNICKER},
|
|
|
|
{RS_FACILITY_CLASS_TWINS, FACILITY_CLASS_TWINS},
|
|
|
|
{RS_FACILITY_CLASS_SAILOR, FACILITY_CLASS_SAILOR},
|
|
|
|
{RS_FACILITY_CLASS_COLLECTOR, FACILITY_CLASS_COLLECTOR},
|
|
|
|
{RS_FACILITY_CLASS_WALLY, FACILITY_CLASS_WALLY},
|
|
|
|
{RS_FACILITY_CLASS_BRENDAN_1, FACILITY_CLASS_BRENDAN},
|
|
|
|
{RS_FACILITY_CLASS_BRENDAN_2, FACILITY_CLASS_BRENDAN_2},
|
|
|
|
{RS_FACILITY_CLASS_BRENDAN_3, FACILITY_CLASS_BRENDAN_3},
|
|
|
|
{RS_FACILITY_CLASS_MAY_1, FACILITY_CLASS_MAY},
|
|
|
|
{RS_FACILITY_CLASS_MAY_2, FACILITY_CLASS_MAY_2},
|
|
|
|
{RS_FACILITY_CLASS_MAY_3, FACILITY_CLASS_MAY_3},
|
|
|
|
{RS_FACILITY_CLASS_PKMN_BREEDER_M, FACILITY_CLASS_PKMN_BREEDER_M},
|
|
|
|
{RS_FACILITY_CLASS_PKMN_BREEDER_F, FACILITY_CLASS_PKMN_BREEDER_F},
|
|
|
|
{RS_FACILITY_CLASS_PKMN_RANGER_M, FACILITY_CLASS_PKMN_RANGER_M},
|
|
|
|
{RS_FACILITY_CLASS_PKMN_RANGER_F, FACILITY_CLASS_PKMN_RANGER_F},
|
|
|
|
{RS_FACILITY_CLASS_MAGMA_LEADER, FACILITY_CLASS_MAGMA_LEADER_MAXIE},
|
|
|
|
{RS_FACILITY_CLASS_MAGMA_GRUNT_M, FACILITY_CLASS_MAGMA_GRUNT_M},
|
|
|
|
{RS_FACILITY_CLASS_MAGMA_GRUNT_F, FACILITY_CLASS_MAGMA_GRUNT_F},
|
|
|
|
{RS_FACILITY_CLASS_LASS, FACILITY_CLASS_LASS},
|
|
|
|
{RS_FACILITY_CLASS_BUG_CATCHER, FACILITY_CLASS_BUG_CATCHER},
|
|
|
|
{RS_FACILITY_CLASS_HIKER, FACILITY_CLASS_HIKER},
|
|
|
|
{RS_FACILITY_CLASS_YOUNG_COUPLE, FACILITY_CLASS_YOUNG_COUPLE},
|
|
|
|
{RS_FACILITY_CLASS_OLD_COUPLE, FACILITY_CLASS_OLD_COUPLE},
|
|
|
|
{RS_FACILITY_CLASS_SIS_AND_BRO, FACILITY_CLASS_SIS_AND_BRO},
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
#define PARTNER_TEXTS(name) \
|
|
|
|
BattleFrontier_BattleTowerMultiPartnerRoom_Text_##name##Intro, \
|
|
|
|
BattleFrontier_BattleTowerMultiPartnerRoom_Text_##name##Mon1, \
|
|
|
|
BattleFrontier_BattleTowerMultiPartnerRoom_Text_##name##Mon2Ask, \
|
|
|
|
BattleFrontier_BattleTowerMultiPartnerRoom_Text_##name##Accept, \
|
|
|
|
BattleFrontier_BattleTowerMultiPartnerRoom_Text_##name##Reject
|
|
|
|
|
|
|
|
static const u8 *const sPartnerApprenticeTexts1[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice1)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts2[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice2)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts3[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice3)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts4[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice4)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts5[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice5)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts6[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice6)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts7[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice7)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts8[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice8)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts9[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice9)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts10[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice10)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts11[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice11)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts12[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice12)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts13[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice13)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts14[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice14)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts15[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice15)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerApprenticeTexts16[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Apprentice16)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsLass[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Lass)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsYoungster[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Youngster)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsHiker[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Hiker)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsBeauty[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Beauty)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsFisherman[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Fisherman)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsLady[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Lady)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsCyclingTriathleteF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(CyclingTriathleteF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsBugCatcher[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(BugCatcher)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsSchoolKidM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(SchoolKidM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsRichBoy[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(RichBoy)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsBlackBelt[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(BlackBelt)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsTuberF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(TuberF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsHexManiac[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(HexManiac)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPkmnBreederM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PkmnBreederM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsRunningTriathleteF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(RunningTriathleteF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsRunningTriathleteM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(RunningTriathleteM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsBattleGirl[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(BattleGirl)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsCyclingTriathleteM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(CyclingTriathleteM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsTuberM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(TuberM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsGuitarist[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Guitarist)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsGentleman[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Gentleman)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPokefanM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PokefanM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsExpertM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(ExpertM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsExpertF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(ExpertF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsDragonTamer[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(DragonTamer)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsBirdKeeper[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(BirdKeeper)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsNinjaBoy[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(NinjaBoy)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsParasolLady[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(ParasolLady)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsBugManiac[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(BugManiac)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsSailor[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Sailor)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsCollector[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Collector)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPkmnRangerM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PkmnRangerM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPkmnRangerF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PkmnRangerF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsAromaLady[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(AromaLady)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsRuinManiac[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(RuinManiac)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsCoolTrainerM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(CoolTrainerM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsCoolTrainerF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(CoolTrainerF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPokemaniac[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Pokemaniac)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsKindler[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Kindler)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsCamper[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Camper)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPicnicker[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(Picnicker)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPsychicM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PsychicM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPsychicF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PsychicF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsSchoolKidF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(SchoolKidF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPkmnBreederF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PkmnBreederF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsPokefanF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(PokefanF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsSwimmerF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(SwimmerF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsSwimmingTriathleteM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(SwimmingTriathleteM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsSwimmingTriathleteF[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(SwimmingTriathleteF)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static const u8 *const sPartnerTextsSwimmerM[] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
PARTNER_TEXTS(SwimmerM)
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
u32 facilityClass;
|
|
|
|
const u8 *const *strings;
|
2020-01-08 05:43:06 -05:00
|
|
|
} const sPartnerTrainerTextTables[] =
|
|
|
|
{
|
|
|
|
{FACILITY_CLASS_LASS, sPartnerTextsLass},
|
|
|
|
{FACILITY_CLASS_YOUNGSTER, sPartnerTextsYoungster},
|
|
|
|
{FACILITY_CLASS_HIKER, sPartnerTextsHiker},
|
|
|
|
{FACILITY_CLASS_BEAUTY, sPartnerTextsBeauty},
|
|
|
|
{FACILITY_CLASS_FISHERMAN, sPartnerTextsFisherman},
|
|
|
|
{FACILITY_CLASS_LADY, sPartnerTextsLady},
|
|
|
|
{FACILITY_CLASS_CYCLING_TRIATHLETE_F, sPartnerTextsCyclingTriathleteF},
|
|
|
|
{FACILITY_CLASS_BUG_CATCHER, sPartnerTextsBugCatcher},
|
|
|
|
{FACILITY_CLASS_SCHOOL_KID_M, sPartnerTextsSchoolKidM},
|
|
|
|
{FACILITY_CLASS_RICH_BOY, sPartnerTextsRichBoy},
|
|
|
|
{FACILITY_CLASS_BLACK_BELT, sPartnerTextsBlackBelt},
|
|
|
|
{FACILITY_CLASS_TUBER_F, sPartnerTextsTuberF},
|
|
|
|
{FACILITY_CLASS_HEX_MANIAC, sPartnerTextsHexManiac},
|
|
|
|
{FACILITY_CLASS_PKMN_BREEDER_M, sPartnerTextsPkmnBreederM},
|
|
|
|
{FACILITY_CLASS_RUNNING_TRIATHLETE_F, sPartnerTextsRunningTriathleteF},
|
|
|
|
{FACILITY_CLASS_RUNNING_TRIATHLETE_M, sPartnerTextsRunningTriathleteM},
|
|
|
|
{FACILITY_CLASS_BATTLE_GIRL, sPartnerTextsBattleGirl},
|
|
|
|
{FACILITY_CLASS_CYCLING_TRIATHLETE_M, sPartnerTextsCyclingTriathleteM},
|
|
|
|
{FACILITY_CLASS_TUBER_M, sPartnerTextsTuberM},
|
|
|
|
{FACILITY_CLASS_GUITARIST, sPartnerTextsGuitarist},
|
|
|
|
{FACILITY_CLASS_GENTLEMAN, sPartnerTextsGentleman},
|
|
|
|
{FACILITY_CLASS_POKEFAN_M, sPartnerTextsPokefanM},
|
|
|
|
{FACILITY_CLASS_EXPERT_M, sPartnerTextsExpertM},
|
|
|
|
{FACILITY_CLASS_EXPERT_F, sPartnerTextsExpertF},
|
|
|
|
{FACILITY_CLASS_DRAGON_TAMER, sPartnerTextsDragonTamer},
|
|
|
|
{FACILITY_CLASS_BIRD_KEEPER, sPartnerTextsBirdKeeper},
|
|
|
|
{FACILITY_CLASS_NINJA_BOY, sPartnerTextsNinjaBoy},
|
|
|
|
{FACILITY_CLASS_PARASOL_LADY, sPartnerTextsParasolLady},
|
|
|
|
{FACILITY_CLASS_BUG_MANIAC, sPartnerTextsBugManiac},
|
|
|
|
{FACILITY_CLASS_SAILOR, sPartnerTextsSailor},
|
|
|
|
{FACILITY_CLASS_COLLECTOR, sPartnerTextsCollector},
|
|
|
|
{FACILITY_CLASS_PKMN_RANGER_M, sPartnerTextsPkmnRangerM},
|
|
|
|
{FACILITY_CLASS_PKMN_RANGER_F, sPartnerTextsPkmnRangerF},
|
|
|
|
{FACILITY_CLASS_AROMA_LADY, sPartnerTextsAromaLady},
|
|
|
|
{FACILITY_CLASS_RUIN_MANIAC, sPartnerTextsRuinManiac},
|
|
|
|
{FACILITY_CLASS_COOLTRAINER_M, sPartnerTextsCoolTrainerM},
|
|
|
|
{FACILITY_CLASS_COOLTRAINER_F, sPartnerTextsCoolTrainerF},
|
|
|
|
{FACILITY_CLASS_POKEMANIAC, sPartnerTextsPokemaniac},
|
|
|
|
{FACILITY_CLASS_KINDLER, sPartnerTextsKindler},
|
|
|
|
{FACILITY_CLASS_CAMPER, sPartnerTextsCamper},
|
|
|
|
{FACILITY_CLASS_PICNICKER, sPartnerTextsPicnicker},
|
|
|
|
{FACILITY_CLASS_PSYCHIC_M, sPartnerTextsPsychicM},
|
|
|
|
{FACILITY_CLASS_PSYCHIC_F, sPartnerTextsPsychicF},
|
|
|
|
{FACILITY_CLASS_SCHOOL_KID_F, sPartnerTextsSchoolKidF},
|
|
|
|
{FACILITY_CLASS_PKMN_BREEDER_F, sPartnerTextsPkmnBreederF},
|
|
|
|
{FACILITY_CLASS_POKEFAN_F, sPartnerTextsPokefanF},
|
|
|
|
{FACILITY_CLASS_SWIMMER_F, sPartnerTextsSwimmerF},
|
|
|
|
{FACILITY_CLASS_SWIMMING_TRIATHLETE_M, sPartnerTextsSwimmingTriathleteM},
|
|
|
|
{FACILITY_CLASS_SWIMMING_TRIATHLETE_F, sPartnerTextsSwimmingTriathleteF},
|
|
|
|
{FACILITY_CLASS_SWIMMER_M, sPartnerTextsSwimmerM}
|
|
|
|
};
|
|
|
|
|
|
|
|
static const u8 *const *const sPartnerApprenticeTextTables[NUM_APPRENTICES] =
|
|
|
|
{
|
|
|
|
sPartnerApprenticeTexts1,
|
|
|
|
sPartnerApprenticeTexts2,
|
|
|
|
sPartnerApprenticeTexts3,
|
|
|
|
sPartnerApprenticeTexts4,
|
|
|
|
sPartnerApprenticeTexts5,
|
|
|
|
sPartnerApprenticeTexts6,
|
|
|
|
sPartnerApprenticeTexts7,
|
|
|
|
sPartnerApprenticeTexts8,
|
|
|
|
sPartnerApprenticeTexts9,
|
|
|
|
sPartnerApprenticeTexts10,
|
|
|
|
sPartnerApprenticeTexts11,
|
|
|
|
sPartnerApprenticeTexts12,
|
|
|
|
sPartnerApprenticeTexts13,
|
|
|
|
sPartnerApprenticeTexts14,
|
|
|
|
sPartnerApprenticeTexts15,
|
|
|
|
sPartnerApprenticeTexts16
|
2018-12-02 23:22:42 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
u16 species;
|
|
|
|
u8 fixedIV;
|
|
|
|
u8 level;
|
|
|
|
u8 nature;
|
2020-01-08 05:43:06 -05:00
|
|
|
u8 evs[NUM_STATS];
|
2019-09-08 11:53:48 -04:00
|
|
|
u16 moves[MAX_MON_MOVES];
|
2020-01-08 05:43:06 -05:00
|
|
|
} const sStevenMons[MULTI_PARTY_SIZE] =
|
2018-12-02 23:22:42 -05:00
|
|
|
{
|
|
|
|
{
|
|
|
|
.species = SPECIES_METANG,
|
|
|
|
.fixedIV = 31,
|
|
|
|
.level = 42,
|
|
|
|
.nature = NATURE_BRAVE,
|
|
|
|
.evs = {0, 252, 252, 0, 6, 0},
|
|
|
|
.moves = {MOVE_LIGHT_SCREEN, MOVE_PSYCHIC, MOVE_REFLECT, MOVE_METAL_CLAW}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.species = SPECIES_SKARMORY,
|
|
|
|
.fixedIV = 31,
|
|
|
|
.level = 43,
|
|
|
|
.nature = NATURE_IMPISH,
|
|
|
|
.evs = {252, 0, 0, 0, 6, 252},
|
|
|
|
.moves = {MOVE_TOXIC, MOVE_AERIAL_ACE, MOVE_PROTECT, MOVE_STEEL_WING}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.species = SPECIES_AGGRON,
|
|
|
|
.fixedIV = 31,
|
|
|
|
.level = 44,
|
|
|
|
.nature = NATURE_ADAMANT,
|
|
|
|
.evs = {0, 252, 0, 0, 252, 6},
|
|
|
|
.moves = {MOVE_THUNDER, MOVE_PROTECT, MOVE_SOLAR_BEAM, MOVE_DRAGON_CLAW}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#include "data/battle_frontier/battle_tent.h"
|
|
|
|
|
2019-11-16 18:11:27 -05:00
|
|
|
static void (* const sBattleTowerFuncs[])(void) =
|
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
[BATTLE_TOWER_FUNC_INIT] = InitTowerChallenge,
|
|
|
|
[BATTLE_TOWER_FUNC_GET_DATA] = GetTowerData,
|
|
|
|
[BATTLE_TOWER_FUNC_SET_DATA] = SetTowerData,
|
|
|
|
[BATTLE_TOWER_FUNC_SET_OPPONENT] = SetNextFacilityOpponent,
|
|
|
|
[BATTLE_TOWER_FUNC_SET_BATTLE_WON] = SetTowerBattleWon,
|
|
|
|
[BATTLE_TOWER_FUNC_GIVE_RIBBONS] = AwardBattleTowerRibbons,
|
|
|
|
[BATTLE_TOWER_FUNC_SAVE] = SaveTowerChallenge,
|
|
|
|
[BATTLE_TOWER_FUNC_GET_OPPONENT_INTRO] = GetOpponentIntroSpeech,
|
|
|
|
[BATTLE_TOWER_FUNC_NOP] = nullsub_61,
|
|
|
|
[BATTLE_TOWER_FUNC_NOP2] = nullsub_116,
|
|
|
|
[BATTLE_TOWER_FUNC_LOAD_PARTNERS] = LoadMultiPartnerCandidatesData,
|
|
|
|
[BATTLE_TOWER_FUNC_PARTNER_MSG] = ShowPartnerCandidateMessage,
|
|
|
|
[BATTLE_TOWER_FUNC_LOAD_LINK_OPPONENTS] = LoadLinkMultiOpponentsData,
|
|
|
|
[BATTLE_TOWER_FUNC_13] = sub_8164DCC,
|
|
|
|
[BATTLE_TOWER_FUNC_SET_PARTNER_GFX] = SetMultiPartnerGfx,
|
|
|
|
[BATTLE_TOWER_FUNC_SET_INTERVIEW_DATA] = SetTowerInterviewData,
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
static const u32 sWinStreakFlags[][2] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
{STREAK_TOWER_SINGLES_50, STREAK_TOWER_SINGLES_OPEN},
|
|
|
|
{STREAK_TOWER_DOUBLES_50, STREAK_TOWER_DOUBLES_OPEN},
|
|
|
|
{STREAK_TOWER_MULTIS_50, STREAK_TOWER_MULTIS_OPEN},
|
|
|
|
{STREAK_TOWER_LINK_MULTIS_50, STREAK_TOWER_LINK_MULTIS_OPEN},
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
static const u32 sWinStreakMasks[][2] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
{~(STREAK_TOWER_SINGLES_50), ~(STREAK_TOWER_SINGLES_OPEN)},
|
|
|
|
{~(STREAK_TOWER_DOUBLES_50), ~(STREAK_TOWER_DOUBLES_OPEN)},
|
|
|
|
{~(STREAK_TOWER_MULTIS_50), ~(STREAK_TOWER_MULTIS_OPEN)},
|
|
|
|
{~(STREAK_TOWER_LINK_MULTIS_50), ~(STREAK_TOWER_LINK_MULTIS_OPEN)},
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
// The challenge number at which an Apprentice can appear, depending on how many of their questions were answered
|
|
|
|
static const u8 sApprenticeChallengeThreshold[MAX_APPRENTICE_QUESTIONS] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
1, 2, 3, 4, 5, 8, 9, 10, 11, 12
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
// Unclear why this was duplicated
|
|
|
|
static const u8 sBattleTowerPartySizes2[] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
[FRONTIER_MODE_SINGLES] = FRONTIER_PARTY_SIZE,
|
|
|
|
[FRONTIER_MODE_DOUBLES] = FRONTIER_DOUBLES_PARTY_SIZE,
|
|
|
|
[FRONTIER_MODE_MULTIS] = FRONTIER_MULTI_PARTY_SIZE,
|
|
|
|
[FRONTIER_MODE_LINK_MULTIS] = FRONTIER_MULTI_PARTY_SIZE,
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
// Trainer ID ranges for possible frontier trainers to encounter on particular challenges
|
|
|
|
// Trainers are scaled by difficulty, so higher trainer IDs have better teams
|
|
|
|
static const u16 sFrontierTrainerIdRanges[][2] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
{FRONTIER_TRAINER_BRADY, FRONTIER_TRAINER_JILL}, // 0 - 99
|
|
|
|
{FRONTIER_TRAINER_TREVIN, FRONTIER_TRAINER_CHLOE}, // 80 - 119
|
|
|
|
{FRONTIER_TRAINER_ERIK, FRONTIER_TRAINER_SOFIA}, // 100 - 139
|
|
|
|
{FRONTIER_TRAINER_NORTON, FRONTIER_TRAINER_JAZLYN}, // 120 - 159
|
|
|
|
{FRONTIER_TRAINER_BRADEN, FRONTIER_TRAINER_ALISON}, // 140 - 179
|
|
|
|
{FRONTIER_TRAINER_ZACHERY, FRONTIER_TRAINER_LAMAR}, // 160 - 199
|
|
|
|
{FRONTIER_TRAINER_HANK, FRONTIER_TRAINER_TESS}, // 180 - 219
|
|
|
|
{FRONTIER_TRAINER_JAXON, FRONTIER_TRAINER_GRETEL}, // 200 - 299
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
static const u16 sFrontierTrainerIdRangesHard[][2] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
{FRONTIER_TRAINER_ERIK, FRONTIER_TRAINER_CHLOE}, // 100 - 119
|
|
|
|
{FRONTIER_TRAINER_NORTON, FRONTIER_TRAINER_SOFIA}, // 120 - 139
|
|
|
|
{FRONTIER_TRAINER_BRADEN, FRONTIER_TRAINER_JAZLYN}, // 140 - 159
|
|
|
|
{FRONTIER_TRAINER_ZACHERY, FRONTIER_TRAINER_ALISON}, // 160 - 179
|
|
|
|
{FRONTIER_TRAINER_HANK, FRONTIER_TRAINER_LAMAR}, // 180 - 199
|
|
|
|
{FRONTIER_TRAINER_JAXON, FRONTIER_TRAINER_TESS}, // 200 - 219
|
|
|
|
{FRONTIER_TRAINER_LEON, FRONTIER_TRAINER_RAUL}, // 220 - 239
|
|
|
|
{FRONTIER_TRAINER_JAXON, FRONTIER_TRAINER_GRETEL}, // 200 - 299
|
|
|
|
};
|
|
|
|
|
|
|
|
// Trainer IDs? Don't make sense as part of previous array, min/max relationship reversed and never accessed
|
|
|
|
static const u16 sUnused_085DFA1A[][2] =
|
|
|
|
{
|
|
|
|
{179, 141}, // FRONTIER_TRAINER_ALISON - FRONTIER_TRAINER_KAYDEN
|
|
|
|
{200, 183}, // FRONTIER_TRAINER_JAXON - FRONTIER_TRAINER_HUNTER
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
static const u8 sBattleTowerPartySizes[FRONTIER_MODE_COUNT] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
[FRONTIER_MODE_SINGLES] = FRONTIER_PARTY_SIZE,
|
|
|
|
[FRONTIER_MODE_DOUBLES] = FRONTIER_DOUBLES_PARTY_SIZE,
|
|
|
|
[FRONTIER_MODE_MULTIS] = FRONTIER_MULTI_PARTY_SIZE,
|
|
|
|
[FRONTIER_MODE_LINK_MULTIS] = FRONTIER_MULTI_PARTY_SIZE,
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
static const u16 sRecordTrainerSpeechWon[] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
EC_WORD_YAY, EC_WORD_YAY, EC_WORD_EXCL_EXCL, EC_WORD_I_VE, EC_WORD_WON, EC_WORD_EXCL_EXCL
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
static const u16 sRecordTrainerSpeechLost[] =
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
EC_WORD_TOO, EC_WORD_BAD, EC_WORD_ELLIPSIS, EC_WORD_WE, EC_WORD_LOST, EC_WORD_ELLIPSIS
|
2018-10-25 21:27:10 +02:00
|
|
|
};
|
2018-08-26 17:54:58 +02:00
|
|
|
|
|
|
|
// code
|
2019-11-16 18:11:27 -05:00
|
|
|
void CallBattleTowerFunc(void)
|
2018-08-26 17:54:58 +02:00
|
|
|
{
|
2019-11-16 18:11:27 -05:00
|
|
|
sBattleTowerFuncs[gSpecialVar_0x8004]();
|
2018-08-26 17:54:58 +02:00
|
|
|
}
|
|
|
|
|
2019-11-28 21:09:35 -05:00
|
|
|
static void InitTowerChallenge(void)
|
2018-08-26 17:54:58 +02:00
|
|
|
{
|
|
|
|
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
|
|
|
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.challengeStatus = CHALLENGE_STATUS_SAVING;
|
2018-10-21 00:06:42 +02:00
|
|
|
gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.challengePaused = FALSE;
|
2020-01-08 05:43:06 -05:00
|
|
|
gSaveBlock2Ptr->frontier.disableRecordBattle = FALSE;
|
2019-11-24 16:58:40 -05:00
|
|
|
ResetFrontierTrainerIds();
|
|
|
|
if (!(gSaveBlock2Ptr->frontier.winStreakActiveFlags & sWinStreakFlags[battleMode][lvlMode]))
|
2018-10-27 17:39:05 +02:00
|
|
|
gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode] = 0;
|
2018-08-26 17:54:58 +02:00
|
|
|
|
2018-10-22 19:22:57 +02:00
|
|
|
ValidateBattleTowerRecordChecksums();
|
2018-12-27 16:30:47 -06:00
|
|
|
SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
|
2018-08-26 17:54:58 +02:00
|
|
|
gTrainerBattleOpponent_A = 0;
|
|
|
|
}
|
|
|
|
|
2019-11-28 21:09:35 -05:00
|
|
|
static void GetTowerData(void)
|
2018-08-26 17:54:58 +02:00
|
|
|
{
|
|
|
|
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
|
|
|
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
|
|
|
|
|
|
|
switch (gSpecialVar_0x8005)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
break;
|
2019-11-28 22:46:39 -05:00
|
|
|
case TOWER_DATA_WIN_STREAK:
|
2018-10-20 00:33:51 +02:00
|
|
|
gSpecialVar_Result = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
|
2018-08-26 17:54:58 +02:00
|
|
|
break;
|
2019-11-28 22:46:39 -05:00
|
|
|
case TOWER_DATA_WIN_STREAK_ACTIVE:
|
2019-11-24 16:58:40 -05:00
|
|
|
gSpecialVar_Result = ((gSaveBlock2Ptr->frontier.winStreakActiveFlags & sWinStreakFlags[battleMode][lvlMode]) != 0);
|
2018-08-26 17:54:58 +02:00
|
|
|
break;
|
2019-11-28 22:46:39 -05:00
|
|
|
case TOWER_DATA_LVL_MODE:
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.towerLvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
2018-08-26 17:54:58 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-28 21:09:35 -05:00
|
|
|
static void SetTowerData(void)
|
2018-08-26 17:54:58 +02:00
|
|
|
{
|
|
|
|
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
|
|
|
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
|
|
|
|
|
|
|
switch (gSpecialVar_0x8005)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
break;
|
2019-11-28 22:46:39 -05:00
|
|
|
case TOWER_DATA_WIN_STREAK:
|
2018-10-27 17:39:05 +02:00
|
|
|
gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode] = gSpecialVar_0x8006;
|
2018-08-26 17:54:58 +02:00
|
|
|
break;
|
2019-11-28 22:46:39 -05:00
|
|
|
case TOWER_DATA_WIN_STREAK_ACTIVE:
|
2018-08-26 17:54:58 +02:00
|
|
|
if (gSpecialVar_0x8006)
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.winStreakActiveFlags |= sWinStreakFlags[battleMode][lvlMode];
|
2018-08-26 17:54:58 +02:00
|
|
|
else
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.winStreakActiveFlags &= sWinStreakMasks[battleMode][lvlMode];
|
2018-08-26 17:54:58 +02:00
|
|
|
break;
|
2019-11-28 22:46:39 -05:00
|
|
|
case TOWER_DATA_LVL_MODE:
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.towerLvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
2018-08-26 17:54:58 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-10-20 00:33:51 +02:00
|
|
|
|
2019-11-28 22:46:39 -05:00
|
|
|
static void SetTowerBattleWon(void)
|
2018-10-20 00:33:51 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
if (gTrainerBattleOpponent_A == TRAINER_EREADER)
|
2018-10-22 19:22:57 +02:00
|
|
|
ClearEReaderTrainer(&gSaveBlock2Ptr->frontier.ereaderTrainer);
|
2018-10-20 00:33:51 +02:00
|
|
|
|
2019-11-28 22:46:39 -05:00
|
|
|
// towerNumWins is never read outside this conditional
|
2019-11-24 16:58:40 -05:00
|
|
|
if (gSaveBlock2Ptr->frontier.towerNumWins < MAX_STREAK)
|
|
|
|
gSaveBlock2Ptr->frontier.towerNumWins++;
|
2018-10-20 00:33:51 +02:00
|
|
|
|
2018-10-21 00:06:42 +02:00
|
|
|
gSaveBlock2Ptr->frontier.curChallengeBattleNum++;
|
2018-10-21 20:13:12 +02:00
|
|
|
SaveCurrentWinStreak();
|
2018-10-21 00:06:42 +02:00
|
|
|
gSpecialVar_Result = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
|
2018-10-20 00:33:51 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static bool8 ChooseSpecialBattleTowerTrainer(void)
|
2018-10-20 00:33:51 +02:00
|
|
|
{
|
|
|
|
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++)
|
|
|
|
{
|
2018-10-21 20:13:12 +02:00
|
|
|
u32 *record = (u32*)(&gSaveBlock2Ptr->frontier.towerRecords[i]);
|
2018-10-20 00:33:51 +02:00
|
|
|
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++)
|
|
|
|
{
|
2018-10-21 20:13:12 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.towerRecords[i].party[j].species != 0
|
|
|
|
&& gSaveBlock2Ptr->frontier.towerRecords[i].party[j].level <= GetFrontierEnemyMonLevel(lvlMode))
|
2018-10-20 00:33:51 +02:00
|
|
|
validMons++;
|
|
|
|
}
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
if (validMons >= sBattleTowerPartySizes2[battleMode]
|
2018-10-21 20:13:12 +02:00
|
|
|
&& gSaveBlock2Ptr->frontier.towerRecords[i].winStreak == winStreak
|
|
|
|
&& gSaveBlock2Ptr->frontier.towerRecords[i].lvlMode == lvlMode
|
2018-10-20 00:33:51 +02:00
|
|
|
&& recordHasData
|
2018-10-21 20:13:12 +02:00
|
|
|
&& gSaveBlock2Ptr->frontier.towerRecords[i].checksum == checksum)
|
2018-10-20 00:33:51 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
trainerIds[idsCount] = i + TRAINER_RECORD_MIXING_FRIEND;
|
2018-10-20 00:33:51 +02:00
|
|
|
idsCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (battleMode == FRONTIER_MODE_SINGLES)
|
|
|
|
{
|
2018-10-24 23:14:45 +02:00
|
|
|
ValidateApprenticesChecksums();
|
2019-11-20 17:36:52 -05:00
|
|
|
for (i = 0; i < APPRENTICE_COUNT; i++)
|
2018-10-20 00:33:51 +02:00
|
|
|
{
|
|
|
|
if (gSaveBlock2Ptr->apprentices[i].lvlMode != 0
|
2020-01-08 05:43:06 -05:00
|
|
|
&& sApprenticeChallengeThreshold[gSaveBlock2Ptr->apprentices[i].numQuestions] == winStreak
|
2018-10-20 00:33:51 +02:00
|
|
|
&& gSaveBlock2Ptr->apprentices[i].lvlMode - 1 == lvlMode)
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
trainerIds[idsCount] = i + TRAINER_RECORD_MIXING_APPRENTICE;
|
2018-10-20 00:33:51 +02:00
|
|
|
idsCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idsCount != 0)
|
|
|
|
{
|
|
|
|
gTrainerBattleOpponent_A = trainerIds[Random() % idsCount];
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2018-10-21 00:06:42 +02:00
|
|
|
|
2019-11-28 22:46:39 -05:00
|
|
|
static void SetNextFacilityOpponent(void)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
|
|
|
if (lvlMode == FRONTIER_LVL_TENT)
|
|
|
|
{
|
2019-11-28 22:46:39 -05:00
|
|
|
SetNextBattleTentOpponent();
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u16 id;
|
|
|
|
u32 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
2018-10-27 21:01:35 +02:00
|
|
|
u16 winStreak = GetCurrentFacilityWinStreak();
|
|
|
|
u32 challengeNum = winStreak / 7;
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-21 00:06:42 +02:00
|
|
|
|
|
|
|
if (battleMode == FRONTIER_MODE_MULTIS || battleMode == FRONTIER_MODE_LINK_MULTIS)
|
|
|
|
{
|
|
|
|
id = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
|
2019-02-07 11:37:28 -06:00
|
|
|
gTrainerBattleOpponent_A = gSaveBlock2Ptr->frontier.trainerIds[id * 2];
|
|
|
|
gTrainerBattleOpponent_B = gSaveBlock2Ptr->frontier.trainerIds[id * 2 + 1];
|
2018-10-21 00:06:42 +02:00
|
|
|
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
|
|
|
|
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1);
|
|
|
|
}
|
|
|
|
else if (ChooseSpecialBattleTowerTrainer())
|
|
|
|
{
|
|
|
|
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
while (1)
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
id = GetRandomScaledFrontierTrainerId(challengeNum, gSaveBlock2Ptr->frontier.curChallengeBattleNum);
|
2018-10-21 00:06:42 +02:00
|
|
|
|
|
|
|
// Ensure trainer wasn't previously fought in this challenge.
|
|
|
|
for (i = 0; i < gSaveBlock2Ptr->frontier.curChallengeBattleNum; i++)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
if (gSaveBlock2Ptr->frontier.trainerIds[i] == id)
|
2018-10-21 00:06:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == gSaveBlock2Ptr->frontier.curChallengeBattleNum)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
gTrainerBattleOpponent_A = id;
|
|
|
|
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
|
|
|
|
if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < 7)
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
u16 GetRandomScaledFrontierTrainerId(u8 challengeNum, u8 battleNum)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u16 trainerId;
|
|
|
|
|
|
|
|
if (challengeNum <= 7)
|
|
|
|
{
|
|
|
|
if (battleNum == 6)
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
// The last battle in each challenge has a jump in difficulty, pulls from a table with higher ranges
|
|
|
|
trainerId = (sFrontierTrainerIdRangesHard[challengeNum][1] - sFrontierTrainerIdRangesHard[challengeNum][0]) + 1;
|
|
|
|
trainerId = sFrontierTrainerIdRangesHard[challengeNum][0] + (Random() % trainerId);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
trainerId = (sFrontierTrainerIdRanges[challengeNum][1] - sFrontierTrainerIdRanges[challengeNum][0]) + 1;
|
|
|
|
trainerId = sFrontierTrainerIdRanges[challengeNum][0] + (Random() % trainerId);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
// After challenge 7, trainer IDs always come from the last, hardest range, which is the same for both trainer ID tables
|
|
|
|
trainerId = (sFrontierTrainerIdRanges[7][1] - sFrontierTrainerIdRanges[7][0]) + 1;
|
|
|
|
trainerId = sFrontierTrainerIdRanges[7][0] + (Random() % trainerId);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return trainerId;
|
|
|
|
}
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
// Unused
|
|
|
|
static void GetRandomScaledFrontierTrainerIdRange(u8 challengeNum, u8 battleNum, u16 *trainerIdPtr, u8 *rangePtr)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
u16 trainerId, range;
|
2018-10-21 00:06:42 +02:00
|
|
|
|
|
|
|
if (challengeNum <= 7)
|
|
|
|
{
|
|
|
|
if (battleNum == 6)
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
// The last battle in each challenge has a jump in difficulty, pulls from a table with higher ranges
|
|
|
|
range = (sFrontierTrainerIdRangesHard[challengeNum][1] - sFrontierTrainerIdRangesHard[challengeNum][0]) + 1;
|
|
|
|
trainerId = sFrontierTrainerIdRangesHard[challengeNum][0];
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
range = (sFrontierTrainerIdRanges[challengeNum][1] - sFrontierTrainerIdRanges[challengeNum][0]) + 1;
|
|
|
|
trainerId = sFrontierTrainerIdRanges[challengeNum][0];
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
// After challenge 7, trainer IDs always come from the last, hardest range, which is the same for both trainer ID tables
|
|
|
|
range = (sFrontierTrainerIdRanges[7][1] - sFrontierTrainerIdRanges[7][0]) + 1;
|
|
|
|
trainerId = sFrontierTrainerIdRanges[7][0];
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*trainerIdPtr = trainerId;
|
2019-12-20 18:52:29 -05:00
|
|
|
*rangePtr = range;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetBattleFacilityTrainerGfxId(u16 trainerId, u8 tempVarId)
|
|
|
|
{
|
|
|
|
u32 i;
|
|
|
|
u8 facilityClass;
|
|
|
|
u8 trainerObjectGfxId;
|
|
|
|
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
|
|
|
}
|
|
|
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
|
|
|
{
|
2019-11-21 00:14:40 -05:00
|
|
|
SetFrontierBrainObjEventGfx_2();
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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:
|
2019-11-20 23:12:51 -05:00
|
|
|
VarSet(VAR_OBJ_GFX_ID_0, OBJ_EVENT_GFX_BOY_1);
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
case 1:
|
2019-11-20 23:12:51 -05:00
|
|
|
VarSet(VAR_OBJ_GFX_ID_1, OBJ_EVENT_GFX_BOY_1);
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
case 15:
|
2019-11-20 23:12:51 -05:00
|
|
|
VarSet(VAR_OBJ_GFX_ID_E, OBJ_EVENT_GFX_BOY_1);
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetEReaderTrainerGfxId(void)
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
SetBattleFacilityTrainerGfxId(TRAINER_EREADER, 0);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetBattleFacilityTrainerGfxId(u16 trainerId)
|
|
|
|
{
|
|
|
|
u32 i;
|
|
|
|
u8 facilityClass;
|
|
|
|
u8 trainerObjectGfxId;
|
|
|
|
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
{
|
2019-11-20 23:12:51 -05:00
|
|
|
return OBJ_EVENT_GFX_BOY_1;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-22 19:22:57 +02:00
|
|
|
void PutNewBattleTowerRecord(struct EmeraldBattleTowerRecord *newRecordEm)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u16 slotValues[6];
|
|
|
|
u16 slotIds[6];
|
|
|
|
s32 i, j, k;
|
|
|
|
s32 slotsCount = 0;
|
2018-10-22 19:22:57 +02:00
|
|
|
struct EmeraldBattleTowerRecord *newRecord = newRecordEm; // Needed to match.
|
2018-10-21 00:06:42 +02:00
|
|
|
|
|
|
|
// Find a record slot of the same player and replace it.
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
{
|
|
|
|
k = 0;
|
2019-09-08 11:53:48 -04:00
|
|
|
for (j = 0; j < TRAINER_ID_LENGTH; j++)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2018-10-22 19:22:57 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.towerRecords[i].trainerId[j] != newRecord->trainerId[j])
|
2018-10-21 00:06:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (j == 4)
|
|
|
|
{
|
|
|
|
for (k = 0; k < PLAYER_NAME_LENGTH; k++)
|
|
|
|
{
|
|
|
|
// BUG: Wrong variable used, 'j' instead of 'k'.
|
2018-10-22 19:22:57 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.towerRecords[i].name[j] != newRecord->name[j])
|
2018-10-21 00:06:42 +02:00
|
|
|
break;
|
2018-10-22 19:22:57 +02:00
|
|
|
if (newRecord->name[j] == EOS)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
k = PLAYER_NAME_LENGTH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k == PLAYER_NAME_LENGTH)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i < 5)
|
|
|
|
{
|
2018-10-22 19:22:57 +02:00
|
|
|
gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecord;
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find an empty record slot.
|
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
{
|
2018-10-21 20:13:12 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.towerRecords[i].winStreak == 0)
|
2018-10-21 00:06:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i < 5)
|
|
|
|
{
|
2018-10-22 19:22:57 +02:00
|
|
|
gSaveBlock2Ptr->frontier.towerRecords[i] = *newRecord;
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find possible slots to replace the record.
|
2018-10-21 20:13:12 +02:00
|
|
|
slotValues[0] = gSaveBlock2Ptr->frontier.towerRecords[0].winStreak;
|
2018-10-21 00:06:42 +02:00
|
|
|
slotIds[0] = 0;
|
|
|
|
slotsCount++;
|
|
|
|
|
|
|
|
for (i = 1; i < 5; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < slotsCount; j++)
|
|
|
|
{
|
2018-10-21 20:13:12 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.towerRecords[i].winStreak < slotValues[j])
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
j = 0;
|
|
|
|
slotsCount = 1;
|
2018-10-21 20:13:12 +02:00
|
|
|
slotValues[0] = gSaveBlock2Ptr->frontier.towerRecords[i].winStreak;
|
2018-10-21 00:06:42 +02:00
|
|
|
slotIds[0] = i;
|
|
|
|
break;
|
|
|
|
}
|
2018-10-21 20:13:12 +02:00
|
|
|
else if (gSaveBlock2Ptr->frontier.towerRecords[i].winStreak > slotValues[j])
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == slotsCount)
|
|
|
|
{
|
2018-10-21 20:13:12 +02:00
|
|
|
slotValues[slotsCount] = gSaveBlock2Ptr->frontier.towerRecords[i].winStreak;
|
2018-10-21 00:06:42 +02:00
|
|
|
slotIds[slotsCount] = i;
|
|
|
|
slotsCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i = Random() % slotsCount;
|
2018-10-22 19:22:57 +02:00
|
|
|
gSaveBlock2Ptr->frontier.towerRecords[slotIds[i]] = *newRecord;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetFrontierTrainerFrontSpriteId(u16 trainerId)
|
|
|
|
{
|
2018-10-25 21:27:10 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-21 00:06:42 +02:00
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
|
|
|
|
}
|
|
|
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
|
|
|
{
|
|
|
|
return GetFrontierBrainTrainerPicIndex();
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
return gFacilityClassToPicIndex[gFacilityTrainers[trainerId].facilityClass];
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
2018-11-01 15:06:50 +01:00
|
|
|
return gFacilityClassToPicIndex[GetRecordedBattleRecordMixFriendClass()];
|
2018-10-21 00:06:42 +02:00
|
|
|
else
|
2018-10-26 23:54:41 +02:00
|
|
|
return gFacilityClassToPicIndex[gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass];
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
2018-11-01 15:06:50 +01:00
|
|
|
return gFacilityClassToPicIndex[gApprentices[GetRecordedBattleApprenticeId()].facilityClass];
|
2018-10-21 00:06:42 +02:00
|
|
|
else
|
2018-10-26 23:54:41 +02:00
|
|
|
return gFacilityClassToPicIndex[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass];
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 GetFrontierOpponentClass(u16 trainerId)
|
|
|
|
{
|
|
|
|
u8 trainerClass = 0;
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-21 00:06:42 +02:00
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
trainerClass = gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass];
|
|
|
|
}
|
|
|
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
|
|
|
{
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 04:22:50 -03:00
|
|
|
trainerClass = GetFrontierBrainTrainerClass();
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else if (trainerId == TRAINER_STEVEN_PARTNER)
|
|
|
|
{
|
|
|
|
trainerClass = gTrainers[TRAINER_STEVEN].trainerClass;
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
trainerClass = gFacilityClassToTrainerClass[gFacilityTrainers[trainerId].facilityClass];
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
|
|
|
{
|
2018-11-01 15:06:50 +01:00
|
|
|
trainerClass = gFacilityClassToTrainerClass[GetRecordedBattleRecordMixFriendClass()];
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
trainerClass = gFacilityClassToTrainerClass[gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass];
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 04:22:50 -03:00
|
|
|
#ifndef NONMATCHING
|
|
|
|
asm("");
|
|
|
|
#endif
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
|
|
|
{
|
2018-11-01 15:06:50 +01:00
|
|
|
trainerClass = gFacilityClassToTrainerClass[gApprentices[GetRecordedBattleApprenticeId()].facilityClass];
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
trainerClass = gFacilityClassToTrainerClass[gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass];
|
Undo PokeCodec's PRs
This commit undoes most of PokeCodec's PRs after the debate in chat. Some
harmless or completely superseded PRs have been left alone, as there is not
much benefit in attempting to undo them.
Reverts #1104, #1108, #1115, #1118, #1119, #1124, #1126, #1127, #1132, #1136,
#1137, #1139, #1140, #1144, #1148, #1149, #1150, #1153, #1155, #1177, #1179,
#1180, #1181, #1182 and #1183.
2020-09-13 04:22:50 -03:00
|
|
|
#ifndef NONMATCHING
|
|
|
|
asm("");
|
|
|
|
#endif
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return trainerClass;
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static u8 GetFrontierTrainerFacilityClass(u16 trainerId)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u8 facilityClass;
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-21 00:06:42 +02:00
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
2018-11-01 15:06:50 +01:00
|
|
|
facilityClass = GetRecordedBattleRecordMixFriendClass();
|
2018-10-21 00:06:42 +02:00
|
|
|
else
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
2018-11-01 15:06:50 +01:00
|
|
|
facilityClass = gApprentices[GetRecordedBattleApprenticeId()].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
else
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return facilityClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetFrontierTrainerName(u8 *dst, u16 trainerId)
|
|
|
|
{
|
|
|
|
s32 i = 0;
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-21 00:06:42 +02:00
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
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];
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
for (i = 0; i < PLAYER_NAME_LENGTH; i++)
|
|
|
|
dst[i] = gFacilityTrainers[trainerId].trainerName[i];
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
|
|
|
{
|
|
|
|
sub_8186468(dst);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
struct EmeraldBattleTowerRecord *record = &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND];
|
2018-10-21 00:06:42 +02:00
|
|
|
TVShowConvertInternationalString(dst, record->name, record->language);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u8 id, language;
|
|
|
|
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
|
|
|
{
|
2018-11-01 15:06:50 +01:00
|
|
|
id = GetRecordedBattleApprenticeId();
|
|
|
|
language = GetRecordedBattleApprenticeLanguage();
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
struct Apprentice *apprentice = &gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE];
|
2018-10-21 00:06:42 +02:00
|
|
|
id = apprentice->id;
|
|
|
|
language = apprentice->language;
|
|
|
|
}
|
|
|
|
TVShowConvertInternationalString(dst, GetApprenticeNameInLanguage(id, language), language);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dst[i] = EOS;
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static bool8 IsFrontierTrainerFemale(u16 trainerId)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u32 i;
|
|
|
|
u8 facilityClass;
|
|
|
|
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.ereaderTrainer.facilityClass;
|
|
|
|
}
|
|
|
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
|
|
|
{
|
|
|
|
return IsFrontierBrainFemale();
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
facilityClass = gFacilityTrainers[trainerId].facilityClass;
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
facilityClass = gApprentices[gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id].facilityClass;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2018-10-22 19:22:57 +02:00
|
|
|
void FillFrontierTrainerParty(u8 monsCount)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
ZeroEnemyPartyMons();
|
2018-10-22 19:22:57 +02:00
|
|
|
FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
2018-10-22 19:22:57 +02:00
|
|
|
void FillFrontierTrainersParties(u8 monsCount)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
ZeroEnemyPartyMons();
|
2018-10-22 19:22:57 +02:00
|
|
|
FillTrainerParty(gTrainerBattleOpponent_A, 0, monsCount);
|
|
|
|
FillTrainerParty(gTrainerBattleOpponent_B, 3, monsCount);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void FillTentTrainerParty(u8 monsCount)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
ZeroEnemyPartyMons();
|
2018-10-24 23:14:45 +02:00
|
|
|
FillTentTrainerParty_(gTrainerBattleOpponent_A, 0, monsCount);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
2018-10-22 19:22:57 +02:00
|
|
|
static void FillTrainerParty(u16 trainerId, u8 firstMonId, u8 monCount)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
s32 i, j;
|
|
|
|
u16 chosenMonIndices[4];
|
2019-12-18 02:32:52 -05:00
|
|
|
u8 friendship = MAX_FRIENDSHIP;
|
2018-10-24 23:14:45 +02:00
|
|
|
u8 level = SetFacilityPtrsGetLevel();
|
2018-10-21 00:06:42 +02:00
|
|
|
u8 fixedIV = 0;
|
|
|
|
u8 bfMonCount;
|
2020-01-05 10:50:32 -05:00
|
|
|
const u16 *monSet = NULL;
|
2018-10-21 00:06:42 +02:00
|
|
|
u32 otID = 0;
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
// Normal battle frontier trainer.
|
|
|
|
fixedIV = GetFrontierTrainerFixedIvs(trainerId);
|
2020-01-05 10:50:32 -05:00
|
|
|
monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
for (i = firstMonId; i < firstMonId + 3; i++)
|
2019-01-13 12:12:27 +01:00
|
|
|
CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i - firstMonId]);
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
|
|
|
{
|
|
|
|
CreateFrontierBrainPokemon();
|
|
|
|
return;
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
// Record mixed player.
|
|
|
|
for (j = 0, i = firstMonId; i < firstMonId + monCount; j++, i++)
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
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)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2019-01-13 12:12:27 +01:00
|
|
|
CreateBattleTowerMon2(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].party[j], FALSE);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Apprentice.
|
|
|
|
for (i = firstMonId; i < firstMonId + 3; i++)
|
2018-10-26 23:54:41 +02:00
|
|
|
CreateApprenticeMon(&gEnemyParty[i], &gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE], i - firstMonId);
|
2018-10-21 00:06:42 +02:00
|
|
|
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.
|
2020-01-05 10:50:32 -05:00
|
|
|
for (bfMonCount = 0; monSet[bfMonCount] != 0xFFFF; bfMonCount++)
|
2018-10-21 00:06:42 +02:00
|
|
|
;
|
|
|
|
i = 0;
|
|
|
|
otID = Random32();
|
|
|
|
while (i != monCount)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 monId = monSet[Random() % bfMonCount];
|
|
|
|
if ((level == 50 || level == 20) && monId > FRONTIER_MONS_HIGH_TIER)
|
2018-10-21 00:06:42 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Ensure this pokemon species isn't a duplicate.
|
|
|
|
for (j = 0; j < i + firstMonId; j++)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
if (GetMonData(&gEnemyParty[j], MON_DATA_SPECIES, NULL) == gFacilityTrainerMons[monId].species)
|
2018-10-21 00:06:42 +02:00
|
|
|
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
|
2020-01-05 10:50:32 -05:00
|
|
|
&& GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) == gBattleFrontierHeldItems[gFacilityTrainerMons[monId].itemTableId])
|
2018-10-21 00:06:42 +02:00
|
|
|
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++)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
if (chosenMonIndices[j] == monId)
|
2018-10-21 00:06:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (j != i)
|
|
|
|
continue;
|
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
chosenMonIndices[i] = monId;
|
2018-10-21 00:06:42 +02:00
|
|
|
|
|
|
|
// Place the chosen pokemon into the trainer's party.
|
2018-11-11 16:44:27 +01:00
|
|
|
CreateMonWithEVSpreadNatureOTID(&gEnemyParty[i + firstMonId],
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].species,
|
2018-10-21 00:06:42 +02:00
|
|
|
level,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].nature,
|
2018-10-21 00:06:42 +02:00
|
|
|
fixedIV,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].evSpread,
|
2018-10-21 00:06:42 +02:00
|
|
|
otID);
|
|
|
|
|
2019-12-18 02:32:52 -05:00
|
|
|
friendship = MAX_FRIENDSHIP;
|
2018-10-21 00:06:42 +02:00
|
|
|
// Give the chosen pokemon its specified moves.
|
2018-12-25 12:50:15 -05:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonMoveSlot(&gEnemyParty[i + firstMonId], gFacilityTrainerMons[monId].moves[j], j);
|
|
|
|
if (gFacilityTrainerMons[monId].moves[j] == MOVE_FRUSTRATION)
|
2018-10-21 00:06:42 +02:00
|
|
|
friendship = 0; // Frustration is more powerful the lower the pokemon's friendship is.
|
|
|
|
}
|
|
|
|
|
|
|
|
SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_FRIENDSHIP, &friendship);
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monId].itemTableId]);
|
2018-10-21 00:06:42 +02:00
|
|
|
|
|
|
|
// 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.
|
2018-10-25 21:27:10 +02:00
|
|
|
static void Unused_CreateApprenticeMons(u16 trainerId, u8 firstMonId)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
s32 i, j;
|
2019-12-18 02:32:52 -05:00
|
|
|
u8 friendship = MAX_FRIENDSHIP;
|
2018-10-21 00:06:42 +02:00
|
|
|
u8 level = 0;
|
|
|
|
u8 fixedIV = 0;
|
|
|
|
struct Apprentice *apprentice = &gSaveBlock2Ptr->apprentices[0];
|
|
|
|
|
2019-11-20 17:36:52 -05:00
|
|
|
if (apprentice->numQuestions < 5)
|
2018-10-21 00:06:42 +02:00
|
|
|
fixedIV = 6;
|
|
|
|
else
|
|
|
|
fixedIV = 9;
|
|
|
|
|
|
|
|
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_50)
|
|
|
|
level = 100;
|
|
|
|
else
|
|
|
|
level = 50;
|
|
|
|
|
|
|
|
for (i = 0; i != 3; i++)
|
|
|
|
{
|
2018-10-22 19:22:57 +02:00
|
|
|
CreateMonWithEVSpread(&gEnemyParty[firstMonId + i], apprentice->party[i].species, level, fixedIV, 8);
|
2019-12-18 02:32:52 -05:00
|
|
|
friendship = MAX_FRIENDSHIP;
|
2018-12-25 12:50:15 -05:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2018-10-22 19:22:57 +02:00
|
|
|
if (apprentice->party[i].moves[j] == MOVE_FRUSTRATION)
|
2018-10-21 00:06:42 +02:00
|
|
|
friendship = 0;
|
|
|
|
}
|
|
|
|
SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_FRIENDSHIP, &friendship);
|
2018-10-22 19:22:57 +02:00
|
|
|
SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_HELD_ITEM, &apprentice->party[i].item);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 GetRandomFrontierMonFromSet(u16 trainerId)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2018-10-24 23:14:45 +02:00
|
|
|
u8 level = SetFacilityPtrsGetLevel();
|
2020-01-05 10:50:32 -05:00
|
|
|
const u16 *monSet = gFacilityTrainers[trainerId].monSet;
|
|
|
|
u8 numMons = 0;
|
|
|
|
u32 monId = monSet[numMons];
|
2018-10-21 00:06:42 +02:00
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
while (monId != 0xFFFF)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
numMons++;
|
|
|
|
monId = monSet[numMons];
|
|
|
|
if (monId == 0xFFFF)
|
2018-10-21 00:06:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
monId = monSet[Random() % numMons];
|
|
|
|
} while((level == 50 || level == 20) && monId > FRONTIER_MONS_HIGH_TIER);
|
2018-10-21 00:06:42 +02:00
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
return monId;
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
static void FillFactoryTrainerParty(void)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
ZeroEnemyPartyMons();
|
|
|
|
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
|
2018-10-26 23:54:41 +02:00
|
|
|
FillFactoryFrontierTrainerParty(gTrainerBattleOpponent_A, 0);
|
2018-10-21 00:06:42 +02:00
|
|
|
else
|
2018-10-26 23:54:41 +02:00
|
|
|
FillFactoryTentTrainerParty(gTrainerBattleOpponent_A, 0);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
static void FillFactoryFrontierTrainerParty(u16 trainerId, u8 firstMonId)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u8 i, j;
|
|
|
|
u8 friendship;
|
|
|
|
u8 level;
|
|
|
|
u8 fixedIV;
|
|
|
|
u32 otID;
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode; // Unused variable.
|
|
|
|
u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
2018-10-27 17:39:05 +02:00
|
|
|
u8 challengeNum = gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][0] / 7;
|
2018-10-21 00:06:42 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.curChallengeBattleNum < 6)
|
2018-11-11 16:44:27 +01:00
|
|
|
fixedIV = GetFactoryMonFixedIV(challengeNum, 0);
|
2018-10-21 00:06:42 +02:00
|
|
|
else
|
2018-11-11 16:44:27 +01:00
|
|
|
fixedIV = GetFactoryMonFixedIV(challengeNum, 1);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId == TRAINER_EREADER)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
for (i = firstMonId; i < firstMonId + 3; i++)
|
2019-01-13 12:12:27 +01:00
|
|
|
CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i - firstMonId]);
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (trainerId == TRAINER_FRONTIER_BRAIN)
|
|
|
|
{
|
2018-11-11 16:44:27 +01:00
|
|
|
FillFactoryBrainParty();
|
2018-10-21 00:06:42 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fixedIV = 31;
|
|
|
|
}
|
|
|
|
|
2018-10-24 23:14:45 +02:00
|
|
|
level = SetFacilityPtrsGetLevel();
|
2018-10-21 00:06:42 +02:00
|
|
|
otID = T1_READ_32(gSaveBlock2Ptr->playerTrainerId);
|
2019-12-02 08:44:34 -05:00
|
|
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 monId = gUnknown_03006298[i];
|
2018-11-11 16:44:27 +01:00
|
|
|
CreateMonWithEVSpreadNatureOTID(&gEnemyParty[firstMonId + i],
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].species,
|
2018-10-21 00:06:42 +02:00
|
|
|
level,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].nature,
|
2018-10-21 00:06:42 +02:00
|
|
|
fixedIV,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].evSpread,
|
2018-10-21 00:06:42 +02:00
|
|
|
otID);
|
|
|
|
|
|
|
|
friendship = 0;
|
2018-12-25 12:50:15 -05:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonMoveAvoidReturn(&gEnemyParty[firstMonId + i], gFacilityTrainerMons[monId].moves[j], j);
|
2018-10-21 00:06:42 +02:00
|
|
|
|
|
|
|
SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_FRIENDSHIP, &friendship);
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monId].itemTableId]);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
static void FillFactoryTentTrainerParty(u16 trainerId, u8 firstMonId)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
u8 i, j;
|
|
|
|
u8 friendship;
|
|
|
|
u8 level = 30;
|
|
|
|
u8 fixedIV = 0;
|
|
|
|
u32 otID = T1_READ_32(gSaveBlock2Ptr->playerTrainerId);
|
|
|
|
|
2019-12-02 08:44:34 -05:00
|
|
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 monId = gUnknown_03006298[i];
|
2018-11-11 16:44:27 +01:00
|
|
|
CreateMonWithEVSpreadNatureOTID(&gEnemyParty[firstMonId + i],
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].species,
|
2018-10-21 00:06:42 +02:00
|
|
|
level,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].nature,
|
2018-10-21 00:06:42 +02:00
|
|
|
fixedIV,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].evSpread,
|
2018-10-21 00:06:42 +02:00
|
|
|
otID);
|
|
|
|
|
|
|
|
friendship = 0;
|
2018-12-25 12:50:15 -05:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonMoveAvoidReturn(&gEnemyParty[firstMonId + i], gFacilityTrainerMons[monId].moves[j], j);
|
|
|
|
if (gFacilityTrainerMons[monId].moves[j] == MOVE_FRUSTRATION)
|
2018-10-21 00:06:42 +02:00
|
|
|
friendship = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_FRIENDSHIP, &friendship);
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonData(&gEnemyParty[firstMonId + i], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monId].itemTableId]);
|
2018-10-21 00:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-21 20:13:12 +02:00
|
|
|
void FrontierSpeechToString(const u16 *words)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
ConvertEasyChatWordsToString(gStringVar4, words, 3, 2);
|
2018-12-20 22:53:08 +01:00
|
|
|
if (GetStringWidth(1, gStringVar4, -1) > 204u)
|
2018-10-21 00:06:42 +02:00
|
|
|
{
|
|
|
|
s32 i = 0;
|
|
|
|
|
|
|
|
ConvertEasyChatWordsToString(gStringVar4, words, 2, 3);
|
|
|
|
while (gStringVar4[i++] != CHAR_NEWLINE)
|
|
|
|
;
|
|
|
|
while (gStringVar4[i] != CHAR_NEWLINE)
|
|
|
|
i++;
|
|
|
|
|
|
|
|
gStringVar4[i] = CHAR_PROMPT_SCROLL;
|
|
|
|
}
|
|
|
|
}
|
2018-10-21 20:13:12 +02:00
|
|
|
|
2019-11-28 22:46:39 -05:00
|
|
|
static void GetOpponentIntroSpeech(void)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
u16 trainerId;
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-21 20:13:12 +02:00
|
|
|
|
|
|
|
if (gSpecialVar_0x8005)
|
|
|
|
trainerId = gTrainerBattleOpponent_B;
|
|
|
|
else
|
|
|
|
trainerId = gTrainerBattleOpponent_A;
|
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-21 20:13:12 +02:00
|
|
|
FrontierSpeechToString(gSaveBlock2Ptr->frontier.ereaderTrainer.greeting);
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-21 20:13:12 +02:00
|
|
|
FrontierSpeechToString(gFacilityTrainers[trainerId].speechBefore);
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
|
|
|
FrontierSpeechToString(gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].greeting);
|
2018-10-21 20:13:12 +02:00
|
|
|
else
|
2019-11-20 17:36:52 -05:00
|
|
|
BufferApprenticeChallengeText(trainerId - TRAINER_RECORD_MIXING_APPRENTICE);
|
2018-10-21 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void HandleSpecialTrainerBattleEnd(void)
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
|
2018-11-01 15:06:50 +01:00
|
|
|
RecordedBattle_SaveBattleOutcome();
|
2018-10-21 20:13:12 +02:00
|
|
|
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:
|
2018-10-22 19:22:57 +02:00
|
|
|
CopyEReaderTrainerFarewellMessage();
|
2018-10-21 20:13:12 +02:00
|
|
|
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:
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
case FRONTIER_MODE_DOUBLES:
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainerParty(FRONTIER_DOUBLES_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
|
|
|
|
break;
|
|
|
|
case FRONTIER_MODE_MULTIS:
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainersParties(FRONTIER_MULTI_PARTY_SIZE);
|
2019-02-07 11:37:28 -06:00
|
|
|
gPartnerTrainerId = gSaveBlock2Ptr->frontier.trainerIds[17];
|
2018-10-24 23:14:45 +02:00
|
|
|
FillPartnerParty(gPartnerTrainerId);
|
2018-10-21 20:13:12 +02:00
|
|
|
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;
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainersParties(FRONTIER_MULTI_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(0));
|
2018-10-21 20:13:12 +02:00
|
|
|
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);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(12));
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
case SPECIAL_BATTLE_EREADER:
|
|
|
|
ZeroEnemyPartyMons();
|
|
|
|
for (i = 0; i < 3; i++)
|
2019-01-13 12:12:27 +01:00
|
|
|
CreateBattleTowerMon(&gEnemyParty[i], &gSaveBlock2Ptr->frontier.ereaderTrainer.party[i]);
|
2018-10-21 20:13:12 +02:00
|
|
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_EREADER_TRAINER;
|
|
|
|
gTrainerBattleOpponent_A = 0;
|
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(13));
|
2018-10-21 20:13:12 +02:00
|
|
|
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)
|
2020-04-09 15:18:53 -04:00
|
|
|
FillFrontierTrainerParty(DOME_BATTLE_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
sub_806E694(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(3));
|
2018-10-21 20:13:12 +02:00
|
|
|
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)
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
else
|
2019-11-24 16:58:40 -05:00
|
|
|
FillTentTrainerParty(FRONTIER_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(4));
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
case SPECIAL_BATTLE_ARENA:
|
|
|
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_ARENA;
|
|
|
|
if (gSaveBlock2Ptr->frontier.lvlMode != FRONTIER_LVL_TENT)
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
else
|
2019-11-24 16:58:40 -05:00
|
|
|
FillTentTrainerParty(FRONTIER_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(5));
|
2018-10-21 20:13:12 +02:00
|
|
|
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;
|
2018-10-26 23:54:41 +02:00
|
|
|
FillFactoryTrainerParty();
|
2018-10-21 20:13:12 +02:00
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(6));
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
case SPECIAL_BATTLE_PIKE_SINGLE:
|
|
|
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER;
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(7));
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
case SPECIAL_BATTLE_PYRAMID:
|
|
|
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID;
|
2019-11-24 16:58:40 -05:00
|
|
|
FillFrontierTrainerParty(FRONTIER_PARTY_SIZE);
|
2018-10-21 20:13:12 +02:00
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(10));
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
case SPECIAL_BATTLE_PIKE_DOUBLE:
|
|
|
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS;
|
2018-10-22 19:22:57 +02:00
|
|
|
FillFrontierTrainersParties(1);
|
2018-10-21 20:13:12 +02:00
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
2020-07-02 15:45:37 -04:00
|
|
|
BattleTransition_StartOnField(GetSpecialBattleTransition(7));
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
case SPECIAL_BATTLE_STEVEN:
|
|
|
|
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER;
|
2018-10-24 23:14:45 +02:00
|
|
|
FillPartnerParty(TRAINER_STEVEN_PARTNER);
|
2018-10-21 20:13:12 +02:00
|
|
|
gApproachingTrainerId = 0;
|
2019-11-01 17:50:54 -04:00
|
|
|
BattleSetup_ConfigureTrainerBattle(MossdeepCity_SpaceCenter_2F_EventScript_MaxieTrainer + 1);
|
2018-10-21 20:13:12 +02:00
|
|
|
gApproachingTrainerId = 1;
|
2019-11-01 17:50:54 -04:00
|
|
|
BattleSetup_ConfigureTrainerBattle(MossdeepCity_SpaceCenter_2F_EventScript_TabithaTrainer + 1);
|
2018-10-21 20:13:12 +02:00
|
|
|
gPartnerTrainerId = TRAINER_STEVEN_PARTNER;
|
|
|
|
CreateTask(Task_StartBattleAfterTransition, 1);
|
|
|
|
PlayMapChosenOrBattleBGM(0);
|
|
|
|
BattleTransition_StartOnField(B_TRANSITION_MAGMA);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void SaveCurrentWinStreak(void)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
u8 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
|
|
|
u8 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
|
|
|
u16 winStreak = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
|
|
|
|
|
2018-10-27 17:39:05 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode] < winStreak)
|
|
|
|
gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode] = winStreak;
|
2018-10-21 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void sub_8163EE4(void)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
u8 lvlMode, battleMode, class;
|
|
|
|
struct EmeraldBattleTowerRecord *playerRecord = &gSaveBlock2Ptr->frontier.towerPlayer;
|
|
|
|
|
2018-10-22 19:22:57 +02:00
|
|
|
ClearBattleTowerRecord(playerRecord);
|
2018-10-21 20:13:12 +02:00
|
|
|
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;
|
2018-11-01 21:31:10 +01:00
|
|
|
CopyTrainerId(playerRecord->trainerId, gSaveBlock2Ptr->playerTrainerId);
|
2018-10-21 20:13:12 +02:00
|
|
|
StringCopy7(playerRecord->name, gSaveBlock2Ptr->playerName);
|
|
|
|
playerRecord->winStreak = GetCurrentBattleTowerWinStreak(lvlMode, battleMode);
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
2019-02-27 12:45:31 -06:00
|
|
|
playerRecord->greeting[i] = gSaveBlock1Ptr->easyChatBattleStart[i];
|
|
|
|
playerRecord->speechWon[i] = gSaveBlock1Ptr->easyChatBattleWon[i];
|
|
|
|
playerRecord->speechLost[i] = gSaveBlock1Ptr->easyChatBattleLost[i];
|
2018-10-21 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
for (i = 0; i < MAX_FRONTIER_PARTY_SIZE; i++)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
2018-10-22 19:22:57 +02:00
|
|
|
if (gSaveBlock2Ptr->frontier.selectedPartyMons[i] != 0)
|
|
|
|
sub_80686FC(&gPlayerParty[gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1], &playerRecord->party[i]);
|
2018-10-21 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
playerRecord->language = gGameLanguage;
|
|
|
|
CalcEmeraldBattleTowerChecksum(&gSaveBlock2Ptr->frontier.towerPlayer);
|
|
|
|
SaveCurrentWinStreak();
|
|
|
|
}
|
|
|
|
|
2019-11-28 21:09:35 -05:00
|
|
|
static void SaveTowerChallenge(void)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
u16 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
|
|
|
u16 battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
2018-10-27 17:39:05 +02:00
|
|
|
s32 challengeNum = (signed)(gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode] / 7);
|
2018-10-21 20:13:12 +02:00
|
|
|
|
|
|
|
if (gSpecialVar_0x8005 == 0 && (challengeNum > 1 || gSaveBlock2Ptr->frontier.curChallengeBattleNum != 0))
|
|
|
|
sub_8163EE4();
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.challengeStatus = gSpecialVar_0x8005;
|
2018-10-21 20:13:12 +02:00
|
|
|
VarSet(VAR_TEMP_0, 0);
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.challengePaused = TRUE;
|
|
|
|
SaveGameFrontier();
|
2018-10-21 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void nullsub_61(void)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-11-16 20:50:52 -05:00
|
|
|
static void nullsub_116(void)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static void GetApprenticeMultiPartnerParty(u16 trainerId)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
s32 i, count;
|
2020-04-09 15:18:53 -04:00
|
|
|
u32 validSpecies[MULTI_PARTY_SIZE];
|
2018-10-21 20:13:12 +02:00
|
|
|
u16 species1 = GetMonData(&gPlayerParty[0], MON_DATA_SPECIES, NULL);
|
|
|
|
u16 species2 = GetMonData(&gPlayerParty[1], MON_DATA_SPECIES, NULL);
|
|
|
|
|
|
|
|
count = 0;
|
2020-04-09 15:18:53 -04:00
|
|
|
for (i = 0; i < MULTI_PARTY_SIZE; i++)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
u16 apprenticeSpecies = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].party[i].species;
|
2018-10-21 20:13:12 +02:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static void GetRecordMixFriendMultiPartnerParty(u16 trainerId)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
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++)
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
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)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
validSpecies[count] = i;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gUnknown_03006298[2] = validSpecies[Random() % count];
|
|
|
|
do
|
|
|
|
{
|
|
|
|
gUnknown_03006298[3] = validSpecies[Random() % count];
|
|
|
|
} while (gUnknown_03006298[2] == gUnknown_03006298[3]);
|
|
|
|
}
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static void LoadMultiPartnerCandidatesData(void)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
s32 i, j, k;
|
|
|
|
u32 spArray[5];
|
|
|
|
s32 r10;
|
|
|
|
u16 trainerId;
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 monId;
|
2018-10-21 20:13:12 +02:00
|
|
|
u32 lvlMode, battleMode;
|
|
|
|
s32 challengeNum;
|
|
|
|
u32 species1, species2;
|
|
|
|
u32 level;
|
2019-11-20 22:55:44 -05:00
|
|
|
struct ObjectEventTemplate *objEventTemplates;
|
2018-10-21 20:13:12 +02:00
|
|
|
|
2019-11-20 22:55:44 -05:00
|
|
|
objEventTemplates = gSaveBlock1Ptr->objectEventTemplates;
|
2018-10-21 20:13:12 +02:00
|
|
|
lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
|
|
|
|
battleMode = VarGet(VAR_FRONTIER_BATTLE_MODE);
|
2018-10-27 17:39:05 +02:00
|
|
|
challengeNum = gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode] / 7;
|
2018-10-21 20:13:12 +02:00
|
|
|
species1 = GetMonData(&gPlayerParty[0], MON_DATA_SPECIES, NULL);
|
|
|
|
species2 = GetMonData(&gPlayerParty[1], MON_DATA_SPECIES, NULL);
|
2018-10-24 23:14:45 +02:00
|
|
|
level = SetFacilityPtrsGetLevel();
|
2018-10-21 20:13:12 +02:00
|
|
|
|
2018-10-22 19:22:57 +02:00
|
|
|
j = 0;
|
|
|
|
do
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
trainerId = GetRandomScaledFrontierTrainerId(challengeNum, 0);
|
2018-10-21 20:13:12 +02:00
|
|
|
for (i = 0; i < j; i++)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
if (gSaveBlock2Ptr->frontier.trainerIds[i] == trainerId)
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
2019-02-07 11:37:28 -06:00
|
|
|
if (gFacilityTrainers[gSaveBlock2Ptr->frontier.trainerIds[i]].facilityClass == gFacilityTrainers[trainerId].facilityClass)
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (i != j);
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[j] = trainerId;
|
2018-10-22 19:22:57 +02:00
|
|
|
j++;
|
|
|
|
} while (j < 6);
|
2018-10-21 20:13:12 +02:00
|
|
|
|
|
|
|
r10 = 8;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
trainerId = gSaveBlock2Ptr->frontier.trainerIds[i];
|
2019-11-20 22:55:44 -05:00
|
|
|
objEventTemplates[i + 1].graphicsId = GetBattleFacilityTrainerGfxId(trainerId);
|
2018-10-21 20:13:12 +02:00
|
|
|
for (j = 0; j < 2; j++)
|
|
|
|
{
|
|
|
|
while (1)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
monId = GetRandomFrontierMonFromSet(trainerId);
|
|
|
|
if (j % 2 != 0 && gFacilityTrainerMons[gSaveBlock2Ptr->frontier.trainerIds[r10 - 1]].itemTableId == gFacilityTrainerMons[monId].itemTableId)
|
2018-10-21 20:13:12 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
for (k = 8; k < r10; k++)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
if (gFacilityTrainerMons[gSaveBlock2Ptr->frontier.trainerIds[k]].species == gFacilityTrainerMons[monId].species)
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
2020-01-05 10:50:32 -05:00
|
|
|
if (species1 == gFacilityTrainerMons[monId].species)
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
2020-01-05 10:50:32 -05:00
|
|
|
if (species2 == gFacilityTrainerMons[monId].species)
|
2018-10-21 20:13:12 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (k == r10)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[r10] = monId;
|
2018-10-21 20:13:12 +02:00
|
|
|
r10++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r10 = 0;
|
2018-10-24 23:14:45 +02:00
|
|
|
ValidateApprenticesChecksums();
|
2019-11-20 17:36:52 -05:00
|
|
|
for (i = 0; i < APPRENTICE_COUNT; i++)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
if (gSaveBlock2Ptr->apprentices[i].lvlMode != 0
|
2020-01-08 05:43:06 -05:00
|
|
|
&& sApprenticeChallengeThreshold[gSaveBlock2Ptr->apprentices[i].numQuestions] / 7 <= challengeNum
|
2018-10-21 20:13:12 +02:00
|
|
|
&& gSaveBlock2Ptr->apprentices[i].lvlMode - 1 == lvlMode)
|
|
|
|
{
|
|
|
|
k = 0;
|
2020-04-09 15:18:53 -04:00
|
|
|
for (j = 0; j < MULTI_PARTY_SIZE; j++)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
2018-10-22 19:22:57 +02:00
|
|
|
if (species1 != gSaveBlock2Ptr->apprentices[i].party[j].species
|
|
|
|
&& species2 != gSaveBlock2Ptr->apprentices[i].party[j].species)
|
2018-10-21 20:13:12 +02:00
|
|
|
{
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (k > 2)
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
spArray[r10] = i + TRAINER_RECORD_MIXING_APPRENTICE;
|
2018-10-21 20:13:12 +02:00
|
|
|
r10++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (r10 != 0)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[6] = spArray[Random() % r10];
|
2019-11-20 22:55:44 -05:00
|
|
|
objEventTemplates[7].graphicsId = GetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.trainerIds[6]);
|
2018-10-21 20:13:12 +02:00
|
|
|
FlagClear(FLAG_HIDE_BATTLE_TOWER_MULTI_BATTLE_PARTNER_ALT_1);
|
2020-01-08 05:43:06 -05:00
|
|
|
GetApprenticeMultiPartnerParty(gSaveBlock2Ptr->frontier.trainerIds[6]);
|
2018-10-21 20:13:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
spArray[r10] = i + TRAINER_RECORD_MIXING_FRIEND;
|
2018-10-21 20:13:12 +02:00
|
|
|
r10++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (r10 != 0)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[7] = spArray[Random() % r10];
|
2019-11-20 22:55:44 -05:00
|
|
|
objEventTemplates[8].graphicsId = GetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.trainerIds[7]);
|
2018-10-21 20:13:12 +02:00
|
|
|
FlagClear(FLAG_HIDE_BATTLE_TOWER_MULTI_BATTLE_PARTNER_ALT_2);
|
2020-01-08 05:43:06 -05:00
|
|
|
GetRecordMixFriendMultiPartnerParty(gSaveBlock2Ptr->frontier.trainerIds[7]);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
static void sub_81646BC(u16 trainerId, u16 monId)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
u16 move = 0;
|
|
|
|
u16 species = 0;
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-22 19:22:57 +02:00
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId != TRAINER_EREADER)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
move = gFacilityTrainerMons[monId].moves[0];
|
|
|
|
species = gFacilityTrainerMons[monId].species;
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
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;
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
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;
|
2018-10-22 19:22:57 +02:00
|
|
|
for (i = 0; i < PLAYER_NAME_LENGTH; i++)
|
2018-10-26 23:54:41 +02:00
|
|
|
gStringVar3[i] = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].playerName[i];
|
2018-10-22 19:22:57 +02:00
|
|
|
gStringVar3[i] = EOS;
|
2018-10-26 23:54:41 +02:00
|
|
|
ConvertInternationalString(gStringVar3, gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].language);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StringCopy(gStringVar1, gMoveNames[move]);
|
|
|
|
StringCopy(gStringVar2, gSpeciesNames[species]);
|
|
|
|
}
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static void ShowPartnerCandidateMessage(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
s32 i, j, partnerId;
|
2020-01-05 10:50:32 -05:00
|
|
|
s32 monId;
|
2018-10-24 23:14:45 +02:00
|
|
|
s32 level = SetFacilityPtrsGetLevel();
|
2018-10-27 21:01:35 +02:00
|
|
|
u16 winStreak = GetCurrentFacilityWinStreak();
|
|
|
|
s32 challengeNum = winStreak / 7;
|
2018-10-22 19:22:57 +02:00
|
|
|
s32 k = gSpecialVar_LastTalked - 2;
|
2019-02-07 11:37:28 -06:00
|
|
|
s32 trainerId = gSaveBlock2Ptr->frontier.trainerIds[k];
|
2018-10-22 19:22:57 +02:00
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
for (partnerId = 0; partnerId < ARRAY_COUNT(sPartnerTrainerTextTables); partnerId++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
if (sPartnerTrainerTextTables[partnerId].facilityClass == GetFrontierTrainerFacilityClass(trainerId))
|
2018-10-22 19:22:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (gSpecialVar_0x8005)
|
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
case PARTNER_MSGID_INTRO:
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-22 19:22:57 +02:00
|
|
|
return;
|
2019-12-20 18:52:29 -05:00
|
|
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
GetFrontierTrainerName(gStringVar1, trainerId);
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
GetFrontierTrainerName(gStringVar1, trainerId);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
for (i = 0; i < PLAYER_NAME_LENGTH; i++)
|
2018-10-26 23:54:41 +02:00
|
|
|
gStringVar1[i] = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].playerName[i];
|
2018-10-22 19:22:57 +02:00
|
|
|
gStringVar1[i] = EOS;
|
2018-10-26 23:54:41 +02:00
|
|
|
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);
|
2018-10-22 19:22:57 +02:00
|
|
|
GetFrontierTrainerName(gStringVar3, trainerId);
|
|
|
|
}
|
|
|
|
break;
|
2020-01-08 05:43:06 -05:00
|
|
|
case PARTNER_MSGID_MON1:
|
2020-01-05 10:50:32 -05:00
|
|
|
monId = gSaveBlock2Ptr->frontier.trainerIds[8 + k * 2];
|
|
|
|
sub_81646BC(trainerId, monId);
|
2018-10-22 19:22:57 +02:00
|
|
|
break;
|
2020-01-08 05:43:06 -05:00
|
|
|
case PARTNER_MSGID_MON2_ASK:
|
2020-01-05 10:50:32 -05:00
|
|
|
monId = gSaveBlock2Ptr->frontier.trainerIds[9 + k * 2];
|
|
|
|
sub_81646BC(trainerId, monId);
|
2018-10-22 19:22:57 +02:00
|
|
|
break;
|
2020-01-08 05:43:06 -05:00
|
|
|
case PARTNER_MSGID_ACCEPT:
|
2018-10-22 19:22:57 +02:00
|
|
|
gPartnerTrainerId = trainerId;
|
2019-12-20 18:52:29 -05:00
|
|
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[18] = gSaveBlock2Ptr->frontier.trainerIds[8 + k * 2];
|
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[19] = gSaveBlock2Ptr->frontier.trainerIds[9 + k * 2];
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[18] = gUnknown_03006298[2];
|
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[19] = gUnknown_03006298[3];
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[18] = gUnknown_03006298[0];
|
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[19] = gUnknown_03006298[1];
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
for (k = 0; k < 14; k++)
|
|
|
|
{
|
|
|
|
while (1)
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
i = GetRandomScaledFrontierTrainerId(challengeNum, k / 2);
|
2018-10-22 19:22:57 +02:00
|
|
|
if (gPartnerTrainerId == i)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (j = 0; j < k; j++)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
if (gSaveBlock2Ptr->frontier.trainerIds[j] == i)
|
2018-10-22 19:22:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (j == k)
|
|
|
|
break;
|
|
|
|
}
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[k] = i;
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[17] = trainerId;
|
2018-10-22 19:22:57 +02:00
|
|
|
break;
|
2020-01-08 05:43:06 -05:00
|
|
|
case PARTNER_MSGID_REJECT:
|
2018-10-22 19:22:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-22 19:22:57 +02:00
|
|
|
return;
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
// First check is redundant, only needs to make sure it's not an Apprentice
|
2019-12-20 18:52:29 -05:00
|
|
|
if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
ShowFieldMessage(sPartnerTrainerTextTables[partnerId].strings[gSpecialVar_0x8005]);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
ShowFieldMessage(sPartnerTrainerTextTables[partnerId].strings[gSpecialVar_0x8005]);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
2020-01-08 05:43:06 -05:00
|
|
|
// Trainer is a former/record-mixed Apprentice, do Apprentice message
|
2018-10-22 19:22:57 +02:00
|
|
|
else
|
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
u8 apprenticeId = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].id;
|
|
|
|
ShowFieldMessage(sPartnerApprenticeTextTables[apprenticeId][gSpecialVar_0x8005]);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static void LoadLinkMultiOpponentsData(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2018-10-27 17:39:05 +02:00
|
|
|
challengeNum = gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode] / 7;
|
2018-12-31 02:22:21 -06:00
|
|
|
if (IsLinkTaskFinished())
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
trainerId = GetRandomScaledFrontierTrainerId(challengeNum, i / 2);
|
2018-10-22 19:22:57 +02:00
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
if (gSaveBlock2Ptr->frontier.trainerIds[j] == trainerId)
|
2018-10-22 19:22:57 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (i != j);
|
|
|
|
if (i == j) // This condition is always true, because of the loop above.
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[i] = trainerId;
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
gSpecialVar_Result = 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2018-12-31 02:22:21 -06:00
|
|
|
if (IsLinkTaskFinished())
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
SendBlock(bitmask_all_link_players_but_self(), &gSaveBlock2Ptr->frontier.trainerIds, sizeof(gSaveBlock2Ptr->frontier.trainerIds));
|
2018-10-22 19:22:57 +02:00
|
|
|
gSpecialVar_Result = 3;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if ((GetBlockReceivedStatus() & 3) == 3)
|
|
|
|
{
|
|
|
|
ResetBlockReceivedFlags();
|
2019-02-07 11:37:28 -06:00
|
|
|
memcpy(&gSaveBlock2Ptr->frontier.trainerIds, gBlockRecvBuffer, sizeof(gSaveBlock2Ptr->frontier.trainerIds));
|
|
|
|
gTrainerBattleOpponent_A = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2];
|
|
|
|
gTrainerBattleOpponent_B = gSaveBlock2Ptr->frontier.trainerIds[battleNum * 2 + 1];
|
2018-10-22 19:22:57 +02:00
|
|
|
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
|
|
|
|
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_B, 1);
|
|
|
|
if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType == 0)
|
|
|
|
gSpecialVar_Result = 4;
|
|
|
|
else
|
|
|
|
gSpecialVar_Result = 6;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
2020-08-13 03:09:47 -04:00
|
|
|
SetCloseLinkCallback();
|
2018-10-22 19:22:57 +02:00
|
|
|
gSpecialVar_Result = 5;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
if (gReceivedRemoteLinkPlayers == 0)
|
|
|
|
{
|
|
|
|
gSpecialVar_Result = 6;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void sub_8164DCC(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
if (gWirelessCommType != 0)
|
2020-08-13 03:09:47 -04:00
|
|
|
SetCloseLinkCallback();
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
|
2020-01-08 05:43:06 -05:00
|
|
|
static void SetMultiPartnerGfx(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-08 05:43:06 -05:00
|
|
|
// 0xF below means use VAR_OBJ_GFX_ID_E
|
|
|
|
SetBattleFacilityTrainerGfxId(gSaveBlock2Ptr->frontier.trainerIds[17], 0xF);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
|
2019-11-28 22:46:39 -05:00
|
|
|
static void SetTowerInterviewData(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
u8 text[32];
|
|
|
|
|
|
|
|
if (VarGet(VAR_FRONTIER_BATTLE_MODE) != FRONTIER_MODE_SINGLES)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GetFrontierTrainerName(text, gTrainerBattleOpponent_A);
|
|
|
|
StripExtCtrlCodes(text);
|
2019-11-24 16:58:40 -05:00
|
|
|
StringCopy(gSaveBlock2Ptr->frontier.towerInterview.opponentName, text);
|
|
|
|
GetBattleTowerTrainerLanguage(&gSaveBlock2Ptr->frontier.towerInterview.opponentLanguage, gTrainerBattleOpponent_A);
|
|
|
|
gSaveBlock2Ptr->frontier.towerInterview.opponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[1]], MON_DATA_SPECIES, NULL);
|
|
|
|
gSaveBlock2Ptr->frontier.towerInterview.playerSpecies = GetMonData(&gPlayerParty[gBattlerPartyIndexes[0]], MON_DATA_SPECIES, NULL);
|
2018-10-22 19:22:57 +02:00
|
|
|
for (i = 0; i < POKEMON_NAME_LENGTH + 1; i++)
|
2019-11-24 16:58:40 -05:00
|
|
|
gSaveBlock2Ptr->frontier.towerInterview.opponentMonNickname[i] = gBattleMons[0].nickname[i];
|
|
|
|
gSaveBlock2Ptr->frontier.towerBattleOutcome = gBattleOutcome;
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void ValidateBattleTowerRecordChecksums(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void ClearBattleTowerRecord(struct EmeraldBattleTowerRecord *record)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
u32 i;
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(struct EmeraldBattleTowerRecord) / 4; i++)
|
|
|
|
((u32 *)record)[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 GetCurrentBattleTowerWinStreak(u8 lvlMode, u8 battleMode)
|
|
|
|
{
|
2018-10-27 17:39:05 +02:00
|
|
|
u16 winStreak = gSaveBlock2Ptr->frontier.towerWinStreaks[battleMode][lvlMode];
|
2018-10-22 19:22:57 +02:00
|
|
|
|
|
|
|
if (winStreak > 9999)
|
|
|
|
return 9999;
|
|
|
|
else
|
|
|
|
return winStreak;
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static u8 GetMonCountForBattleMode(u8 battleMode)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
u8 partySizes[ARRAY_COUNT(sBattleTowerPartySizes)];
|
|
|
|
memcpy(partySizes, sBattleTowerPartySizes, sizeof(sBattleTowerPartySizes));
|
2018-10-22 19:22:57 +02:00
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
if (battleMode < ARRAY_COUNT(sBattleTowerPartySizes))
|
|
|
|
return partySizes[battleMode];
|
2018-10-22 19:22:57 +02:00
|
|
|
else
|
2019-11-24 16:58:40 -05:00
|
|
|
return FRONTIER_PARTY_SIZE;
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct RibbonCounter
|
|
|
|
{
|
|
|
|
u8 partyIndex;
|
|
|
|
u8 count;
|
|
|
|
};
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void AwardBattleTowerRibbons(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2019-11-10 21:54:00 -05:00
|
|
|
if (ribbons[0].count > NUM_CUTIES_RIBBONS)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2019-11-10 21:54:00 -05:00
|
|
|
TryPutSpotTheCutiesOnAir(&gSaveBlock1Ptr->playerParty[ribbons[0].partyIndex], ribbonType);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a leftover debugging function that is used to populate the E-Reader
|
|
|
|
// trainer with the player's current data.
|
2018-10-25 21:27:10 +02:00
|
|
|
static void FillEReaderTrainerWithPlayerData(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
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)];
|
|
|
|
}
|
|
|
|
|
2018-11-01 21:31:10 +01:00
|
|
|
CopyTrainerId(ereaderTrainer->trainerId, gSaveBlock2Ptr->playerTrainerId);
|
2018-10-22 19:22:57 +02:00
|
|
|
StringCopy7(ereaderTrainer->name, gSaveBlock2Ptr->playerName);
|
|
|
|
|
|
|
|
ereaderTrainer->winStreak = 1;
|
|
|
|
|
|
|
|
j = 7;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
2019-02-27 12:45:31 -06:00
|
|
|
ereaderTrainer->greeting[i] = gSaveBlock1Ptr->easyChatBattleStart[i];
|
2018-10-22 19:22:57 +02:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
void GetEreaderTrainerName(u8 *dst)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
for (i = 0; i < 5; i++)
|
2018-10-25 21:27:10 +02:00
|
|
|
dst[i] = gSaveBlock2Ptr->frontier.ereaderTrainer.name[i];
|
2018-10-22 19:22:57 +02:00
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
dst[i] = EOS;
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void SetEReaderTrainerChecksum(struct BattleTowerEReaderTrainer *ereaderTrainer)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void CopyEReaderTrainerFarewellMessage(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-01-08 04:26:26 -05:00
|
|
|
void TryHideBattleTowerReporter(void)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2019-11-24 16:58:40 -05:00
|
|
|
if (gSaveBlock2Ptr->frontier.challengeStatus == CHALLENGE_STATUS_SAVING)
|
2020-01-08 04:26:26 -05:00
|
|
|
HideBattleTowerReporter();
|
2019-01-02 21:12:43 +00:00
|
|
|
if (FlagGet(FLAG_CANCEL_BATTLE_ROOM_CHALLENGE) == TRUE)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-08 04:26:26 -05:00
|
|
|
HideBattleTowerReporter();
|
2019-01-02 21:12:43 +00:00
|
|
|
FlagClear(FLAG_CANCEL_BATTLE_ROOM_CHALLENGE);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STEVEN_OTID 61226
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void FillPartnerParty(u16 trainerId)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
s32 i, j;
|
|
|
|
u32 ivs, level;
|
|
|
|
u32 friendship;
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 monId;
|
2018-10-22 19:22:57 +02:00
|
|
|
u32 otID;
|
|
|
|
u8 trainerName[PLAYER_NAME_LENGTH + 1];
|
2018-10-24 23:14:45 +02:00
|
|
|
SetFacilityPtrsGetLevel();
|
2018-10-22 19:22:57 +02:00
|
|
|
|
|
|
|
if (trainerId == TRAINER_STEVEN_PARTNER)
|
|
|
|
{
|
2020-04-09 15:18:53 -04:00
|
|
|
for (i = 0; i < MULTI_PARTY_SIZE; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
j = Random32();
|
|
|
|
} while (IsShinyOtIdPersonality(STEVEN_OTID, j) || sStevenMons[i].nature != GetNatureFromPersonality(j));
|
2020-04-09 15:18:53 -04:00
|
|
|
CreateMon(&gPlayerParty[MULTI_PARTY_SIZE + i],
|
2018-10-22 19:22:57 +02:00
|
|
|
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.
|
2019-08-30 23:06:43 -04:00
|
|
|
OT_ID_PRESET, STEVEN_OTID);
|
2019-10-17 19:22:03 -04:00
|
|
|
for (j = 0; j < PARTY_SIZE; j++)
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_HP_EV + j, &sStevenMons[i].evs[j]);
|
2018-12-25 12:50:15 -05:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonMoveSlot(&gPlayerParty[MULTI_PARTY_SIZE + i], sStevenMons[i].moves[j], j);
|
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_NAME, gTrainers[TRAINER_STEVEN].trainerName);
|
2018-10-22 19:22:57 +02:00
|
|
|
j = MALE;
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j);
|
|
|
|
CalculateMonStats(&gPlayerParty[MULTI_PARTY_SIZE + i]);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId == TRAINER_EREADER)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
// Scrapped, lol.
|
|
|
|
trainerName[0] = gGameLanguage;
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2018-10-24 23:14:45 +02:00
|
|
|
level = SetFacilityPtrsGetLevel();
|
2018-10-22 19:22:57 +02:00
|
|
|
ivs = GetFrontierTrainerFixedIvs(trainerId);
|
|
|
|
otID = Random32();
|
2020-04-09 15:18:53 -04:00
|
|
|
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
monId = gSaveBlock2Ptr->frontier.trainerIds[i + 18];
|
2020-04-09 15:18:53 -04:00
|
|
|
CreateMonWithEVSpreadNatureOTID(&gPlayerParty[MULTI_PARTY_SIZE + i],
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].species,
|
2018-10-22 19:22:57 +02:00
|
|
|
level,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].nature,
|
2018-10-22 19:22:57 +02:00
|
|
|
ivs,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].evSpread,
|
2018-10-22 19:22:57 +02:00
|
|
|
otID);
|
2019-12-18 02:32:52 -05:00
|
|
|
friendship = MAX_FRIENDSHIP;
|
2018-12-25 12:50:15 -05:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonMoveSlot(&gPlayerParty[MULTI_PARTY_SIZE + i], gFacilityTrainerMons[monId].moves[j], j);
|
2020-01-05 10:50:32 -05:00
|
|
|
if (gFacilityTrainerMons[monId].moves[j] == MOVE_FRUSTRATION)
|
2018-10-22 19:22:57 +02:00
|
|
|
friendship = 0;
|
|
|
|
}
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_FRIENDSHIP, &friendship);
|
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monId].itemTableId]);
|
2018-10-22 19:22:57 +02:00
|
|
|
for (j = 0; j < PLAYER_NAME_LENGTH + 1; j++)
|
|
|
|
trainerName[j] = gFacilityTrainers[trainerId].trainerName[j];
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_NAME, &trainerName);
|
2018-10-22 19:22:57 +02:00
|
|
|
j = IsFrontierTrainerFemale(trainerId);
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
trainerId -= TRAINER_RECORD_MIXING_FRIEND;
|
2020-04-09 15:18:53 -04:00
|
|
|
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
struct EmeraldBattleTowerRecord *record = &gSaveBlock2Ptr->frontier.towerRecords[trainerId];
|
2019-02-07 11:37:28 -06:00
|
|
|
struct BattleTowerPokemon monData = record->party[gSaveBlock2Ptr->frontier.trainerIds[18 + i]];
|
2018-10-22 19:22:57 +02:00
|
|
|
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;
|
|
|
|
}
|
2020-04-09 15:18:53 -04:00
|
|
|
CreateBattleTowerMon2(&gPlayerParty[MULTI_PARTY_SIZE + i], &monData, TRUE);
|
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_NAME, trainerName);
|
2018-10-26 23:54:41 +02:00
|
|
|
j = IsFrontierTrainerFemale(trainerId + TRAINER_RECORD_MIXING_FRIEND);
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
trainerId -= TRAINER_RECORD_MIXING_APPRENTICE;
|
2020-04-09 15:18:53 -04:00
|
|
|
for (i = 0; i < FRONTIER_MULTI_PARTY_SIZE; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
2020-04-09 15:18:53 -04:00
|
|
|
CreateApprenticeMon(&gPlayerParty[MULTI_PARTY_SIZE + i], &gSaveBlock2Ptr->apprentices[trainerId], gSaveBlock2Ptr->frontier.trainerIds[18 + i]);
|
2018-10-26 23:54:41 +02:00
|
|
|
j = IsFrontierTrainerFemale(trainerId + TRAINER_RECORD_MIXING_APPRENTICE);
|
2020-04-09 15:18:53 -04:00
|
|
|
SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_OT_GENDER, &j);
|
2018-10-22 19:22:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool32 RubyBattleTowerRecordToEmerald(struct RSBattleTowerRecord *src, struct EmeraldBattleTowerRecord *dst)
|
|
|
|
{
|
|
|
|
s32 i, validMons = 0;
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
if (src->party[i].species)
|
|
|
|
validMons++;
|
|
|
|
}
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
if (validMons != FRONTIER_PARTY_SIZE)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
memset(dst, 0, sizeof(*dst));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dst->lvlMode = src->lvlMode;
|
|
|
|
dst->winStreak = src->winStreak;
|
2018-12-05 22:21:26 +01:00
|
|
|
// BUG: Reading outside the array. sRubyFacilityClassToEmerald has less than FACILITY_CLASSES_COUNT entries.
|
2019-11-24 16:58:40 -05:00
|
|
|
// Fix by using ARRAY_COUNT(sRubyFacilityClassToEmerald)
|
2018-12-05 22:21:26 +01:00
|
|
|
for (i = 0; i < FACILITY_CLASSES_COUNT; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
{
|
|
|
|
if (sRubyFacilityClassToEmerald[i][0] == src->facilityClass)
|
|
|
|
break;
|
|
|
|
}
|
2018-12-05 22:21:26 +01:00
|
|
|
if (i != FACILITY_CLASSES_COUNT)
|
2018-10-22 19:22:57 +02:00
|
|
|
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];
|
2019-09-08 11:53:48 -04:00
|
|
|
for (i = 0; i < TRAINER_ID_LENGTH; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
dst->trainerId[i] = src->trainerId[i];
|
2019-11-24 16:58:40 -05:00
|
|
|
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
dst->greeting[i] = src->greeting[i];
|
2019-11-24 16:58:40 -05:00
|
|
|
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
|
|
|
dst->speechWon[i] = sRecordTrainerSpeechWon[i];
|
|
|
|
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
|
|
|
dst->speechLost[i] = sRecordTrainerSpeechLost[i];
|
|
|
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
2018-10-22 19:22:57 +02:00
|
|
|
dst->party[i] = src->party[i];
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
CpuFill32(0, &dst->party[FRONTIER_PARTY_SIZE], sizeof(dst->party[FRONTIER_PARTY_SIZE]));
|
2018-10-22 19:22:57 +02:00
|
|
|
CalcEmeraldBattleTowerChecksum(dst);
|
|
|
|
return TRUE;
|
2018-10-21 20:13:12 +02:00
|
|
|
}
|
|
|
|
}
|
2018-10-24 23:14:45 +02:00
|
|
|
|
|
|
|
bool32 EmeraldBattleTowerRecordToRuby(struct EmeraldBattleTowerRecord *src, struct RSBattleTowerRecord *dst)
|
|
|
|
{
|
|
|
|
s32 i, validMons = 0;
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
if (src->party[i].species)
|
|
|
|
validMons++;
|
|
|
|
}
|
|
|
|
|
2019-11-24 16:58:40 -05:00
|
|
|
if (validMons != FRONTIER_PARTY_SIZE)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
memset(dst, 0, sizeof(*dst));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dst->lvlMode = src->lvlMode;
|
|
|
|
dst->winStreak = src->winStreak;
|
2018-12-05 22:21:26 +01:00
|
|
|
// BUG: Reading outside the array. sRubyFacilityClassToEmerald has less than FACILITY_CLASSES_COUNT entries.
|
2019-11-24 16:58:40 -05:00
|
|
|
// Fix by using ARRAY_COUNT(sRubyFacilityClassToEmerald) instead
|
2018-12-05 22:21:26 +01:00
|
|
|
for (i = 0; i < FACILITY_CLASSES_COUNT; i++)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
if (sRubyFacilityClassToEmerald[i][1] == src->facilityClass)
|
|
|
|
break;
|
|
|
|
}
|
2018-12-05 22:21:26 +01:00
|
|
|
if (i != FACILITY_CLASSES_COUNT)
|
2018-10-24 23:14:45 +02:00
|
|
|
dst->facilityClass = sRubyFacilityClassToEmerald[i][0];
|
|
|
|
else
|
2019-11-24 16:58:40 -05:00
|
|
|
dst->facilityClass = RS_FACILITY_CLASS_YOUNGSTER;
|
2018-10-24 23:14:45 +02:00
|
|
|
|
|
|
|
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
|
|
|
|
dst->name[i] = src->name[i];
|
2019-09-08 11:53:48 -04:00
|
|
|
for (i = 0; i < TRAINER_ID_LENGTH; i++)
|
2018-10-24 23:14:45 +02:00
|
|
|
dst->trainerId[i] = src->trainerId[i];
|
2019-11-24 16:58:40 -05:00
|
|
|
for (i = 0; i < EASY_CHAT_BATTLE_WORDS_COUNT; i++)
|
2018-10-24 23:14:45 +02:00
|
|
|
dst->greeting[i] = src->greeting[i];
|
2019-11-24 16:58:40 -05:00
|
|
|
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
|
2018-10-24 23:14:45 +02:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void ClearApprentice(struct Apprentice *apprentice)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
for (i = 0; i < (sizeof(struct Apprentice)) / 4; i++)
|
|
|
|
((u32 *)apprentice)[i] = 0;
|
|
|
|
ResetApprenticeStruct(apprentice);
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void ValidateApprenticesChecksums(void)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
s32 i, j;
|
|
|
|
|
2019-11-20 17:36:52 -05:00
|
|
|
for (i = 0; i < APPRENTICE_COUNT; i++)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2018-10-26 23:54:41 +02:00
|
|
|
if (trainerId == TRAINER_EREADER)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
*dst = gGameLanguage;
|
|
|
|
}
|
2019-12-20 18:52:29 -05:00
|
|
|
else if (trainerId < FRONTIER_TRAINERS_COUNT)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
*dst = gGameLanguage;
|
|
|
|
}
|
2018-10-26 23:54:41 +02:00
|
|
|
else if (trainerId < TRAINER_RECORD_MIXING_APPRENTICE)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
2018-11-01 15:06:50 +01:00
|
|
|
*dst = GetRecordedBattleRecordMixFriendLanguage();
|
2018-10-24 23:14:45 +02:00
|
|
|
else
|
2018-10-26 23:54:41 +02:00
|
|
|
*dst = gSaveBlock2Ptr->frontier.towerRecords[trainerId - TRAINER_RECORD_MIXING_FRIEND].language;
|
2018-10-24 23:14:45 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
|
2018-11-01 15:06:50 +01:00
|
|
|
*dst = GetRecordedBattleApprenticeLanguage();
|
2018-10-24 23:14:45 +02:00
|
|
|
else
|
2018-10-26 23:54:41 +02:00
|
|
|
*dst = gSaveBlock2Ptr->apprentices[trainerId - TRAINER_RECORD_MIXING_APPRENTICE].language;
|
2018-10-24 23:14:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
// Frontier Trainer parties are roughly scaled in difficulty with higher trainer IDs, so scale IVs as well
|
|
|
|
// Duplicated in Battle Dome as GetDomeTrainerMonIvs
|
2018-10-25 21:27:10 +02:00
|
|
|
static u8 GetFrontierTrainerFixedIvs(u16 trainerId)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
2019-12-20 18:52:29 -05:00
|
|
|
u8 fixedIv;
|
2018-10-24 23:14:45 +02:00
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
if (trainerId <= FRONTIER_TRAINER_JILL) // 0 - 99
|
|
|
|
fixedIv = 3;
|
|
|
|
else if (trainerId <= FRONTIER_TRAINER_CHLOE) // 100 - 119
|
|
|
|
fixedIv = 6;
|
|
|
|
else if (trainerId <= FRONTIER_TRAINER_SOFIA) // 120 - 139
|
|
|
|
fixedIv = 9;
|
|
|
|
else if (trainerId <= FRONTIER_TRAINER_JAZLYN) // 140 - 159
|
|
|
|
fixedIv = 12;
|
|
|
|
else if (trainerId <= FRONTIER_TRAINER_ALISON) // 160 - 179
|
|
|
|
fixedIv = 15;
|
|
|
|
else if (trainerId <= FRONTIER_TRAINER_LAMAR) // 180 - 199
|
|
|
|
fixedIv = 18;
|
|
|
|
else if (trainerId <= FRONTIER_TRAINER_TESS) // 200 - 219
|
|
|
|
fixedIv = 21;
|
|
|
|
else // 220+ (- 299)
|
|
|
|
fixedIv = 31;
|
2018-10-24 23:14:45 +02:00
|
|
|
|
2019-12-20 18:52:29 -05:00
|
|
|
return fixedIv;
|
2018-10-24 23:14:45 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static u16 sub_8165D40(void)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static u8 SetTentPtrsGetLevel(void)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
u8 level = 30;
|
2019-12-18 02:32:52 -05:00
|
|
|
u32 facility = VarGet(VAR_FRONTIER_FACILITY);
|
2018-10-24 23:14:45 +02:00
|
|
|
|
2019-12-18 02:32:52 -05:00
|
|
|
if (facility == FRONTIER_FACILITY_FACTORY)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
gFacilityTrainers = gSlateportBattleTentTrainers;
|
|
|
|
gFacilityTrainerMons = gSlateportBattleTentMons;
|
|
|
|
}
|
2019-12-18 02:32:52 -05:00
|
|
|
else if (facility == FRONTIER_FACILITY_PALACE)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
gFacilityTrainers = gVerdanturfBattleTentTrainers;
|
|
|
|
gFacilityTrainerMons = gVerdanturfBattleTentMons;
|
|
|
|
}
|
2019-12-18 02:32:52 -05:00
|
|
|
else if (facility == FRONTIER_FACILITY_ARENA)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
gFacilityTrainers = gFallarborBattleTentTrainers;
|
|
|
|
gFacilityTrainerMons = gFallarborBattleTentMons;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gFacilityTrainers = gBattleFrontierTrainers;
|
|
|
|
gFacilityTrainerMons = gBattleFrontierMons;
|
|
|
|
}
|
|
|
|
|
|
|
|
level = GetHighestLevelInPlayerParty();
|
|
|
|
if (level < 30)
|
|
|
|
level = 30;
|
|
|
|
|
|
|
|
return level;
|
|
|
|
}
|
|
|
|
|
2019-11-28 22:46:39 -05:00
|
|
|
static void SetNextBattleTentOpponent(void)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
u16 trainerId;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
trainerId = sub_8165D40();
|
|
|
|
for (i = 0; i < gSaveBlock2Ptr->frontier.curChallengeBattleNum; i++)
|
|
|
|
{
|
2019-02-07 11:37:28 -06:00
|
|
|
if (gSaveBlock2Ptr->frontier.trainerIds[i] == trainerId)
|
2018-10-24 23:14:45 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (i != gSaveBlock2Ptr->frontier.curChallengeBattleNum);
|
|
|
|
|
|
|
|
gTrainerBattleOpponent_A = trainerId;
|
|
|
|
SetBattleFacilityTrainerGfxId(gTrainerBattleOpponent_A, 0);
|
|
|
|
if (gSaveBlock2Ptr->frontier.curChallengeBattleNum + 1 < 3)
|
2019-02-07 11:37:28 -06:00
|
|
|
gSaveBlock2Ptr->frontier.trainerIds[gSaveBlock2Ptr->frontier.curChallengeBattleNum] = gTrainerBattleOpponent_A;
|
2018-10-24 23:14:45 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 21:27:10 +02:00
|
|
|
static void FillTentTrainerParty_(u16 trainerId, u8 firstMonId, u8 monCount)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
s32 i, j;
|
2020-04-09 15:18:53 -04:00
|
|
|
u16 chosenMonIndices[MAX_FRONTIER_PARTY_SIZE];
|
2018-10-24 23:14:45 +02:00
|
|
|
u8 friendship;
|
|
|
|
u8 level = SetTentPtrsGetLevel();
|
|
|
|
u8 fixedIV = 0;
|
|
|
|
u8 bfMonCount;
|
2020-01-05 10:50:32 -05:00
|
|
|
const u16 *monSet = NULL;
|
2018-10-24 23:14:45 +02:00
|
|
|
u32 otID = 0;
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 monId;
|
2018-10-24 23:14:45 +02:00
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
monSet = gFacilityTrainers[gTrainerBattleOpponent_A].monSet;
|
2018-10-24 23:14:45 +02:00
|
|
|
|
|
|
|
bfMonCount = 0;
|
2020-01-05 10:50:32 -05:00
|
|
|
monId = monSet[bfMonCount];
|
|
|
|
while (monId != 0xFFFF)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
|
|
|
bfMonCount++;
|
2020-01-05 10:50:32 -05:00
|
|
|
monId = monSet[bfMonCount];
|
|
|
|
if (monId == 0xFFFF)
|
2018-10-24 23:14:45 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
otID = Random32();
|
|
|
|
while (i != monCount)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
u16 monId = monSet[Random() % bfMonCount];
|
2018-10-24 23:14:45 +02:00
|
|
|
|
|
|
|
// Ensure this pokemon species isn't a duplicate.
|
|
|
|
for (j = 0; j < i + firstMonId; j++)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
if (GetMonData(&gEnemyParty[j], MON_DATA_SPECIES, NULL) == gFacilityTrainerMons[monId].species)
|
2018-10-24 23:14:45 +02:00
|
|
|
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
|
2020-01-05 10:50:32 -05:00
|
|
|
&& GetMonData(&gEnemyParty[j], MON_DATA_HELD_ITEM, NULL) == gBattleFrontierHeldItems[gFacilityTrainerMons[monId].itemTableId])
|
2018-10-24 23:14:45 +02:00
|
|
|
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++)
|
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
if (chosenMonIndices[j] == monId)
|
2018-10-24 23:14:45 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (j != i)
|
|
|
|
continue;
|
|
|
|
|
2020-01-05 10:50:32 -05:00
|
|
|
chosenMonIndices[i] = monId;
|
2018-10-24 23:14:45 +02:00
|
|
|
|
|
|
|
// Place the chosen pokemon into the trainer's party.
|
2018-11-11 16:44:27 +01:00
|
|
|
CreateMonWithEVSpreadNatureOTID(&gEnemyParty[i + firstMonId],
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].species,
|
2018-10-24 23:14:45 +02:00
|
|
|
level,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].nature,
|
2018-10-24 23:14:45 +02:00
|
|
|
fixedIV,
|
2020-01-05 10:50:32 -05:00
|
|
|
gFacilityTrainerMons[monId].evSpread,
|
2018-10-24 23:14:45 +02:00
|
|
|
otID);
|
|
|
|
|
2019-12-18 02:32:52 -05:00
|
|
|
friendship = MAX_FRIENDSHIP;
|
2018-10-24 23:14:45 +02:00
|
|
|
// Give the chosen pokemon its specified moves.
|
2018-12-25 12:50:15 -05:00
|
|
|
for (j = 0; j < MAX_MON_MOVES; j++)
|
2018-10-24 23:14:45 +02:00
|
|
|
{
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonMoveSlot(&gEnemyParty[i + firstMonId], gFacilityTrainerMons[monId].moves[j], j);
|
|
|
|
if (gFacilityTrainerMons[monId].moves[j] == MOVE_FRUSTRATION)
|
2018-10-24 23:14:45 +02:00
|
|
|
friendship = 0; // Frustration is more powerful the lower the pokemon's friendship is.
|
|
|
|
}
|
|
|
|
|
|
|
|
SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_FRIENDSHIP, &friendship);
|
2020-01-05 10:50:32 -05:00
|
|
|
SetMonData(&gEnemyParty[i + firstMonId], MON_DATA_HELD_ITEM, &gBattleFrontierHeldItems[gFacilityTrainerMons[monId].itemTableId]);
|
2018-10-24 23:14:45 +02:00
|
|
|
|
|
|
|
// The pokemon was successfully added to the trainer's party, so it's safe to move on to
|
|
|
|
// the next party slot.
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2018-10-25 21:27:10 +02:00
|
|
|
|
2019-01-13 12:12:27 +01:00
|
|
|
u8 FacilityClassToGraphicsId(u8 facilityClass)
|
2018-10-25 21:27:10 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2019-11-20 23:12:51 -05:00
|
|
|
return OBJ_EVENT_GFX_BOY_1;
|
2018-10-25 21:27:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|