Skip to content

Single Mystery Random Starter

judicornadamsfoster edited this page Aug 22, 2026 · 1 revision
randomstarter1 randomstarter2

this code changes the starters in Birch's bag so that there is only one pokeball in the bag that is randomly chosen from a list, with no clue what pokemon will be chosen until the Zigzagoon battle starts. Secondary code is then set when in Birch's lab after the battle to set the rival's team based on your starter (or randomly chooses the team if the starters are changed to any other than the gen 3 starters)

this code uses Lunos' CheckSpecies code from https://www.pokecommunity.com/threads/simple-modifications-directory.416647/post-10213715
(Check for a specific Pokémon species (using a custom special) [Em])


pull from branch

git remote add tenaya15 https://github.com/tenaya15/tenaya15emerald.git
git pull tenaya15 single_mystery_random_starter

compare


src/starter_choose.c

after the INCGFX_* lines
add

#include "random.h"

static u16 sRandomStarterSpecies;

static const u16 sRandomStarterPool[] =
{
    SPECIES_TREECKO,
    SPECIES_TORCHIC,
    SPECIES_MUDKIP,
};

__

in section u16 GetStarterPokemon(u16 chosenStarterId) (now at line 361)
replace all with

{
    return sRandomStarterSpecies;
}

__

in section void CB2_ChooseStarter(void)

add after line u8 spriteId; (now line 386)


    sRandomStarterSpecies = sRandomStarterPool[Random() % ARRAY_COUNT(sRandomStarterPool)];

__

still in section void CB2_ChooseStarter(void)
delete the following lines (now lines 460 to 464)
this removes the other 2 pokeballs from the bag

// Create three Poké Ball sprites
spriteId = CreateSprite(&sSpriteTemplate_Pokeball, sPokeballCoords[0][0], sPokeballCoords[0][1], 2);
gSprites[spriteId].sTaskId = taskId;
gSprites[spriteId].sBallId = 0;
(blank line)

and also delete the following lines (now lines 463 to 466)

spriteId = CreateSprite(&sSpriteTemplate_Pokeball, sPokeballCoords[2][0], sPokeballCoords[2][1], 2);
gSprites[spriteId].sTaskId = taskId;
gSprites[spriteId].sBallId = 2;
(blank line)

so the whole section should be:

void CB2_ChooseStarter(void)
{
    u8 taskId;
    u8 spriteId;

    sRandomStarterSpecies = sRandomStarterPool[Random() % ARRAY_COUNT(sRandomStarterPool)];

    SetVBlankCallback(NULL);

    SetGpuReg(REG_OFFSET_DISPCNT, 0);
    SetGpuReg(REG_OFFSET_BG3CNT, 0);
    SetGpuReg(REG_OFFSET_BG2CNT, 0);
    SetGpuReg(REG_OFFSET_BG1CNT, 0);
    SetGpuReg(REG_OFFSET_BG0CNT, 0);

    ChangeBgX(0, 0, BG_COORD_SET);
    ChangeBgY(0, 0, BG_COORD_SET);
    ChangeBgX(1, 0, BG_COORD_SET);
    ChangeBgY(1, 0, BG_COORD_SET);
    ChangeBgX(2, 0, BG_COORD_SET);
    ChangeBgY(2, 0, BG_COORD_SET);
    ChangeBgX(3, 0, BG_COORD_SET);
    ChangeBgY(3, 0, BG_COORD_SET);

    DmaFill16(3, 0, VRAM, VRAM_SIZE);
    DmaFill32(3, 0, OAM, OAM_SIZE);
    DmaFill16(3, 0, PLTT, PLTT_SIZE);

    LZ77UnCompVram(gBirchBagGrass_Gfx, (void *)VRAM);
    LZ77UnCompVram(gBirchBagTilemap, (void *)(BG_SCREEN_ADDR(6)));
    LZ77UnCompVram(gBirchGrassTilemap, (void *)(BG_SCREEN_ADDR(7)));

    ResetBgsAndClearDma3BusyFlags(0);
    InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));
    InitWindows(sWindowTemplates);

    DeactivateAllTextPrinters();
    LoadUserWindowBorderGfx(0, 0x2A8, BG_PLTT_ID(13));
    ClearScheduledBgCopiesToVram();
    ScanlineEffect_Stop();
    ResetTasks();
    ResetSpriteData();
    ResetPaletteFade();
    FreeAllSpritePalettes();
    ResetAllPicSprites();

    LoadPalette(GetOverworldTextboxPalettePtr(), BG_PLTT_ID(14), PLTT_SIZE_4BPP);
    LoadPalette(gBirchBagGrass_Pal, BG_PLTT_ID(0), sizeof(gBirchBagGrass_Pal));
    LoadCompressedSpriteSheet(&sSpriteSheet_PokeballSelect[0]);
    LoadCompressedSpriteSheet(&sSpriteSheet_StarterCircle[0]);
    LoadSpritePalettes(sSpritePalettes_StarterChoose);
    BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, RGB_BLACK);

    EnableInterrupts(DISPSTAT_VBLANK);
    SetVBlankCallback(VblankCB_StarterChoose);
    SetMainCallback2(CB2_StarterChoose);

    SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR);
    SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ);
    SetGpuReg(REG_OFFSET_WIN0H, 0);
    SetGpuReg(REG_OFFSET_WIN0V, 0);
    SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN);
    SetGpuReg(REG_OFFSET_BLDALPHA, 0);
    SetGpuReg(REG_OFFSET_BLDY, 7);
    SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);

    ShowBg(0);
    ShowBg(2);
    ShowBg(3);

    taskId = CreateTask(Task_StarterChoose, 0);
    gTasks[taskId].tStarterSelection = 1;

    // Create hand sprite
    spriteId = CreateSprite(&sSpriteTemplate_Hand, 120, 56, 2);
    gSprites[spriteId].data[0] = taskId;

    spriteId = CreateSprite(&sSpriteTemplate_Pokeball, sPokeballCoords[1][0], sPokeballCoords[1][1], 2);
    gSprites[spriteId].sTaskId = taskId;
    gSprites[spriteId].sBallId = 1;

    sStarterLabelWindowId = WINDOW_NONE;
}

__

in section static void Task_StarterChoose(u8 taskId)
delete (now line 478) CreateStarterPokemonLabel(gTasks[taskId].tStarterSelection);

__

in section static void Task_HandleStarterChooseInput(u8 taskId) (now at line 485)
replace the entire section with

{
    if (JOY_NEW(A_BUTTON))
    {
        gSpecialVar_Result = 0;
        ResetAllPicSprites();
        SetMainCallback2(gMain.savedCallback);
    }
}


data/maps/LittlerootTown_ProfessorBirchsLab.inc

this code sets the rival's team

in section LittlerootTown_ProfessorBirchsLab_RandomStarter_EventScript_AgreeToSeeRival::
add this line after setvar VAR_BIRCH_LAB_STATE, 3 (line 134)

	goto RandomStarter_EventScript_SetRival

__

add this code to the end of the file

RandomStarter_EventScript_SetRival::

	setvar 0x8005, SPECIES_TREECKO
	special CheckSpecies
	goto_if_eq VAR_RESULT, TRUE, RandomStarter_EventScript_SetVar_Grass

	setvar 0x8005, SPECIES_TORCHIC
	special CheckSpecies
	goto_if_eq VAR_RESULT, TRUE, RandomStarter_EventScript_SetVar_Fire

	setvar 0x8005, SPECIES_MUDKIP
	special CheckSpecies
	goto_if_eq VAR_RESULT, TRUE, RandomStarter_EventScript_SetVar_Water

//if none of these
	goto RandomStarter_EventScript_RivalRandom

RandomStarter_EventScript_RivalRandom::
    random 3
    switch VAR_RESULT
    case 0, RandomStarter_EventScript_SetVar_Grass
    case 1, RandomStarter_EventScript_SetVar_Fire
    case 2, RandomStarter_EventScript_SetVar_Water

RandomStarter_EventScript_SetVar_Grass::
	setvar VAR_STARTER_MON, 0
	releaseall
	end

RandomStarter_EventScript_SetVar_Fire::
	setvar VAR_STARTER_MON, 1
	releaseall
	end

RandomStarter_EventScript_SetVar_Water::
	setvar VAR_STARTER_MON, 2
	releaseall
	end


this last part adds Lunos' code for checking the party

https://www.pokecommunity.com/threads/simple-modifications-directory.416647/post-10213715
(Check for a specific Pokémon species (using a custom special) [Em])


src/specials.inc

add to end of file

	def_special CheckSpecies


src/field_specials.c

add to end of file

void CheckSpecies(void)
{
    u8 i;
    u16 species;
    struct Pokemon *pokemon;
    for (i = 0; i < CalculatePlayerPartyCount(); i++)
    {
        pokemon = &gPlayerParty[i];
        if (GetMonData(pokemon, MON_DATA_SANITY_HAS_SPECIES) && !GetMonData(pokemon, MON_DATA_IS_EGG))
        {
            species = GetMonData(pokemon, MON_DATA_SPECIES);
            if (species == gSpecialVar_0x8005)
            {
                gSpecialVar_Result = TRUE;
                return;
            }
            else
            {
                gSpecialVar_Result = FALSE;
            }
        }
    }
}


Clone this wiki locally