• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[Pokeemerald] Add routes as Fly destinations

18,811
Posts
21
Years
  • Add routes as Fly destinations in pokeemerald

    Modern Pokémon games have given players the ability to fast-travel to almost any area the player has visited. Now you can do the same with your pokeemerald-based hack!

    This tutorial at this point will help you do the bare minimum to make it so you can use Fly to get to other routes. You'll have to decide for yourself how to do the rest. You should feel free to modify parameters that suit the way you want it to work.

    First, set some heal points

    Before we begin, you'll want to assign a "Heal Point" (a respawn/flying point) for the player to land, for the areas you want to implement flying to. You want to do this as otherwise, the player will fast-travel to (what I presume is) the center of the map, which may put the player where you don't want them to be — like on a mountain, or surfing in water without actually having a surfing Pokémon. This feature isn't directly exposed in Porymap (as of the time of writing), so you'll need to do a bit of this by hand.

    In include/constants/heal_locations.h, add new heal locations as you need them:
    Code:
    […]
    #define HEAL_LOCATION_FALLARBOR_TOWN 17
    #define HEAL_LOCATION_VERDANTURF_TOWN 18
    #define HEAL_LOCATION_PACIFIDLOG_TOWN 19
    #define HEAL_LOCATION_EVER_GRANDE_CITY_POKEMON_LEAGUE 20
    #define HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR 21
    #define HEAL_LOCATION_BATTLE_FRONTIER_OUTSIDE_EAST 22
    #define HEAL_LOCATION_ROUTE_101 23
    #define HEAL_LOCATION_ROUTE_102 24
    #define HEAL_LOCATION_ROUTE_103 25
    […]
    You can name these anything you want, though you'll probably want to start with HEAL_LOCATION for your sanity.

    Then, in src/data/heal_locations.h, make a new line in the sHealLocations struct for every location you want to put a spawn point in, with each location named after the heal locations you defined in the previous step:
    Code:
    static const struct HealLocation sHealLocations[] =
    {
        […]
        [HEAL_LOCATION_PACIFIDLOG_TOWN - 1] = {MAP_GROUP(PACIFIDLOG_TOWN), MAP_NUM(PACIFIDLOG_TOWN), 8, 16},
        [HEAL_LOCATION_EVER_GRANDE_CITY_POKEMON_LEAGUE - 1] = {MAP_GROUP(EVER_GRANDE_CITY), MAP_NUM(EVER_GRANDE_CITY), 18, 6},
        [HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR - 1] = {MAP_GROUP(SOUTHERN_ISLAND_EXTERIOR), MAP_NUM(SOUTHERN_ISLAND_EXTERIOR), 15, 20},
        [HEAL_LOCATION_BATTLE_FRONTIER_OUTSIDE_EAST - 1] = {MAP_GROUP(BATTLE_FRONTIER_OUTSIDE_EAST), MAP_NUM(BATTLE_FRONTIER_OUTSIDE_EAST), 3, 52},
        [HEAL_LOCATION_ROUTE_101 - 1] = {MAP_GROUP(ROUTE101), MAP_NUM(ROUTE101), 5, 10},
    };
    The format is [CONSTANT_NAME - 1] = {MAP_GROUP(ROUTE101), MAP_NUM(ROUTE101), xPos, yPos},
    If you're feeling particularly lazy, just define your x and y coordinates as 1, 1 for each map and then reload your Porymap project, load the applicable map, and drag the newly-appearing [H] heal point in the coordinates you put down to where you might actually want it.

    Define location types

    Before we take wing (heh) we should probably create a route type that people can fly to in include/region_map.h. Something like MAPSECTYPE_ROUTE_CANFLY:
    Code:
    enum {
        MAPSECTYPE_NONE,
        MAPSECTYPE_ROUTE,
        MAPSECTYPE_ROUTE_CANFLY,
        MAPSECTYPE_CITY_CANFLY,
        MAPSECTYPE_CITY_CANTFLY,
        MAPSECTYPE_BATTLE_FRONTIER
    };
    You should specifically create this type so that in the game code in the next step, you can define the conditions to be able to fly to an area. That, and you don't want people flying to places they haven't been to yet. (Do you?)

    edit: Also add this new location type to the Pokénav, or else it won't know what the location is. In src/pokenav_region_map.c, under the UpdateMapSecInfoWindow() function, add our MAPSECTYPE_ROUTE_CANFLY constant to the switch statement just MAPSECTYPE_ROUTE:
    Code:
    static void UpdateMapSecInfoWindow(struct Pokenav5Struct_2 *state)
    {
        struct RegionMap *regionMap = GetSubstructPtr(16);
        switch (regionMap->mapSecType)
        {
        case MAPSECTYPE_CITY_CANFLY:
            […]
        case MAPSECTYPE_CITY_CANTFLY:
            […]
        case MAPSECTYPE_ROUTE:
        case MAPSECTYPE_ROUTE_CANFLY:
        case MAPSECTYPE_BATTLE_FRONTIER:
            […]
        […]
    }

    Time to add the fly points

    Time to fly (heh heh) over to src/region_map.c.

    Let's actually tell region_map.c where our heal locations are. In the sMapHealLocations struct, unless you've specifically removed them, the routes are already defined.
    Code:
    static const u8 sMapHealLocations[][3] =
    {
        […]
        {MAP_GROUP(ROUTE101), MAP_NUM(ROUTE101), HEAL_LOCATION_ROUTE_101},
        {MAP_GROUP(ROUTE102), MAP_NUM(ROUTE102), 0},
        {MAP_GROUP(ROUTE103), MAP_NUM(ROUTE103), 0},
        {MAP_GROUP(ROUTE104), MAP_NUM(ROUTE104), 0},
        {MAP_GROUP(ROUTE105), MAP_NUM(ROUTE105), 0},
        {MAP_GROUP(ROUTE106), MAP_NUM(ROUTE106), 0},
        {MAP_GROUP(ROUTE107), MAP_NUM(ROUTE107), 0},
        {MAP_GROUP(ROUTE108), MAP_NUM(ROUTE108), 0},
        {MAP_GROUP(ROUTE109), MAP_NUM(ROUTE109), 0},
        {MAP_GROUP(ROUTE110), MAP_NUM(ROUTE110), 0},
        {MAP_GROUP(ROUTE111), MAP_NUM(ROUTE111), 0},
        {MAP_GROUP(ROUTE112), MAP_NUM(ROUTE112), 0},
        {MAP_GROUP(ROUTE113), MAP_NUM(ROUTE113), 0},
        {MAP_GROUP(ROUTE114), MAP_NUM(ROUTE114), 0},
        {MAP_GROUP(ROUTE115), MAP_NUM(ROUTE115), 0},
        {MAP_GROUP(ROUTE116), MAP_NUM(ROUTE116), 0},
        {MAP_GROUP(ROUTE117), MAP_NUM(ROUTE117), 0},
        {MAP_GROUP(ROUTE118), MAP_NUM(ROUTE118), 0},
        {MAP_GROUP(ROUTE119), MAP_NUM(ROUTE119), 0},
        {MAP_GROUP(ROUTE120), MAP_NUM(ROUTE120), 0},
        {MAP_GROUP(ROUTE121), MAP_NUM(ROUTE121), 0},
        {MAP_GROUP(ROUTE122), MAP_NUM(ROUTE122), 0},
        {MAP_GROUP(ROUTE123), MAP_NUM(ROUTE123), 0},
        {MAP_GROUP(ROUTE124), MAP_NUM(ROUTE124), 0},
        {MAP_GROUP(ROUTE125), MAP_NUM(ROUTE125), 0},
        {MAP_GROUP(ROUTE126), MAP_NUM(ROUTE126), 0},
        {MAP_GROUP(ROUTE127), MAP_NUM(ROUTE127), 0},
        {MAP_GROUP(ROUTE128), MAP_NUM(ROUTE128), 0},
        {MAP_GROUP(ROUTE129), MAP_NUM(ROUTE129), 0},
        {MAP_GROUP(ROUTE130), MAP_NUM(ROUTE130), 0},
        {MAP_GROUP(ROUTE131), MAP_NUM(ROUTE131), 0},
        {MAP_GROUP(ROUTE132), MAP_NUM(ROUTE132), 0},
        {MAP_GROUP(ROUTE133), MAP_NUM(ROUTE133), 0},
        {MAP_GROUP(ROUTE134), MAP_NUM(ROUTE134), 0}
    }
    These don't have a heal location currently set, though since you'd defined their constants in the previous step, you can now map each listed route to a heal location (or spawn point), like the HEAL_LOCATION_ROUTE_101 you see here.

    Look for the GetMapsecType() function. At this point, you'll be able to define flag conditions to determine whether a player can fly to the route. Note the MAPSECTYPE_ROUTE_CANFLY constant we created earlier, as the ternary operator here allows us to use the flag to determine whether someone can fly to the route or not:
    Code:
    static u8 GetMapsecType(u16 mapSecId)
    {
        switch (mapSecId)
        {
        case MAPSEC_NONE:
            return MAPSECTYPE_NONE;
        case MAPSEC_LITTLEROOT_TOWN:
            return FlagGet(FLAG_VISITED_LITTLEROOT_TOWN) ? MAPSECTYPE_CITY_CANFLY : MAPSECTYPE_CITY_CANTFLY;
        case MAPSEC_OLDALE_TOWN:
            return FlagGet(FLAG_VISITED_OLDALE_TOWN) ? MAPSECTYPE_CITY_CANFLY : MAPSECTYPE_CITY_CANTFLY;
        […]
        case MAPSEC_ROUTE_101:
            return FlagGet(FLAG_VISITED_OLDALE_TOWN) ? MAPSECTYPE_ROUTE_CANFLY : MAPSECTYPE_ROUTE;
        case MAPSEC_ROUTE_102:
            return FlagGet(FLAG_VISITED_PETALBURG_CITY) ? MAPSECTYPE_ROUTE_CANFLY : MAPSECTYPE_ROUTE;
        case MAPSEC_ROUTE_103:
            return FlagGet(FLAG_VISITED_PETALBURG_CITY) ? MAPSECTYPE_ROUTE_CANFLY : MAPSECTYPE_ROUTE;
        case MAPSEC_ROUTE_104:
            return FlagGet(FLAG_VISITED_RUSTBORO_CITY) ? MAPSECTYPE_ROUTE_CANFLY : MAPSECTYPE_ROUTE;
        case MAPSEC_ROUTE_105:
            return FlagGet(FLAG_BADGE05_GET) ? MAPSECTYPE_ROUTE_CANFLY : MAPSECTYPE_ROUTE;
        case MAPSEC_ROUTE_106:
            return FlagGet(FLAG_BADGE05_GET) ? MAPSECTYPE_ROUTE_CANFLY : MAPSECTYPE_ROUTE;
    }
    In my case, you'll notice that to access Route 101, the Oldale Town flag must be set. To access Route 105, you must have the 5th badge. You get it. If you really want to, you can create your own set of FLAG_VISITED flags in include/constants/flags.h, which might be useful in creating graphics to indicate if the user can fly to the route. (This is outside the scope of this tutorial for now.)

    Ready for takeoff? Nearly! The last step is to now make our new constant allow us to actually fly to the route. The game checks the flags, and is now setting the map type, so now it's time to put our MAPSECTYPE_ROUTE_CANFLY constant in the CB_HandleFlyMapInput() function:
    Code:
    static void CB_HandleFlyMapInput(void)
    {
        if (sFlyMap->state == 0)
        {
            switch (DoRegionMapInputCallback())
            {
            […]
            case MAP_INPUT_A_BUTTON:
                if (sFlyMap->regionMap.mapSecType == MAPSECTYPE_CITY_CANFLY || sFlyMap->regionMap.mapSecType == MAPSECTYPE_ROUTE_CANFLY || sFlyMap->regionMap.mapSecType == MAPSECTYPE_BATTLE_FRONTIER)
                { […] }
            […]
            }
        }
    }

    And we're off!

    A few notes

    This tutorial hasn't told you how to indicate whether the user can fly to these maps. If you want to indicate them, you'll want to check out the functions shown in the LoadFlyDestIcons() functions, perhaps modifying CreateFlyDestIcons() or creating a brand new function for yourself. If you try to copy CreateFlyDestIcons(), you'll need to figure out ways to indicate whether the map can be flown to — perhaps using flags like that function does, or a switch statement. Plus you'll want to generate some kind of sprite like the game does to indicate that you can fly to the route. It's all up to you!

    Fin.
     
    Last edited:
    18,811
    Posts
    21
    Years
  • And hey, if you followed this guide to the end, do note that I forgot to add a switch statement for the Pokénav. Added an "edit" relating to MAPSECTYPE_ROUTE_CANFLY in src/pokenav_region_map.c that you should totally check out so the Pokénav displays your new fly zones.
     
    Back
    Top