- 18,833
- Posts
- 22
- Years
- Melbourne, Australia
- Seen today
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
[…]
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},
};
[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 ininclude/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
};
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 tosrc/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}
}
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;
}
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 theLoadFlyDestIcons()
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: