diff --git a/asm/battle_intro.s b/asm/battle_intro.s index 04a0301ce..f65bc3307 100644 --- a/asm/battle_intro.s +++ b/asm/battle_intro.s @@ -228,6 +228,9 @@ HandleIntroSlide: @ 81181D4 ldr r0, =0x00000c03 cmp r1, r0 beq _08118208 + adds r0, r0, #1 + cmp r1, r0 + bhi _08118208 ldr r0, =sub_8118D68 b _08118258 .pool diff --git a/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc b/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc index b4046d022..4e46bd1d0 100644 --- a/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc +++ b/data/maps/EverGrandeCity_PokemonLeague_1F/scripts.inc @@ -47,6 +47,11 @@ EverGrandeCity_PokemonLeague_1F_Pokemart_229624: @ 8229624 end EverGrandeCity_PokemonLeague_1F_EventScript_229636:: @ 8229636 + setvar VAR_0x8004, 11 + setvar VAR_0x8006, 404 + setvar VAR_0x8007, 3 + special DoSpecialTrainerBattle + waitstate lockall checkflag FLAG_0x107 goto_eq EverGrandeCity_PokemonLeague_1F_EventScript_2296BB diff --git a/include/battle.h b/include/battle.h index d25ee3a33..bbdc3a7a3 100644 --- a/include/battle.h +++ b/include/battle.h @@ -861,6 +861,7 @@ extern u8 gBattleMonForms[MAX_BATTLERS_COUNT]; extern u32 gFieldStatuses; extern struct FieldTimer gFieldTimers; extern u8 gBattlerAbility; +extern u16 gPartnerSpriteId; extern void (*gPreBattleCallback1)(void); extern void (*gBattleMainFunc)(void); diff --git a/include/battle_setup.h b/include/battle_setup.h index 88100cf4e..4e6f8ebe2 100644 --- a/include/battle_setup.h +++ b/include/battle_setup.h @@ -47,6 +47,7 @@ void BattleSetup_StartLegendaryBattle(void); void StartGroudonKyogreBattle(void); void StartRegiBattle(void); u8 BattleSetup_GetTerrainId(void); +u8 GetTrainerBattleTransition(void); u8 sub_80B100C(s32 arg0); void ChooseStarter(void); void ResetTrainerOpponentIds(void); diff --git a/include/constants/battle_frontier.h b/include/constants/battle_frontier.h index b5ad4f072..61d9ccb08 100644 --- a/include/constants/battle_frontier.h +++ b/include/constants/battle_frontier.h @@ -37,6 +37,7 @@ #define SPECIAL_BATTLE_STEVEN 8 #define SPECIAL_BATTLE_PIKE_DOUBLE 9 #define SPECIAL_BATTLE_PYRAMID 10 +#define SPECIAL_BATTLE_MULTI 11 // For 'ShowFacilityResultsWindow' function which is a part of the 'CallFrontierUtilFunc' special. #define RESULTS_LINK_CONTEST 7 diff --git a/include/constants/trainers.h b/include/constants/trainers.h index 2ea9f7c62..9b333b531 100644 --- a/include/constants/trainers.h +++ b/include/constants/trainers.h @@ -13,6 +13,7 @@ #define TRAINER_LINK_OPPONENT 2048 #define TRAINER_OPPONENT_C00 3072 #define TRAINER_STEVEN_PARTNER 3075 +#define TRAINER_CUSTOM_PARTNER 3076 #define TRAINER_PIC_HIKER 0 #define TRAINER_PIC_AQUA_GRUNT_M 1 diff --git a/src/battle_bg.c b/src/battle_bg.c index 51138040c..7bc042bfd 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -1107,7 +1107,7 @@ void DrawBattleEntryBackground(void) } else if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000 | BATTLE_TYPE_EREADER_TRAINER)) { - if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || gPartnerTrainerId == TRAINER_STEVEN_PARTNER) + if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || gPartnerTrainerId == TRAINER_STEVEN_PARTNER || gPartnerTrainerId >= TRAINER_CUSTOM_PARTNER) { LZDecompressVram(gBattleTerrainAnimTiles_Building, (void*)(VRAM + 0x4000)); LZDecompressVram(gBattleTerrainAnimTilemap_Building, (void*)(VRAM + 0xE000)); diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 5da609b15..9f7acdbf0 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2318,7 +2318,7 @@ static void PlayerHandleDrawTrainerPic(void) else // First mon, on the left. xPos = 32; - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId != TRAINER_STEVEN_PARTNER) + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId != TRAINER_STEVEN_PARTNER && gPartnerTrainerId < TRAINER_CUSTOM_PARTNER) { xPos = 90; yPos = (8 - gTrainerFrontPicCoords[trainerPicId].coords) * 4 + 80; @@ -2336,7 +2336,7 @@ static void PlayerHandleDrawTrainerPic(void) } // Use front pic table for any tag battles unless your partner is Steven. - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId != TRAINER_STEVEN_PARTNER) + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId != TRAINER_STEVEN_PARTNER && gPartnerTrainerId < TRAINER_CUSTOM_PARTNER) { trainerPicId = PlayerGenderToFrontTrainerPicId(gSaveBlock2Ptr->playerGender); DecompressTrainerFrontPic(trainerPicId, gActiveBattler); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 65e6c2dd8..3ab8869aa 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -1315,6 +1315,12 @@ static void PlayerPartnerHandleDrawTrainerPic(void) xPos = 90; yPos = (8 - gTrainerBackPicCoords[trainerPicId].coords) * 4 + 80; } + else if (gPartnerTrainerId >= TRAINER_CUSTOM_PARTNER) + { + trainerPicId = gPartnerSpriteId; + xPos = 90; + yPos = (8 - gTrainerBackPicCoords[trainerPicId].coords) * 4 + 80; + } else { trainerPicId = GetFrontierTrainerFrontSpriteId(gPartnerTrainerId); @@ -1323,7 +1329,7 @@ static void PlayerPartnerHandleDrawTrainerPic(void) } // Use back pic only if the partner is Steven - if (gPartnerTrainerId == TRAINER_STEVEN_PARTNER) + if (gPartnerTrainerId == TRAINER_STEVEN_PARTNER || gPartnerTrainerId >= TRAINER_CUSTOM_PARTNER) { DecompressTrainerBackPic(trainerPicId, gActiveBattler); SetMultiuseSpriteTemplateToTrainerBack(trainerPicId, GetBattlerPosition(gActiveBattler)); @@ -1799,6 +1805,11 @@ static void PlayerPartnerHandleIntroTrainerBallThrow(void) u8 spriteId = TRAINER_BACK_PIC_STEVEN; LoadCompressedPalette(gTrainerBackPicPaletteTable[spriteId].data, 0x100 + paletteNum * 16, 32); } + else if (gPartnerTrainerId >= TRAINER_CUSTOM_PARTNER) + { + u8 spriteId = gPartnerSpriteId; + LoadCompressedPalette(gTrainerBackPicPaletteTable[spriteId].data, 0x100 + paletteNum * 16, 32); + } else { u8 spriteId = GetFrontierTrainerFrontSpriteId(gPartnerTrainerId); diff --git a/src/battle_main.c b/src/battle_main.c index e2101a9c4..6d4a960ff 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -191,7 +191,6 @@ EWRAM_DATA u8 gDisplayedStringBattle[300] = {0}; EWRAM_DATA u8 gBattleTextBuff1[TEXT_BUFF_ARRAY_COUNT] = {0}; EWRAM_DATA u8 gBattleTextBuff2[TEXT_BUFF_ARRAY_COUNT] = {0}; EWRAM_DATA u8 gBattleTextBuff3[TEXT_BUFF_ARRAY_COUNT] = {0}; -EWRAM_DATA static u32 sUnusedUnknownArray[25] = {0}; EWRAM_DATA u32 gBattleTypeFlags = 0; EWRAM_DATA u8 gBattleTerrain = 0; EWRAM_DATA u32 gUnknown_02022FF4 = 0; @@ -288,6 +287,7 @@ EWRAM_DATA u8 gBattleMonForms[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u32 gFieldStatuses = 0; EWRAM_DATA struct FieldTimer gFieldTimers = {0}; EWRAM_DATA u8 gBattlerAbility = 0; +EWRAM_DATA u16 gPartnerSpriteId = 0; // IWRAM common vars void (*gPreBattleCallback1)(void); @@ -616,7 +616,7 @@ static void CB2_InitBattleInternal(void) gBattle_WIN0H = 240; - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId != TRAINER_STEVEN_PARTNER) + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId != TRAINER_STEVEN_PARTNER && gPartnerTrainerId < TRAINER_CUSTOM_PARTNER) { gBattle_WIN0V = 159; gBattle_WIN1H = 240; @@ -2693,7 +2693,7 @@ static void sub_80398D0(struct Sprite *sprite) { sprite->invisible = FALSE; sprite->callback = SpriteCallbackDummy_2; - sUnusedUnknownArray[0] = 0; + // sUnusedUnknownArray[0] = 0; } } } diff --git a/src/battle_message.c b/src/battle_message.c index e5ba3d30b..ee47ad46f 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2684,7 +2684,7 @@ static const u8 *BattleStringGetPlayerName(u8 *text, u8 battlerId) toCpy = gSaveBlock2Ptr->playerName; break; case B_POSITION_PLAYER_RIGHT: - if (gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_MULTI)) + if (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_MULTI)) { toCpy = gLinkPlayers[2].name; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d4175643f..7d856dae6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3360,7 +3360,7 @@ static bool32 IsBattleLostForPlayer(void) u32 i; u32 HP_count = 0; - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId == TRAINER_STEVEN_PARTNER) + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && (gPartnerTrainerId == TRAINER_STEVEN_PARTNER || gPartnerTrainerId >= TRAINER_CUSTOM_PARTNER)) { for (i = 0; i < 3; i++) { diff --git a/src/battle_setup.c b/src/battle_setup.c index 3913cabb1..d42f57237 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -79,7 +79,6 @@ static void DoStandardWildBattle(bool32 isDouble); static void CB2_EndWildBattle(void); static void CB2_EndScriptedWildBattle(void); static u8 GetWildBattleTransition(void); -static u8 GetTrainerBattleTransition(void); static void sub_80B1218(void); static void sub_80B1234(void); static void CB2_GiveStarter(void); @@ -795,7 +794,7 @@ static u8 GetWildBattleTransition(void) } } -static u8 GetTrainerBattleTransition(void) +u8 GetTrainerBattleTransition(void) { u8 minPartyCount; u8 transitionType; diff --git a/src/battle_tower.c b/src/battle_tower.c index 165b6bf64..b4a92a846 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -792,6 +792,10 @@ u8 GetFrontierOpponentClass(u16 trainerId) { trainerClass = gTrainers[TRAINER_STEVEN].trainerClass; } + else if (trainerId >= TRAINER_CUSTOM_PARTNER) + { + trainerClass = gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].trainerClass; + } else if (trainerId < TRAINER_RECORD_MIXING_FRIEND) { trainerClass = gFacilityClassToTrainerClass[gFacilityTrainers[trainerId].facilityClass]; @@ -875,6 +879,11 @@ void GetFrontierTrainerName(u8 *dst, u16 trainerId) for (i = 0; i < PLAYER_NAME_LENGTH; i++) dst[i] = gTrainers[TRAINER_STEVEN].trainerName[i]; } + else if (trainerId >= TRAINER_CUSTOM_PARTNER) + { + for (i = 0; gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].trainerName[i] != EOS; i++) + dst[i] = gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].trainerName[i]; + } else if (trainerId < TRAINER_RECORD_MIXING_FRIEND) { for (i = 0; i < PLAYER_NAME_LENGTH; i++) @@ -1463,6 +1472,19 @@ void DoSpecialTrainerBattle(void) PlayMapChosenOrBattleBGM(0); BattleTransition_StartOnField(B_TRANSITION_MAGMA); break; + case SPECIAL_BATTLE_MULTI: + gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER; + gPartnerSpriteId = gSpecialVar_0x8007; + FillPartnerParty(gSpecialVar_0x8006 + TRAINER_CUSTOM_PARTNER); + gApproachingTrainerId = 0; + BattleSetup_ConfigureTrainerBattle(MossdeepCity_SpaceCenter_2F_EventScript_224157 + 1); + gApproachingTrainerId = 1; + BattleSetup_ConfigureTrainerBattle(MossdeepCity_SpaceCenter_2F_EventScript_224166 + 1); + gPartnerTrainerId = gSpecialVar_0x8006 + TRAINER_CUSTOM_PARTNER; + CreateTask(Task_StartBattleAfterTransition, 1); + PlayMapChosenOrBattleBGM(0); + BattleTransition_StartOnField(GetTrainerBattleTransition()); + break; } } @@ -2307,6 +2329,14 @@ static void FillPartnerParty(u16 trainerId) CalculateMonStats(&gPlayerParty[3 + i]); } } + else if (trainerId >= TRAINER_CUSTOM_PARTNER) + { + for (i = 0; i < 3; i++) + { + // Temporary. + CreateMon(&gPlayerParty[3 + i], Random() % NUM_SPECIES, Random() % MAX_LEVEL, Random() % 31, 0, 0, 0, 0); + } + } else if (trainerId == TRAINER_EREADER) { // Scrapped, lol.