• 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?".
  • Forum moderator applications are now open! Click here for details.
  • 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] Following Pokémon

247
Posts
6
Years
  • Age 25
  • Seen yesterday
Updates:
Spoiler:
12/5/23: Cleared up bugs caused by overlapping local ids, and made follower go into pokeball when deposited at the daycare.

In the official Gen 4 Pokémon games (HearGold/SoulSilver, and to a lesser extent Diamond/Pearl/Platinum), we were able to have our lead Pokémon follow behind us as we walked about the region. After a great long deal of sprite copying and formatting, I am proud to present you with some code that will allow you to do the same in your pokeemerald hacks!

Currently, only Gen 1-4 Pokémon are accounted for. I plan to add the sprites for the later generations, but....it takes a while to get all of those sprites formatted, so it'll be awhile till that happens. I'll update this post whenever a new generation is added to the repository.

Screenshots:
Spoiler:

Acquisition:
Spoiler:

Recommended Use:
Spoiler:


For those of you using Porymap and the Pokémon Expansion, if you use some of the follower graphics as normal event objects, the sprite you see in Porymap will not be the same sprite you see in-game, since Porymap automatically assumes that POKEMON_EXPANSION is not defined when reading your project's repository to get the sprite data. You can fix this by going into include/constants/event_objects.h and deleting everything from
#ifndef POKEMON_EXPANSION to #else, including those two lines, as well as the #endif related to them.

I have not added any sort of script that allows you to talk to your following Pokémon like in HG/SS. This is primarily because I'd imagine that many people would want different possible interactions to have with different Pokémon.......and partially because I was lazy, so it made it easier to justify the thought of leaving that up to other people. If you do want a following Pokémon project where there are interaction scripts with the followers, you can add your own by giving the follower object event a script of your own making or by giving it a custom script following the Follow Me process, or you can try pokemerrp's project. Her project has interaction scripts and a couple of other nice additions, so give that project a look.

I hope you enjoy having your Pokémon be able to walk/fly/etc. with you in your hacks! If you notice any glitches or issues with your following Pokémon, please let me know so I can try to fix it as quickly as possible. I'm sure there's some specific interaction that I haven't accounted for out there.

Credits:
ghoulslash for his Follow Me code. This wouldn't be possible without it.
Dragoon and redblueyellow from The Spriters Resource for the sprite rips
vxo for his Dynamic Palette and Adding OW Sprites tutorial.
The Conqueror for helping me get past silly mistakes.
Sonikku A for creating and sharing with me new footprints for the Pokémon.
pokemerrp from RHH Discord for sharing formatted overworld sprites.
UltimaSoul for helping with memory issues.
malice936 on Devianart for the other overworld Pokéball sprites.
Karl for helping me clean up some of the Pokéball overworld sprites, catching and fixing an elevation bug, and providing macros and bug fixes for the follower_face commands.
ExpoSeed for updated dynamic palette system.
kfm for finding fix to guaranteed-encounter bug.

Known Glitches:
-On a very rare occasion, the game freezes when the follower is initially created. I can't make it happen consistently, although I suspect it has something to do with my emulator, since the few times I remember it happening occurred when I had the speed-up function on.
-Sometimes, when the sparkle animation of the grow-out-of-Pokéball animation plays, there's a flash of pink.

To-Do List:
-Add sprites for later generation Pokémon
-Reduce spritesheet size to reduce memory usage
-Implement Sonikku A's New Footprints.
-Add animation of following Pokémon going into/out of a pokéball when it becomes hidden/reappears.
-Add an overworld sprite for Beast Balls.

Maybe-Do List: (Basically a list of things that I might do if people really want me to)
-Add gender-specific overworld sprites and code to account for said sprites
-Add palettes and code to account for shiny Pokémon.
-Add custom sparkles for each Pokéball type.
 
Last edited:
4
Posts
2
Years
  • Age 35
  • Seen Oct 29, 2021
This is pretty awesome and thank you for the work. If i can make a suggestion, i would suggest that you make a branch that is just for the following pokemon because if you try and merge the master it will just give you and error of
Code:
fatal: refusing to merge unrelated histories
 

Lunos

Random Uruguayan User
3,108
Posts
15
Years
Woah! This is so cool!
So far, there was only one public implementation that I knew of, but it wasn't self-isolated. It was added alongside a handful of other random changes in the span of multiple commits, so it was hard to incorporate into a project.
Thank you for making a public implementation, I'll try to give it a spin later!
 
17
Posts
3
Years
  • Age 24
  • Seen Feb 19, 2024
I'm using Merrp's followers, though she has a similar issue for lack of actual object hopping. I've been looking to have a none baked solution, and noticed that the game does have hopping in specific events
-When surfing
-Cable Car
Cable car in particular seems to be easier to understand (shift up/down 1 pixel every 9 frames from the timer), while surf is gradual bobbing and relies on states across different voids
Potentially you can reduce the sheet in half if this is implemented, though I have no idea how to implement this for the follower sprite object

The code for hopping from src/cable_car.c;

Code:
#define sState data[2]
#define sTimer data[3]

static void SpriteCB_Player(struct Sprite *sprite)
{
    if (sCableCar->state != STATE_END)
    {
        // Move along with cable car
        if (!GOING_DOWN)
        {
            sprite->pos1.x = sprite->sXPos - (u8)(0.14f * S16TOPOSFLOAT(sCableCar->timer));
            sprite->pos1.y = sprite->sYPos - (u8)(0.067f * S16TOPOSFLOAT(sCableCar->timer));
        }
        else
        {
            sprite->pos1.x = sprite->sXPos + (u8)(0.14f * S16TOPOSFLOAT(sCableCar->timer));
            sprite->pos1.y = sprite->sYPos + (u8)(0.067f * S16TOPOSFLOAT(sCableCar->timer));
        }

        // Bounce up and down
        switch (sprite->sState)
        {
        case 0:
            sprite->pos2.y = 17;
            if (sprite->sTimer++ > 9)
            {
                sprite->sTimer = 0;
                sprite->sState++;
            }
            break;
        default:
            sprite->pos2.y = 16;
            if (sprite->sTimer++ > 9)
            {
                sprite->sTimer = 0;
                sprite->sState = 0;
            }
            break;
        }
    }
}

#undef sState
#undef sTimer

And, for surfing in src/field_effect_helpers.c;

Code:
// States for bobbing up and down while surfing
void SetSurfBobState(u8 spriteId, u8 value)
{
    gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF) | (value & 0xF);
}

Code:
void UpdateSurfBlobFieldEffect(struct Sprite *sprite)
{
    struct ObjectEvent *objectEvent;
    struct Sprite *linkedSprite;

    objectEvent = &gObjectEvents[sprite->data[2]];
    linkedSprite = &gSprites[objectEvent->spriteId];
    SynchroniseSurfAnim(objectEvent, sprite);
    sub_81556E8(objectEvent, sprite);
    CreateBobbingEffect(objectEvent, linkedSprite, sprite);
    sprite->oam.priority = linkedSprite->oam.priority;
}

Code:
static void CreateBobbingEffect(struct ObjectEvent *objectEvent, struct Sprite *linkedSprite, struct Sprite *sprite)
{
    u16 unk_085CDC6A[] = {3, 7};
    u8 bobState = GetSurfBobState(sprite);
    if (bobState != 0)
    {
        if (((u16)(++ sprite->data[4]) & unk_085CDC6A[sprite->data[5]]) == 0)
        {
            sprite->pos2.y += sprite->data[3];
        }
        if ((sprite->data[4] & 0x0F) == 0)
        {
            sprite->data[3] = -sprite->data[3];
        }
        if (bobState != 2)
        {
            if (GetSurfBobWhileFishingState(sprite) == 0)
                linkedSprite->pos2.y = sprite->pos2.y;
            else
                linkedSprite->pos2.y = sprite->data[1] + sprite->pos2.y;
            sprite->pos1.x = linkedSprite->pos1.x;
            sprite->pos1.y = linkedSprite->pos1.y + 8;
        }
    }
}
 
247
Posts
6
Years
  • Age 25
  • Seen yesterday
This is pretty awesome and thank you for the work. If i can make a suggestion, i would suggest that you make a branch that is just for the following pokemon because if you try and merge the master it will just give you and error of
Code:
fatal: refusing to merge unrelated histories

I now have this stuff as a branch in my repository that's forked from rh-hideout's repository and updated the git command stuff in the initial post. Hopefully that works.


I initially tried to implement the bouncing like that, but the speed of the bouncing changed depending on if the Pokémon was standing still or walking. However, now that you've shown me that it's done that way in the official code, I'll give it another try.
 
53
Posts
7
Years
  • Age 29
  • Seen Aug 25, 2023
"The Conqueror for helping me get past silly mistakes."

Holy shit small world and also ironic and based. As I am making a rom hack that I wanted Clefairy to follow you around similar to how it is in Yellow. So glad I could help in a small way and for something I actually wanted and needed. Just hope that you can help me if adding it does not go so well.
 
53
Posts
7
Years
  • Age 29
  • Seen Aug 25, 2023
IDK if this happens to others or if its just me as I just downloaded your main and then tried to add your following branch. But your battle_ai_main.c file is littered with errors most of the undeclared first us in function type.

Would also like to add your following pokemon branch seems to have added stuff not related to following pokemon. "graphics/pokemon/rillaboom/normal.pal" as an example. Making it annoying with trying to find what files are related to following mons and which are not.
 
Last edited:
247
Posts
6
Years
  • Age 25
  • Seen yesterday
IDK if this happens to others or if its just me as I just downloaded your main and then tried to add your following branch. But your battle_ai_main.c file is littered with errors most of the undeclared first us in function type.

Would also like to add your following pokemon branch seems to have added stuff not related to following pokemon. "graphics/pokemon/rillaboom/normal.pal" as an example. Making it annoying with trying to find what files are related to following mons and which are not.

You are absolutely correct. I just realized that I had just slapped the Following Pokémon code over the master branch, not worrying about if some of the changed files or functions would cause issues. I just updated the branch, so it should be good now. Thanks for pointing that out!
 

Lunos

Random Uruguayan User
3,108
Posts
15
Years
Acquisition:
If you just want to pull from my repository for all of the code and sprites, here are the commands:
Code:
git remote add wiservisor https://github.com/WiserVisor/pokeemerald-expansion.git
git pull wiservisor FollowingPokemon
You should kind of update that.
Since you created a full repository for the feature and are no longer hosting a branch in your Pokeemerald-expansion repository, newcomers can be misled when they try to follow the steps to acquire the branch.

EDIT: Actually, nevermind that. It seems that you made a clean repository that has Pokeemerald and the feature implemented in 1 or 2 commits total. This is a terrible, terrible idea.
First things first, if you make a new repository with a clean history, storing all the files of Pokeemerald and your changes in 1 or 2 commits, no one will be able to discern your own changes from the codebase's in its base state easily.

Secondly, due to the commit history being so blatantly different between a Pokeemerald project's and this "FollowingPokeemerald" repository, people will not be able to pull the branch as is. Git does not allow to pull the branch of a repository when there's such a disparity between the commit histories of both, a user's own branch and the one they want to pull.

This takes us to 3rd and last point.
One can use Git's "cherry-pick" feature to incorporate the 2 commits into their project.
One can also pass the --allow-unrelated-histories parameter through git pull at the time of incorporating this into their project.
One issue with doing either is that newbies are unlikely to know about these methods, but the most important problem is...
Spoiler:


For everyone's sake but also to follow good practices, in my opinion, you should have a pullable branch just like you had before.
One based on Pret's Pokeemerald repository or whichever else you want, with their commit history untouched, and containing the feature implemented normally in its own commit or set of commits on top.
 
Last edited:
247
Posts
6
Years
  • Age 25
  • Seen yesterday
For everyone's sake but also to follow good practices, in my opinion, you should have a pullable branch just like you had before.
One based on Pret's Pokeemerald repository or whichever else you want, with their commit history untouched, and containing the feature implemented normally in its own commit or set of commits on top.

This is the plan. I had some weird issues with my repository, which led me to needing to make some significant changes with it. It's in the works, but not up-and-running at the moment. I'll update the main post to reflect the current state of this project.
 
247
Posts
6
Years
  • Age 25
  • Seen yesterday
I have updated my repository so that it is forked from Pret's repository, so you can just pull from it. I've also shrunk the size of all of the spritesheets, which should save you a bit of space! The main post of this thread is updated to reflect these changes. Let me know if any glitches show up, since I only did a small amount of testing after implementing all of these changes due to my assumption that nothing should have issues (always a safe assumption) and laziness.
 

Kobazco

Gex Fan
39
Posts
12
Years
  • Age 24
  • Seen Nov 21, 2023
I have updated my repository so that it is forked from Pret's repository, so you can just pull from it. I've also shrunk the size of all of the spritesheets, which should save you a bit of space! The main post of this thread is updated to reflect these changes. Let me know if any glitches show up, since I only did a small amount of testing after implementing all of these changes due to my assumption that nothing should have issues (always a safe assumption) and laziness.

Just implemented this into a new project with battle engine and item expansion as a test, and it works perfectly!

Except when I talk to my Pokemon, I know you say in the main post that you haven't done anything with that yet, but it causes some really weird... side effects for me. Most commonly the coin counter pops up at the top of my screen, and another time it teleported me to a Pokemon center but I was trapped in the void.
 
17
Posts
3
Years
  • Age 24
  • Seen Feb 19, 2024
Did you get my footprint sprites? I can't tell if my message went through
 
247
Posts
6
Years
  • Age 25
  • Seen yesterday
Except when I talk to my Pokemon, I know you say in the main post that you haven't done anything with that yet, but it causes some really weird... side effects for me. Most commonly the coin counter pops up at the top of my screen, and another time it teleported me to a Pokemon center but I was trapped in the void.

I just now pushed a fix for that. As it turned out, there was an error in the Follow Me code at the point where the custom script is assigned to the follower. It does this assignment before it's able to see whether or not the follower should have a custom script. It then always tries to use a custom script, even though the follower has none. Thanks for giving me a reason to dig a bit deeper into that issue, because it had confused me for awhile, but I had just chosen to ignore it.

Did you get my footprint sprites? I can't tell if my message went through
Yes I did. Thanks for that! I'll be implementing those next.
 
247
Posts
6
Years
  • Age 25
  • Seen yesterday
I have now implemented Sonikku A's custom footprints for several of the Gen 1 Pokémon, as well as made some other footprint adjustments, like making sure the flying/floating Pokémon don't make footprints.
 
30
Posts
4
Years
  • Age 67
  • Seen Jan 25, 2024
Any idea why a clean build of your following branch results in a clone of your character following instead of a pokemon sprite? It's funny, in a cursed sort of way. As soon as you get your starter from the professor the sprite is your twin, and even catching a new one, switching, pokemon healing center, etc doesn't fix it?
 
247
Posts
6
Years
  • Age 25
  • Seen yesterday
Any idea why a clean build of your following branch results in a clone of your character following instead of a pokemon sprite? It's funny, in a cursed sort of way. As soon as you get your starter from the professor the sprite is your twin, and even catching a new one, switching, pokemon healing center, etc doesn't fix it?

That is because I have only added in sprites for all of the Gen 1 Pokémon. Since your starter can only be Torchic, Mudkip, or Treecko (unless you change them in src/starter_choose.c), and those are all Gen 3 Pokémon, the game doesn't know what to do with them. In the code, if there's some weird issue with an object event's graphics, it will default to just using the Brendan sprite. That's what you're seeing. Once I add the Gen 3 Pokémon sprites, that issue will go away.
 
30
Posts
4
Years
  • Age 67
  • Seen Jan 25, 2024
My mistake, thanks very much. For some reason, I thought they simply wouldn't show if the sprite wasn't available. Good to know. I'll continue to watch for an updated version!
 
247
Posts
6
Years
  • Age 25
  • Seen yesterday
Just added sprites for all Gen 2 Pokémon!....excluding all of the Unowns except A. Regardless of which type of Unown you have, in the overworld, it will just appear as an A Unown. With the way I have all of the graphic data stored, stuff like alternate forms and whatnot will need to be put at the end of the list, and I am faaaar from reaching the end of that list. Once again, let me know if something starts acting screwy so I can fix it as quickly as possible.
 
Back
Top