• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Our weekly protagonist poll is now up! Vote for your favorite Conquest protagonist in the poll by clicking here.
  • 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.

Simple Modifications Directory

FR/LG Start with "Running Shoes"

This is pretty simple, but I didn't see it mentioned. The Running Shoes doesn't seem to be an actual item, it just unlocks the ability to dash with the B button.

There may be other spots where this will work, but I opened data\maps\PalletTown_PlayersHouse_2F\scripts.inc. Look for the line PalletTown_PlayersHouse_2F_FirstWarpIn::. Above the "end" line, add the line setflag FLAG_SYS_B_DASH.
 
FR/LG Start with "Running Shoes"

This is pretty simple, but I didn't see it mentioned. The Running Shoes doesn't seem to be an actual item, it just unlocks the ability to dash with the B button.

There may be other spots where this will work, but I opened data\maps\PalletTown_PlayersHouse_2F\scripts.inc. Look for the line PalletTown_PlayersHouse_2F_FirstWarpIn::. Above the "end" line, add the line setflag FLAG_SYS_B_DASH.
Alternatively, you could remove the usage of && FlagGet(FLAG_SYS_B_DASH) from PlayerNotOnBikeMoving in src/field_player_avatar.c to accomplish the same thing and also free up 1 flag to reuse however you want.
 
I'm trying to apply the Gen VI EXP Share using this method. I'm guessing the issues I'm running into are because I'm trying to apply it to Fire Red instead of Emerald. I'm stuck on an error I don't know how to fix. Here's what I'm getting and the code. Please help. Oh, and if altering the code so the EXP Share is automatic (like Gen VIII), that would be awesome.

src/item_use.c: In function `ItemUseOutOfBattle_ExpShare':
src/item_use.c:840: structure has no member named `tUsingRegisteredKeyItem'
src/item_use.c:841: `Task_CloseCantUseKeyItemMessage' undeclared (first use in this function)
src/item_use.c:841: (Each undeclared identifier is reported only once
src/item_use.c:841: for each function it appears in.)
agbcc: warnings being treated as errors
src/item_use.c:841: warning: passing arg 2 of `DisplayItemMessageOnField' makes integer from pointer without a cast
src/item_use.c:841: too few arguments to function `DisplayItemMessageOnField'
src/item_use.c:843: warning: implicit declaration of function `DisplayItemMessage'
src/item_use.c:843: `CloseItemMessage' undeclared (first use in this function)
src/item_use.c:849: structure has no member named `tUsingRegisteredKeyItem'
src/item_use.c:850: warning: passing arg 2 of `DisplayItemMessageOnField' makes integer from pointer without a cast
src/item_use.c:850: too few arguments to function `DisplayItemMessageOnField'
make: *** [Makefile:302: build/firered/src/item_use.o] Error 1
make: *** Deleting file 'build/firered/src/item_use.o'
C-like:
void ItemUseOutOfBattle_ExpShare(u8 taskId)
{
    bool8  expShareOn = FlagGet(FLAG_EXP_SHARE);
    if (!expShareOn)
    {
        FlagSet(FLAG_EXP_SHARE);
        PlaySE(SE_EXP_MAX);
        if (gTasks[taskId].tUsingRegisteredKeyItem) // to account for pressing select in the overworld
            DisplayItemMessageOnField(taskId, gText_ExpShareTurnOn, Task_CloseCantUseKeyItemMessage);
        else
            DisplayItemMessage(taskId, 1, gText_ExpShareTurnOn, CloseItemMessage);
    }
    else
    {
        FlagClear(FLAG_EXP_SHARE);
        PlaySE(SE_PC_OFF);
        if (gTasks[taskId].tUsingRegisteredKeyItem) // to account for pressing select in the overworld
            DisplayItemMessageOnField(taskId, gText_ExpShareTurnOff, Task_CloseCantUseKeyItemMessage);
        else
            DisplayItemMessage(taskId, 1, gText_ExpShareTurnOff, CloseItemMessage);
    }
}
 
FR/LG ELECTRIC-TYPE IS IMMUNE TO PARALYSIS

Open the file src\battle_script_commands.c. Search for the line case STATUS1_PARALYSIS: and scroll down to the line if (gBattleMons[gEffectBattler].status1). Below the break; line, add the following:
C-like:
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ELECTRIC))
   break;

This only disables Electric-types from being paralyzed. Any moves that only cause paralysis (like Thunder Wave) will still animate like normal. I haven't figured out that part of it yet. 😟
 
FR/LG Fix Pokédex Display Error
The FR and LG games have an infamous display error in the Pokédex where a multi-word species name only displays the first word. This fixes that.
  1. Open src\pokedex_screen.c.
  2. Search for the line void DexScreen_PrintMonCategory(u8 windowId, u16 species, u8 x, u8 y).
  3. Delete or comment out the lines while ((categoryName[index] != CHAR_SPACE) && (index < 11)) and the #else below it.
I have no idea why this line is even here in the first place. The next condition says categoryName[index] != EOS. Assuming EOS means "end of string," the line being removed is just redundant.
 
Last edited:
FR/LG Make TMs Reusable
First off, this is just to prevent TMs from being removed from your inventory after use. This will not make them appear in the menu like HMs, prevent them from being sold, prevent reusing them to restore PP to the move, etc. I just managed to make this part of it work, so I'm sharing it for anyone interested.
  1. Open src\party_menu.c.
  2. Search for the line static void Task_LearnedMove(u8 taskId).
  3. Delete or comment out the lines if (item < ITEM_HM01) and RemoveBagItem(item, 1);.
  4. Search for the line if (ItemId_GetPocket(gSpecialVar_ItemId) == POCKET_TM_CASE && PSA_IsCancelDisabled() == TRUE).
  5. Change if (gSpecialVar_ItemId < ITEM_HM01) to if (gSpecialVar_ItemId < ITEM_TM01). (Looking at it now, this line and the following RemoveBagItem line could probably just be removed, too.)
So far this has worked for me with no other problems.
 
Last edited:
Set Trainer's Levels Dynamically POKEEMERALD
how to implement it?
just go to src/battle_main.c and inside of CreateNPCTrainerParty, define this:
Code:
    u8 reallevel = 0;
    u8 fixedLVL = 0;
    {
    if (GetMonData(&gPlayerParty[5], MON_DATA_SPECIES) != SPECIES_NONE)
        fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[1], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[2], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[3], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[4], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[5], MON_DATA_LEVEL)) / 6;
    else if ((GetMonData(&gPlayerParty[5], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[4], MON_DATA_SPECIES) != SPECIES_NONE))
            fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[2], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[3], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[4], MON_DATA_LEVEL)) / 5;
        else if ((GetMonData(&gPlayerParty[4], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[3], MON_DATA_SPECIES) != SPECIES_NONE))
            fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[2], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[3], MON_DATA_LEVEL)) / 4;
            else if ((GetMonData(&gPlayerParty[3], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[2], MON_DATA_SPECIES) != SPECIES_NONE))
                fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[2], MON_DATA_LEVEL)) / 3;
                else if ((GetMonData(&gPlayerParty[2], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[1], MON_DATA_SPECIES) != SPECIES_NONE))
                    fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)) / 2;
                    else if ((GetMonData(&gPlayerParty[1], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[0], MON_DATA_SPECIES) != SPECIES_NONE))
                        fixedLVL = GetMonData(&gPlayerParty[0], MON_DATA_LEVEL);
    }
Now, search "CreateMon(&party, partyData.species" and replace the whole line with this:
Code:
                CreateMon(&party[i], partyData[i].species, reallevel, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
now, right before those lines, put this:
Code:
                {
                    min = fixedLVL-2;
                    max = fixedLVL+2;
                        range = max - min + 1;
                        rand = Random() % range;
                }

                if (min <=0)
                    min=1;
                reallevel = min + rand;
now, modify the "-2" in the first one, and put a -4 or a -3 (this will be the minimum level that the trainer will have) and in the last one, change the +2 for a +3 or a +4.
this is for making regular trainers weaker and gym leaders, rivals and elite 4 stronger and making the game harder without having to grind so much... because you don't have to grind at all...

PD: I don't know if i can post this here, because it already has its own page but, i wanted to contribute

Set Wild Pokémon's Levels Dynamically POKEEEMERALD
And now, you'll learn how to make Wild Pokémon's level being around the same as yours, and is easier than trainer's one...
just go to
Code:
src\wild_encounter.c
and search this:
Code:
static u8 ChooseWildMonLevel(const struct WildPokemon *wildPokemon)
Now, just replace this part:
Code:
    // Make sure minimum level is less than maximum level
    if (wildPokemon->maxLevel >= wildPokemon->minLevel)
    {
        min = wildPokemon->minLevel;
        max = wildPokemon->maxLevel;
    }
    else
    {
        min = wildPokemon->maxLevel;
        max = wildPokemon->minLevel;
    }
    range = max - min + 1;
    rand = Random() % range;
with this:
Code:
    u8 fixedLVL = 0;
    {
    if (GetMonData(&gPlayerParty[5], MON_DATA_SPECIES) != SPECIES_NONE)
        fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[1], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[2], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[3], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[4], MON_DATA_LEVEL) + GetMonData(&gPlayerParty[5], MON_DATA_LEVEL)) / 6;
    else if ((GetMonData(&gPlayerParty[5], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[4], MON_DATA_SPECIES) != SPECIES_NONE))
            fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[2], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[3], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[4], MON_DATA_LEVEL)) / 5;
        else if ((GetMonData(&gPlayerParty[4], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[3], MON_DATA_SPECIES) != SPECIES_NONE))
            fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[2], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[3], MON_DATA_LEVEL)) / 4;
            else if ((GetMonData(&gPlayerParty[3], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[2], MON_DATA_SPECIES) != SPECIES_NONE))
                fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[2], MON_DATA_LEVEL)) / 3;
                else if ((GetMonData(&gPlayerParty[2], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[1], MON_DATA_SPECIES) != SPECIES_NONE))
                    fixedLVL = (GetMonData(&gPlayerParty[0], MON_DATA_LEVEL)+GetMonData(&gPlayerParty[1], MON_DATA_LEVEL)) / 2;
                    else if ((GetMonData(&gPlayerParty[1], MON_DATA_SPECIES) == SPECIES_NONE) && (GetMonData(&gPlayerParty[0], MON_DATA_SPECIES) != SPECIES_NONE))
                        fixedLVL = GetMonData(&gPlayerParty[0], MON_DATA_LEVEL);
    }

    // Make sure minimum level is less than maximum level
    {
        min = fixedLVL-3;
        max = fixedLVL+3;
    }
    if (min <= 0)
        min = 1;
    range = max - min + 1;
    rand = Random() % range;
And that's it! now Wild Pokémon's levels will be minor by 3 or mayor by 3 to yours. if the "min" value is equal or minor than 0, it'll be set to one, just for the optimal calculations and a wild pokémon not having level 0 or 57.
I had to make a couple changes to get these working for me. I don't know if it's a FireRed thing or not.

For the trainer parties, I had to define the variables for max, min, range, and rand. I defined them all as u8, and that's been working. Also, the section that's labelled "right before those lines," make sure that's above if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & (BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_TOWER))). I'm loving this code, though I do wish it randomized the level of every Pokémon a trainer has, rather than giving them all the same random level, but I could see how setting that up could be rather difficult.

For the wild Pokémon levels, there were already variables defined (except for fixedLVL), but the names are different. I didn't want to change them to what the code here used in case that screwed up something else, so here's the conversions:
min -> lo
max -> hi
range -> mod
rand -> res

I also had to add the line return lo + res; at the end for it to work correctly.
 
Let a Pokémon forget any move they know (Emerald)

As you all know, there's certain moves that a Pokémon can't forget on their own, these are the Hidden Machine Moves.
There is a function which handles that, it's called CanReplaceMove and it can be found in the src/pokemon_summary_screen.c file.
By making this function always return a value of TRUE, we can let any Pokémon forget any of their moves at will.

To do this, let's open up the src/pokemon_summary_screen.c file and change the CanReplaceMove function from this:
Code:
static bool8 CanReplaceMove(void)
{
    if (sMonSummaryScreen->firstMoveIndex == MAX_MON_MOVES
        || sMonSummaryScreen->newMove == MOVE_NONE
        || IsMoveHm(sMonSummaryScreen->summary.moves[sMonSummaryScreen->firstMoveIndex]) != TRUE)
        return TRUE;
    else
        return FALSE;
}

To this:
Code:
static bool8 CanReplaceMove(void)
{
    return TRUE;
}

Save, build a ROM and that's basically it.




Alternatively, we can instead remove this function and adjust the code where it's called from accordingly.
Thankfully, the CanReplaceMove function is only called in the Task_HandleReplaceMoveInput function, so basically we'd need to:
1) Remove the declaration of the CanReplaceMove function (Line 214 by default).
2) Remove the CanReplaceMove function (Lines 2210 to 2218 by default).
3) Adjust the if check of the Task_HandleReplaceMoveInput function where CanReplaceMove is called, changing it from this:
Code:
            else if (gMain.newKeys & A_BUTTON)
            {
                if (CanReplaceMove() == TRUE)
                {
                    StopPokemonAnimations();
                    PlaySE(SE_SELECT);
                    sMoveSlotToReplace = sMonSummaryScreen->firstMoveIndex;
                    gSpecialVar_0x8005 = sMoveSlotToReplace;
                    BeginCloseSummaryScreen(taskId);
                }
                else
                {
                    PlaySE(SE_HAZURE);
                    ShowCantForgetHMsWindow(taskId);
                }
            }

To this:
Code:
            else if (gMain.newKeys & A_BUTTON)
            {
                StopPokemonAnimations();
                PlaySE(SE_SELECT);
                sMoveSlotToReplace = sMonSummaryScreen->firstMoveIndex;
                gSpecialVar_0x8005 = sMoveSlotToReplace;
                BeginCloseSummaryScreen(taskId);
            }

Quick Showcase:
[PokeCommunity.com] Simple Modifications Directory


And that's pretty much it.




EDIT: I completely forgot to link it here, but thespbgamer brought up a fair point in this thread about 3 months after I originally posted this.
The changes I present in this post don't cover the replacement of a move in battle, because I absolutely forgot that was a thing honestly.
Click here if you want to learn how to address that.

EDIT2: And just as I finish editing this post, Jaizu is telling me that I also forgot to mention the removal of a move after evolution.
Just go to src/evolution_scene.c and remove the 2 if statements that call the IsHMMove2 function.
That means you have to do something like this:
Spoiler:

As evidenced by git grep "IsHMMove2", the function is not used anywhere else, so y'all can safely remove it if you want to.

EDIT3 (14/07/2024): Psf just pointed out to me another edge case that I was missing here.
The Move Deleter who lives in Lilycove City refuses to remove Surf if you only have 1 single Pokémon that knows it in your savefile.
One can infer this is Game Freak preventing some super obscure and extremely specific edge case.
Easiest way to deal with it is to delete all the code in the IsLastMonThatKnowsSurf function at src/party_menu.c and replace it with gSpecialVar_Result = FALSE;, nice and easy.​
This works a bit differently in FRLG (because of course it does). In src\pokemon_summary_screen.c, the function looks like this:
C-like:
static u8 PokeSum_CanForgetSelectedMove(void)
{
    u16 move;

    move = GetMonMoveBySlotId(&sMonSummaryScreen->currentMon, sMoveSelectionCursorPos);

    if (IsMoveHm(move) == TRUE && sMonSummaryScreen->mode != PSS_MODE_FORGET_MOVE)
        return FALSE;

    return TRUE;
}
Like the original example, change that FALSE to TRUE. The other two fixes listed for move changes in battle and evolution work as written. Oddly, it seems FRLG got rid of the Surf check. I couldn't find it anywhere in the code, then I was able to delete it with no problems in-game.

Oh, the other difference is the IsHMMove2 function is in the file src\pokemon.c, for those who want to delete it.
 
SET LEVEL FLOORS FOR TRAINERS WHEN USING DYNAMIC LEVELS (FRLG)

After using Diego Martens Set Trainer's Levels Dynamically hack, I felt there was a slight problem. Since the code bases enemy levels off of the average of the player's Pokémon levels, a player could sort of cheat by leveling up a couple Pokémon, but leaving the rest at a lower level. This would, of course, lower the average, thus lowering the enemy levels. One solution (that just occurred to me now, actually), would be to have the function use only the highest party member level instead of the average. The solution I came up with was to set level floors based on the number of badges owned. I decided to only set this for trainer battles, since I figured a player should be able to lower wild encounter levels if they want.

All changes will be done in src\battle_main.c.
  1. Above static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum), add the following function:
    C:
    static u8 GetNumberOfBadges(void){
        u16 badgeFlag;
        u8 count = 0;
    
        for (badgeFlag = FLAG_BADGE01_GET; badgeFlag < FLAG_BADGE01_GET + NUM_BADGES; badgeFlag++)
        {
            if (FlagGet(badgeFlag))
                count++;
        }
    
        return count;
    }
  2. Under static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum), add the variable u8 badgeCount = GetNumberOfBadges();
  3. Under the if statements that calculate the party's average level, add this block of code:
    C:
                    if (badgeCount == 0)
                        {
                            min = fixedLVL-2;
                            max = fixedLVL+3;
                                range = max - min + 1;
                                rand = Random() % range;
                            if (min <= 2)
                                min = 3;
                        }
    
                    else if (badgeCount == 1)
                        {
                            min = 16;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
                    else if (badgeCount == 2)
                        {
                            min = 21;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
                    else if (badgeCount == 3)
                        {
                            min = 26;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
                    else if (badgeCount == 4)
                        {
                            min = 31;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
                    else if (badgeCount == 5)
                        {
                            min = 36;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
                    else if (badgeCount == 6)
                        {
                            min = 41;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
                    else if (badgeCount == 7)
                        {
                            min = 46;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
                    else if (badgeCount == 8)
                        {
                            min = 51;
                            max = fixedLVL+3;
                                if (max - min > 0)
                                    {
                                        range = max - min + 1;
                                        rand = Random() % range;
                                    }
                                else
                                    {
                                        range = 3;
                                        rand = Random() % range;
                                    }
                        }
    
                        reallevel = min + rand;
Of course, feel free to adjust the minimum levels and the level range as desired.

I'm aware this isn't the most efficient coding. I'm still learning, and this was the first major process I wrote myself.
 
Display Mugshots/Other Images In The Overworld (Emerald / Firered)

This modification allows you to load images onto BG0 from a script. It can only show one 16-color image at a time.
[PokeCommunity.com] Simple Modifications Directory
[PokeCommunity.com] Simple Modifications Directory


1. Installation
Spoiler:


2. Adding new mugshots
Spoiler:


3. Using mugshots in a script
Spoiler:
Is there a way to draw the mugshots other than msgbox? Like a button press or map load?
 
Is there a way to draw the mugshots other than msgbox? Like a button press or map load?
Yes, you can. Pokeemerald contains the entire source code of Pokémon Emerald, so you can do whatever you want within the limits of the GBA's hardware.
Using msgbox is not mandatory.
You can totally add an if statement in a function like ProcessPlayerFieldInput which handles your key inputs in the overworld with whatever conditions for button presses you want, that either activates an overworld script that runs the callnative DrawMugshot via ScriptContext_SetupScript, or that runs a VarSet(VAR_0x8005, [value]); and then calls DrawMugshot();.
Alternatively, you can totally load a mugshot between maps by working with LoadMapFromCameraTransition which is executed when you move between connected maps.

Examples:

[PokeCommunity.com] Simple Modifications Directory

The sky is the limit for the most part.
 
Yes, you can. Pokeemerald contains the entire source code of Pokémon Emerald, so you can do whatever you want within the limits of the GBA's hardware.
Using msgbox is not mandatory.
You can totally add an if statement in a function like ProcessPlayerFieldInput which handles your key inputs in the overworld with whatever conditions for button presses you want, that either activates an overworld script that runs the callnative DrawMugshot via ScriptContext_SetupScript, or that runs a VarSet(VAR_0x8005, [value]); and then calls DrawMugshot();.
Alternatively, you can totally load a mugshot between maps by working with LoadMapFromCameraTransition which is executed when you move between connected maps.

Examples:

View attachment 173118

The sky is the limit for the most part.
You mad scientist thank you so much! The sky is too high for me. My limit is probably like 2 stories high xD
 
Move Relearner as an option in the Pokémon Party Screen (Emerald)

In Pokémon Legends Arceus, a new addition was made to change a Pokémon's moveset from the Party Menu. This adds this feature to Pokeemerald.

First, we define some stuff:

We go to include/flags.h and we replace any flag with the _UNUSED nametag with this:
Code:
FLAG_PARTY_MOVES
Then, we go to include/strings.h, and we add this after the last one:
Code:
extern const u8 gText_Moves_Menu[];
After that, we go to src/strings.c, and we add afer the last one:
Code:
const u8 gText_Moves_Menu[] = _("Change Moves");


Then, we go to include/party_menu.h and we add:
Code:
void CB2_ReturnToPartyMenuFromSummaryScreen(void);

Then, we go to src/data/party_menu.h and we add:
Code:
MENU_MOVES,
Anywhere in the the enum section with the menus. It's the one with "MENU_SUMMARY".

After that, we search for "[MENU_SUMMARY] = {gText_Summary5, CursorCb_Summary}," and we add underneath:
Code:
[MENU_MOVES] = {gText_Moves_Menu, CursorCb_Moves},

Then, we go to src/party_menu.c:
We add on the top "#include move_relearner.h" where all the other includes are
We search for "u8 actions[8];" and we change it with "u8 actions[10];"
We search for "static void CB2_ReturnToPartyMenuFromSummaryScreen(void);" and we delete the line entirely
We search for "static void CursorCb_Summary(u8);" and we add right after:
Code:
static void CursorCb_Moves(u8);
Then, we search for "static void CB2_ReturnToPartyMenuFromSummaryScreen" and we delete de "static" part
then, we search for CursorCb_Summary(u8 taskId) and right after we add:
Code:
static void CursorCb_Moves(u8 taskId)
{
    PlaySE(SE_SELECT);
    FlagSet(FLAG_PARTY_MOVES);
    gSpecialVar_0x8004 = gPartyMenu.slotId;
    gSpecialVar_0x8005 = GetNumberOfRelearnableMoves(&gPlayerParty[gSpecialVar_0x8004]);
    DisplayPartyPokemonDataForRelearner(gSpecialVar_0x8004);
    TeachMoveRelearnerMove();
    sPartyMenuInternal->exitCallback = TeachMoveRelearnerMove;
    Task_ClosePartyMenu(taskId);
}

Then, we search "AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SWITCH);" and right under, but outside de "if" declaration, we add:
Code:
        if (GetNumberOfRelearnableMoves(&mons[slotId]) != 0) {
            AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_MOVES);
        }
(It should look like this:)
Spoiler:

Then, we go to scr/move_relearner.c, and we add an include like this at the start:
#include "party_menu.h"
Lastly, we search for "SetMainCallback2(CB2_ReturnToField);" and we replace the line for:

Code:
            if (FlagGet(FLAG_PARTY_MOVES))
            {
                CB2_ReturnToPartyMenuFromSummaryScreen();
                FlagClear(FLAG_PARTY_MOVES);
            }
            else
            {
                SetMainCallback2(CB2_ReturnToField);
            }
If we want to add PLA's PP tracking system, so we can´t infinetly restore our PP's later on, we have to do this:



And then, we should have this! (ignore the "nickname" addition)
[PokeCommunity.com] Simple Modifications Directory

This gif shows that the option only appears if the Pokémon has any moves to relearn.
This addition does not add the option to make pokemon relearn moves they've been taught via TMs, only level-up moves are avaible.
I tried to implement this on pokefirered. While I got it to compile, it isn't working right. Instead of a "Change Moves" option, I get Cut. Any idea why that's happening?

For context, here are the changes I made. I followed the instructions as best I could, but I had to do things a bit differently because of the way pokefirered's files are set up.

There is no include/flags.h. Instead, it's located at included/constants/flag.h. The only flags defined as unused are hidden item flags, and I didn't know if using one of those could cause problems.
Spoiler: Click to view


Here's the end of include/strings.h. No changes to what you said to do.
Spoiler: Click to view


Here's my src/strings.c. Again, no changes other than putting the text in all-caps to fit the formatting.
Spoiler: Click to view


Here's include/party_menu.h. Nothing different.
Spoiler: Click to view


I pondered changing something for src/data/party_menu.h. As you can see, all the MENU_SUMMARY, MENU_SWITCH, etc. are listed as CURSOR_OPTION. I kept MENU_MOVES, but I'm not sure if that would cause a problem.
Spoiler: Click to view


src/party_menu.c had to be changed slightly because of that, plus the code not always matching up. The function DisplayPartyPokemonDataForRelearner didn't exist, so I had to create it. I imagine here is probably where the problem lies.
Spoiler: Click to view

Spoiler: Click to view

Spoiler: Click to view

Spoiler: Click to view

Spoiler: Click to view

Spoiler: Click to view


Finally, src/learn_move.c.
Spoiler: Click to view


Any help would be greatly appreciated. Sorry for the huge post.
 
Last edited:
Hi guys sorry if this might not be the right thread to ask, but is there a way to show 2 Pokemon pictures at the same time. Like, using showmonpic but show 2 Pokemons at once instead of just 1?
 
[Pokeemerald] Register items in a list menu!
This adds a list menu on the L button, which allows registering a choosen amount of items, currently 10 (but less or more are possible with changing 1 define).
[PokeCommunity.com] Simple Modifications Directory


The menu offers:
-variable number of registered items
-allows changing the order by moving items with select!!!
-remembers last item used and opens on that
-includes a Cancel button for 1 handed mode
-if L=A button mode is choosen, button automatically changes to R
-retains the select register button for another item

[PokeCommunity.com] Simple Modifications Directory
[PokeCommunity.com] Simple Modifications Directory


HOW TO:
Code:
git remote add xaman https://github.com/TheXaman/pokeemerald/
git pull xaman tx_registered_items_menu
make

I hope you enjoy it, if you find any bugs or have suggestions: please let me know!


Credits:
ghoulslash
TheXaman
Hello, I would like to know if there is any way to translate to spanish the game of many types, and as I saw that you were in the credits I thought I would ask you because it is very difficult for me, and it is my first rom that I try to translate.
 
Hello, I would like to know if there is any way to translate to spanish the game of many types, and as I saw that you were in the credits I thought I would ask you because it is very difficult for me, and it is my first rom that I try to translate.
I don't recall that feature branch having any sort of text that you'd need to translate, so there's nothing for you to worry about on that end.

Spanish: Hasta donde recuerdo esa rama no tiene ningun texto que necesites traducir, asi que no tenés nada de que preocuparte.

Hi guys sorry if this might not be the right thread to ask, but is there a way to show 2 Pokemon pictures at the same time. Like, using showmonpic but show 2 Pokemons at once instead of just 1?
Also yeah, this is not the thread to ask questions.
This thread is meant for people to share modifications for others to use in their decomp based projects.
Make a new thread in the Decomps & Disassemblies section of the forum if you need help to achieve X or Y thing or you want to ask questions about the usage of the decomps.
 
Show multiple Pokemon with showmonpic (Emerald)

This modification allows the showmonpic script command to show more than one Pokemon at a time. Otherwise the command is unchanged and the hidemonpic command will hide all shown Pokemon.

[PokeCommunity.com] Simple Modifications Directory


Spoiler: How to
 
Back
Top