5 RoamersPlus ‐ multiple Roamers at once
judicornadamsfoster edited this page 2026-09-14 21:18:29 +01:00

original source: DarkDown's pokecommunity post

From DarkDown's post:

IMPORTANT:
If using the RHH expansion, my changes go to src/battle_ai_script_commands.c instead go into src/battle_ai_main.c

As most of you already know, in Pokemon Emerald, the player hears about the Eon Pokemon on TV and then chooses one of them to appear in the game.
The chosen Pokemon will then roam through certain routes and flee from battles instead of engaging the player in battle.
At its default state the game only allows for one roamer to exist at a time.
This branch allows you to set up as many roamers as you can fit into your saveblocks.
The Saveblock1 size of a Roamer has been reduced from 28 to 24 bytes. Each roamer beyond the first will of course take up an additional 24 bytes.

Other features:

Unbound Roaming
An optional feature that extends roaming to all routes. Normally roamers do not frequent most of the western routes.
Terrestrial Roamers
These roamers cannot be found on water tiles and do not roam on sea routes. Why is that Entei surfing?
Battling Roamers
Choose whether a roamer flees or battles normally.
Stalkers
These "roamers" will always move to your location. They leave the area after battle, but will follow you to the next area. Stalkers are not shown on the Pokedex by default.
Respawning Roamers
Select one of four respawning modes: no respawn, daily, weekly or instant respawn. Respawning roamers will not stop existing until they are caught.
Scaling Roamers
Adding a roamer with a level of 0 will create a scaling roamer. A scaling roamer's level increases based on your highest level party member and a constant modifier.
Includes an optional feature that allows roamers to evolve if they are high enough level.
Roamers will not level down or devolve if encountered with a weaker party.
Save/Load Persistent Locations
Roamer locations are added to SaveBlock1 and thus will not be randomized on game load.

A branch that does not include Persistent Locations can be found here. In this branch the Roamer struct takes up 16 bytes.

I included an example that, at the start of a new game or when InitRoamer() is called, creates the following roamers to showcase these features:

A basic Latias roamer that respawns weekly
A terrestrial Pikachu roamer that respawns daily
A terrestrial Pikachu that does not flee from battle
A scaling Weedle stalker that does not flee from battle and respawns instantly

All these species are also added to the Pokedex so you can track them.


How To Use:

pull from these updated branches:

Unbound / Terrestrial / Battling Roamers / Stalkers / Respawning / Scaling / Persistant Locations
compare

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

The above, but without Persistant Locations
compare

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

which ever branch you use, you will need to manually edit a few conflicts in 5 files.


How To Add Roamers

for each Roamer (or set of Roamers) you want to add, follow these steps

You don't have to have your Roamers all released at the same time.

The example below adds 2 sets of Roamers that will be unlocked at different times.


your chosen map script

In your map script file (or where you store your custom scripts)
however you want to activate it,
call the special in your scripts

	special InitJohtoRoamers

and

	special InitKantoRoamers

data/specials.inc

Add to end of file

	def_special InitKantoRoamers
	def_special InitJohtoRoamers


include/roamer.h

Add to the end of file, before #endif

void InitKantoRoamers(void);
void InitJohtoRoamers(void);


src/roamer.c

Add your function to the end of the file

In each funtion you should have:
at least one line stating the Roamer type
(DarkDown's examples)

  • TryAddRoamer(SPECIES_LATIAS, 40, FLEES, WEEKLY_RESPAWN);
  • TryAddTerrestrialRoamer(SPECIES_PIKACHU, 8, FLEES, DAILY_RESPAWN);
  • TryAddTerrestrialRoamer(SPECIES_PIKACHU, 15, DOES_NOT_FLEE, NO_RESPAWN);
  • TryAddStalker(SPECIES_WEEDLE, 0, DOES_NOT_FLEE, AMPHIBIOUS, INSTANT_RESPAWN);

if you want the Roamer to show as seen in the Pokedex (so you can follow where it is)

  • GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_LATIAS), FLAG_SET_SEEN);

In each Roamer line you should have:

  • the species eg. SPECIES_LATIAS
  • the level from 1 to 100, use 0 for scaling levels
  • if you want the Roamer to be able to flee, choose from FLEES or DOES_NOT_FLEE
  • for TryAddStalker only, choose from AMPHIBIOUS or TERRESTRIAL depending if you want the Stalker to appear in land and water or just land
  • if you want the Roamer to be able to respawn, choose from NO_RESPAWN, DAILY_RESPAWN, WEEKLY_RESPAWN or INSTANT_RESPAWN

// adds the 3 Kanto Birds but does not add them to pokedex
void InitKantoRoamers(void)
{
    TryAddRoamer(SPECIES_ARTICUNO, 40, FLEES, NO_RESPAWN);
    TryAddRoamer(SPECIES_ZAPDOS, 40, FLEES, NO_RESPAWN);
    TryAddRoamer(SPECIES_MOLTRES, 40, FLEES, NO_RESPAWN);
}

// adds the 3 Johto Beasts and adds them to pokedex to track them
void InitJohtoRoamers(void)
{
    GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_ENTEI), FLAG_SET_SEEN);
    GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_RAIKOU), FLAG_SET_SEEN);
    GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_SUICUNE), FLAG_SET_SEEN);
    TryAddTerrestrialRoamer(SPECIES_ENTEI, 40, FLEES, NO_RESPAWN);
    TryAddTerrestrialRoamer(SPECIES_RAIKOU, 40, FLEES, NO_RESPAWN);
    TryAddTerrestrialRoamer(SPECIES_SUICUNE, 40, FLEES, NO_RESPAWN);
}


end of guide


Sneed69's branches kept here for archive purposes:

Sneed69 branches

Unbound / Terrestrial / Battling Roamers / Stalkers / Respawning / Scaling / Persistant Locations
compare

git remote add Sneed69 https://github.com/Sneed69/pokeemerald.git  
git pull Sneed69 RoamersPlus

The above, but without Persistant Locations
compare

git remote add Sneed69 https://github.com/Sneed69/pokeemerald.git  
git pull Sneed69 RoamersPlus-No-Persistent-Locations

MANUAL CHANGES:

pokeemerald has renamed a few things since DarkDown posted his branch,
the following was renamed

src/pokedex_area_screen.c

in funtion static void FindMapsWithMon(u16 species)
search and replace:
for (i = 0; gWildMonHeaders[i].mapGroup != MAP_GROUP(UNDEFINED); i++)
change to:

        for (i = 0; gWildMonHeaders[i].mapGroup != MAP_GROUP(MAP_UNDEFINED); i++)

src/roamer.c

in function void RoamerMoveToOtherLocationSet(u8 index)
search for:
ROAMER(index)->locationMapGroup = MAP_GROUP(NONE);
ROAMER(index)->locationMapNum = MAP_NUM(NONE);
change to

            ROAMER(index)->locationMapGroup = MAP_GROUP(0x7F);  
            ROAMER(index)->locationMapNum = MAP_NUM(0x7F);  

__
in function void RoamerMove(u8 index)
search for:
|| mapNum == MAP_NUM(UNDEFINED));
change to:

                        || mapNum == MAP_NUM(MAP_UNDEFINED));