Skip to content

Nickname your Pokémon from the party menu

LOuroboros edited this page Dec 30, 2022 · 3 revisions
In Pokémon Let's Go, Pikachu/Eevee, you can nickname your Pokémon from the party menu. Let's implement that feature into pokeemerald!
The credits for this feature go to the following users: Shinny456, TheXaman, Lunos and Zadien.

In include/strings.h:

  extern const u8 gText_Speed[];
  extern const u8 gText_Dash[];
  extern const u8 gText_Plus[];
+ extern const u8 gText_Nickname[];

  //pokedex text
  extern const u8 gText_CryOf[];

In src/party_menu.c:

enum
{
    MENU_SUMMARY,
+   MENU_NICKNAME,
    MENU_SWITCH,
    MENU_CANCEL1,
    MENU_ITEM,
  static void BlitBitmapToPartyWindow_LeftColumn(u8, u8, u8, u8, u8, u8);
  static void BlitBitmapToPartyWindow_RightColumn(u8, u8, u8, u8, u8, u8);
  static void CursorCb_Summary(u8);
+ static void CursorCb_Nickname(u8);
  static void CursorCb_Switch(u8);
  static void CursorCb_Cancel1(u8);
  static void CursorCb_Item(u8);
sPartyMenuInternal->numActions = 0;
    AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUMMARY);
+   AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_NICKNAME);

    // Add field moves to action list
    for (i = 0; i < MAX_MON_MOVES; i++)
     Task_ClosePartyMenu(taskId);
}

+ void ChangePokemonNickname(void);
+ static void CursorCb_Nickname(u8 taskId)
+ {
+     PlaySE(SE_SELECT);
+     gSpecialVar_0x8004 = gPartyMenu.slotId;
+     sPartyMenuInternal->exitCallback = ChangePokemonNickname;
+     Task_ClosePartyMenu(taskId);
+ }
+    
static void CB2_ShowPokemonSummaryScreen(void)
{
    if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)

Around Line 125:

- u8 actions[8];
+ u8 actions[9];

In src/data/party_menu.h:

} static const sCursorOptions[] =
{
    [MENU_SUMMARY] = {gText_Summary5, CursorCb_Summary},
+   [MENU_NICKNAME] = {gText_Nickname, CursorCb_Nickname},
    [MENU_SWITCH] = {gText_Switch2, CursorCb_Switch},
    [MENU_CANCEL1] = {gText_Cancel2, CursorCb_Cancel1},
    [MENU_ITEM] = {gText_Item, CursorCb_Item},

And finally, in src/strings.c:

const u8 gText_PokeBalls[] = _("POKé BALLS");
const u8 gText_Berry[] = _("BERRY");
const u8 gText_Berries[] = _("BERRIES");
+const u8 gText_Nickname[] = _("NICKNAME");

Optional additions:

Technically, you could stop here. But there are a few changes you can make to this feature that will make it better:

Disable the ability to assign nicknames to Pokémon with a different OT ID

Normally, the Player is not allowed to change the nickname of Pokémon that were originally owned by another trainer and received through a link trade.

In order to do this, and have a more faithful mechanic implemented in our project, we just need to perform a simple change inside the SetPartyMonFieldSelectionActions function of src/party_menu.c

sPartyMenuInternal->numActions = 0;
    AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUMMARY);
-   AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_NICKNAME);
+   if (!IsTradedMon(&mons[slotId]))
+       AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_NICKNAME);

    if (!InBattlePike())

Return to the party screen after assigning a nickname

This is a pretty simple change, and it improves upon the feature. Who would want to be thrown back into the overworld after giving a nickname to a Pokémon, specially when you're likely to have more business to attend to inside of the party screen, right?

To do this, we'll make the following changes inside src/party_menu.c:

 #include "constants/party_menu.h"
 #include "constants/rgb.h"
 #include "constants/songs.h"
+#include "naming_screen.h"

 
 #define PARTY_PAL_SELECTED     (1 << 0)
 #define PARTY_PAL_FAINTED      (1 << 1)
     Task_ClosePartyMenu(taskId);
 }
 
-void ChangePokemonNickname(void);
+static void ChangePokemonNicknamePartyScreen_CB(void)
+{
+    SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar2);
+    CB2_ReturnToPartyMenuFromSummaryScreen();
+}
+
+static void ChangePokemonNicknamePartyScreen(void)
+{
+    GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar3);
+    GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar2);
+    DoNamingScreen(NAMING_SCREEN_NICKNAME, gStringVar2, GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPECIES, NULL), GetMonGender(&gPlayerParty[gSpecialVar_0x8004]), GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_PERSONALITY, NULL), ChangePokemonNicknamePartyScreen_CB);
+}
+
 static void CursorCb_Nickname(u8 taskId)
 {
     PlaySE(SE_SELECT);
     gSpecialVar_0x8004 = gPartyMenu.slotId;
-    sPartyMenuInternal->exitCallback = ChangePokemonNickname;
+    sPartyMenuInternal->exitCallback = ChangePokemonNicknamePartyScreen;
     Task_ClosePartyMenu(taskId);
 }

Now, when you're returned to the party screen after assigning a nickname to a Pokémon, you will notice that the party slot that is highlighted is the slot of the Pokémon whose summary screen data you last saw, instead of the slot of the Pokémon you just changed the nickname of, as anyone would expect.

This happens as a result of reusing the CB2_ReturnToPartyMenuFromSummaryScreen function, which sets the currently highlighted slot stored in the global variable gPartyMenu.slotId, to the same value held by another global variable, gLastViewedMonIndex, used by the summary screen.

Thus, in order to correct this, we just need to remove its usage from the CB2_ReturnToPartyMenuFromSummaryScreen function.

static void CB2_ReturnToPartyMenuFromSummaryScreen(void)
{
    gPaletteFade.bufferTransferDisabled = TRUE;
-   gPartyMenu.slotId = gLastViewedMonIndex;
    InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_DO_WHAT_WITH_MON, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
}
Clone this wiki locally