summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_controller_oak_old_man.c10
-rw-r--r--src/battle_controller_player.c10
-rw-r--r--src/battle_controller_pokedude.c10
-rw-r--r--src/battle_controllers.c6
-rw-r--r--src/battle_gfx_sfx_util.c6
-rw-r--r--src/battle_main.c52
-rw-r--r--src/battle_script_commands.c14
-rw-r--r--src/berry_pouch.c6
-rw-r--r--src/data/party_menu.h1316
-rw-r--r--src/data/pokemon/tutor_learnsets.h2813
-rw-r--r--src/daycare.c2
-rw-r--r--src/field_fadetransition.c2
-rw-r--r--src/field_poison.c4
-rw-r--r--src/field_specials.c4
-rw-r--r--src/fieldmap.c2
-rw-r--r--src/fldeff_softboiled.c60
-rw-r--r--src/fldeff_sweetscent.c2
-rw-r--r--src/item.c2
-rw-r--r--src/item_pc.c8
-rw-r--r--src/item_use.c163
-rw-r--r--src/list_menu.c126
-rw-r--r--src/mailbox_pc.c4
-rw-r--r--src/map_preview_screen.c2
-rw-r--r--src/menu.c8
-rw-r--r--src/menu_helpers.c4
-rw-r--r--src/new_menu_helpers.c4
-rw-r--r--src/option_menu.c2
-rw-r--r--src/party_menu.c6381
-rw-r--r--src/player_pc.c32
-rw-r--r--src/pokemon.c10
-rw-r--r--src/pokemon_icon.c2
-rw-r--r--src/quest_log.c36
-rw-r--r--src/roamer.c2
-rw-r--r--src/save_menu_util.c2
-rw-r--r--src/start_menu.c6
-rw-r--r--src/tm_case.c12
-rw-r--r--src/trade.c36
-rw-r--r--src/wild_pokemon_area.c2
38 files changed, 10836 insertions, 327 deletions
diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c
index a6730cbbb..08c89ec1e 100644
--- a/src/battle_controller_oak_old_man.c
+++ b/src/battle_controller_oak_old_man.c
@@ -355,7 +355,7 @@ static void OpenPartyMenuToChooseMon(void)
caseId = gTasks[gUnknown_3004FFC[gActiveBattler]].data[0];
DestroyTask(gUnknown_3004FFC[gActiveBattler]);
FreeAllWindowBuffers();
- OpenPartyMenuInBattle(caseId);
+ OpenPartyMenuInTutorialBattle(caseId);
}
}
@@ -363,8 +363,8 @@ static void WaitForMonSelection(void)
{
if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active)
{
- if (gUnknown_203B0C0 == 1)
- BtlController_EmitChosenMonReturnValue(1, gUnknown_203B0C1, gUnknown_203B0DC);
+ if (gPartyMenuUseExitCallback == 1)
+ BtlController_EmitChosenMonReturnValue(1, gSelectedMonPartyId, gBattlePartyCurrentOrder);
else
BtlController_EmitChosenMonReturnValue(1, 6, NULL);
OakOldManBufferExecCompleted();
@@ -1879,7 +1879,7 @@ static void OakOldManHandleChooseItem(void)
gBattlerControllerFuncs[gActiveBattler] = OpenBagAndChooseItem;
gBattlerInMenuId = gActiveBattler;
for (i = 0; i < 3; ++i)
- gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][i + 1];
+ gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][i + 1];
}
static void OakOldManHandleChoosePokemon(void)
@@ -1892,7 +1892,7 @@ static void OakOldManHandleChoosePokemon(void)
*(&gBattleStruct->field_8B) = gBattleBufferA[gActiveBattler][2];
*(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3];
for (i = 0; i < 3; ++i)
- gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][4 + i];
+ gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][4 + i];
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
gBattlerControllerFuncs[gActiveBattler] = OpenPartyMenuToChooseMon;
gBattlerInMenuId = gActiveBattler;
diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c
index 16bf1ec87..baa794f70 100644
--- a/src/battle_controller_player.c
+++ b/src/battle_controller_player.c
@@ -1305,7 +1305,7 @@ static void OpenPartyMenuToChooseMon(void)
caseId = gTasks[gUnknown_3004FFC[gActiveBattler]].data[0];
DestroyTask(gUnknown_3004FFC[gActiveBattler]);
FreeAllWindowBuffers();
- OpenPartyMenuInBattle(caseId);
+ OpenPartyMenuInTutorialBattle(caseId);
}
}
@@ -1313,8 +1313,8 @@ static void WaitForMonSelection(void)
{
if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active)
{
- if (gUnknown_203B0C0 == 1)
- BtlController_EmitChosenMonReturnValue(1, gUnknown_203B0C1, gUnknown_203B0DC);
+ if (gPartyMenuUseExitCallback == 1)
+ BtlController_EmitChosenMonReturnValue(1, gSelectedMonPartyId, gBattlePartyCurrentOrder);
else
BtlController_EmitChosenMonReturnValue(1, 6, NULL);
if ((gBattleBufferA[gActiveBattler][1] & 0xF) == 1)
@@ -2462,7 +2462,7 @@ static void PlayerHandleChooseItem(void)
gBattlerControllerFuncs[gActiveBattler] = OpenBagAndChooseItem;
gBattlerInMenuId = gActiveBattler;
for (i = 0; i < 3; ++i)
- gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][1 + i];
+ gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][1 + i];
}
static void PlayerHandleChoosePokemon(void)
@@ -2475,7 +2475,7 @@ static void PlayerHandleChoosePokemon(void)
*(&gBattleStruct->field_8B) = gBattleBufferA[gActiveBattler][2];
*(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3];
for (i = 0; i < 3; ++i)
- gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][4 + i];
+ gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][4 + i];
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
gBattlerControllerFuncs[gActiveBattler] = OpenPartyMenuToChooseMon;
gBattlerInMenuId = gActiveBattler;
diff --git a/src/battle_controller_pokedude.c b/src/battle_controller_pokedude.c
index 57a405f3c..0b71a92e8 100644
--- a/src/battle_controller_pokedude.c
+++ b/src/battle_controller_pokedude.c
@@ -706,7 +706,7 @@ static void OpenPartyMenuToChooseMon(void)
gBattlerControllerFuncs[gActiveBattler] = WaitForMonSelection;
DestroyTask(gUnknown_3004FFC[gActiveBattler]);
FreeAllWindowBuffers();
- sub_8127968();
+ OpenPartyMenuInBattle();
}
}
@@ -714,8 +714,8 @@ static void WaitForMonSelection(void)
{
if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active)
{
- if (gUnknown_203B0C0 == 1)
- BtlController_EmitChosenMonReturnValue(1, gUnknown_203B0C1, gUnknown_203B0DC);
+ if (gPartyMenuUseExitCallback == 1)
+ BtlController_EmitChosenMonReturnValue(1, gSelectedMonPartyId, gBattlePartyCurrentOrder);
else
BtlController_EmitChosenMonReturnValue(1, 6, NULL);
PokedudeBufferExecCompleted();
@@ -1985,7 +1985,7 @@ static void PokedudeHandleChooseItem(void)
gBattlerControllerFuncs[gActiveBattler] = OpenBagAndChooseItem;
gBattlerInMenuId = gActiveBattler;
for (i = 0; i < 3; ++i)
- gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][i + 1];
+ gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][i + 1];
}
static void PokedudeHandleChoosePokemon(void)
@@ -1998,7 +1998,7 @@ static void PokedudeHandleChoosePokemon(void)
*(&gBattleStruct->field_8B) = gBattleBufferA[gActiveBattler][2];
*(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3];
for (i = 0; i < 3; ++i)
- gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][4 + i];
+ gBattlePartyCurrentOrder[i] = gBattleBufferA[gActiveBattler][4 + i];
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
gBattlerControllerFuncs[gActiveBattler] = OpenPartyMenuToChooseMon;
gBattlerInMenuId = gActiveBattler;
diff --git a/src/battle_controllers.c b/src/battle_controllers.c
index 6fb090307..ca2ef0b22 100644
--- a/src/battle_controllers.c
+++ b/src/battle_controllers.c
@@ -75,7 +75,7 @@ void sub_800D30C(void)
SetBattlePartyIds();
if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
for (i = 0; i < gBattlersCount; ++i)
- sub_8127DA8(i, 0);
+ BufferBattlePartyCurrentOrderBySide(i, 0);
}
static void InitSinglePlayerBtlControllers(void)
@@ -199,11 +199,11 @@ static void InitLinkBtlControllers(void)
{
case 0:
case 3:
- sub_8127DA8(gLinkPlayers[i].id, 0);
+ BufferBattlePartyCurrentOrderBySide(gLinkPlayers[i].id, 0);
break;
case 1:
case 2:
- sub_8127DA8(gLinkPlayers[i].id, 1);
+ BufferBattlePartyCurrentOrderBySide(gLinkPlayers[i].id, 1);
break;
}
if (i == multiplayerId)
diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c
index d2e728d0c..d7bccb298 100644
--- a/src/battle_gfx_sfx_util.c
+++ b/src/battle_gfx_sfx_util.c
@@ -620,7 +620,7 @@ bool8 BattleInitAllSprites(u8 *state, u8 *battlerId)
break;
case 6:
LoadAndCreateEnemyShadowSprites();
- sub_8127CAC();
+ BufferBattlePartyCurrentOrder();
retVal = TRUE;
break;
}
@@ -859,8 +859,8 @@ void HandleBattleLowHpMusicChange(void)
{
u8 playerBattler1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
u8 playerBattler2 = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
- u8 battler1PartyId = pokemon_order_func(gBattlerPartyIndexes[playerBattler1]);
- u8 battler2PartyId = pokemon_order_func(gBattlerPartyIndexes[playerBattler2]);
+ u8 battler1PartyId = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[playerBattler1]);
+ u8 battler2PartyId = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[playerBattler2]);
if (GetMonData(&gPlayerParty[battler1PartyId], MON_DATA_HP) != 0)
HandleLowHpMusicChange(&gPlayerParty[battler1PartyId], playerBattler1);
diff --git a/src/battle_main.c b/src/battle_main.c
index 1125a8d2d..d307d4f55 100644
--- a/src/battle_main.c
+++ b/src/battle_main.c
@@ -144,7 +144,7 @@ static EWRAM_DATA u32 gUnknown_2022AE8[25] = {0};
EWRAM_DATA u32 gBattleTypeFlags = 0;
EWRAM_DATA u8 gBattleTerrain = 0;
EWRAM_DATA u32 gUnknown_2022B54 = 0;
-EWRAM_DATA struct UnknownPokemonStruct4 gUnknown_2022B58[3] = {0};
+EWRAM_DATA struct UnknownPokemonStruct4 gMultiPartnerParty[3] = {0};
EWRAM_DATA u8 *gUnknown_2022BB8 = NULL;
EWRAM_DATA u8 *gUnknown_2022BBC = NULL;
EWRAM_DATA u16 *gUnknown_2022BC0 = NULL;
@@ -1078,16 +1078,16 @@ static void sub_80108C4(void)
for (i = 0; i < 3; ++i)
{
- gUnknown_2022B58[i].species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES);
- gUnknown_2022B58[i].heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
- nick = gUnknown_2022B58[i].nickname;
+ gMultiPartnerParty[i].species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES);
+ gMultiPartnerParty[i].heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+ nick = gMultiPartnerParty[i].nickname;
GetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, nick);
- gUnknown_2022B58[i].level = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
- gUnknown_2022B58[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
- gUnknown_2022B58[i].maxhp = GetMonData(&gPlayerParty[i], MON_DATA_MAX_HP);
- gUnknown_2022B58[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
- gUnknown_2022B58[i].personality = GetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY);
- gUnknown_2022B58[i].gender = GetMonGender(&gPlayerParty[i]);
+ gMultiPartnerParty[i].level = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
+ gMultiPartnerParty[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ gMultiPartnerParty[i].maxhp = GetMonData(&gPlayerParty[i], MON_DATA_MAX_HP);
+ gMultiPartnerParty[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
+ gMultiPartnerParty[i].personality = GetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY);
+ gMultiPartnerParty[i].gender = GetMonGender(&gPlayerParty[i]);
StripExtCtrlCodes(nick);
if (GetMonData(&gPlayerParty[i], MON_DATA_LANGUAGE) != LANGUAGE_JAPANESE)
{
@@ -1098,7 +1098,7 @@ static void sub_80108C4(void)
cur[j] = EOS;
}
}
- memcpy(&gBattleStruct->field_184, gUnknown_2022B58, sizeof(gUnknown_2022B58));
+ memcpy(&gBattleStruct->field_184, gMultiPartnerParty, sizeof(gMultiPartnerParty));
}
static void CB2_PreInitMultiBattle(void)
@@ -1123,7 +1123,7 @@ static void CB2_PreInitMultiBattle(void)
if (gReceivedRemoteLinkPlayers != 0 && IsLinkTaskFinished())
{
sub_80108C4();
- SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_184, sizeof(gUnknown_2022B58));
+ SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_184, sizeof(gMultiPartnerParty));
++gBattleCommunication[MULTIUSE_STATE];
}
break;
@@ -1137,13 +1137,13 @@ static void CB2_PreInitMultiBattle(void)
continue;
if ((!(gLinkPlayers[i].id & 1) && !(gLinkPlayers[playerMultiplierId].id & 1))
|| (gLinkPlayers[i].id & 1 && gLinkPlayers[playerMultiplierId].id & 1))
- memcpy(gUnknown_2022B58, gBlockRecvBuffer[i], sizeof(gUnknown_2022B58));
+ memcpy(gMultiPartnerParty, gBlockRecvBuffer[i], sizeof(gMultiPartnerParty));
}
++gBattleCommunication[MULTIUSE_STATE];
*savedCallback = gMain.savedCallback;
*savedBattleTypeFlags = gBattleTypeFlags;
gMain.savedCallback = CB2_PreInitMultiBattle;
- sub_8128198();
+ ShowPartyMenuToShowcaseMultiBattleParty();
}
break;
case 2:
@@ -3004,22 +3004,22 @@ void sub_8013F6C(u8 battler)
u8 r4, r1;
for (i = 0; i < 3; ++i)
- gUnknown_203B0DC[i] = *(battler * 3 + i + (u8 *)(gBattleStruct->field_60));
- r4 = pokemon_order_func(gBattlerPartyIndexes[battler]);
- r1 = pokemon_order_func(*(gBattleStruct->monToSwitchIntoId + battler));
- sub_8127FF4(r4, r1);
+ gBattlePartyCurrentOrder[i] = *(battler * 3 + i + (u8 *)(gBattleStruct->field_60));
+ r4 = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[battler]);
+ r1 = GetPartyIdFromBattlePartyId(*(gBattleStruct->monToSwitchIntoId + battler));
+ SwitchPartyMonSlots(r4, r1);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
for (i = 0; i < 3; ++i)
{
- *(battler * 3 + i + (u8 *)(gBattleStruct->field_60)) = gUnknown_203B0DC[i];
- *(BATTLE_PARTNER(battler) * 3 + i + (u8 *)(gBattleStruct->field_60)) = gUnknown_203B0DC[i];
+ *(battler * 3 + i + (u8 *)(gBattleStruct->field_60)) = gBattlePartyCurrentOrder[i];
+ *(BATTLE_PARTNER(battler) * 3 + i + (u8 *)(gBattleStruct->field_60)) = gBattlePartyCurrentOrder[i];
}
}
else
{
for (i = 0; i < 3; ++i)
- *(battler * 3 + i + (u8 *)(gBattleStruct->field_60)) = gUnknown_203B0DC[i];
+ *(battler * 3 + i + (u8 *)(gBattleStruct->field_60)) = gBattlePartyCurrentOrder[i];
}
}
@@ -3137,7 +3137,7 @@ static void HandleTurnActionSelectionState(void)
*(gBattleStruct->field_58 + gActiveBattler) = gBattlerPartyIndexes[gActiveBattler];
if (gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION) || gStatuses3[gActiveBattler] & STATUS3_ROOTED)
{
- BtlController_EmitChoosePokemon(0, PARTY_CANT_SWITCH, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ BtlController_EmitChoosePokemon(0, PARTY_ACTION_CANT_SWITCH, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
}
else if ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_SHADOW_TAG))
|| ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_ARENA_TRAP))
@@ -3146,16 +3146,16 @@ static void HandleTurnActionSelectionState(void)
|| ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0))
&& IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)))
{
- BtlController_EmitChoosePokemon(0, ((i - 1) << 4) | PARTY_ABILITY_PREVENTS, 6, gLastUsedAbility, gBattleStruct->field_60[gActiveBattler]);
+ BtlController_EmitChoosePokemon(0, ((i - 1) << 4) | PARTY_ACTION_ABILITY_PREVENTS, 6, gLastUsedAbility, gBattleStruct->field_60[gActiveBattler]);
}
else
{
if (gActiveBattler == 2 && gChosenActionByBattler[0] == B_ACTION_SWITCH)
- BtlController_EmitChoosePokemon(0, PARTY_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 0), ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ BtlController_EmitChoosePokemon(0, PARTY_ACTION_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 0), ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
else if (gActiveBattler == 3 && gChosenActionByBattler[1] == B_ACTION_SWITCH)
- BtlController_EmitChoosePokemon(0, PARTY_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 1), ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ BtlController_EmitChoosePokemon(0, PARTY_ACTION_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 1), ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
else
- BtlController_EmitChoosePokemon(0, PARTY_CHOOSE_MON, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ BtlController_EmitChoosePokemon(0, PARTY_ACTION_CHOOSE_MON, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
}
MarkBattlerForControllerExec(gActiveBattler);
break;
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 8a0e32ba8..a20f47ad4 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -4504,7 +4504,7 @@ static void atk4F_jumpifcantswitch(void)
static void sub_8024398(u8 arg0)
{
*(gBattleStruct->field_58 + gActiveBattler) = gBattlerPartyIndexes[gActiveBattler];
- BtlController_EmitChoosePokemon(0, PARTY_MUST_CHOOSE_MON, arg0, 0, gBattleStruct->field_60[gActiveBattler]);
+ BtlController_EmitChoosePokemon(0, PARTY_ACTION_SEND_OUT, arg0, 0, gBattleStruct->field_60[gActiveBattler]);
MarkBattlerForControllerExec(gActiveBattler);
}
@@ -4739,9 +4739,9 @@ static void atk50_openpartyscreen(void)
else
{
if (gBattlescriptCurrInstr[1] & OPEN_PARTY_ALLOW_CANCEL)
- hitmarkerFaintBits = PARTY_CHOOSE_MON; // Used here as the caseId for the EmitChoose function.
+ hitmarkerFaintBits = PARTY_ACTION_CHOOSE_MON; // Used here as the caseId for the EmitChoose function.
else
- hitmarkerFaintBits = PARTY_MUST_CHOOSE_MON;
+ hitmarkerFaintBits = PARTY_ACTION_SEND_OUT;
battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1] & ~(OPEN_PARTY_ALLOW_CANCEL));
if (gSpecialStatuses[battlerId].flag40)
{
@@ -5831,7 +5831,7 @@ static void DrawLevelUpWindow1(void)
{
u16 currStats[NUM_STATS];
- GetMonLevelUpWindowStats(&gPlayerParty[gBattleStruct->expGetterMonId], currStats);
+ BufferMonStatsToTaskData(&gPlayerParty[gBattleStruct->expGetterMonId], currStats);
DrawLevelUpWindowPg1(12, gBattleResources->beforeLvlUp->stats, currStats, 0xE, 0xD, 0xF);
}
@@ -5839,7 +5839,7 @@ static void DrawLevelUpWindow2(void)
{
u16 currStats[NUM_STATS];
- GetMonLevelUpWindowStats(&gPlayerParty[gBattleStruct->expGetterMonId], currStats);
+ BufferMonStatsToTaskData(&gPlayerParty[gBattleStruct->expGetterMonId], currStats);
DrawLevelUpWindowPg2(12, currStats, 0xE, 0xD, 0xF);
}
@@ -7140,8 +7140,8 @@ static void atk8F_forcerandomswitch(void)
*(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = i;
if (!IsMultiBattle())
sub_8013F6C(gBattlerTarget);
- sub_8127EC4(gBattlerTarget, i, 0);
- sub_8127EC4(gBattlerTarget ^ 2, i, 1);
+ SwitchPartyOrderLinkMulti(gBattlerTarget, i, 0);
+ SwitchPartyOrderLinkMulti(gBattlerTarget ^ 2, i, 1);
}
}
else
diff --git a/src/berry_pouch.c b/src/berry_pouch.c
index b8b66c0bc..bb1b106af 100644
--- a/src/berry_pouch.c
+++ b/src/berry_pouch.c
@@ -765,7 +765,7 @@ static void PrintSelectedBerryDescription(s32 itemIdx)
static void SetDescriptionWindowBorderPalette(s32 pal)
{
- SetBgRectPal(1, 0, 16, 30, 4, pal + 1);
+ SetBgTilemapPalette(1, 0, 16, 30, 4, pal + 1);
ScheduleBgCopyTilemapToVram(1);
}
@@ -1194,7 +1194,7 @@ static void Task_BerryPouch_Give(u8 taskId)
Task_Give_PrintThereIsNoPokemon(taskId);
else
{
- sResources->exitCallback = sub_8126EDC;
+ sResources->exitCallback = CB2_ChooseMonToGiveItem;
gTasks[taskId].func = BerryPouch_StartFadeToExitCallback;
}
}
@@ -1251,7 +1251,7 @@ static void Task_ContextMenu_FromPartyGiveMenu(u8 taskId)
}
else
{
- sResources->exitCallback = c2_8123744;
+ sResources->exitCallback = CB2_GiveHoldItem;
gTasks[taskId].func = BerryPouch_StartFadeToExitCallback;
}
}
diff --git a/src/data/party_menu.h b/src/data/party_menu.h
new file mode 100644
index 000000000..fa74d1ad8
--- /dev/null
+++ b/src/data/party_menu.h
@@ -0,0 +1,1316 @@
+static const struct BgTemplate sPartyMenuBgTemplates[] =
+{
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 1,
+ .baseTile = 0
+ },
+ {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0
+ },
+ {
+ .bg = 2,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 28,
+ .screenSize = 1,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0
+ },
+};
+
+enum
+{
+ PARTY_BOX_LEFT_COLUMN,
+ PARTY_BOX_RIGHT_COLUMN,
+};
+
+static const struct PartyMenuBoxInfoRects sPartyBoxInfoRects[] =
+{
+ [PARTY_BOX_LEFT_COLUMN] =
+ {
+ BlitBitmapToPartyWindow_LeftColumn,
+ {
+ // The below are the x, y, width, and height for each of the following info
+ 24, 11, 40, 13, // Nickname
+ 32, 20, 32, 8, // Level
+ 64, 20, 8, 8, // Gender
+ 38, 36, 24, 8, // HP
+ 53, 36, 24, 8, // Max HP
+ 24, 35, 48, 3 // HP bar
+ },
+ 12, 34, 64, 16 // Description text (e.g. NO USE)
+ },
+ [PARTY_BOX_RIGHT_COLUMN] =
+ {
+ BlitBitmapToPartyWindow_RightColumn,
+ {
+ // The below are the x, y, width, and height for each of the following info
+ 22, 3, 40, 13, // Nickname
+ 32, 12, 32, 8, // Level
+ 64, 12, 8, 8, // Gender
+ 102, 12, 24, 8, // HP
+ 117, 12, 24, 8, // Max HP
+ 88, 10, 48, 3 // HP bar
+ },
+ 77, 4, 64, 16 // Description text
+ },
+};
+
+static const u8 sPartyMenuSpriteCoords[PARTY_LAYOUT_COUNT][PARTY_SIZE][4 * 2] =
+{
+ [PARTY_LAYOUT_SINGLE] =
+ {
+ { 16, 40, 20, 50, 56, 52, 16, 34},
+ {104, 18, 108, 28, 144, 27, 102, 25},
+ {104, 42, 108, 52, 144, 51, 102, 49},
+ {104, 66, 108, 76, 144, 75, 102, 73},
+ {104, 90, 108, 100, 144, 99, 102, 97},
+ {104, 114, 108, 124, 144, 123, 102, 121},
+ },
+ [PARTY_LAYOUT_DOUBLE] =
+ {
+ { 16, 24, 20, 34, 56, 36, 16, 18},
+ { 16, 80, 20, 90, 56, 92, 16, 74},
+ {104, 18, 108, 28, 144, 27, 102, 25},
+ {104, 50, 108, 60, 144, 59, 102, 57},
+ {104, 82, 108, 92, 144, 91, 102, 89},
+ {104, 114, 108, 124, 144, 123, 102, 121},
+ },
+ [PARTY_LAYOUT_MULTI] =
+ {
+ { 16, 24, 20, 34, 56, 36, 16, 18},
+ { 16, 80, 20, 90, 56, 92, 16, 74},
+ {104, 26, 106, 36, 144, 35, 102, 33},
+ {104, 50, 106, 60, 144, 59, 102, 57},
+ {104, 82, 106, 92, 144, 91, 102, 89},
+ {104, 106, 106, 116, 144, 115, 102, 113},
+ },
+ [PARTY_LAYOUT_MULTI_SHOWCASE] =
+ {
+ { 16, 32, 20, 42, 56, 44, 16, 26},
+ {104, 34, 106, 44, 144, 43, 102, 41},
+ {104, 58, 106, 68, 144, 67, 102, 65},
+ { 16, 104, 20, 114, 56, 116, 16, 98},
+ {104, 106, 106, 116, 144, 115, 102, 113},
+ {104, 130, 106, 140, 144, 139, 102, 137},
+ },
+};
+
+static const u32 sConfirmButton_Tilemap[] = INCBIN_U32("graphics/interface/party_menu_confirm_button.bin");
+static const u32 sCancelButton_Tilemap[] = INCBIN_U32("graphics/interface/party_menu_cancel_button.bin");
+
+static const u8 sFontColorTable[][3] =
+{
+ {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_LIGHT_GREY, TEXT_COLOR_DARK_GREY}, // Default
+ {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_GREEN}, // Unused
+ {TEXT_COLOR_TRANSPARENT, TEXT_DYNAMIC_COLOR_2, TEXT_DYNAMIC_COLOR_3}, // Gender symbol
+ {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY}, // Selection actions
+ {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, // Field moves
+ {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY}, // Unused
+};
+
+static const struct WindowTemplate sSinglePartyMenuWindowTemplate[] =
+{
+ {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 3,
+ .width = 10,
+ .height = 7,
+ .paletteNum = 3,
+ .baseBlock = 0x63,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 1,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 4,
+ .baseBlock = 0xA9,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 4,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 5,
+ .baseBlock = 0xDF,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 7,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 6,
+ .baseBlock = 0x115,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 10,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 7,
+ .baseBlock = 0x14B,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 13,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 8,
+ .baseBlock = 0x181,
+ },
+ {
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 14,
+ .baseBlock = 0x1DF,
+ },
+ DUMMY_WIN_TEMPLATE,
+};
+
+static const struct WindowTemplate sDoublePartyMenuWindowTemplate[] =
+{
+ {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 1,
+ .width = 10,
+ .height = 7,
+ .paletteNum = 3,
+ .baseBlock = 0x63,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 8,
+ .width = 10,
+ .height = 7,
+ .paletteNum = 4,
+ .baseBlock = 0xA9,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 1,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 5,
+ .baseBlock = 0xEF,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 5,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 6,
+ .baseBlock = 0x125,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 9,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 7,
+ .baseBlock = 0x15B,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 13,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 8,
+ .baseBlock = 0x191,
+ },
+ {
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 14,
+ .baseBlock = 0x1DF,
+ },
+ DUMMY_WIN_TEMPLATE,
+};
+
+static const struct WindowTemplate sMultiPartyMenuWindowTemplate[] =
+{
+ {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 1,
+ .width = 10,
+ .height = 7,
+ .paletteNum = 3,
+ .baseBlock = 0x63,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 8,
+ .width = 10,
+ .height = 7,
+ .paletteNum = 4,
+ .baseBlock = 0xA9,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 2,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 5,
+ .baseBlock = 0xEF,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 5,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 6,
+ .baseBlock = 0x125,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 9,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 7,
+ .baseBlock = 0x15B,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 12,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 8,
+ .baseBlock = 0x191,
+ },
+ {
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 15,
+ .width = 28,
+ .height = 4,
+ .paletteNum = 14,
+ .baseBlock = 0x1DF,
+ },
+ DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sShowcaseMultiPartyMenuWindowTemplate[] =
+{
+ {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 2,
+ .width = 10,
+ .height = 7,
+ .paletteNum = 3,
+ .baseBlock = 0x63,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 3,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 5,
+ .baseBlock = 0xA9,
+ },
+ {
+ .bg = 0,
+ .tilemapLeft = 12,
+ .tilemapTop = 6,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 6,
+ .baseBlock = 0xDF,
+ },
+ {
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 11,
+ .width = 10,
+ .height = 7,
+ .paletteNum = 4,
+ .baseBlock = 0x115,
+ },
+ {
+ .bg = 2,
+ .tilemapLeft = 12,
+ .tilemapTop = 12,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 7,
+ .baseBlock = 0x16B,
+ },
+ {
+ .bg = 2,
+ .tilemapLeft = 12,
+ .tilemapTop = 15,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 8,
+ .baseBlock = 0x1A1,
+ },
+ DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sCancelButtonWindowTemplate =
+{
+ .bg = 0,
+ .tilemapLeft = 24,
+ .tilemapTop = 17,
+ .width = 6,
+ .height = 2,
+ .paletteNum = 3,
+ .baseBlock = 0x1C7,
+};
+
+static const struct WindowTemplate sMultiCancelButtonWindowTemplate =
+{
+ .bg = 0,
+ .tilemapLeft = 24,
+ .tilemapTop = 18,
+ .width = 6,
+ .height = 2,
+ .paletteNum = 3,
+ .baseBlock = 0x1C7,
+};
+
+static const struct WindowTemplate sConfirmButtonWindowTemplate =
+{
+ .bg = 0,
+ .tilemapLeft = 24,
+ .tilemapTop = 16,
+ .width = 6,
+ .height = 2,
+ .paletteNum = 3,
+ .baseBlock = 0x1D3,
+};
+
+static const struct WindowTemplate sDefaultPartyMsgWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 17,
+ .width = 21,
+ .height = 2,
+ .paletteNum = 15,
+ .baseBlock = 0x24F,
+};
+
+static const struct WindowTemplate sDoWhatWithMonMsgWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 17,
+ .width = 16,
+ .height = 2,
+ .paletteNum = 15,
+ .baseBlock = 0x279,
+};
+
+static const struct WindowTemplate sDoWhatWithItemMsgWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 17,
+ .width = 19,
+ .height = 2,
+ .paletteNum = 15,
+ .baseBlock = 0x299,
+};
+
+static const struct WindowTemplate sDoWhatWithMailMsgWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 17,
+ .width = 16,
+ .height = 2,
+ .paletteNum = 15,
+ .baseBlock = 0x299,
+};
+
+static const struct WindowTemplate sWhichMoveMsgWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 1,
+ .tilemapTop = 17,
+ .width = 15,
+ .height = 2,
+ .paletteNum = 15,
+ .baseBlock = 0x299,
+};
+
+static const struct WindowTemplate sItemGiveTakeWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 22,
+ .tilemapTop = 13,
+ .width = 7,
+ .height = 6,
+ .paletteNum = 14,
+ .baseBlock = 0x373,
+};
+
+static const struct WindowTemplate sMailReadTakeWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 19,
+ .tilemapTop = 13,
+ .width = 10,
+ .height = 6,
+ .paletteNum = 14,
+ .baseBlock = 0x373,
+};
+
+static const struct WindowTemplate sMoveSelectWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 18,
+ .tilemapTop = 11,
+ .width = 11,
+ .height = 8,
+ .paletteNum = 14,
+ .baseBlock = 0x2BF,
+};
+
+static const struct WindowTemplate sPartyMenuYesNoWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 21,
+ .tilemapTop = 9,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 14,
+ .baseBlock = 0x2BF,
+};
+
+static const struct WindowTemplate sLevelUpStatsWindowTemplate =
+{
+ .bg = 2,
+ .tilemapLeft = 19,
+ .tilemapTop = 1,
+ .width = 10,
+ .height = 11,
+ .paletteNum = 14,
+ .baseBlock = 0x2BF,
+};
+
+static const struct WindowTemplate gUnknown_845A170 =
+{
+ .bg = 2,
+ .tilemapLeft = 2,
+ .tilemapTop = 15,
+ .width = 26,
+ .height = 4,
+ .paletteNum = 14,
+ .baseBlock = 0x1DF,
+};
+
+static const struct WindowTemplate gUnknown_845A178 =
+{
+ .bg = 2,
+ .tilemapLeft = 0,
+ .tilemapTop = 13,
+ .width = 18,
+ .height = 3,
+ .paletteNum = 12,
+ .baseBlock = 0x373,
+};
+
+static const u8 sMainSlotTileNums[] =
+{
+ 24, 25, 25, 25, 25, 25, 25, 25, 25, 26,
+ 32, 33, 33, 33, 33, 33, 33, 33, 33, 34,
+ 32, 33, 33, 33, 33, 33, 33, 33, 33, 34,
+ 32, 33, 33, 33, 33, 33, 33, 33, 33, 34,
+ 40, 59, 60, 58, 58, 58, 58, 58, 58, 61,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 17,
+ 46, 47, 47, 47, 47, 47, 47, 47, 47, 48,
+};
+
+static const u8 sMainSlotTileNums_Egg[] =
+{
+ 24, 25, 25, 25, 25, 25, 25, 25, 25, 26,
+ 32, 33, 33, 33, 33, 33, 33, 33, 33, 34,
+ 32, 33, 33, 33, 33, 33, 33, 33, 33, 34,
+ 32, 33, 33, 33, 33, 33, 33, 33, 33, 34,
+ 40, 41, 41, 41, 41, 41, 41, 41, 41, 42,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 17,
+ 46, 47, 47, 47, 47, 47, 47, 47, 47, 48,
+};
+
+static const u8 sOtherSlotsTileNums[] =
+{
+ 43, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 45, 49, 33,
+ 33, 33, 33, 33, 33, 33, 33, 52, 53, 51,
+ 51, 51, 51, 51, 51, 54, 55, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 57,
+};
+
+static const u8 sOtherSlotsTileNums_Egg[] =
+{
+ 43, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 45, 49, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 50, 55, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 57,
+};
+
+static const u8 sEmptySlotTileNums[] =
+{
+ 21, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 23, 30, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 31, 37, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 39,
+};
+
+static const u8 sGenderPalOffsets[] = {11, 12};
+
+static const u8 sHPBarPalOffsets[] = {9, 10};
+
+static const u8 sPartyBoxPalOffsets1[] = {4, 5, 6};
+
+static const u8 sPartyBoxPalOffsets2[] = {1, 7, 8};
+
+static const u8 sGenderMalePalIds[] = {59, 60};
+
+static const u8 sGenderFemalePalIds[] = {75, 76};
+
+static const u8 sHPBarGreenPalIds[] = {57, 58};
+
+static const u8 sHPBarYellowPalIds[] = {73, 74};
+
+static const u8 sHPBarRedPalIds[] = {89, 90};
+
+static const u8 sPartyBoxEmptySlotPalIds1[] = {52, 53, 54};
+
+static const u8 sPartyBoxMultiPalIds1[] = {68, 69, 70};
+
+static const u8 sPartyBoxFaintedPalIds1[] = {84, 85, 86};
+
+static const u8 sPartyBoxCurrSelectionPalIds1[] = {116, 117, 118};
+
+static const u8 sPartyBoxCurrSelectionMultiPalIds[] = {132, 133, 134};
+
+static const u8 sPartyBoxCurrSelectionFaintedPalIds[] = {148, 149, 150};
+
+static const u8 sPartyBoxSelectedForActionPalIds1[] = {100, 101, 102};
+
+static const u8 sPartyBoxEmptySlotPalIds2[] = {49, 55, 56};
+
+static const u8 sPartyBoxMultiPalIds2[] = {65, 71, 72};
+
+static const u8 sPartyBoxFaintedPalIds2[] = {81, 87, 88};
+
+static const u8 sPartyBoxCurrSelectionPalIds2[] = {97, 103, 104};
+
+static const u8 sPartyBoxSelectedForActionPalIds2[] = {161, 167, 168};
+
+static const u8 *const sActionStringTable[] =
+{
+ [PARTY_MSG_CHOOSE_MON] = gText_ChoosePokemon,
+ [PARTY_MSG_CHOOSE_MON_OR_CANCEL] = gText_ChoosePokemonCancel,
+ [PARTY_MSG_CHOOSE_MON_AND_CONFIRM] = gText_ChoosePokemonConfirm,
+ [PARTY_MSG_MOVE_TO_WHERE] = gText_MoveToWhere,
+ [PARTY_MSG_TEACH_WHICH_MON] = gText_TeachWhichPokemon,
+ [PARTY_MSG_USE_ON_WHICH_MON] = gText_UseOnWhichPokemon,
+ [PARTY_MSG_GIVE_TO_WHICH_MON] = gText_GiveToWhichPokemon,
+ [PARTY_MSG_NOTHING_TO_CUT] = gText_NothingToCut,
+ [PARTY_MSG_CANT_SURF_HERE] = gText_CantSurfHere,
+ [PARTY_MSG_ALREADY_SURFING] = gText_AlreadySurfing,
+ [PARTY_MSG_CURRENT_TOO_FAST] = gText_CurrentIsTooFast,
+ [PARTY_MSG_ENJOY_CYCLING] = gText_EnjoyCycling,
+ [PARTY_MSG_ALREADY_IN_USE] = gText_InUseAlready_PM,
+ [PARTY_MSG_CANT_USE_HERE] = gText_CantUseHere,
+ [PARTY_MSG_NO_MON_FOR_BATTLE] = gText_NoPokemonForBattle,
+ [PARTY_MSG_CHOOSE_MON_2] = gText_ChoosePokemon2,
+ [PARTY_MSG_NOT_ENOUGH_HP] = gText_NotEnoughHp,
+ [PARTY_MSG_THREE_MONS_ARE_NEEDED] = gText_ThreePkmnAreNeeded,
+ [PARTY_MSG_TWO_MONS_ARE_NEEDED] = gText_TwoPokemonAreNeeded,
+ [PARTY_MSG_MONS_CANT_BE_SAME] = gText_PokemonCantBeSame,
+ [PARTY_MSG_NO_SAME_HOLD_ITEMS] = gText_NoIdenticalHoldItems,
+ [PARTY_MSG_UNUSED] = gString_Dummy,
+ [PARTY_MSG_DO_WHAT_WITH_MON] = gText_DoWhatWithPokemon,
+ [PARTY_MSG_RESTORE_WHICH_MOVE] = gText_RestoreWhichMove,
+ [PARTY_MSG_BOOST_PP_WHICH_MOVE] = gText_BoostPp,
+ [PARTY_MSG_DO_WHAT_WITH_ITEM] = gText_DoWhatWithItem,
+ [PARTY_MSG_DO_WHAT_WITH_MAIL] = gText_DoWhatWithMail,
+};
+
+static const u8 *const sDescriptionStringTable[] =
+{
+ [PARTYBOX_DESC_NO_USE] = gText_NoUse,
+ [PARTYBOX_DESC_ABLE_3] = gText_Able,
+ [PARTYBOX_DESC_FIRST] = gText_First_PM,
+ [PARTYBOX_DESC_SECOND] = gText_Second_PM,
+ [PARTYBOX_DESC_THIRD] = gText_Third_PM,
+ [PARTYBOX_DESC_ABLE] = gText_Able2,
+ [PARTYBOX_DESC_NOT_ABLE] = gText_NotAble,
+ [PARTYBOX_DESC_ABLE_2] = gText_Able3,
+ [PARTYBOX_DESC_NOT_ABLE_2] = gText_NotAble2,
+ [PARTYBOX_DESC_LEARNED] = gText_Learned,
+};
+
+static const u8 *const sHMDescriptionTable[] =
+{
+ gText_LightUpDarkness,
+ gText_CutATreeOrGrass,
+ gText_FlyToAKnownTown,
+ gText_MoveHeavyBoulders,
+ gText_TravelOnWater,
+ gText_ShatterACrackedRock,
+ gText_ClimbAWaterfall,
+ gText_ReturnToAHealingSpot,
+ gText_EscapeFromHere,
+ gText_ShareHp,
+ gText_ShareHp,
+ gText_LureWildPokemon,
+};
+
+static const u32 sHeldItemGfx[] = INCBIN_U32("graphics/interface/hold_icons.4bpp");
+static const u16 sHeldItemPalette[] = INCBIN_U16("graphics/interface/hold_icons.gbapal");
+
+static const struct OamData sOamData_HeldItem =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(8x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(8x8),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sSpriteAnim_HeldItem[] =
+{
+ ANIMCMD_FRAME(0, 1),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_HeldMail[] =
+{
+ ANIMCMD_FRAME(1, 1),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_HeldItem[] =
+{
+ sSpriteAnim_HeldItem,
+ sSpriteAnim_HeldMail,
+};
+
+static const struct SpriteSheet sSpriteSheet_HeldItem =
+{
+ sHeldItemGfx, sizeof(sHeldItemGfx), 0xD750
+};
+
+static const struct SpritePalette sSpritePalette_HeldItem =
+{
+ sHeldItemPalette, 0xD750
+};
+
+static const struct SpriteTemplate sSpriteTemplate_HeldItem =
+{
+ 0xD750,
+ 0xD750,
+ &sOamData_HeldItem,
+ sSpriteAnimTable_HeldItem,
+ NULL,
+ gDummySpriteAffineAnimTable,
+ SpriteCallbackDummy,
+};
+
+static const struct OamData sOamData_MenuPokeball =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(32x32),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x32),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sPokeballAnim_Closed[] =
+{
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sPokeballAnim_Open[] =
+{
+ ANIMCMD_FRAME(16, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_MenuPokeball[] =
+{
+ sPokeballAnim_Closed,
+ sPokeballAnim_Open,
+};
+
+static const struct CompressedSpriteSheet sSpriteSheet_MenuPokeball =
+{
+ gPartyMenuPokeball_Gfx, 0x400, 0x04b0
+};
+
+static const struct CompressedSpritePalette sSpritePalette_MenuPokeball =
+{
+ gPartyMenuPokeball_Pal, 0x04b0
+};
+
+// Used for the pokeball sprite on each party slot / Cancel button
+static const struct SpriteTemplate sSpriteTemplate_MenuPokeball =
+{
+ .tileTag = 0x04b0,
+ .paletteTag = 0x04b0,
+ .oam = &sOamData_MenuPokeball,
+ .anims = sSpriteAnimTable_MenuPokeball,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+static const struct OamData sOamData_MenuPokeballSmall =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(16x16),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(16x16),
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sSmallPokeballAnim_Closed[] =
+{
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSmallPokeballAnim_Open[] =
+{
+ ANIMCMD_FRAME(4, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSmallPokeballAnim_Blank1[] =
+{
+ ANIMCMD_FRAME(8, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSmallPokeballAnim_Blank2[] =
+{
+ ANIMCMD_FRAME(12, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSmallPokeballAnim_Blank3[] =
+{
+ ANIMCMD_FRAME(16, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSmallPokeballAnim_Blank4[] =
+{
+ ANIMCMD_FRAME(20, 0),
+ ANIMCMD_END
+};
+
+// The blanks below are never used. See SpriteCB_BounceConfirmCancelButton, where they were intended to be used
+static const union AnimCmd *const sSpriteAnimTable_MenuPokeballSmall[] =
+{
+ sSmallPokeballAnim_Closed,
+ sSmallPokeballAnim_Open,
+ sSmallPokeballAnim_Blank1,
+ sSmallPokeballAnim_Blank2,
+ sSmallPokeballAnim_Blank3,
+ sSmallPokeballAnim_Blank4,
+};
+
+static const struct CompressedSpriteSheet sSpriteSheet_MenuPokeballSmall =
+{
+ gPartyMenuPokeballSmall_Gfx, 0x0300, 0x04b1
+};
+
+// Used for the pokeball sprite next to Cancel and Confirm when both are present, otherwise sSpriteTemplate_MenuPokeball is used
+static const struct SpriteTemplate sSpriteTemplate_MenuPokeballSmall =
+{
+ .tileTag = 1201,
+ .paletteTag = 1200,
+ .oam = &sOamData_MenuPokeballSmall,
+ .anims = sSpriteAnimTable_MenuPokeballSmall,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+static const struct OamData sOamData_StatusCondition =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(32x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x8),
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sSpriteAnim_StatusPoison[] =
+{
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_StatusParalyzed[] =
+{
+ ANIMCMD_FRAME(4, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_StatusSleep[] =
+{
+ ANIMCMD_FRAME(8, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_StatusFrozen[] =
+{
+ ANIMCMD_FRAME(12, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_StatusBurn[] =
+{
+ ANIMCMD_FRAME(16, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_StatusPokerus[] =
+{
+ ANIMCMD_FRAME(20, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_StatusFaint[] =
+{
+ ANIMCMD_FRAME(24, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_Blank[] =
+{
+ ANIMCMD_FRAME(28, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteTemplate_StatusCondition[] =
+{
+ sSpriteAnim_StatusPoison,
+ sSpriteAnim_StatusParalyzed,
+ sSpriteAnim_StatusSleep,
+ sSpriteAnim_StatusFrozen,
+ sSpriteAnim_StatusBurn,
+ sSpriteAnim_StatusPokerus,
+ sSpriteAnim_StatusFaint,
+ sSpriteAnim_Blank,
+};
+
+static const struct CompressedSpriteSheet sSpriteSheet_StatusIcons =
+{
+ gStatusGfx_Icons, 0x400, 1202
+};
+
+static const struct CompressedSpritePalette sSpritePalette_StatusIcons =
+{
+ gStatusPal_Icons, 1202
+};
+
+static const struct SpriteTemplate sSpriteTemplate_StatusIcons =
+{
+ .tileTag = 1202,
+ .paletteTag = 1202,
+ .oam = &sOamData_StatusCondition,
+ .anims = sSpriteTemplate_StatusCondition,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+static const bool8 sMultiBattlePartnersPartyMask[PARTY_SIZE + 2] =
+{
+ FALSE,
+ TRUE,
+ FALSE,
+ FALSE,
+ TRUE,
+ TRUE,
+ FALSE,
+};
+
+static const u16 sTMHMMoves_Duplicate[] =
+{
+ MOVE_FOCUS_PUNCH,
+ MOVE_DRAGON_CLAW,
+ MOVE_WATER_PULSE,
+ MOVE_CALM_MIND,
+ MOVE_ROAR,
+ MOVE_TOXIC,
+ MOVE_HAIL,
+ MOVE_BULK_UP,
+ MOVE_BULLET_SEED,
+ MOVE_HIDDEN_POWER,
+ MOVE_SUNNY_DAY,
+ MOVE_TAUNT,
+ MOVE_ICE_BEAM,
+ MOVE_BLIZZARD,
+ MOVE_HYPER_BEAM,
+ MOVE_LIGHT_SCREEN,
+ MOVE_PROTECT,
+ MOVE_RAIN_DANCE,
+ MOVE_GIGA_DRAIN,
+ MOVE_SAFEGUARD,
+ MOVE_FRUSTRATION,
+ MOVE_SOLAR_BEAM,
+ MOVE_IRON_TAIL,
+ MOVE_THUNDERBOLT,
+ MOVE_THUNDER,
+ MOVE_EARTHQUAKE,
+ MOVE_RETURN,
+ MOVE_DIG,
+ MOVE_PSYCHIC,
+ MOVE_SHADOW_BALL,
+ MOVE_BRICK_BREAK,
+ MOVE_DOUBLE_TEAM,
+ MOVE_REFLECT,
+ MOVE_SHOCK_WAVE,
+ MOVE_FLAMETHROWER,
+ MOVE_SLUDGE_BOMB,
+ MOVE_SANDSTORM,
+ MOVE_FIRE_BLAST,
+ MOVE_ROCK_TOMB,
+ MOVE_AERIAL_ACE,
+ MOVE_TORMENT,
+ MOVE_FACADE,
+ MOVE_SECRET_POWER,
+ MOVE_REST,
+ MOVE_ATTRACT,
+ MOVE_THIEF,
+ MOVE_STEEL_WING,
+ MOVE_SKILL_SWAP,
+ MOVE_SNATCH,
+ MOVE_OVERHEAT,
+ MOVE_CUT,
+ MOVE_FLY,
+ MOVE_SURF,
+ MOVE_STRENGTH,
+ MOVE_FLASH,
+ MOVE_ROCK_SMASH,
+ MOVE_WATERFALL,
+ MOVE_DIVE,
+};
+
+enum
+{
+ MENU_SUMMARY,
+ MENU_SWITCH,
+ MENU_CANCEL1,
+ MENU_ITEM,
+ MENU_GIVE,
+ MENU_TAKE_ITEM,
+ MENU_MAIL,
+ MENU_TAKE_MAIL,
+ MENU_READ,
+ MENU_CANCEL2,
+ MENU_SHIFT,
+ MENU_SEND_OUT,
+ MENU_ENTER,
+ MENU_NO_ENTRY,
+ MENU_STORE,
+ MENU_REGISTER,
+ MENU_TRADE1,
+ MENU_TRADE2,
+ MENU_FIELD_MOVES,
+};
+
+enum
+{
+ FIELD_MOVE_FLASH,
+ FIELD_MOVE_CUT,
+ FIELD_MOVE_FLY,
+ FIELD_MOVE_STRENGTH,
+ FIELD_MOVE_SURF,
+ FIELD_MOVE_ROCK_SMASH,
+ FIELD_MOVE_WATERFALL,
+ FIELD_MOVE_TELEPORT,
+ FIELD_MOVE_DIG,
+ FIELD_MOVE_MILK_DRINK,
+ FIELD_MOVE_SOFT_BOILED,
+ FIELD_MOVE_SWEET_SCENT,
+ FIELD_MOVE_END,
+};
+
+static struct
+{
+ const u8 *text;
+ TaskFunc func;
+} const sCursorOptions[] =
+{
+ [MENU_SUMMARY] = {gText_Summary5, CursorCB_Summary},
+ [MENU_SWITCH] = {gText_Switch2, CursorCB_Switch},
+ [MENU_CANCEL1] = {gFameCheckerText_Cancel, CursorCB_Cancel1},
+ [MENU_ITEM] = {gText_Item, CursorCB_Item},
+ [MENU_GIVE] = {gOtherText_Give, CursorCB_Give},
+ [MENU_TAKE_ITEM] = {gText_Take, CursorCB_TakeItem},
+ [MENU_MAIL] = {gText_Mail, CursorCB_Mail},
+ [MENU_TAKE_MAIL] = {gText_Take2, CursorCB_TakeMail},
+ [MENU_READ] = {gText_Read2, CursorCB_Read},
+ [MENU_CANCEL2] = {gFameCheckerText_Cancel, CursorCB_Cancel2},
+ [MENU_SHIFT] = {gText_Shift, CursorCB_SendMon},
+ [MENU_SEND_OUT] = {gText_SendOut, CursorCB_SendMon},
+ [MENU_ENTER] = {gText_Enter, CursorCB_Enter},
+ [MENU_NO_ENTRY] = {gText_NoEntry, CursorCB_NoEntry},
+ [MENU_STORE] = {gText_Store, CursorCB_Store},
+ [MENU_REGISTER] = {gText_Register, CursorCB_Register},
+ [MENU_TRADE1] = {gText_Trade4, CursorCB_Trade1},
+ [MENU_TRADE2] = {gText_Trade4, CursorCB_Trade2},
+ [MENU_FIELD_MOVES + FIELD_MOVE_FLASH] = {gMoveNames[MOVE_FLASH], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_CUT] = {gMoveNames[MOVE_CUT], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_FLY] = {gMoveNames[MOVE_FLY], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_STRENGTH] = {gMoveNames[MOVE_STRENGTH], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_SURF] = {gMoveNames[MOVE_SURF], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_ROCK_SMASH] = {gMoveNames[MOVE_ROCK_SMASH], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_WATERFALL] = {gMoveNames[MOVE_WATERFALL], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_TELEPORT] = {gMoveNames[MOVE_TELEPORT], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_DIG] = {gMoveNames[MOVE_DIG], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_MILK_DRINK] = {gMoveNames[MOVE_MILK_DRINK], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_SOFT_BOILED] = {gMoveNames[MOVE_SOFT_BOILED], CursorCB_FieldMove},
+ [MENU_FIELD_MOVES + FIELD_MOVE_SWEET_SCENT] = {gMoveNames[MOVE_SWEET_SCENT], CursorCB_FieldMove},
+};
+
+static const u8 sPartyMenuAction_SummarySwitchCancel[] = {MENU_SUMMARY, MENU_SWITCH, MENU_CANCEL1};
+static const u8 sPartyMenuAction_ShiftSummaryCancel[] = {MENU_SHIFT, MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_SendOutSummaryCancel[] = {MENU_SEND_OUT, MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_SummaryCancel[] = {MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_EnterSummaryCancel[] = {MENU_ENTER, MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_NoEntrySummaryCancel[] = {MENU_NO_ENTRY, MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_StoreSummaryCancel[] = {MENU_STORE, MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_GiveTakeItemCancel[] = {MENU_GIVE, MENU_TAKE_ITEM, MENU_CANCEL2};
+static const u8 sPartyMenuAction_ReadTakeMailCancel[] = {MENU_READ, MENU_TAKE_MAIL, MENU_CANCEL2};
+static const u8 sPartyMenuAction_RegisterSummaryCancel[] = {MENU_REGISTER, MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_TradeSummaryCancel1[] = {MENU_TRADE1, MENU_SUMMARY, MENU_CANCEL1};
+static const u8 sPartyMenuAction_TradeSummaryCancel2[] = {MENU_TRADE2, MENU_SUMMARY, MENU_CANCEL1};
+
+// IDs for the action lists that appear when a party mon is selected
+enum
+{
+ ACTIONS_NONE,
+ ACTIONS_SWITCH,
+ ACTIONS_SHIFT,
+ ACTIONS_SEND_OUT,
+ ACTIONS_ENTER,
+ ACTIONS_NO_ENTRY,
+ ACTIONS_STORE,
+ ACTIONS_SUMMARY_ONLY,
+ ACTIONS_ITEM,
+ ACTIONS_MAIL,
+ ACTIONS_REGISTER,
+ ACTIONS_TRADE,
+ ACTIONS_SPIN_TRADE,
+};
+
+static const u8 *const sPartyMenuActions[] =
+{
+ [ACTIONS_NONE] = NULL,
+ [ACTIONS_SWITCH] = sPartyMenuAction_SummarySwitchCancel,
+ [ACTIONS_SHIFT] = sPartyMenuAction_ShiftSummaryCancel,
+ [ACTIONS_SEND_OUT] = sPartyMenuAction_SendOutSummaryCancel,
+ [ACTIONS_ENTER] = sPartyMenuAction_EnterSummaryCancel,
+ [ACTIONS_NO_ENTRY] = sPartyMenuAction_NoEntrySummaryCancel,
+ [ACTIONS_STORE] = sPartyMenuAction_StoreSummaryCancel,
+ [ACTIONS_SUMMARY_ONLY] = sPartyMenuAction_SummaryCancel,
+ [ACTIONS_ITEM] = sPartyMenuAction_GiveTakeItemCancel,
+ [ACTIONS_MAIL] = sPartyMenuAction_ReadTakeMailCancel,
+ [ACTIONS_REGISTER] = sPartyMenuAction_RegisterSummaryCancel,
+ [ACTIONS_TRADE] = sPartyMenuAction_TradeSummaryCancel1,
+ [ACTIONS_SPIN_TRADE] = sPartyMenuAction_TradeSummaryCancel2,
+};
+
+static const u8 sPartyMenuActionCounts[] =
+{
+ [ACTIONS_NONE] = 0,
+ [ACTIONS_SWITCH] = NELEMS(sPartyMenuAction_SummarySwitchCancel),
+ [ACTIONS_SHIFT] = NELEMS(sPartyMenuAction_ShiftSummaryCancel),
+ [ACTIONS_SEND_OUT] = NELEMS(sPartyMenuAction_SendOutSummaryCancel),
+ [ACTIONS_ENTER] = NELEMS(sPartyMenuAction_EnterSummaryCancel),
+ [ACTIONS_NO_ENTRY] = NELEMS(sPartyMenuAction_NoEntrySummaryCancel),
+ [ACTIONS_STORE] = NELEMS(sPartyMenuAction_StoreSummaryCancel),
+ [ACTIONS_SUMMARY_ONLY] = NELEMS(sPartyMenuAction_SummaryCancel),
+ [ACTIONS_ITEM] = NELEMS(sPartyMenuAction_GiveTakeItemCancel),
+ [ACTIONS_MAIL] = NELEMS(sPartyMenuAction_ReadTakeMailCancel),
+ [ACTIONS_REGISTER] = NELEMS(sPartyMenuAction_RegisterSummaryCancel),
+ [ACTIONS_TRADE] = NELEMS(sPartyMenuAction_TradeSummaryCancel1),
+ [ACTIONS_SPIN_TRADE] = NELEMS(sPartyMenuAction_TradeSummaryCancel2),
+};
+
+static const u16 sFieldMoves[] =
+{
+ MOVE_FLASH, MOVE_CUT, MOVE_FLY, MOVE_STRENGTH, MOVE_SURF, MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_TELEPORT,
+ MOVE_DIG, MOVE_MILK_DRINK, MOVE_SOFT_BOILED, MOVE_SWEET_SCENT, FIELD_MOVE_END // this may be misuse of enum. same in emerald
+};
+
+static struct
+{
+ bool8 (*fieldMoveFunc)(void);
+ u8 msgId;
+} const sFieldMoveCursorCallbacks[] =
+{
+ [FIELD_MOVE_FLASH] = {SetUpFieldMove_Flash, PARTY_MSG_CANT_USE_HERE},
+ [FIELD_MOVE_CUT] = {SetUpFieldMove_Cut, PARTY_MSG_NOTHING_TO_CUT},
+ [FIELD_MOVE_FLY] = {SetUpFieldMove_Fly, PARTY_MSG_CANT_USE_HERE},
+ [FIELD_MOVE_STRENGTH] = {SetUpFieldMove_Strength, PARTY_MSG_CANT_USE_HERE},
+ [FIELD_MOVE_SURF] = {SetUpFieldMove_Surf, PARTY_MSG_CANT_SURF_HERE},
+ [FIELD_MOVE_ROCK_SMASH] = {SetUpFieldMove_RockSmash, PARTY_MSG_CANT_USE_HERE},
+ [FIELD_MOVE_WATERFALL] = {SetUpFieldMove_Waterfall, PARTY_MSG_CANT_USE_HERE},
+ [FIELD_MOVE_TELEPORT] = {SetUpFieldMove_Teleport, PARTY_MSG_CANT_USE_HERE},
+ [FIELD_MOVE_DIG] = {SetUpFieldMove_Dig, PARTY_MSG_CANT_USE_HERE},
+ [FIELD_MOVE_MILK_DRINK] = {SetUpFieldMove_SoftBoiled, PARTY_MSG_NOT_ENOUGH_HP},
+ [FIELD_MOVE_SOFT_BOILED] = {SetUpFieldMove_SoftBoiled, PARTY_MSG_NOT_ENOUGH_HP},
+ [FIELD_MOVE_SWEET_SCENT] = {SetUpFieldMove_SweetScent, PARTY_MSG_CANT_USE_HERE},
+};
+
+static const u8 *const sUnionRoomTradeMessages[] =
+{
+ [UR_TRADE_MSG_NOT_MON_PARTNER_WANTS - 1] = gText_NotPkmnOtherTrainerWants,
+ [UR_TRADE_MSG_NOT_EGG - 1] = gText_ThatIsntAnEgg,
+ [UR_TRADE_MSG_MON_CANT_BE_TRADED_1 - 1] = gText_PkmnCantBeTradedNow,
+ [UR_TRADE_MSG_MON_CANT_BE_TRADED_2 - 1] = gText_PkmnCantBeTradedNow,
+ [UR_TRADE_MSG_PARTNERS_MON_CANT_BE_TRADED - 1] = gText_OtherTrainersPkmnCantBeTraded,
+ [UR_TRADE_MSG_EGG_CANT_BE_TRADED -1] = gText_EggCantBeTradedNow,
+ [UR_TRADE_MSG_PARTNER_CANT_ACCEPT_MON - 1] = gText_OtherTrainerCantAcceptPkmn,
+ [UR_TRADE_MSG_CANT_TRADE_WITH_PARTNER_1 - 1] = gText_CantTradeWithTrainer,
+ [UR_TRADE_MSG_CANT_TRADE_WITH_PARTNER_2 - 1] = gText_CantTradeWithTrainer,
+};
+
+static const u16 sTMHMMoves[] =
+{
+ MOVE_FOCUS_PUNCH,
+ MOVE_DRAGON_CLAW,
+ MOVE_WATER_PULSE,
+ MOVE_CALM_MIND,
+ MOVE_ROAR,
+ MOVE_TOXIC,
+ MOVE_HAIL,
+ MOVE_BULK_UP,
+ MOVE_BULLET_SEED,
+ MOVE_HIDDEN_POWER,
+ MOVE_SUNNY_DAY,
+ MOVE_TAUNT,
+ MOVE_ICE_BEAM,
+ MOVE_BLIZZARD,
+ MOVE_HYPER_BEAM,
+ MOVE_LIGHT_SCREEN,
+ MOVE_PROTECT,
+ MOVE_RAIN_DANCE,
+ MOVE_GIGA_DRAIN,
+ MOVE_SAFEGUARD,
+ MOVE_FRUSTRATION,
+ MOVE_SOLAR_BEAM,
+ MOVE_IRON_TAIL,
+ MOVE_THUNDERBOLT,
+ MOVE_THUNDER,
+ MOVE_EARTHQUAKE,
+ MOVE_RETURN,
+ MOVE_DIG,
+ MOVE_PSYCHIC,
+ MOVE_SHADOW_BALL,
+ MOVE_BRICK_BREAK,
+ MOVE_DOUBLE_TEAM,
+ MOVE_REFLECT,
+ MOVE_SHOCK_WAVE,
+ MOVE_FLAMETHROWER,
+ MOVE_SLUDGE_BOMB,
+ MOVE_SANDSTORM,
+ MOVE_FIRE_BLAST,
+ MOVE_ROCK_TOMB,
+ MOVE_AERIAL_ACE,
+ MOVE_TORMENT,
+ MOVE_FACADE,
+ MOVE_SECRET_POWER,
+ MOVE_REST,
+ MOVE_ATTRACT,
+ MOVE_THIEF,
+ MOVE_STEEL_WING,
+ MOVE_SKILL_SWAP,
+ MOVE_SNATCH,
+ MOVE_OVERHEAT,
+ MOVE_CUT,
+ MOVE_FLY,
+ MOVE_SURF,
+ MOVE_STRENGTH,
+ MOVE_FLASH,
+ MOVE_ROCK_SMASH,
+ MOVE_WATERFALL,
+ MOVE_DIVE,
+};
diff --git a/src/data/pokemon/tutor_learnsets.h b/src/data/pokemon/tutor_learnsets.h
new file mode 100644
index 000000000..5396c1ecc
--- /dev/null
+++ b/src/data/pokemon/tutor_learnsets.h
@@ -0,0 +1,2813 @@
+static const u16 sTutorMoves[TUTOR_MOVE_COUNT] =
+{
+ [TUTOR_MOVE_MEGA_PUNCH] = MOVE_MEGA_PUNCH,
+ [TUTOR_MOVE_SWORDS_DANCE] = MOVE_SWORDS_DANCE,
+ [TUTOR_MOVE_MEGA_KICK] = MOVE_MEGA_KICK,
+ [TUTOR_MOVE_BODY_SLAM] = MOVE_BODY_SLAM,
+ [TUTOR_MOVE_DOUBLE_EDGE] = MOVE_DOUBLE_EDGE,
+ [TUTOR_MOVE_COUNTER] = MOVE_COUNTER,
+ [TUTOR_MOVE_SEISMIC_TOSS] = MOVE_SEISMIC_TOSS,
+ [TUTOR_MOVE_MIMIC] = MOVE_MIMIC,
+ [TUTOR_MOVE_METRONOME] = MOVE_METRONOME,
+ [TUTOR_MOVE_SOFT_BOILED] = MOVE_SOFT_BOILED,
+ [TUTOR_MOVE_DREAM_EATER] = MOVE_DREAM_EATER,
+ [TUTOR_MOVE_THUNDER_WAVE] = MOVE_THUNDER_WAVE,
+ [TUTOR_MOVE_EXPLOSION] = MOVE_EXPLOSION,
+ [TUTOR_MOVE_ROCK_SLIDE] = MOVE_ROCK_SLIDE,
+ [TUTOR_MOVE_SUBSTITUTE] = MOVE_SUBSTITUTE,
+};
+
+#define TUTOR(move) (1 << (TUTOR_##move))
+
+static const u16 sTutorLearnsets[] =
+{
+ [SPECIES_NONE] = 0,
+
+ [SPECIES_BULBASAUR] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_IVYSAUR] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VENUSAUR] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CHARMANDER] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CHARMELEON] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CHARIZARD] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SQUIRTLE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WARTORTLE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BLASTOISE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CATERPIE] = 0,
+
+ [SPECIES_METAPOD] = 0,
+
+ [SPECIES_BUTTERFREE] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WEEDLE] = 0,
+
+ [SPECIES_KAKUNA] = 0,
+
+ [SPECIES_BEEDRILL] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PIDGEY] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PIDGEOTTO] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PIDGEOT] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RATTATA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RATICATE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SPEAROW] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FEAROW] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_EKANS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ARBOK] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PIKACHU] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RAICHU] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SANDSHREW] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SANDSLASH] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NIDORAN_F] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NIDORINA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NIDOQUEEN] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NIDORAN_M] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NIDORINO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NIDOKING] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CLEFAIRY] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CLEFABLE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VULPIX] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NINETALES] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_JIGGLYPUFF] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WIGGLYTUFF] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ZUBAT] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GOLBAT] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ODDISH] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GLOOM] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VILEPLUME] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PARAS] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PARASECT] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VENONAT] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VENOMOTH] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DIGLETT] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DUGTRIO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MEOWTH] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PERSIAN] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PSYDUCK] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GOLDUCK] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MANKEY] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PRIMEAPE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GROWLITHE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ARCANINE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_POLIWAG] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_POLIWHIRL] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_POLIWRATH] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ABRA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KADABRA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ALAKAZAM] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MACHOP] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MACHOKE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MACHAMP] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BELLSPROUT] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WEEPINBELL] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VICTREEBEL] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TENTACOOL] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TENTACRUEL] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GEODUDE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GRAVELER] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GOLEM] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PONYTA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RAPIDASH] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SLOWPOKE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SLOWBRO] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAGNEMITE] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAGNETON] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FARFETCHD] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DODUO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DODRIO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SEEL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DEWGONG] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GRIMER] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MUK] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHELLDER] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CLOYSTER] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GASTLY] = TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HAUNTER] = TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GENGAR] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ONIX] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DROWZEE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HYPNO] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KRABBY] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KINGLER] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VOLTORB] = TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ELECTRODE] = TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_EXEGGCUTE] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_EXEGGUTOR] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CUBONE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAROWAK] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HITMONLEE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HITMONCHAN] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LICKITUNG] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KOFFING] = TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WEEZING] = TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RHYHORN] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RHYDON] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CHANSEY] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TANGELA] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KANGASKHAN] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HORSEA] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SEADRA] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GOLDEEN] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SEAKING] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_STARYU] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_STARMIE] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MR_MIME] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SCYTHER] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_JYNX] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ELECTABUZZ] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAGMAR] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PINSIR] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TAUROS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAGIKARP] = 0,
+
+ [SPECIES_GYARADOS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LAPRAS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DITTO] = 0,
+
+ [SPECIES_EEVEE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VAPOREON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_JOLTEON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FLAREON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PORYGON] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_OMANYTE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_OMASTAR] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KABUTO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KABUTOPS] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_AERODACTYL] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SNORLAX] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ARTICUNO] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ZAPDOS] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MOLTRES] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DRATINI] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DRAGONAIR] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DRAGONITE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MEWTWO] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MEW] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CHIKORITA] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BAYLEEF] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MEGANIUM] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CYNDAQUIL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_QUILAVA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TYPHLOSION] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TOTODILE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CROCONAW] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FERALIGATR] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SENTRET] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FURRET] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HOOTHOOT] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NOCTOWL] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LEDYBA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LEDIAN] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SPINARAK] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ARIADOS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CROBAT] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CHINCHOU] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LANTURN] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PICHU] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CLEFFA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_IGGLYBUFF] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TOGEPI] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TOGETIC] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NATU] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_XATU] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAREEP] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FLAAFFY] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_AMPHAROS] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BELLOSSOM] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MARILL] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_AZUMARILL] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SUDOWOODO] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_POLITOED] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HOPPIP] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SKIPLOOM] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_JUMPLUFF] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_AIPOM] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SUNKERN] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SUNFLORA] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_YANMA] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WOOPER] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_QUAGSIRE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ESPEON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_UMBREON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MURKROW] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SLOWKING] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MISDREAVUS] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_UNOWN] = 0,
+
+ [SPECIES_WOBBUFFET] = 0,
+
+ [SPECIES_GIRAFARIG] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PINECO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FORRETRESS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DUNSPARCE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GLIGAR] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_STEELIX] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SNUBBULL] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GRANBULL] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_QWILFISH] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SCIZOR] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHUCKLE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HERACROSS] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SNEASEL] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TEDDIURSA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_URSARING] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SLUGMA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAGCARGO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SWINUB] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PILOSWINE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CORSOLA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_REMORAID] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_OCTILLERY] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DELIBIRD] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MANTINE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SKARMORY] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HOUNDOUR] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HOUNDOOM] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KINGDRA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PHANPY] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DONPHAN] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PORYGON2] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_STANTLER] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SMEARGLE] = 0,
+
+ [SPECIES_TYROGUE] = TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HITMONTOP] = TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SMOOCHUM] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ELEKID] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAGBY] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MILTANK] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BLISSEY] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SOFT_BOILED)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RAIKOU] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ENTEI] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SUICUNE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LARVITAR] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PUPITAR] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TYRANITAR] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LUGIA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HO_OH] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CELEBI] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TREECKO] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GROVYLE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SCEPTILE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TORCHIC] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_COMBUSKEN] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BLAZIKEN] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MUDKIP] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MARSHTOMP] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SWAMPERT] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_POOCHYENA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MIGHTYENA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ZIGZAGOON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LINOONE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WURMPLE] = 0,
+
+ [SPECIES_SILCOON] = 0,
+
+ [SPECIES_BEAUTIFLY] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CASCOON] = 0,
+
+ [SPECIES_DUSTOX] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LOTAD] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LOMBRE] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LUDICOLO] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SEEDOT] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NUZLEAF] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHIFTRY] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NINCADA] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NINJASK] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHEDINJA] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TAILLOW] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SWELLOW] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHROOMISH] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BRELOOM] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SPINDA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WINGULL] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PELIPPER] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SURSKIT] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MASQUERAIN] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WAILMER] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WAILORD] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SKITTY] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DELCATTY] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KECLEON] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BALTOY] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CLAYDOL] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NOSEPASS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TORKOAL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SABLEYE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BARBOACH] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WHISCASH] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LUVDISC] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CORPHISH] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CRAWDAUNT] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FEEBAS] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MILOTIC] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CARVANHA] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHARPEDO] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TRAPINCH] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VIBRAVA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_FLYGON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAKUHITA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HARIYAMA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ELECTRIKE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MANECTRIC] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_NUMEL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CAMERUPT] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SPHEAL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SEALEO] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WALREIN] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CACNEA] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CACTURNE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SNORUNT] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GLALIE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LUNATONE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SOLROCK] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_AZURILL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SPOINK] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GRUMPIG] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_PLUSLE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MINUN] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MAWILE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MEDITITE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_MEDICHAM] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SWABLU] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ALTARIA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WYNAUT] = 0,
+
+ [SPECIES_DUSKULL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DUSCLOPS] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ROSELIA] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SLAKOTH] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VIGOROTH] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SLAKING] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GULPIN] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SWALOT] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_TROPIUS] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_WHISMUR] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LOUDRED] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_EXPLOUD] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CLAMPERL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_HUNTAIL] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GOREBYSS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ABSOL] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHUPPET] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BANETTE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SEVIPER] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ZANGOOSE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RELICANTH] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ARON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LAIRON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_AGGRON] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CASTFORM] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_VOLBEAT] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ILLUMISE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LILEEP] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CRADILY] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ANORITH] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_ARMALDO] = TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RALTS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KIRLIA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GARDEVOIR] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BAGON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SHELGON] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_SALAMENCE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_BELDUM] = 0,
+
+ [SPECIES_METANG] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_METAGROSS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_REGIROCK] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_REGICE] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_REGISTEEL] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_EXPLOSION)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_KYOGRE] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_GROUDON] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_SWORDS_DANCE)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_RAYQUAZA] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LATIAS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_LATIOS] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_JIRACHI] = TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_METRONOME)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_DEOXYS] = TUTOR(MOVE_MEGA_PUNCH)
+ | TUTOR(MOVE_MEGA_KICK)
+ | TUTOR(MOVE_BODY_SLAM)
+ | TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_COUNTER)
+ | TUTOR(MOVE_SEISMIC_TOSS)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_THUNDER_WAVE)
+ | TUTOR(MOVE_ROCK_SLIDE)
+ | TUTOR(MOVE_SUBSTITUTE),
+
+ [SPECIES_CHIMECHO] = TUTOR(MOVE_DOUBLE_EDGE)
+ | TUTOR(MOVE_MIMIC)
+ | TUTOR(MOVE_DREAM_EATER)
+ | TUTOR(MOVE_SUBSTITUTE),
+};
diff --git a/src/daycare.c b/src/daycare.c
index f034bc220..8862dfda9 100644
--- a/src/daycare.c
+++ b/src/daycare.c
@@ -1582,7 +1582,7 @@ void ShowDaycareLevelMenu(void)
void ChooseSendDaycareMon(void)
{
- sub_8128370();
+ ChooseMonForDaycare();
gMain.savedCallback = CB2_ReturnToField;
}
diff --git a/src/field_fadetransition.c b/src/field_fadetransition.c
index 58caad509..d6bf4ea07 100644
--- a/src/field_fadetransition.c
+++ b/src/field_fadetransition.c
@@ -522,7 +522,7 @@ static bool32 sub_807E40C(void)
bool32 sub_807E418(void)
{
- if (field_weather_is_fade_finished() == TRUE && sub_80F83B0())
+ if (IsWeatherNotFadingIn() == TRUE && sub_80F83B0())
return TRUE;
else
return FALSE;
diff --git a/src/field_poison.c b/src/field_poison.c
index 474fbcd69..07c2b763f 100644
--- a/src/field_poison.c
+++ b/src/field_poison.c
@@ -43,7 +43,7 @@ static void FaintFromFieldPoison(u8 partyIdx)
static bool32 MonFaintedFromPoison(u8 partyIdx)
{
struct Pokemon *pokemon = gPlayerParty + partyIdx;
- if (IsMonValidSpecies(pokemon) && !GetMonData(pokemon, MON_DATA_HP) && pokemon_ailments_get_primary(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN)
+ if (IsMonValidSpecies(pokemon) && !GetMonData(pokemon, MON_DATA_HP) && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN)
return TRUE;
return FALSE;
}
@@ -97,7 +97,7 @@ s32 DoPoisonFieldEffect(void)
u32 numFainted = 0;
for (i = 0; i < PARTY_SIZE; i++)
{
- if (GetMonData(pokemon, MON_DATA_SANITY_HAS_SPECIES) && pokemon_ailments_get_primary(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN)
+ if (GetMonData(pokemon, MON_DATA_SANITY_HAS_SPECIES) && GetAilmentFromStatus(GetMonData(pokemon, MON_DATA_STATUS)) == AILMENT_PSN)
{
hp = GetMonData(pokemon, MON_DATA_HP);
if (hp == 0 || --hp == 0)
diff --git a/src/field_specials.c b/src/field_specials.c
index 617faa017..374c74f3c 100644
--- a/src/field_specials.c
+++ b/src/field_specials.c
@@ -1863,7 +1863,7 @@ void sub_80CC59C(void)
{
if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE22) && (gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE22) || gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE23)))
{
- sp0.unk0 = get_mapheader_by_bank_and_number(sInsideOutsidePairs[r5].grp, sInsideOutsidePairs[r5].num)->regionMapSectionId;
+ sp0.unk0 = Overworld_GetMapHeaderByGroupAndId(sInsideOutsidePairs[r5].grp, sInsideOutsidePairs[r5].num)->regionMapSectionId;
if (gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE22))
sp0.unk1 = r5;
else
@@ -1875,7 +1875,7 @@ void sub_80CC59C(void)
}
if (gSaveBlock1Ptr->location.mapGroup == sInsideOutsidePairs[r5].grp2 && gSaveBlock1Ptr->location.mapNum == sInsideOutsidePairs[r5].num2)
{
- sp0.unk0 = get_mapheader_by_bank_and_number(sInsideOutsidePairs[r5].grp, sInsideOutsidePairs[r5].num)->regionMapSectionId;
+ sp0.unk0 = Overworld_GetMapHeaderByGroupAndId(sInsideOutsidePairs[r5].grp, sInsideOutsidePairs[r5].num)->regionMapSectionId;
sp0.unk1 = r5;
if (r5 == 22)
{
diff --git a/src/fieldmap.c b/src/fieldmap.c
index 000b8105b..4244762c0 100644
--- a/src/fieldmap.c
+++ b/src/fieldmap.c
@@ -60,7 +60,7 @@ const u8 gUnknown_8352F10[] = {
const struct MapHeader * mapconnection_get_mapheader(struct MapConnection * connection)
{
- return get_mapheader_by_bank_and_number(connection->mapGroup, connection->mapNum);
+ return Overworld_GetMapHeaderByGroupAndId(connection->mapGroup, connection->mapNum);
}
void not_trainer_hill_battle_pyramid(void)
diff --git a/src/fldeff_softboiled.c b/src/fldeff_softboiled.c
index 400a1d382..60437c125 100644
--- a/src/fldeff_softboiled.c
+++ b/src/fldeff_softboiled.c
@@ -13,9 +13,9 @@ static void sub_80E58A0(u8 taskId);
static void sub_80E5934(u8 taskId);
extern const u8 gUnknown_84169F8[];
-extern const u8 gUnknown_8416F27[];
+extern const u8 gText_PkmnHPRestoredByVar2[];
-bool8 hm_prepare_dive_probably(void)
+bool8 SetUpFieldMove_SoftBoiled(void)
{
u16 maxHp = GetMonData(&gPlayerParty[GetCursorSelectionMonId()], MON_DATA_MAX_HP);
u16 curHp = GetMonData(&gPlayerParty[GetCursorSelectionMonId()], MON_DATA_HP);
@@ -26,27 +26,27 @@ bool8 hm_prepare_dive_probably(void)
return FALSE;
}
-void sub_80E56DC(u8 taskId)
+void ChooseMonForSoftboiled(u8 taskId)
{
- gUnknown_203B0A0.unkB = 10;
- gUnknown_203B0A0.unkA = gUnknown_203B0A0.unk9;
- sub_811F818(GetCursorSelectionMonId(), 1);
- sub_8121D0C(5);
- gTasks[taskId].func = sub_811FB28;
+ gPartyMenu.action = 10;
+ gPartyMenu.slotId2 = gPartyMenu.slotId;
+ AnimatePartySlot(GetCursorSelectionMonId(), 1);
+ DisplayPartyMenuStdMessage(5);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
}
-void sub_80E5724(u8 taskId)
+void Task_TryUseSoftboiledOnPartyMon(u8 taskId)
{
- u8 r8 = gUnknown_203B0A0.unk9;
- u8 r5 = gUnknown_203B0A0.unkA;
+ u8 r8 = gPartyMenu.slotId;
+ u8 r5 = gPartyMenu.slotId2;
u16 curHp;
s16 delta;
if (r5 > 6)
{
- gUnknown_203B0A0.unkB = 0;
- sub_8121D0C(0);
- gTasks[taskId].func = sub_811FB28;
+ gPartyMenu.action = 0;
+ DisplayPartyMenuStdMessage(0);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
}
else
{
@@ -58,7 +58,7 @@ void sub_80E5724(u8 taskId)
else
{
PlaySE(SE_KAIFUKU);
- sub_8120760(taskId, r8, -1, GetMonData(&gPlayerParty[r8], MON_DATA_MAX_HP) / 5, sub_80E57E8);
+ PartyMenuModifyHP(taskId, r8, -1, GetMonData(&gPlayerParty[r8], MON_DATA_MAX_HP) / 5, sub_80E57E8);
}
}
}
@@ -66,46 +66,46 @@ void sub_80E5724(u8 taskId)
static void sub_80E57E8(u8 taskId)
{
PlaySE(SE_KAIFUKU);
- sub_8120760(taskId, gUnknown_203B0A0.unkA, 1, GetMonData(&gPlayerParty[gUnknown_203B0A0.unk9], MON_DATA_MAX_HP) / 5, sub_80E583C);
+ PartyMenuModifyHP(taskId, gPartyMenu.slotId2, 1, GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_MAX_HP) / 5, sub_80E583C);
}
static void sub_80E583C(u8 taskId)
{
- GetMonNickname(&gPlayerParty[gUnknown_203B0A0.unkA], gStringVar1);
- StringExpandPlaceholders(gStringVar4, gUnknown_8416F27);
- sub_81202F8(gStringVar4, 0);
+ GetMonNickname(&gPlayerParty[gPartyMenu.slotId2], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnHPRestoredByVar2);
+ DisplayPartyMenuMessage(gStringVar4, 0);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = sub_80E58A0;
}
static void sub_80E58A0(u8 taskId)
{
- if (sub_8120370() != TRUE)
+ if (IsPartyMenuTextPrinterActive() != TRUE)
{
- gUnknown_203B0A0.unkB = 0;
- sub_811F818(gUnknown_203B0A0.unk9, 0);
- gUnknown_203B0A0.unk9 = gUnknown_203B0A0.unkA;
- sub_811F818(gUnknown_203B0A0.unkA, 1);
+ gPartyMenu.action = 0;
+ AnimatePartySlot(gPartyMenu.slotId, 0);
+ gPartyMenu.slotId = gPartyMenu.slotId2;
+ AnimatePartySlot(gPartyMenu.slotId2, 1);
ClearStdWindowAndFrameToTransparent(6, 0);
ClearWindowTilemap(6);
- sub_8121D0C(0);
- gTasks[taskId].func = sub_811FB28;
+ DisplayPartyMenuStdMessage(0);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
}
}
static void sub_80E5900(u8 taskId)
{
- if (sub_8120370() != TRUE)
+ if (IsPartyMenuTextPrinterActive() != TRUE)
{
- sub_8121D0C(5);
- gTasks[taskId].func = sub_811FB28;
+ DisplayPartyMenuStdMessage(5);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
}
}
static void sub_80E5934(u8 taskId)
{
PlaySE(SE_SELECT);
- sub_81202F8(gUnknown_84169F8, 0);
+ DisplayPartyMenuMessage(gUnknown_84169F8, 0);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = sub_80E5900;
}
diff --git a/src/fldeff_sweetscent.c b/src/fldeff_sweetscent.c
index b6ea1daed..943d8504c 100644
--- a/src/fldeff_sweetscent.c
+++ b/src/fldeff_sweetscent.c
@@ -22,7 +22,7 @@ static void FailSweetScentEncounter(u8 taskId);
static void Unused_StartSweetscentFldeff(void)
{
- gUnknown_203B0A0.unk9 = 0;
+ gPartyMenu.slotId = 0;
FieldCallback_SweetScent();
}
diff --git a/src/item.c b/src/item.c
index 677c13ad7..e16d5055c 100644
--- a/src/item.c
+++ b/src/item.c
@@ -412,7 +412,7 @@ bool8 AddPCItem(u16 itemId, u16 count)
return TRUE;
}
-void RemoveItemFromPC(u16 itemId, u16 count)
+void RemovePCItem(u16 itemId, u16 count)
{
u32 i;
u16 quantity;
diff --git a/src/item_pc.c b/src/item_pc.c
index 60a74ac59..3e0c50b60 100644
--- a/src/item_pc.c
+++ b/src/item_pc.c
@@ -709,7 +709,7 @@ static void ItemPc_SetScrollPosition(void)
static void ItemPc_SetMessageWindowPalette(int a0)
{
- SetBgRectPal(1, 0, 14, 30, 6, a0 + 1);
+ SetBgTilemapPalette(1, 0, 14, 30, 6, a0 + 1);
ScheduleBgCopyTilemapToVram(1);
}
@@ -926,7 +926,7 @@ static void Task_ItemPcWaitButtonAndFinishWithdrawMultiple(u8 taskId)
{
PlaySE(SE_SELECT);
itemId = ItemPc_GetItemIdBySlotId(data[1]);
- RemoveItemFromPC(itemId, data[8]);
+ RemovePCItem(itemId, data[8]);
ItemPcCompaction();
Task_ItemPcCleanUpWithdraw(taskId);
}
@@ -1029,8 +1029,8 @@ static void Task_ItemPcGive(u8 taskId)
static void ItemPc_CB2_SwitchToPartyMenu(void)
{
- PartyMenuInit(0, 0, 6, 0, 6, sub_811FB28, ItemPc_CB2_ReturnFromPartyMenu);
- gUnknown_203B0A0.unkC = ItemPc_GetItemIdBySlotId(ItemPc_GetCursorPosition());
+ InitPartyMenu(0, 0, 6, 0, 6, Task_HandleChooseMonInput, ItemPc_CB2_ReturnFromPartyMenu);
+ gPartyMenu.bagItem = ItemPc_GetItemIdBySlotId(ItemPc_GetCursorPosition());
}
static void ItemPc_CB2_ReturnFromPartyMenu(void)
diff --git a/src/item_use.c b/src/item_use.c
index db0475370..256711463 100644
--- a/src/item_use.c
+++ b/src/item_use.c
@@ -44,37 +44,36 @@
#include "constants/songs.h"
#include "constants/map_types.h"
-EWRAM_DATA void (*sItemUseOnFieldCB)(u8 taskId) = NULL;
-
-void sub_80A1084(void);
-void sub_80A109C(u8 taskId);
-void sub_80A112C(u8 taskId);
-void sub_80A11C0(u8 taskId);
-bool8 sub_80A1194(void);
-void sub_80A1208(void);
-void ItemUseOnFieldCB_Bicycle(u8 taskId);
-bool8 ItemUseCheckFunc_Rod(void);
-void ItemUseOnFieldCB_Rod(u8 taskId);
-void FieldUseFunc_EvoItem(u8 taskId);
-void sub_80A1648(u8 taskId);
-void sub_80A1674(u8 taskId);
-void InitTMCaseFromBag(void);
-void Task_InitTMCaseFromField(u8 taskId);
-void InitBerryPouchFromBag(void);
-void Task_InitBerryPouchFromField(u8 taskId);
-void InitBerryPouchFromBattle(void);
-void InitTeachyTvFromBag(void);
-void Task_InitTeachyTvFromField(u8 taskId);
-void sub_80A19E8(u8 taskId);
-void sub_80A1A44(void);
-void sub_80A1B48(u8 taskId);
-void sub_80A1C08(u8 taskId);
-void sub_80A1CAC(void);
-void sub_80A1CC0(u8 taskId);
-void sub_80A1D58(void);
-void sub_80A1D68(u8 taskId);
-void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId);
-void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId);
+static EWRAM_DATA void (*sItemUseOnFieldCB)(u8 taskId) = NULL;
+
+static void sub_80A1084(void);
+static void sub_80A109C(u8 taskId);
+static void sub_80A112C(u8 taskId);
+static void sub_80A11C0(u8 taskId);
+static bool8 sub_80A1194(void);
+static void sub_80A1208(void);
+static void ItemUseOnFieldCB_Bicycle(u8 taskId);
+static bool8 ItemUseCheckFunc_Rod(void);
+static void ItemUseOnFieldCB_Rod(u8 taskId);
+static void sub_80A1648(u8 taskId);
+static void sub_80A1674(u8 taskId);
+static void InitTMCaseFromBag(void);
+static void Task_InitTMCaseFromField(u8 taskId);
+static void InitBerryPouchFromBag(void);
+static void Task_InitBerryPouchFromField(u8 taskId);
+static void InitBerryPouchFromBattle(void);
+static void InitTeachyTvFromBag(void);
+static void Task_InitTeachyTvFromField(u8 taskId);
+static void sub_80A19E8(u8 taskId);
+static void sub_80A1A44(void);
+static void sub_80A1B48(u8 taskId);
+static void sub_80A1C08(u8 taskId);
+static void sub_80A1CAC(void);
+static void sub_80A1CC0(u8 taskId);
+static void sub_80A1D58(void);
+static void sub_80A1D68(u8 taskId);
+static void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId);
+static void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId);
// No clue what this is
static const u8 sUnref_83E27B4[] = {
@@ -132,14 +131,14 @@ static const u8 sUnref_83E27B4[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-void (*const gUnknown_83E2954[])(void) = {
- sub_8124C8C,
+static void (*const gUnknown_83E2954[])(void) = {
+ CB2_ShowPartyMenuForItemUse,
CB2_ReturnToField,
NULL,
NULL
};
-void sub_80A0FBC(u8 taskId)
+static void sub_80A0FBC(u8 taskId)
{
u8 itemType;
if (gSpecialVar_ItemId == ITEM_ENIGMA_BERRY)
@@ -160,7 +159,7 @@ void sub_80A0FBC(u8 taskId)
}
}
-void sub_80A103C(u8 taskId)
+static void sub_80A103C(u8 taskId)
{
if (gTasks[taskId].data[3] != 1)
{
@@ -171,21 +170,21 @@ void sub_80A103C(u8 taskId)
sItemUseOnFieldCB(taskId);
}
-void sub_80A1084(void)
+static void sub_80A1084(void)
{
sub_807DC00();
CreateTask(sub_80A109C, 8);
}
-void sub_80A109C(u8 taskId)
+static void sub_80A109C(u8 taskId)
{
- if (field_weather_is_fade_finished() == TRUE)
+ if (IsWeatherNotFadingIn() == TRUE)
{
sItemUseOnFieldCB(taskId);
}
}
-void sub_80A10C4(u8 taskId, bool8 a1, u8 a2, const u8 * str)
+static void sub_80A10C4(u8 taskId, bool8 a1, u8 a2, const u8 * str)
{
StringExpandPlaceholders(gStringVar4, str);
if (a1 == FALSE)
@@ -194,12 +193,12 @@ void sub_80A10C4(u8 taskId, bool8 a1, u8 a2, const u8 * str)
DisplayItemMessageOnField(taskId, a2, gStringVar4, sub_80A112C);
}
-void sub_80A1110(u8 taskId, bool8 a1)
+static void sub_80A1110(u8 taskId, bool8 a1)
{
sub_80A10C4(taskId, a1, 4, gUnknown_8416425);
}
-void sub_80A112C(u8 taskId)
+static void sub_80A112C(u8 taskId)
{
ClearDialogWindowAndFrame(0, 1);
DestroyTask(taskId);
@@ -207,7 +206,7 @@ void sub_80A112C(u8 taskId)
ScriptContext2_Disable();
}
-u8 GetItemCompatibilityRule(u16 itemId)
+u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId)
{
if (ItemId_GetPocket(itemId) == POCKET_TM_CASE)
return 1;
@@ -217,12 +216,12 @@ u8 GetItemCompatibilityRule(u16 itemId)
return 0;
}
-void sub_80A1184(void)
+static void sub_80A1184(void)
{
gFieldCallback2 = sub_80A1194;
}
-bool8 sub_80A1194(void)
+static bool8 sub_80A1194(void)
{
FreezeEventObjects();
ScriptContext2_Enable();
@@ -232,9 +231,9 @@ bool8 sub_80A1194(void)
return TRUE;
}
-void sub_80A11C0(u8 taskId)
+static void sub_80A11C0(u8 taskId)
{
- if (field_weather_is_fade_finished() == TRUE)
+ if (IsWeatherNotFadingIn() == TRUE)
{
UnfreezeMapObjects();
ScriptContext2_Disable();
@@ -248,7 +247,7 @@ void FieldUseFunc_OrangeMail(u8 taskId)
ItemMenu_StartFadeToExitCallback(taskId);
}
-void sub_80A1208(void)
+static void sub_80A1208(void)
{
struct MailStruct mail;
@@ -279,7 +278,7 @@ void FieldUseFunc_MachBike(u8 taskId)
sub_80A1110(taskId, gTasks[taskId].data[3]);
}
-void ItemUseOnFieldCB_Bicycle(u8 taskId)
+static void ItemUseOnFieldCB_Bicycle(u8 taskId)
{
if (!TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE))
PlaySE(SE_JITENSYA);
@@ -300,7 +299,7 @@ void FieldUseFunc_OldRod(u8 taskId)
sub_80A1110(taskId, gTasks[taskId].data[3]);
}
-bool8 ItemUseCheckFunc_Rod(void)
+static bool8 ItemUseCheckFunc_Rod(void)
{
s16 x, y;
u16 behavior;
@@ -327,7 +326,7 @@ bool8 ItemUseCheckFunc_Rod(void)
return FALSE;
}
-void ItemUseOnFieldCB_Rod(u8 taskId)
+static void ItemUseOnFieldCB_Rod(u8 taskId)
{
sub_805D2C0(ItemId_GetSecondaryId(gSpecialVar_ItemId));
DestroyTask(taskId);
@@ -391,13 +390,13 @@ void FieldUseFunc_PokeFlute(u8 taskId)
}
}
-void sub_80A1648(u8 taskId)
+static void sub_80A1648(u8 taskId)
{
PlayFanfareByFanfareNum(FANFARE_POKEFLUTE);
gTasks[taskId].func = sub_80A1674;
}
-void sub_80A1674(u8 taskId)
+static void sub_80A1674(u8 taskId)
{
if (WaitFanfare(FALSE))
{
@@ -408,44 +407,44 @@ void sub_80A1674(u8 taskId)
}
}
-void sub_80A16D0(u8 taskId)
+static void sub_80A16D0(u8 taskId)
{
sub_80A0FBC(taskId);
}
void FieldUseFunc_Medicine(u8 taskId)
{
- gUnknown_3005E98 = sub_81252D0;
+ gItemUseCB = ItemUseCB_Medicine;
sub_80A16D0(taskId);
}
void FieldUseFunc_Ether(u8 taskId)
{
- gUnknown_3005E98 = ItemUseCB_PpRestore;
+ gItemUseCB = ItemUseCB_PPRecovery;
sub_80A16D0(taskId);
}
void FieldUseFunc_PpUp(u8 taskId)
{
- gUnknown_3005E98 = dp05_pp_up;
+ gItemUseCB = ItemUseCB_PPUp;
sub_80A16D0(taskId);
}
void FieldUseFunc_RareCandy(u8 taskId)
{
- gUnknown_3005E98 = dp05_rare_candy;
+ gItemUseCB = ItemUseCB_RareCandy;
sub_80A16D0(taskId);
}
void FieldUseFunc_EvoItem(u8 taskId)
{
- gUnknown_3005E98 = sub_8126B60;
+ gItemUseCB = ItemUseCB_EvolutionStone;
sub_80A16D0(taskId);
}
void FieldUseFunc_SacredAsh(u8 taskId)
{
- gUnknown_3005E98 = sub_8126894;
+ gItemUseCB = ItemUseCB_SacredAsh;
sub_80A0FBC(taskId);
}
@@ -464,12 +463,12 @@ void FieldUseFunc_TmCase(u8 taskId)
}
}
-void InitTMCaseFromBag(void)
+static void InitTMCaseFromBag(void)
{
InitTMCase(0, CB2_BagMenuFromStartMenu, 0);
}
-void Task_InitTMCaseFromField(u8 taskId)
+static void Task_InitTMCaseFromField(u8 taskId)
{
if (!gPaletteFade.active)
{
@@ -495,12 +494,12 @@ void FieldUseFunc_BerryPouch(u8 taskId)
}
}
-void InitBerryPouchFromBag(void)
+static void InitBerryPouchFromBag(void)
{
InitBerryPouch(BERRYPOUCH_FROMFIELD, CB2_BagMenuFromStartMenu, 0);
}
-void Task_InitBerryPouchFromField(u8 taskId)
+static void Task_InitBerryPouchFromField(u8 taskId)
{
if (!gPaletteFade.active)
{
@@ -517,7 +516,7 @@ void BattleUseFunc_BerryPouch(u8 taskId)
ItemMenu_StartFadeToExitCallback(taskId);
}
-void InitBerryPouchFromBattle(void)
+static void InitBerryPouchFromBattle(void)
{
InitBerryPouch(BERRYPOUCH_FROMBATTLE, sub_8107ECC, 0);
}
@@ -538,12 +537,12 @@ void FieldUseFunc_TeachyTv(u8 taskId)
}
}
-void InitTeachyTvFromBag(void)
+static void InitTeachyTvFromBag(void)
{
InitTeachyTvController(0, CB2_BagMenuFromStartMenu);
}
-void Task_InitTeachyTvFromField(u8 taskId)
+static void Task_InitTeachyTvFromField(u8 taskId)
{
if (!gPaletteFade.active)
{
@@ -566,7 +565,7 @@ void FieldUseFunc_SuperRepel(u8 taskId)
DisplayItemMessageInBag(taskId, 2, gUnknown_841659E, sub_810A1F8);
}
-void sub_80A19E8(u8 taskId)
+static void sub_80A19E8(u8 taskId)
{
if (!IsSEPlaying())
{
@@ -577,7 +576,7 @@ void sub_80A19E8(u8 taskId)
}
}
-void sub_80A1A44(void)
+static void sub_80A1A44(void)
{
RemoveBagItem(gSpecialVar_ItemId, 1);
sub_8108DC8(ItemId_GetPocket(gSpecialVar_ItemId));
@@ -609,7 +608,7 @@ void FieldUseFunc_BlackFlute(u8 taskId)
}
}
-void sub_80A1B48(u8 taskId)
+static void sub_80A1B48(u8 taskId)
{
if (++gTasks[taskId].data[8] > 7)
{
@@ -638,7 +637,7 @@ void ItemUseOutOfBattle_EscapeRope(u8 taskId)
sub_80A1110(taskId, gTasks[taskId].data[3]);
}
-void sub_80A1C08(u8 taskId)
+static void sub_80A1C08(u8 taskId)
{
Overworld_ResetStateAfterDigEscRope();
sub_80A1A44();
@@ -668,12 +667,12 @@ void FieldUseFunc_TownMap(u8 taskId)
}
}
-void sub_80A1CAC(void)
+static void sub_80A1CAC(void)
{
sub_80BFF50(0, CB2_BagMenuFromStartMenu);
}
-void sub_80A1CC0(u8 taskId)
+static void sub_80A1CC0(u8 taskId)
{
if (!gPaletteFade.active)
{
@@ -700,12 +699,12 @@ void FieldUseFunc_FameChecker(u8 taskId)
}
}
-void sub_80A1D58(void)
+static void sub_80A1D58(void)
{
UseFameChecker(CB2_BagMenuFromStartMenu);
}
-void sub_80A1D68(u8 taskId)
+static void sub_80A1D68(u8 taskId)
{
if (!gPaletteFade.active)
{
@@ -765,7 +764,7 @@ void BattleUseFunc_GuardSpec(u8 taskId)
{
if (ExecuteTableBasedItemEffect(&gPlayerParty[gBattlerPartyIndexes[gBattlerInMenuId]], gSpecialVar_ItemId, gBattlerPartyIndexes[gBattlerInMenuId], 0))
{
- DisplayItemMessageInBag(taskId, 2, gUnknown_84169DC, sub_810A1F8);
+ DisplayItemMessageInBag(taskId, 2, gText_WontHaveEffect, sub_810A1F8);
}
else
{
@@ -774,7 +773,7 @@ void BattleUseFunc_GuardSpec(u8 taskId)
}
}
-void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId)
+static void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId)
{
s16 * data = gTasks[taskId].data;
@@ -787,7 +786,7 @@ void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId)
}
}
-void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId)
+static void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId)
{
if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
{
@@ -796,7 +795,7 @@ void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId)
}
}
-void ItemUse_SwitchToPartyMenuInBattle(u8 taskId)
+static void ItemUse_SwitchToPartyMenuInBattle(u8 taskId)
{
if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_BERRY_POUCH)
{
@@ -812,19 +811,19 @@ void ItemUse_SwitchToPartyMenuInBattle(u8 taskId)
void BattleUseFunc_Medicine(u8 taskId)
{
- gUnknown_3005E98 = ItemUseCB_Medicine;
+ gItemUseCB = ItemUseCB_MedicineStep;
ItemUse_SwitchToPartyMenuInBattle(taskId);
}
-void sub_80A1FD8(u8 taskId)
+static void sub_80A1FD8(u8 taskId)
{
- gUnknown_3005E98 = sub_8126894;
+ gItemUseCB = ItemUseCB_SacredAsh;
ItemUse_SwitchToPartyMenuInBattle(taskId);
}
void BattleUseFunc_Ether(u8 taskId)
{
- gUnknown_3005E98 = ItemUseCB_PpRestore;
+ gItemUseCB = ItemUseCB_PPRecovery;
ItemUse_SwitchToPartyMenuInBattle(taskId);
}
diff --git a/src/list_menu.c b/src/list_menu.c
index d25eb3faf..484da31ad 100644
--- a/src/list_menu.c
+++ b/src/list_menu.c
@@ -70,7 +70,7 @@ static EWRAM_DATA struct MysteryGiftLinkMenuStruct sMysteryGiftLinkMenu = {0};
struct ListMenuOverride gListMenuOverride;
struct ListMenuTemplate gMultiuseListMenuTemplate;
-static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 scrollOffset, u16 selectedRow);
+static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 cursorPos, u16 itemsAbove);
static bool8 ListMenuChangeSelection(struct ListMenu *list, bool8 updateCursorAndCallCallback, u8 count, bool8 movingDown);
static void ListMenuPrintEntries(struct ListMenu *list, u16 startIndex, u16 yOffset, u16 count);
static void ListMenuDrawCursor(struct ListMenu *list);
@@ -172,18 +172,18 @@ s32 DoMysteryGiftListMenu(const struct WindowTemplate *windowTemplate, const str
return LIST_NOTHING_CHOSEN;
}
-u8 ListMenuInit(struct ListMenuTemplate *listMenuTemplate, u16 scrollOffset, u16 selectedRow)
+u8 ListMenuInit(struct ListMenuTemplate *listMenuTemplate, u16 cursorPos, u16 itemsAbove)
{
- u8 taskId = ListMenuInitInternal(listMenuTemplate, scrollOffset, selectedRow);
+ u8 taskId = ListMenuInitInternal(listMenuTemplate, cursorPos, itemsAbove);
PutWindowTilemap(listMenuTemplate->windowId);
CopyWindowToVram(listMenuTemplate->windowId, 2);
return taskId;
}
-u8 ListMenuInitInRect(struct ListMenuTemplate *listMenuTemplate, struct ListMenuWindowRect *rect, u16 scrollOffset, u16 selectedRow)
+u8 ListMenuInitInRect(struct ListMenuTemplate *listMenuTemplate, struct ListMenuWindowRect *rect, u16 cursorPos, u16 itemsAbove)
{
s32 i;
- u8 taskId = ListMenuInitInternal(listMenuTemplate, scrollOffset, selectedRow);
+ u8 taskId = ListMenuInitInternal(listMenuTemplate, cursorPos, itemsAbove);
for (i = 0; rect[i].palNum != 0xFF; i++)
PutWindowRectTilemapOverridePalette(listMenuTemplate->windowId, rect[i].x, rect[i].y, rect[i].width, rect[i].height, rect[i].palNum);
@@ -197,7 +197,7 @@ s32 ListMenu_ProcessInput(u8 listTaskId)
if (JOY_NEW(A_BUTTON))
{
- return list->template.items[list->scrollOffset + list->selectedRow].index;
+ return list->template.items[list->cursorPos + list->itemsAbove].index;
}
else if (JOY_NEW(B_BUTTON))
{
@@ -249,14 +249,14 @@ s32 ListMenu_ProcessInput(u8 listTaskId)
}
}
-void DestroyListMenuTask(u8 listTaskId, u16 *scrollOffset, u16 *selectedRow)
+void DestroyListMenuTask(u8 listTaskId, u16 *cursorPos, u16 *itemsAbove)
{
struct ListMenu *list = (struct ListMenu *)gTasks[listTaskId].data;
- if (scrollOffset != NULL)
- *scrollOffset = list->scrollOffset;
- if (selectedRow != NULL)
- *selectedRow = list->selectedRow;
+ if (cursorPos != NULL)
+ *cursorPos = list->cursorPos;
+ if (itemsAbove != NULL)
+ *itemsAbove = list->itemsAbove;
if (list->taskId != TASK_NONE)
ListMenuRemoveCursorObject(list->taskId, list->template.cursorKind - 2);
@@ -269,7 +269,7 @@ void RedrawListMenu(u8 listTaskId)
struct ListMenu *list = (struct ListMenu *)gTasks[listTaskId].data;
FillWindowPixelBuffer(list->template.windowId, PIXEL_FILL(list->template.fillValue));
- ListMenuPrintEntries(list, list->scrollOffset, 0, list->template.maxShowed);
+ ListMenuPrintEntries(list, list->cursorPos, 0, list->template.maxShowed);
ListMenuDrawCursor(list);
CopyWindowToVram(list->template.windowId, 2);
}
@@ -291,13 +291,13 @@ static void ChangeListMenuCoords(u8 listTaskId, u8 x, u8 y)
SetWindowAttribute(list->template.windowId, WINDOW_TILEMAP_TOP, y);
}
-static s32 ListMenuTestInput(struct ListMenuTemplate *template, u32 scrollOffset, u32 selectedRow, u16 keys, u16 *newScrollOffset, u16 *newSelectedRow)
+static s32 ListMenuTestInput(struct ListMenuTemplate *template, u32 cursorPos, u32 itemsAbove, u16 keys, u16 *newCursorPos, u16 *newItemsAbove)
{
struct ListMenu list;
list.template = *template;
- list.scrollOffset = scrollOffset;
- list.selectedRow = selectedRow;
+ list.cursorPos = cursorPos;
+ list.itemsAbove = itemsAbove;
list.unk_1C = 0;
list.unk_1D = 0;
if (keys == DPAD_UP)
@@ -305,10 +305,10 @@ static s32 ListMenuTestInput(struct ListMenuTemplate *template, u32 scrollOffset
if (keys == DPAD_DOWN)
ListMenuChangeSelection(&list, FALSE, 1, TRUE);
- if (newScrollOffset != NULL)
- *newScrollOffset = list.scrollOffset;
- if (newSelectedRow != NULL)
- *newSelectedRow = list.selectedRow;
+ if (newCursorPos != NULL)
+ *newCursorPos = list.cursorPos;
+ if (newItemsAbove != NULL)
+ *newItemsAbove = list.itemsAbove;
return LIST_NOTHING_CHOSEN;
}
@@ -317,17 +317,17 @@ static void ListMenuGetCurrentItemArrayId(u8 listTaskId, u16 *arrayId)
struct ListMenu *list = (struct ListMenu *)gTasks[listTaskId].data;
if (arrayId != NULL)
- *arrayId = list->scrollOffset + list->selectedRow;
+ *arrayId = list->cursorPos + list->itemsAbove;
}
-void ListMenuGetScrollAndRow(u8 listTaskId, u16 *scrollOffset, u16 *selectedRow)
+void ListMenuGetScrollAndRow(u8 listTaskId, u16 *cursorPos, u16 *itemsAbove)
{
struct ListMenu *list = (struct ListMenu *)gTasks[listTaskId].data;
- if (scrollOffset != NULL)
- *scrollOffset = list->scrollOffset;
- if (selectedRow != NULL)
- *selectedRow = list->selectedRow;
+ if (cursorPos != NULL)
+ *cursorPos = list->cursorPos;
+ if (itemsAbove != NULL)
+ *itemsAbove = list->itemsAbove;
}
u16 ListMenuGetYCoordForPrintingArrowCursor(u8 listTaskId)
@@ -335,17 +335,17 @@ u16 ListMenuGetYCoordForPrintingArrowCursor(u8 listTaskId)
struct ListMenu *list = (struct ListMenu *)gTasks[listTaskId].data;
u8 yMultiplier = GetFontAttribute(list->template.fontId, FONTATTR_MAX_LETTER_HEIGHT) + list->template.itemVerticalPadding;
- return list->selectedRow * yMultiplier + list->template.upText_Y;
+ return list->itemsAbove * yMultiplier + list->template.upText_Y;
}
-static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 scrollOffset, u16 selectedRow)
+static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 cursorPos, u16 itemsAbove)
{
u8 listTaskId = CreateTask(ListMenuDummyTask, 0);
struct ListMenu *list = (struct ListMenu *)gTasks[listTaskId].data;
list->template = *listMenuTemplate;
- list->scrollOffset = scrollOffset;
- list->selectedRow = selectedRow;
+ list->cursorPos = cursorPos;
+ list->itemsAbove = itemsAbove;
list->unk_1C = 0;
list->unk_1D = 0;
list->taskId = TASK_NONE;
@@ -359,7 +359,7 @@ static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 sc
if (list->template.totalItems < list->template.maxShowed)
list->template.maxShowed = list->template.totalItems;
FillWindowPixelBuffer(list->template.windowId, PIXEL_FILL(list->template.fillValue));
- ListMenuPrintEntries(list, list->scrollOffset, 0, list->template.maxShowed);
+ ListMenuPrintEntries(list, list->cursorPos, 0, list->template.maxShowed);
ListMenuDrawCursor(list);
ListMenuCallSelectionChangedCallback(list, TRUE);
@@ -410,7 +410,7 @@ static void ListMenuDrawCursor(struct ListMenu *list)
{
u8 yMultiplier = GetFontAttribute(list->template.fontId, FONTATTR_MAX_LETTER_HEIGHT) + list->template.itemVerticalPadding;
u8 x = list->template.cursor_X;
- u8 y = list->selectedRow * yMultiplier + list->template.upText_Y;
+ u8 y = list->itemsAbove * yMultiplier + list->template.upText_Y;
switch (list->template.cursorKind)
{
@@ -446,7 +446,7 @@ static u8 ListMenuAddCursorObject(struct ListMenu *list, u32 cursorKind)
return ListMenuAddCursorObjectInternal(&cursor, cursorKind);
}
-static void ListMenuErasePrintedCursor(struct ListMenu *list, u16 selectedRow)
+static void ListMenuErasePrintedCursor(struct ListMenu *list, u16 itemsAbove)
{
u8 cursorKind = list->template.cursorKind;
if (cursorKind == 0)
@@ -457,7 +457,7 @@ static void ListMenuErasePrintedCursor(struct ListMenu *list, u16 selectedRow)
FillWindowPixelRect(list->template.windowId,
PIXEL_FILL(list->template.fillValue),
list->template.cursor_X,
- selectedRow * yMultiplier + list->template.upText_Y,
+ itemsAbove * yMultiplier + list->template.upText_Y,
width,
height);
}
@@ -465,8 +465,8 @@ static void ListMenuErasePrintedCursor(struct ListMenu *list, u16 selectedRow)
static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, bool8 movingDown)
{
- u16 selectedRow = list->selectedRow;
- u16 scrollOffset = list->scrollOffset;
+ u16 itemsAbove = list->itemsAbove;
+ u16 cursorPos = list->cursorPos;
u16 newRow;
u32 newScroll;
@@ -477,14 +477,14 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b
else
newRow = list->template.maxShowed - ((list->template.maxShowed / 2) + (list->template.maxShowed % 2)) - 1;
- if (scrollOffset == 0)
+ if (cursorPos == 0)
{
- while (selectedRow != 0)
+ while (itemsAbove != 0)
{
- selectedRow--;
- if (list->template.items[scrollOffset + selectedRow].index != LIST_HEADER)
+ itemsAbove--;
+ if (list->template.items[cursorPos + itemsAbove].index != LIST_HEADER)
{
- list->selectedRow = selectedRow;
+ list->itemsAbove = itemsAbove;
return 1;
}
}
@@ -492,16 +492,16 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b
}
else
{
- while (selectedRow > newRow)
+ while (itemsAbove > newRow)
{
- selectedRow--;
- if (list->template.items[scrollOffset + selectedRow].index != LIST_HEADER)
+ itemsAbove--;
+ if (list->template.items[cursorPos + itemsAbove].index != LIST_HEADER)
{
- list->selectedRow = selectedRow;
+ list->itemsAbove = itemsAbove;
return 1;
}
}
- newScroll = scrollOffset - 1;
+ newScroll = cursorPos - 1;
}
}
else
@@ -511,14 +511,14 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b
else
newRow = ((list->template.maxShowed / 2) + (list->template.maxShowed % 2));
- if (scrollOffset == list->template.totalItems - list->template.maxShowed)
+ if (cursorPos == list->template.totalItems - list->template.maxShowed)
{
- while (selectedRow < list->template.maxShowed - 1)
+ while (itemsAbove < list->template.maxShowed - 1)
{
- selectedRow++;
- if (list->template.items[scrollOffset + selectedRow].index != LIST_HEADER)
+ itemsAbove++;
+ if (list->template.items[cursorPos + itemsAbove].index != LIST_HEADER)
{
- list->selectedRow = selectedRow;
+ list->itemsAbove = itemsAbove;
return 1;
}
}
@@ -526,20 +526,20 @@ static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, b
}
else
{
- while (selectedRow < newRow)
+ while (itemsAbove < newRow)
{
- selectedRow++;
- if (list->template.items[scrollOffset + selectedRow].index != LIST_HEADER)
+ itemsAbove++;
+ if (list->template.items[cursorPos + itemsAbove].index != LIST_HEADER)
{
- list->selectedRow = selectedRow;
+ list->itemsAbove = itemsAbove;
return 1;
}
}
- newScroll = scrollOffset + 1;
+ newScroll = cursorPos + 1;
}
}
- list->selectedRow = newRow;
- list->scrollOffset = newScroll;
+ list->itemsAbove = newRow;
+ list->cursorPos = newScroll;
return 2;
}
@@ -548,7 +548,7 @@ static void ListMenuScroll(struct ListMenu *list, u8 count, bool8 movingDown)
if (count >= list->template.maxShowed)
{
FillWindowPixelBuffer(list->template.windowId, PIXEL_FILL(list->template.fillValue));
- ListMenuPrintEntries(list, list->scrollOffset, 0, list->template.maxShowed);
+ ListMenuPrintEntries(list, list->cursorPos, 0, list->template.maxShowed);
}
else
{
@@ -559,7 +559,7 @@ static void ListMenuScroll(struct ListMenu *list, u8 count, bool8 movingDown)
u16 y, width, height;
ScrollWindow(list->template.windowId, 1, count * yMultiplier, PIXEL_FILL(list->template.fillValue));
- ListMenuPrintEntries(list, list->scrollOffset, 0, count);
+ ListMenuPrintEntries(list, list->cursorPos, 0, count);
y = (list->template.maxShowed * yMultiplier) + list->template.upText_Y;
width = GetWindowAttribute(list->template.windowId, WINDOW_WIDTH) * 8;
@@ -573,7 +573,7 @@ static void ListMenuScroll(struct ListMenu *list, u8 count, bool8 movingDown)
u16 width;
ScrollWindow(list->template.windowId, 0, count * yMultiplier, PIXEL_FILL(list->template.fillValue));
- ListMenuPrintEntries(list, list->scrollOffset + (list->template.maxShowed - count), list->template.maxShowed - count, count);
+ ListMenuPrintEntries(list, list->cursorPos + (list->template.maxShowed - count), list->template.maxShowed - count, count);
width = GetWindowAttribute(list->template.windowId, WINDOW_WIDTH) * 8;
FillWindowPixelRect(list->template.windowId,
@@ -588,7 +588,7 @@ static bool8 ListMenuChangeSelection(struct ListMenu *list, bool8 updateCursorAn
u16 oldSelectedRow;
u8 selectionChange, i, cursorCount;
- oldSelectedRow = list->selectedRow;
+ oldSelectedRow = list->itemsAbove;
cursorCount = 0;
selectionChange = 0;
for (i = 0; i < count; i++)
@@ -602,7 +602,7 @@ static bool8 ListMenuChangeSelection(struct ListMenu *list, bool8 updateCursorAn
break;
cursorCount++;
}
- while (list->template.items[list->scrollOffset + list->selectedRow].index == LIST_HEADER);
+ while (list->template.items[list->cursorPos + list->itemsAbove].index == LIST_HEADER);
}
if (updateCursorAndCallCallback)
@@ -634,7 +634,7 @@ static bool8 ListMenuChangeSelection(struct ListMenu *list, bool8 updateCursorAn
static void ListMenuCallSelectionChangedCallback(struct ListMenu *list, u8 onInit)
{
if (list->template.moveCursorFunc != NULL)
- list->template.moveCursorFunc(list->template.items[list->scrollOffset + list->selectedRow].index, onInit, list);
+ list->template.moveCursorFunc(list->template.items[list->cursorPos + list->itemsAbove].index, onInit, list);
}
void ListMenuOverrideSetColors(u8 cursorPal, u8 fillValue, u8 cursorShadowPal)
diff --git a/src/mailbox_pc.c b/src/mailbox_pc.c
index 0a4535271..5489c4c4e 100644
--- a/src/mailbox_pc.c
+++ b/src/mailbox_pc.c
@@ -123,7 +123,7 @@ u8 MailboxPC_InitListMenu(struct PlayerPCItemPageStruct * playerPcStruct)
gMultiuseListMenuTemplate.itemPrintFunc = ItemPrintFunc;
gMultiuseListMenuTemplate.cursorKind = 0;
gMultiuseListMenuTemplate.scrollMultiple = 0;
- return ListMenuInit(&gMultiuseListMenuTemplate, playerPcStruct->scrollOffset, playerPcStruct->selectedRow);
+ return ListMenuInit(&gMultiuseListMenuTemplate, playerPcStruct->itemsAbove, playerPcStruct->cursorPos);
}
static void MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu * list)
@@ -134,7 +134,7 @@ static void MoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMenu * list)
void MailboxPC_AddScrollIndicatorArrows(struct PlayerPCItemPageStruct * playerPcStruct)
{
- playerPcStruct->scrollIndicatorId = AddScrollIndicatorArrowPairParameterized(2, 0xC2, 0xC, 0x94, playerPcStruct->count - playerPcStruct->pageItems + 1, 110, 110, &playerPcStruct->scrollOffset);
+ playerPcStruct->scrollIndicatorId = AddScrollIndicatorArrowPairParameterized(2, 0xC2, 0xC, 0x94, playerPcStruct->count - playerPcStruct->pageItems + 1, 110, 110, &playerPcStruct->itemsAbove);
}
void MailboxPC_DestroyListMenuBuffer(void)
diff --git a/src/map_preview_screen.c b/src/map_preview_screen.c
index c465a5683..0747e8ade 100644
--- a/src/map_preview_screen.c
+++ b/src/map_preview_screen.c
@@ -495,7 +495,7 @@ static void sub_80F83D0(u8 taskId)
}
break;
case 2:
- if (field_weather_is_fade_finished())
+ if (IsWeatherNotFadingIn())
{
Overworld_PlaySpecialMapMusic();
data[0]++;
diff --git a/src/menu.c b/src/menu.c
index b8a68145c..5a0da28b9 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -815,13 +815,13 @@ static s8 sub_81106F4(void)
MultichoiceGrid_MoveCursor(0, 1);
return MENU_NOTHING_CHOSEN;
}
- else if (JOY_REPT(DPAD_ANY) == DPAD_LEFT || sub_80BF66C() == 1)
+ else if (JOY_REPT(DPAD_ANY) == DPAD_LEFT || GetLRKeysPressedAndHeld() == 1)
{
PlaySE(SE_SELECT);
MultichoiceGrid_MoveCursor(-1, 0);
return MENU_NOTHING_CHOSEN;
}
- else if (JOY_REPT(DPAD_ANY) == DPAD_RIGHT || sub_80BF66C() == 2)
+ else if (JOY_REPT(DPAD_ANY) == DPAD_RIGHT || GetLRKeysPressedAndHeld() == 2)
{
PlaySE(SE_SELECT);
MultichoiceGrid_MoveCursor(1, 0);
@@ -857,13 +857,13 @@ static s8 sub_81107A0(void)
PlaySE(SE_SELECT);
return MENU_NOTHING_CHOSEN;
}
- else if (JOY_REPT(DPAD_ANY) == DPAD_LEFT || sub_80BF66C() == 1)
+ else if (JOY_REPT(DPAD_ANY) == DPAD_LEFT || GetLRKeysPressedAndHeld() == 1)
{
if (oldPos != MultichoiceGrid_MoveCursorIfValid(-1, 0))
PlaySE(SE_SELECT);
return MENU_NOTHING_CHOSEN;
}
- else if (JOY_REPT(DPAD_ANY) == DPAD_RIGHT || sub_80BF66C() == 2)
+ else if (JOY_REPT(DPAD_ANY) == DPAD_RIGHT || GetLRKeysPressedAndHeld() == 2)
{
if (oldPos != MultichoiceGrid_MoveCursorIfValid(1, 0))
PlaySE(SE_SELECT);
diff --git a/src/menu_helpers.c b/src/menu_helpers.c
index f17bff0d0..905e3c1ea 100644
--- a/src/menu_helpers.c
+++ b/src/menu_helpers.c
@@ -83,7 +83,7 @@ u8 GetLRKeysState(void)
return 0;
}
-u8 sub_80BF66C(void)
+u8 GetLRKeysPressedAndHeld(void)
{
if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR)
{
@@ -149,7 +149,7 @@ void SetVBlankHBlankCallbacksToNull(void)
SetHBlankCallback(NULL);
}
-void ClearVramOamPltt(void)
+void ResetVramOamAndBgCntRegs(void)
{
ResetAllBgsCoordinatesAndBgCntRegs();
CpuFill16(0, (void*) VRAM, VRAM_SIZE);
diff --git a/src/new_menu_helpers.c b/src/new_menu_helpers.c
index f879e6810..d2421ed9f 100644
--- a/src/new_menu_helpers.c
+++ b/src/new_menu_helpers.c
@@ -343,7 +343,7 @@ static u16 CopyDecompressedTileDataToVram(u8 bgId, const void *src, u16 size, u1
return LoadBgTilemap(bgId, src, size, offset);
}
-void SetBgRectPal(u8 bgId, u8 left, u8 top, u8 width, u8 height, u8 palette)
+void SetBgTilemapPalette(u8 bgId, u8 left, u8 top, u8 width, u8 height, u8 palette)
{
u8 i, j;
u16 *ptr = GetBgTilemapBuffer(bgId);
@@ -357,7 +357,7 @@ void SetBgRectPal(u8 bgId, u8 left, u8 top, u8 width, u8 height, u8 palette)
}
}
-void CopyRectIntoAltRect(u8 bgId, u16 *dest, u8 left, u8 top, u8 width, u8 height)
+void CopyToBufferFromBgTilemap(u8 bgId, u16 *dest, u8 left, u8 top, u8 width, u8 height)
{
u8 i,j;
const u16 *src = GetBgTilemapBuffer(bgId);
diff --git a/src/option_menu.c b/src/option_menu.c
index 35fe957be..5453dfa9e 100644
--- a/src/option_menu.c
+++ b/src/option_menu.c
@@ -206,7 +206,7 @@ void CB2_OptionsMenuFromStartMenu(void)
u8 i;
if (gMain.savedCallback == NULL)
- gMain.savedCallback = CB2_ReturnToStartMenu;
+ gMain.savedCallback = CB2_ReturnToFieldWithOpenMenu;
sOptionMenuPtr = AllocZeroed(sizeof(struct OptionMenu));
sOptionMenuPtr->state3 = 0;
sOptionMenuPtr->state2 = 0;
diff --git a/src/party_menu.c b/src/party_menu.c
new file mode 100644
index 000000000..399794b2d
--- /dev/null
+++ b/src/party_menu.c
@@ -0,0 +1,6381 @@
+#include "global.h"
+#include "malloc.h"
+#include "battle.h"
+#include "battle_anim.h"
+#include "battle_controllers.h"
+#include "battle_gfx_sfx_util.h"
+#include "battle_interface.h"
+#include "battle_tower.h"
+#include "berry_pouch.h"
+#include "bg.h"
+#include "data.h"
+#include "decompress.h"
+#include "easy_chat.h"
+#include "event_data.h"
+#include "evolution_scene.h"
+#include "field_control_avatar.h"
+#include "field_effect.h"
+#include "field_player_avatar.h"
+#include "field_screen_effect.h"
+#include "field_specials.h"
+#include "field_weather.h"
+#include "fieldmap.h"
+#include "fldeff.h"
+#include "gpu_regs.h"
+#include "graphics.h"
+#include "help_system.h"
+#include "item.h"
+#include "item_menu.h"
+#include "item_use.h"
+#include "link.h"
+#include "link_rfu.h"
+#include "load_save.h"
+#include "mail.h"
+#include "mail_data.h"
+#include "main.h"
+#include "menu.h"
+#include "menu_helpers.h"
+#include "new_menu_helpers.h"
+#include "metatile_behavior.h"
+#include "overworld.h"
+#include "palette.h"
+#include "party_menu.h"
+#include "player_pc.h"
+#include "pokedex.h"
+#include "pokemon.h"
+#include "pokemon_icon.h"
+#include "pokemon_jump.h"
+#include "pokemon_special_anim.h"
+#include "pokemon_storage_system.h"
+#include "pokemon_summary_screen.h"
+#include "quest_log.h"
+#include "region_map.h"
+#include "reshow_battle_screen.h"
+#include "scanline_effect.h"
+#include "script.h"
+#include "sound.h"
+#include "sprite.h"
+#include "start_menu.h"
+#include "string_util.h"
+#include "strings.h"
+#include "task.h"
+#include "teachy_tv.h"
+#include "text.h"
+#include "text_window.h"
+#include "tm_case.h"
+#include "trade.h"
+#include "union_room.h"
+#include "window.h"
+#include "constants/battle.h"
+#include "constants/easy_chat.h"
+#include "constants/field_effects.h"
+#include "constants/flags.h"
+#include "constants/item_effects.h"
+#include "constants/items.h"
+#include "constants/maps.h"
+#include "constants/moves.h"
+#include "constants/pokemon.h"
+#include "constants/songs.h"
+#include "constants/species.h"
+#include "constants/vars.h"
+
+#define PARTY_PAL_SELECTED (1 << 0)
+#define PARTY_PAL_FAINTED (1 << 1)
+#define PARTY_PAL_TO_SWITCH (1 << 2)
+#define PARTY_PAL_MULTI_ALT (1 << 3)
+#define PARTY_PAL_SWITCHING (1 << 4)
+#define PARTY_PAL_TO_SOFTBOIL (1 << 5)
+#define PARTY_PAL_NO_MON (1 << 6)
+#define PARTY_PAL_UNUSED (1 << 7)
+
+#define MENU_DIR_DOWN 1
+#define MENU_DIR_UP -1
+#define MENU_DIR_RIGHT 2
+#define MENU_DIR_LEFT -2
+
+enum
+{
+ CAN_LEARN_MOVE,
+ CANNOT_LEARN_MOVE,
+ ALREADY_KNOWS_MOVE,
+ CANNOT_LEARN_MOVE_IS_EGG
+};
+
+struct PartyMenuBoxInfoRects
+{
+ void (*blitFunc)(u8 windowId, u8 x, u8 y, u8 width, u8 height, bool8 isEgg);
+ u8 dimensions[24];
+ u8 descTextLeft;
+ u8 descTextTop;
+ u8 descTextWidth;
+ u8 descTextHeight;
+};
+
+struct PartyMenuInternal
+{
+ TaskFunc task;
+ MainCallback exitCallback;
+ u32 chooseHalf:1;
+ u32 lastSelectedSlot:3; // Used to return to same slot when going left/right bewtween columns
+ u32 spriteIdConfirmPokeball:7;
+ u32 spriteIdCancelPokeball:7;
+ u32 messageId:14;
+ u8 windowId[3];
+ u8 actions[8];
+ u8 numActions;
+ u16 palBuffer[BG_PLTT_SIZE / sizeof(u16)];
+ s16 data[16];
+};
+
+struct PartyMenuBox
+{
+ const struct PartyMenuBoxInfoRects *infoRects;
+ const u8 *spriteCoords;
+ u8 windowId;
+ u8 monSpriteId;
+ u8 itemSpriteId;
+ u8 pokeballSpriteId;
+ u8 statusSpriteId;
+};
+
+static void BlitBitmapToPartyWindow_LeftColumn(u8 windowId, u8 x, u8 y, u8 width, u8 height, bool8 isEgg);
+static void BlitBitmapToPartyWindow_RightColumn(u8 windowId, u8 x, u8 y, u8 width, u8 height, bool8 isEgg);
+static void CursorCB_Summary(u8 taskId);
+static void CursorCB_Switch(u8 taskId);
+static void CursorCB_Cancel1(u8 taskId);
+static void CursorCB_Item(u8 taskId);
+static void CursorCB_Give(u8 taskId);
+static void CursorCB_TakeItem(u8 taskId);
+static void CursorCB_Mail(u8 taskId);
+static void CursorCB_Read(u8 taskId);
+static void CursorCB_TakeMail(u8 taskId);
+static void CursorCB_Cancel2(u8 taskId);
+static void CursorCB_SendMon(u8 taskId);
+static void CursorCB_Enter(u8 taskId);
+static void CursorCB_NoEntry(u8 taskId);
+static void CursorCB_Store(u8 taskId);
+static void CursorCB_Register(u8 taskId);
+static void CursorCB_Trade1(u8 taskId);
+static void CursorCB_Trade2(u8 taskId);
+static void CursorCB_FieldMove(u8 taskId);
+static bool8 SetUpFieldMove_Fly(void);
+static bool8 SetUpFieldMove_Waterfall(void);
+static bool8 SetUpFieldMove_Surf(void);
+static void CB2_InitPartyMenu(void);
+static void ResetPartyMenu(void);
+static bool8 ShowPartyMenu(void);
+static void SetPartyMonsAllowedInMinigame(void);
+static void ExitPartyMenu(void);
+static bool8 CreatePartyMonSpritesLoop(void);
+static bool8 AllocPartyMenuBg(void);
+static bool8 AllocPartyMenuBgGfx(void);
+static void InitPartyMenuWindows(u8 layout);
+static void InitPartyMenuBoxes(u8 layout);
+static void LoadPartyMenuPokeballGfx(void);
+static void LoadPartyMenuAilmentGfx(void);
+static bool8 RenderPartyMenuBoxes(void);
+static void CreateCancelConfirmPokeballSprites(void);
+static void CreateCancelConfirmWindows(bool8 chooseHalf);
+static void Task_ExitPartyMenu(u8 taskId);
+static void FreePartyPointers(void);
+static void PartyPaletteBufferCopy(u8 offset);
+static void DisplayPartyPokemonDataForMultiBattle(u8 slot);
+static void DisplayPartyPokemonDataForChooseHalf(u8 slot);
+static bool8 DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(u8 slot);
+static void DisplayPartyPokemonData(u8 slot);
+static void DisplayPartyPokemonDataForWirelessMinigame(u8 slot);
+static void LoadPartyBoxPalette(struct PartyMenuBox *menuBox, u8 palFlags);
+static void DrawEmptySlot(u8 windowId);
+static void DisplayPartyPokemonNickname(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c);
+static void DisplayPartyPokemonLevelCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c);
+static void DisplayPartyPokemonGenderNidoranCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c);
+static void DisplayPartyPokemonHPCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c);
+static void DisplayPartyPokemonMaxHPCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c);
+static void DisplayPartyPokemonHPBarCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox);
+static void DisplayPartyPokemonDescriptionText(u8 stringId, struct PartyMenuBox *menuBox, u8 c);
+static bool8 GetBattleEntryEligibility(struct Pokemon *mon);
+static bool8 IsMonAllowedInMinigame(u8 slot);
+static void DisplayPartyPokemonDataToTeachMove(u8 slot, u16 item, u8 tutor);
+static u8 CanMonLearnTMTutor(struct Pokemon *mon, u16 item, u8 tutor);
+static void DisplayPartyPokemonBarDetail(u8 windowId, const u8 *str, u8 color, const u8 *align);
+static void DisplayPartyPokemonLevel(u8 level, struct PartyMenuBox *menuBox);
+static void DisplayPartyPokemonGender(u8 gender, u16 species, u8 *nickname, struct PartyMenuBox *menuBox);
+static void DisplayPartyPokemonHP(u16 hp, struct PartyMenuBox *menuBox);
+static void DisplayPartyPokemonMaxHP(u16 maxhp, struct PartyMenuBox *menuBox);
+static void DisplayPartyPokemonHPBar(u16 hp, u16 maxhp, struct PartyMenuBox *menuBox);
+static void CreatePartyMonIconSpriteParameterized(u16 species, u32 pid, struct PartyMenuBox *menuBox, u8 priority, bool32 handleDeoxys);
+static void CreatePartyMonHeldItemSpriteParameterized(u16 species, u16 item, struct PartyMenuBox *menuBox);
+static void CreatePartyMonPokeballSpriteParameterized(u16 species, struct PartyMenuBox *menuBox);
+static void CreatePartyMonStatusSpriteParameterized(u16 species, u8 status, struct PartyMenuBox *menuBox);
+static void CreatePartyMonIconSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox, u32 slot);
+static void CreatePartyMonHeldItemSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox);
+static void CreatePartyMonPokeballSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox);
+static void CreatePartyMonStatusSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox);
+static void CreateCancelConfirmPokeballSprites(void);
+static void DrawCancelConfirmButtons(void);
+static u8 CreatePokeballButtonSprite(u8 x, u8 y);
+static u8 CreateSmallPokeballButtonSprite(u8 x, u8 y);
+static u8 GetPartyBoxPaletteFlags(u8 slot, u8 animNum);
+static void AnimateSelectedPartyIcon(u8 spriteId, u8 animNum);
+static void PartyMenuStartSpriteAnim(u8 spriteId, u8 animNum);
+static void Task_ClosePartyMenuAndSetCB2(u8 taskId);
+static void UpdatePartyToFieldOrder(void);
+static s8 *GetCurrentPartySlotPtr(void);
+static u16 PartyMenuButtonHandler(s8 *slotPtr);
+static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr);
+static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr);
+static void MoveCursorToConfirm(void);
+static bool8 IsSelectedMonNotEgg(u8 *slotPtr);
+static void TryTutorSelectedMon(u8 taskId);
+static void TryGiveMailToSelectedMon(u8 taskId);
+static void SwitchSelectedMons(u8 taskId);
+static void TryEnterMonForMinigame(u8 taskId, u8 slot);
+static void Task_TryCreateSelectionWindow(u8 taskId);
+static void TryGiveItemOrMailToSelectedMon(u8 taskId);
+static void PartyMenuRemoveWindow(u8 *ptr);
+static void CB2_SetUpExitToBattleScreen(void);
+static void Task_ClosePartyMenuAfterText(u8 taskId);
+static void FinishTwoMonAction(u8 taskId);
+static void CancelParticipationPrompt(u8 taskId);
+static void DisplayCancelChooseMonYesNo(u8 taskId);
+static void Task_CancelChooseMonYesNo(u8 taskId);
+static void Task_HandleCancelChooseMonYesNoInput(u8 taskId);
+static void PartyMenuDisplayYesNoMenu(void);
+static void Task_ReturnToChooseMonAfterText(u8 taskId);
+static void UpdateCurrentPartySelection(s8 *slotPtr, s8 movementDir);
+static void UpdatePartySelectionSingleLayout(s8 *slotPtr, s8 movementDir);
+static void UpdatePartySelectionDoubleLayout(s8 *slotPtr, s8 movementDir);
+static s8 GetNewSlotDoubleLayout(s8 slotId, s8 movementDir);
+static void Task_PrintAndWaitForText(u8 taskId);
+static void PartyMenuPrintText(const u8 *text);
+static void sub_8124B60(struct Pokemon *mon, u16 item, u16 item2);
+static bool16 IsMonAllowedInPokemonJump(struct Pokemon *mon);
+static bool16 IsMonAllowedInDodrioBerryPicking(struct Pokemon *mon);
+static void Task_CancelParticipationYesNo(u8 taskId);
+static void Task_HandleCancelParticipationYesNoInput(u8 taskId);
+static void Task_TryCreateSelectionWindow(u8 taskId);
+static u16 GetTutorMove(u8 tutor);
+static bool8 CanLearnTutorMove(u16 species, u8 tutor);
+static void CreateSelectionWindow(void);
+static bool8 ShouldUseChooseMonText(void);
+static void UpdatePartyMonHPBar(u8 spriteId, struct Pokemon *mon);
+static void SpriteCB_UpdatePartyMonIcon(struct Sprite *sprite);
+static void SpriteCB_BouncePartyMonIcon(struct Sprite *sprite);
+static void SpriteCB_HeldItem(struct Sprite *sprite);
+static void UpdatePartyMonHeldItemSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox);
+static void ShowOrHideHeldItemSprite(u16 item, struct PartyMenuBox *menuBox);
+static void CreateHeldItemSpriteForTrade(u8 spriteId, bool8 isMail);
+static void SetPartyMonAilmentGfx(struct Pokemon *mon, struct PartyMenuBox *menuBox);
+static void UpdatePartyMonAilmentGfx(u8 status, struct PartyMenuBox *menuBox);
+static void SetPartyMonFieldSelectionActions(struct Pokemon *mons, u8 slotId);
+static u8 GetPartyMenuActionsTypeInBattle(struct Pokemon *mon);
+static u8 GetPartySlotEntryStatus(s8 slot);
+static void Task_HandleSelectionMenuInput(u8 taskId);
+static void CB2_ShowPokemonSummaryScreen(void);
+static void CB2_ReturnToPartyMenuFromSummaryScreen(void);
+static void UpdatePartyToBattleOrder(void);
+static void SlidePartyMenuBoxOneStep(u8 taskId);
+static void Task_SlideSelectedSlotsOffscreen(u8 taskId);
+static void SwitchPartyMon(void);
+static void Task_SlideSelectedSlotsOnscreen(u8 taskId);
+static void CB2_WriteMailToGiveMon(void);
+static void Task_SwitchHoldItemsPrompt(u8 taskId);
+static void Task_GiveHoldItem(u8 taskId);
+static void Task_UpdateHeldItemSprite(u8 taskId);
+static void Task_HandleSwitchItemsYesNoInput(u8 taskId);
+static void Task_SwitchItemsYesNo(u8 taskId);
+static void Task_WriteMailToGiveMonAfterText(u8 taskId);
+static void CB2_ReturnToPartyMenuFromWritingMail(void);
+static void CB2_ReturnToPartyMenuFromWritingMail(void);
+static void Task_DisplayGaveMailFromPartyMessage(u8 taskId);
+static void CB2_ReadHeldMail(void);
+static void CB2_ReturnToPartyMenuFromReadingMail(void);
+static void Task_SendMailToPCYesNo(u8 taskId);
+static void Task_HandleSendMailToPCYesNoInput(u8 taskId);
+static void Task_LoseMailMessageYesNo(u8 taskId);
+static void Task_HandleLoseMailMessageYesNoInput(u8 taskId);
+static bool8 TrySwitchInPokemon(void);
+static void DisplayCantUseFlashMessage(void);
+static void DisplayCantUseSurfMessage(void);
+static void Task_CancelAfterAorBPress(u8 taskId);
+static void DisplayFieldMoveExitAreaMessage(u8 taskId);
+static void Task_FieldMoveExitAreaYesNo(u8 taskId);
+static void Task_HandleFieldMoveExitAreaYesNoInput(u8 taskId);
+static void Task_FieldMoveWaitForFade(u8 taskId);
+static u16 GetFieldMoveMonSpecies(void);
+static u8 GetPartyLayoutFromBattleType(void);
+static void Task_SetSacredAshCB(u8 taskId);
+static void CB2_ReturnToBagMenu(void);
+static u8 GetPartyIdFromBattleSlot(u8 slot);
+static void Task_DisplayHPRestoredMessage(u8 taskId);
+static void SetSelectedMoveForPPItem(u8 taskId);
+static void ReturnToUseOnWhichMon(u8 taskId);
+static void TryUsePPItem(u8 taskId);
+static void ItemUseCB_LearnedMove(u8 taskId, UNUSED TaskFunc func);
+static void Task_LearnedMove(u8 taskId);
+static void Task_ReplaceMoveYesNo(u8 taskId);
+static void Task_DoLearnedMoveFanfareAfterText(u8 taskId);
+static void Task_TryLearningNextMove(u8 taskId);
+static void Task_LearnNextMoveOrClosePartyMenu(u8 taskId);
+static void Task_HandleReplaceMoveYesNoInput(u8 taskId);
+static void StopLearningMovePrompt(u8 taskId);
+static void Task_ShowSummaryScreenToForgetMove(u8 taskId);
+static void CB2_ShowSummaryScreenToForgetMove(void);
+static void CB2_ReturnToPartyMenuWhileLearningMove(void);
+static void Task_ReturnToPartyMenuWhileLearningMove(u8 taskId);
+static void DisplayPartyMenuForgotMoveMessage(u8 taskId);
+static void Task_PartyMenuReplaceMove(u8 taskId);
+static void Task_StopLearningMoveYesNo(u8 taskId);
+static void Task_HandleStopLearningMoveYesNoInput(u8 taskId);
+static void Task_TryLearningNextMoveAfterText(u8 taskId);
+static void ItemUseCB_RareCandyStep(u8 taskId, UNUSED TaskFunc func);
+static void Task_DisplayLevelUpStatsPg1(u8 taskId);
+static void Task_DisplayLevelUpStatsPg2(u8 taskId);
+static void UpdateMonDisplayInfoAfterRareCandy(u8 slot, struct Pokemon *mon);
+static void DisplayLevelUpStatsPg1(u8 taskId);
+static void DisplayLevelUpStatsPg2(u8 taskId);
+static void Task_TryLearnNewMoves(u8 taskId);
+static void PartyMenuTryEvolution(u8 taskId);
+static void DisplayMonNeedsToReplaceMove(u8 taskId);
+static void DisplayMonLearnedMove(u8 taskId, u16 move);
+static void Task_SacredAshDisplayHPRestored(u8 taskId);
+static void Task_SacredAshLoop(u8 taskId);
+static void UseSacredAsh(u8 taskId);
+static void CB2_ReturnToBerryPouchMenu(void);
+static void CB2_ReturnToTMCaseMenu(void);
+static void GiveItemOrMailToSelectedMon(u8 taskId);
+static void RemoveItemToGiveFromBag(u16 item);
+static void DisplayItemMustBeRemovedFirstMessage(u8 taskId);
+static void CB2_WriteMailToGiveMonFromBag(void);
+static void GiveItemToSelectedMon(u8 taskId);
+static void Task_UpdateHeldItemSpriteAndClosePartyMenu(u8 taskId);
+static void Task_SwitchItemsFromBagYesNo(u8 taskId);
+static void CB2_ReturnToPartyOrBagMenuFromWritingMail(void);
+static bool8 ReturnGiveItemToBagOrPC(u16 item);
+static void Task_DisplayGaveMailFromBagMessage(u8 taskId);
+static void Task_HandleSwitchItemsFromBagYesNoInput(u8 taskId);
+static void Task_ValidateChosenHalfParty(u8 taskId);
+static bool8 HasPartySlotAlreadyBeenSelected(u8 slot);
+static void Task_ContinueChoosingHalfParty(u8 taskId);
+static void BufferBattlePartyOrder(u8 *partyBattleOrder, u8 flankId);
+static void BufferBattlePartyOrderBySide(u8 *partyBattleOrder, u8 flankId, u8 battlerId);
+static void Task_InitMultiPartnerPartySlideIn(u8 taskId);
+static void Task_WaitAfterMultiPartnerPartySlideIn(u8 taskId);
+static void SlideMultiPartyMenuBoxSpritesOneStep(u8 taskId);
+static void Task_MultiPartnerPartySlideIn(u8 taskId);
+static bool8 CB2_FadeFromPartyMenu(void);
+static void Task_PartyMenuWaitForFade(u8 taskId);
+static void sub_8120C6C(u8 taskId);
+static void sub_8120CA8(u8 taskId);
+static void sub_8120CD8(u8 taskId);
+static void sub_8120D08(u8 taskId);
+static void sub_8120D40(u8 taskId);
+static void sub_8120D7C(u8 taskId);
+static void sub_8120DAC(u8 taskId);
+static void sub_8120DE0(u8 taskId);
+static void sub_8120E1C(u8 taskId);
+static void sub_8120E58(u8 taskId);
+static void sub_8120EE0(u8 taskId);
+static void sub_8120FF0(u8 taskId);
+static bool8 sub_8120F78(u8 taskId);
+static void sub_8120FB0(void);
+static void sub_8122084(u8 windowId, const u8 *str);
+static u8 sub_81220D4(void);
+static void sub_8122110(u8 windowId);
+static void sub_812358C(void);
+static void sub_8124BB0(struct Pokemon *mon, u8 fieldMove);
+static void sub_8124DE0(void);
+static void sub_8124E48(void);
+static void sub_812580C(u8 taskId);
+static void sub_8125898(u8 taskId, UNUSED TaskFunc func);
+static void sub_8125F4C(u8 taskId, UNUSED TaskFunc func);
+static void sub_8125F5C(u8 taskId);
+static void sub_8126BD4(void);
+static bool8 sub_8126C24(void);
+
+static EWRAM_DATA struct PartyMenuInternal *sPartyMenuInternal = NULL;
+EWRAM_DATA struct PartyMenu gPartyMenu = {0};
+static EWRAM_DATA struct PartyMenuBox *sPartyMenuBoxes = NULL;
+static EWRAM_DATA u8 *sPartyBgGfxTilemap = NULL;
+static EWRAM_DATA u8 *sPartyBgTilemapBuffer = NULL;
+EWRAM_DATA bool8 gPartyMenuUseExitCallback = FALSE;
+EWRAM_DATA u8 gSelectedMonPartyId = 0;
+EWRAM_DATA MainCallback gPostMenuFieldCallback = NULL;
+static EWRAM_DATA u16 *sSlot1TilemapBuffer = NULL; // for switching party slots
+static EWRAM_DATA u16 *sSlot2TilemapBuffer = NULL;
+static EWRAM_DATA struct Pokemon *sSacredAshQuestLogMonBackup = NULL;
+EWRAM_DATA u8 gSelectedOrderFromParty[3] = {0};
+static EWRAM_DATA u16 sPartyMenuItemId = ITEM_NONE;
+ALIGNED(4) EWRAM_DATA u8 gBattlePartyCurrentOrder[PARTY_SIZE / 2] = {0}; // bits 0-3 are the current pos of Slot 1, 4-7 are Slot 2, and so on
+
+void (*gItemUseCB)(u8, TaskFunc);
+
+#include "data/pokemon/tutor_learnsets.h"
+#include "data/party_menu.h"
+
+void InitPartyMenu(u8 menuType, u8 layout, u8 partyAction, bool8 keepCursorPos, u8 messageId, TaskFunc task, MainCallback callback)
+{
+ u16 i;
+
+ ResetPartyMenu();
+ sPartyMenuInternal = Alloc(sizeof(struct PartyMenuInternal));
+ if (sPartyMenuInternal == NULL)
+ {
+ SetMainCallback2(callback);
+ }
+ else
+ {
+ gPartyMenu.menuType = menuType;
+ gPartyMenu.exitCallback = callback;
+ gPartyMenu.action = partyAction;
+ sPartyMenuInternal->messageId = messageId;
+ sPartyMenuInternal->task = task;
+ sPartyMenuInternal->exitCallback = NULL;
+ sPartyMenuInternal->lastSelectedSlot = 0;
+ if (menuType == PARTY_MENU_TYPE_CHOOSE_HALF)
+ sPartyMenuInternal->chooseHalf = TRUE;
+ else
+ sPartyMenuInternal->chooseHalf = FALSE;
+ if (layout != KEEP_PARTY_LAYOUT)
+ gPartyMenu.layout = layout;
+ for (i = 0; i < NELEMS(sPartyMenuInternal->data); ++i)
+ sPartyMenuInternal->data[i] = 0;
+ for (i = 0; i < NELEMS(sPartyMenuInternal->windowId); ++i)
+ sPartyMenuInternal->windowId[i] = 0xFF;
+ if (!keepCursorPos)
+ gPartyMenu.slotId = 0;
+ else if (gPartyMenu.slotId > PARTY_SIZE - 1 || GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES) == SPECIES_NONE)
+ gPartyMenu.slotId = 0;
+ gTextFlags.autoScroll = FALSE;
+ CalculatePlayerPartyCount();
+ SetMainCallback2(CB2_InitPartyMenu);
+ }
+}
+
+static void CB2_UpdatePartyMenu(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ DoScheduledBgTilemapCopiesToVram();
+ UpdatePaletteFade();
+}
+
+static void VBlankCB_PartyMenu(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void CB2_InitPartyMenu(void)
+{
+ while (TRUE)
+ {
+ if (sub_80BF748() == TRUE || ShowPartyMenu() == TRUE || MenuHelpers_LinkSomething() == TRUE)
+ break;
+ }
+}
+
+static bool8 ShowPartyMenu(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetVBlankHBlankCallbacksToNull();
+ ResetVramOamAndBgCntRegs();
+ ClearScheduledBgCopiesToVram();
+ ++gMain.state;
+ break;
+ case 1:
+ ScanlineEffect_Stop();
+ ++gMain.state;
+ break;
+ case 2:
+ ResetPaletteFade();
+ gPaletteFade.bufferTransferDisabled = TRUE;
+ ++gMain.state;
+ break;
+ case 3:
+ ResetSpriteData();
+ ++gMain.state;
+ break;
+ case 4:
+ FreeAllSpritePalettes();
+ ++gMain.state;
+ break;
+ case 5:
+ if (!MenuHelpers_LinkSomething())
+ ResetTasks();
+ ++gMain.state;
+ break;
+ case 6:
+ SetPartyMonsAllowedInMinigame();
+ ++gMain.state;
+ break;
+ case 7:
+ if (!AllocPartyMenuBg())
+ {
+ ExitPartyMenu();
+ return TRUE;
+ }
+ else
+ {
+ sPartyMenuInternal->data[0] = 0;
+ ++gMain.state;
+ }
+ break;
+ case 8:
+ if (AllocPartyMenuBgGfx())
+ ++gMain.state;
+ break;
+ case 9:
+ InitPartyMenuWindows(gPartyMenu.layout);
+ ++gMain.state;
+ break;
+ case 10:
+ InitPartyMenuBoxes(gPartyMenu.layout);
+ sPartyMenuInternal->data[0] = 0;
+ ++gMain.state;
+ break;
+ case 11:
+ LoadHeldItemIcons();
+ ++gMain.state;
+ break;
+ case 12:
+ LoadPartyMenuPokeballGfx();
+ ++gMain.state;
+ break;
+ case 13:
+ LoadPartyMenuAilmentGfx();
+ ++gMain.state;
+ break;
+ case 14:
+ LoadMonIconPalettes();
+ ++gMain.state;
+ break;
+ case 15:
+ if (CreatePartyMonSpritesLoop())
+ {
+ sPartyMenuInternal->data[0] = 0;
+ ++gMain.state;
+ }
+ break;
+ case 16:
+ if (RenderPartyMenuBoxes())
+ {
+ sPartyMenuInternal->data[0] = 0;
+ ++gMain.state;
+ }
+ break;
+ case 17:
+ CreateCancelConfirmPokeballSprites();
+ ++gMain.state;
+ break;
+ case 18:
+ CreateCancelConfirmWindows(sPartyMenuInternal->chooseHalf);
+ ++gMain.state;
+ break;
+ case 19:
+ HelpSystem_SetSomeVariable2(5);
+ ++gMain.state;
+ break;
+ case 20:
+ CreateTask(sPartyMenuInternal->task, 0);
+ DisplayPartyMenuStdMessage(sPartyMenuInternal->messageId);
+ ++gMain.state;
+ break;
+ case 21:
+ BlendPalettes(0xFFFFFFFF, 16, RGB_BLACK);
+ ++gMain.state;
+ break;
+ case 22:
+ BeginNormalPaletteFade(0xFFFFFFFF, -2, 16, 0, RGB_BLACK);
+ gPaletteFade.bufferTransferDisabled = FALSE;
+ ++gMain.state;
+ break;
+ default:
+ SetVBlankCallback(VBlankCB_PartyMenu);
+ SetMainCallback2(CB2_UpdatePartyMenu);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void ExitPartyMenu(void)
+{
+ BeginNormalPaletteFade(0xFFFFFFFF, -2, 0, 16, RGB_BLACK);
+ CreateTask(Task_ExitPartyMenu, 0);
+ SetVBlankCallback(VBlankCB_PartyMenu);
+ SetMainCallback2(CB2_UpdatePartyMenu);
+}
+
+static void Task_ExitPartyMenu(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(gPartyMenu.exitCallback);
+ FreePartyPointers();
+ DestroyTask(taskId);
+ }
+}
+
+static void ResetPartyMenu(void)
+{
+ sPartyMenuInternal = NULL;
+ sPartyBgTilemapBuffer = NULL;
+ sPartyMenuBoxes = NULL;
+ sPartyBgGfxTilemap = NULL;
+}
+
+static bool8 AllocPartyMenuBg(void)
+{
+ ResetAllBgsCoordinatesAndBgCntRegs();
+ sPartyBgTilemapBuffer = Alloc(0x800);
+ if (sPartyBgTilemapBuffer == NULL)
+ return FALSE;
+ memset(sPartyBgTilemapBuffer, 0, 0x800);
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sPartyMenuBgTemplates, NELEMS(sPartyMenuBgTemplates));
+ SetBgTilemapBuffer(1, sPartyBgTilemapBuffer);
+ ScheduleBgCopyTilemapToVram(1);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ return TRUE;
+}
+
+static bool8 AllocPartyMenuBgGfx(void)
+{
+ u32 sizeout;
+
+ switch (sPartyMenuInternal->data[0])
+ {
+ case 0:
+ sPartyBgGfxTilemap = MallocAndDecompress(gPartyMenuBg_Gfx, &sizeout);
+ LoadBgTiles(1, sPartyBgGfxTilemap, sizeout, 0);
+ ++sPartyMenuInternal->data[0];
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ LZDecompressWram(gPartyMenuBg_Tilemap, sPartyBgTilemapBuffer);
+ ++sPartyMenuInternal->data[0];
+ }
+ break;
+ case 2:
+ LoadCompressedPalette(gPartyMenuBg_Pal, 0, 0x160);
+ CpuCopy16(gPlttBufferUnfaded, sPartyMenuInternal->palBuffer, 0x160);
+ ++sPartyMenuInternal->data[0];
+ break;
+ case 3:
+ PartyPaletteBufferCopy(4);
+ ++sPartyMenuInternal->data[0];
+ break;
+ case 4:
+ PartyPaletteBufferCopy(5);
+ ++sPartyMenuInternal->data[0];
+ break;
+ case 5:
+ PartyPaletteBufferCopy(6);
+ ++sPartyMenuInternal->data[0];
+ break;
+ case 6:
+ PartyPaletteBufferCopy(7);
+ ++sPartyMenuInternal->data[0];
+ break;
+ case 7:
+ PartyPaletteBufferCopy(8);
+ ++sPartyMenuInternal->data[0];
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void PartyPaletteBufferCopy(u8 offset)
+{
+ offset *= 16;
+ CpuCopy16(&gPlttBufferUnfaded[0x30], &gPlttBufferUnfaded[offset], 32);
+ CpuCopy16(&gPlttBufferUnfaded[0x30], &gPlttBufferFaded[offset], 32);
+}
+
+static void FreePartyPointers(void)
+{
+ if (sPartyMenuInternal)
+ Free(sPartyMenuInternal);
+ if (sPartyBgTilemapBuffer)
+ Free(sPartyBgTilemapBuffer);
+ if (sPartyBgGfxTilemap)
+ Free(sPartyBgGfxTilemap);
+ if (sPartyMenuBoxes)
+ Free(sPartyMenuBoxes);
+ FreeAllWindowBuffers();
+}
+
+static void InitPartyMenuBoxes(u8 layout)
+{
+ u8 i;
+
+ sPartyMenuBoxes = Alloc(sizeof(struct PartyMenuBox[PARTY_SIZE]));
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ sPartyMenuBoxes[i].infoRects = &sPartyBoxInfoRects[PARTY_BOX_RIGHT_COLUMN];
+ sPartyMenuBoxes[i].spriteCoords = sPartyMenuSpriteCoords[layout][i];
+ sPartyMenuBoxes[i].windowId = i;
+ }
+ // The first party mon goes in the left column
+ sPartyMenuBoxes[0].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN];
+ if (layout == PARTY_LAYOUT_MULTI_SHOWCASE)
+ sPartyMenuBoxes[3].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN];
+ else if (layout != PARTY_LAYOUT_SINGLE)
+ sPartyMenuBoxes[1].infoRects = &sPartyBoxInfoRects[PARTY_BOX_LEFT_COLUMN];
+}
+
+static void RenderPartyMenuBox(u8 slot)
+{
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE && slot >= MULTI_PARTY_SIZE)
+ {
+ DisplayPartyPokemonDataForMultiBattle(slot);
+ LoadPartyBoxPalette(&sPartyMenuBoxes[slot], PARTY_PAL_MULTI_ALT);
+ CopyWindowToVram(sPartyMenuBoxes[slot].windowId, 2);
+ PutWindowTilemap(sPartyMenuBoxes[slot].windowId);
+ ScheduleBgCopyTilemapToVram(2);
+ }
+ else
+ {
+ if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) == SPECIES_NONE)
+ {
+ DrawEmptySlot(sPartyMenuBoxes[slot].windowId);
+ CopyWindowToVram(sPartyMenuBoxes[slot].windowId, 2);
+ }
+ else
+ {
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_CHOOSE_HALF)
+ DisplayPartyPokemonDataForChooseHalf(slot);
+ else if (gPartyMenu.menuType == PARTY_MENU_TYPE_MINIGAME)
+ DisplayPartyPokemonDataForWirelessMinigame(slot);
+ else if (!DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(slot))
+ DisplayPartyPokemonData(slot);
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE)
+ AnimatePartySlot(slot, 0);
+ else if (gPartyMenu.slotId == slot)
+ AnimatePartySlot(slot, 1);
+ else
+ AnimatePartySlot(slot, 0);
+ }
+ PutWindowTilemap(sPartyMenuBoxes[slot].windowId);
+ ScheduleBgCopyTilemapToVram(0);
+ }
+}
+
+static void DisplayPartyPokemonData(u8 slot)
+{
+ if (GetMonData(&gPlayerParty[slot], MON_DATA_IS_EGG))
+ {
+ sPartyMenuBoxes[slot].infoRects->blitFunc(sPartyMenuBoxes[slot].windowId, 0, 0, 0, 0, TRUE);
+ DisplayPartyPokemonNickname(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
+ }
+ else
+ {
+ sPartyMenuBoxes[slot].infoRects->blitFunc(sPartyMenuBoxes[slot].windowId, 0, 0, 0, 0, FALSE);
+ DisplayPartyPokemonNickname(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
+ DisplayPartyPokemonLevelCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
+ DisplayPartyPokemonGenderNidoranCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
+ DisplayPartyPokemonHPCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
+ DisplayPartyPokemonMaxHPCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot], 0);
+ DisplayPartyPokemonHPBarCheck(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
+ }
+}
+
+static void DisplayPartyPokemonDescriptionData(u8 slot, u8 stringId)
+{
+ struct Pokemon *mon = &gPlayerParty[slot];
+
+ sPartyMenuBoxes[slot].infoRects->blitFunc(sPartyMenuBoxes[slot].windowId, 0, 0, 0, 0, TRUE);
+ DisplayPartyPokemonNickname(mon, &sPartyMenuBoxes[slot], 0);
+ if (!GetMonData(mon, MON_DATA_IS_EGG))
+ {
+ DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[slot], 0);
+ DisplayPartyPokemonGenderNidoranCheck(mon, &sPartyMenuBoxes[slot], 0);
+ }
+ DisplayPartyPokemonDescriptionText(stringId, &sPartyMenuBoxes[slot], 0);
+}
+
+static void DisplayPartyPokemonDataForChooseHalf(u8 slot)
+{
+ u8 i;
+ struct Pokemon *mon = &gPlayerParty[slot];
+ u8 *order = gSelectedOrderFromParty;
+ u8 maxBattlers;
+
+ if (!GetBattleEntryEligibility(mon))
+ {
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE);
+ }
+ else
+ {
+ if (gPartyMenu.unk_8_6 == 2)
+ maxBattlers = 2;
+ else
+ maxBattlers = 3;
+ for (i = 0; i < maxBattlers; ++i)
+ {
+ if (order[i] != 0 && (order[i] - 1) == slot)
+ {
+ DisplayPartyPokemonDescriptionData(slot, i + PARTYBOX_DESC_FIRST);
+ return;
+ }
+ }
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE_3);
+ }
+}
+
+static void DisplayPartyPokemonDataForWirelessMinigame(u8 slot)
+{
+ if (IsMonAllowedInMinigame(slot) == TRUE)
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE);
+ else
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE);
+}
+
+// Returns TRUE if teaching move or cant evolve with item (i.e. description data is shown), FALSE otherwise
+static bool8 DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(u8 slot)
+{
+ struct Pokemon *currentPokemon = &gPlayerParty[slot];
+ u16 item = gSpecialVar_ItemId;
+
+ if (gPartyMenu.action == PARTY_ACTION_MOVE_TUTOR)
+ {
+ gSpecialVar_Result = FALSE;
+ if (gSpecialVar_0x8005 > 14)
+ return FALSE;
+ DisplayPartyPokemonDataToTeachMove(slot, 0, gSpecialVar_0x8005);
+ }
+ else
+ {
+ if (gPartyMenu.action != PARTY_ACTION_USE_ITEM)
+ return FALSE;
+ switch (CheckIfItemIsTMHMOrEvolutionStone(item))
+ {
+ default:
+ return FALSE;
+ case 1: // TM/HM
+ DisplayPartyPokemonDataToTeachMove(slot, item, 0);
+ break;
+ case 2: // Evolution stone
+ if (!GetMonData(currentPokemon, MON_DATA_IS_EGG) && GetEvolutionTargetSpecies(currentPokemon, 3, item) != SPECIES_NONE)
+ return FALSE;
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NO_USE);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+static void DisplayPartyPokemonDataToTeachMove(u8 slot, u16 item, u8 tutor)
+{
+ switch (CanMonLearnTMTutor(&gPlayerParty[slot], item, tutor))
+ {
+ case CANNOT_LEARN_MOVE:
+ case CANNOT_LEARN_MOVE_IS_EGG:
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NOT_ABLE_2);
+ break;
+ case ALREADY_KNOWS_MOVE:
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_LEARNED);
+ break;
+ default:
+ DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_ABLE_2);
+ break;
+ }
+}
+
+static void DisplayPartyPokemonDataForMultiBattle(u8 slot)
+{
+ struct PartyMenuBox *menuBox = &sPartyMenuBoxes[slot];
+ u8 actualSlot = slot - (3);
+
+ if (gMultiPartnerParty[actualSlot].species == SPECIES_NONE)
+ {
+ DrawEmptySlot(menuBox->windowId);
+ }
+ else
+ {
+ menuBox->infoRects->blitFunc(menuBox->windowId, 0, 0, 0, 0, FALSE);
+ StringCopy(gStringVar1, gMultiPartnerParty[actualSlot].nickname);
+ StringGetEnd10(gStringVar1);
+ if (StringLength(gStringVar1) <= 5)
+ ConvertInternationalString(gStringVar1, 1);
+ DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, menuBox->infoRects->dimensions);
+ DisplayPartyPokemonLevel(gMultiPartnerParty[actualSlot].level, menuBox);
+ DisplayPartyPokemonGender(gMultiPartnerParty[actualSlot].gender, gMultiPartnerParty[actualSlot].species, gMultiPartnerParty[actualSlot].nickname, menuBox);
+ DisplayPartyPokemonHP(gMultiPartnerParty[actualSlot].hp, menuBox);
+ DisplayPartyPokemonMaxHP(gMultiPartnerParty[actualSlot].maxhp, menuBox);
+ DisplayPartyPokemonHPBar(gMultiPartnerParty[actualSlot].hp, gMultiPartnerParty[actualSlot].maxhp, menuBox);
+ }
+}
+
+static bool8 RenderPartyMenuBoxes(void)
+{
+ RenderPartyMenuBox(sPartyMenuInternal->data[0]);
+ if (++sPartyMenuInternal->data[0] == PARTY_SIZE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static u8 *GetPartyMenuBgTile(u16 tileId)
+{
+ return &sPartyBgGfxTilemap[tileId << 5];
+}
+
+static void CreatePartyMonSprites(u8 slot)
+{
+ u8 actualSlot;
+
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE && slot >= MULTI_PARTY_SIZE)
+ {
+ u8 status;
+
+ actualSlot = slot - MULTI_PARTY_SIZE;
+ if (gMultiPartnerParty[actualSlot].species != SPECIES_NONE)
+ {
+ CreatePartyMonIconSpriteParameterized(gMultiPartnerParty[actualSlot].species, gMultiPartnerParty[actualSlot].personality, &sPartyMenuBoxes[slot], 0, FALSE);
+ CreatePartyMonHeldItemSpriteParameterized(gMultiPartnerParty[actualSlot].species, gMultiPartnerParty[actualSlot].heldItem, &sPartyMenuBoxes[slot]);
+ CreatePartyMonPokeballSpriteParameterized(gMultiPartnerParty[actualSlot].species, &sPartyMenuBoxes[slot]);
+ if (gMultiPartnerParty[actualSlot].hp == 0)
+ status = AILMENT_FNT;
+ else
+ status = GetAilmentFromStatus(gMultiPartnerParty[actualSlot].status);
+ CreatePartyMonStatusSpriteParameterized(gMultiPartnerParty[actualSlot].species, status, &sPartyMenuBoxes[slot]);
+ }
+ }
+ else if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ CreatePartyMonIconSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot], slot);
+ CreatePartyMonHeldItemSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
+ CreatePartyMonPokeballSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
+ CreatePartyMonStatusSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
+ }
+}
+
+static bool8 CreatePartyMonSpritesLoop(void)
+{
+ CreatePartyMonSprites(sPartyMenuInternal->data[0]);
+ if (++sPartyMenuInternal->data[0] == PARTY_SIZE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void CreateCancelConfirmPokeballSprites(void)
+{
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_MULTI_SHOWCASE)
+ {
+ // The showcase has no Cancel/Confirm buttons
+ FillBgTilemapBufferRect(1, 14, 23, 17, 7, 2, 1);
+ }
+ else
+ {
+ if (sPartyMenuInternal->chooseHalf)
+ {
+ sPartyMenuInternal->spriteIdConfirmPokeball = CreateSmallPokeballButtonSprite(0xBF, 0x88);
+ DrawCancelConfirmButtons();
+ sPartyMenuInternal->spriteIdCancelPokeball = CreateSmallPokeballButtonSprite(0xBF, 0x98);
+ }
+ else
+ {
+ sPartyMenuInternal->spriteIdCancelPokeball = CreatePokeballButtonSprite(198, 148);
+ }
+ AnimatePartySlot(gPartyMenu.slotId, 1);
+ }
+}
+
+void AnimatePartySlot(u8 slot, u8 animNum)
+{
+ u8 spriteId;
+
+ switch (slot)
+ {
+ default:
+ if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ LoadPartyBoxPalette(&sPartyMenuBoxes[slot], GetPartyBoxPaletteFlags(slot, animNum));
+ AnimateSelectedPartyIcon(sPartyMenuBoxes[slot].monSpriteId, animNum);
+ PartyMenuStartSpriteAnim(sPartyMenuBoxes[slot].pokeballSpriteId, animNum);
+ }
+ return;
+ case PARTY_SIZE: // Confirm
+ if (animNum == 0)
+ SetBgTilemapPalette(1, 23, 16, 7, 2, 1);
+ else
+ SetBgTilemapPalette(1, 23, 16, 7, 2, 2);
+ spriteId = sPartyMenuInternal->spriteIdConfirmPokeball;
+ break;
+ case PARTY_SIZE + 1: // Cancel
+ // The position of the Cancel button changes if Confirm is present
+ if (!sPartyMenuInternal->chooseHalf)
+ {
+ if (animNum == 0)
+ SetBgTilemapPalette(1, 23, 17, 7, 2, 1);
+ else
+ SetBgTilemapPalette(1, 23, 17, 7, 2, 2);
+ }
+ else if (animNum == 0)
+ {
+ SetBgTilemapPalette(1, 23, 18, 7, 2, 1);
+ }
+ else
+ {
+ SetBgTilemapPalette(1, 23, 18, 7, 2, 2);
+ }
+ spriteId = sPartyMenuInternal->spriteIdCancelPokeball;
+ break;
+ }
+ PartyMenuStartSpriteAnim(spriteId, animNum);
+ ScheduleBgCopyTilemapToVram(1);
+}
+
+static u8 GetPartyBoxPaletteFlags(u8 slot, u8 animNum)
+{
+ u8 palFlags = 0;
+
+ if (animNum == 1)
+ palFlags |= PARTY_PAL_SELECTED;
+ if (GetMonData(&gPlayerParty[slot], MON_DATA_HP) == 0)
+ palFlags |= PARTY_PAL_FAINTED;
+ if (gPartyMenu.layout == PARTY_LAYOUT_MULTI
+ && (slot == 1 || slot == 4 || slot == 5))
+ palFlags |= PARTY_PAL_MULTI_ALT;
+ if (gPartyMenu.action == PARTY_ACTION_SWITCHING)
+ palFlags |= PARTY_PAL_SWITCHING;
+ if (gPartyMenu.action == PARTY_ACTION_SWITCH)
+ {
+ if (slot == gPartyMenu.slotId || slot == gPartyMenu.slotId2)
+ palFlags |= PARTY_PAL_TO_SWITCH;
+ }
+ if (gPartyMenu.action == PARTY_ACTION_SOFTBOILED && slot == gPartyMenu.slotId )
+ palFlags |= PARTY_PAL_TO_SOFTBOIL;
+ return palFlags;
+}
+
+static void DrawCancelConfirmButtons(void)
+{
+ CopyToBgTilemapBufferRect_ChangePalette(1, sConfirmButton_Tilemap, 23, 16, 7, 2, 17);
+ CopyToBgTilemapBufferRect_ChangePalette(1, sCancelButton_Tilemap, 23, 18, 7, 2, 17);
+ ScheduleBgCopyTilemapToVram(1);
+}
+
+bool8 IsMultiBattle(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattleTypeFlags & BATTLE_TYPE_TRAINER && gBattleTypeFlags & BATTLE_TYPE_LINK)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void SwapPartyPokemon(struct Pokemon *mon1, struct Pokemon *mon2)
+{
+ struct Pokemon *buffer = Alloc(sizeof(struct Pokemon));
+
+ *buffer = *mon1;
+ *mon1 = *mon2;
+ *mon2 = *buffer;
+ Free(buffer);
+}
+
+static void Task_ClosePartyMenu(u8 taskId)
+{
+ BeginNormalPaletteFade(0xFFFFFFFF, -2, 0, 16, RGB_BLACK);
+ gTasks[taskId].func = Task_ClosePartyMenuAndSetCB2;
+}
+
+static void Task_ClosePartyMenuAndSetCB2(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
+ UpdatePartyToFieldOrder();
+ if (sPartyMenuInternal->exitCallback != NULL)
+ SetMainCallback2(sPartyMenuInternal->exitCallback);
+ else
+ SetMainCallback2(gPartyMenu.exitCallback);
+ FreePartyPointers();
+ DestroyTask(taskId);
+ }
+}
+
+u8 GetCursorSelectionMonId(void)
+{
+ return gPartyMenu.slotId;
+}
+
+u8 GetPartyMenuType(void)
+{
+ return gPartyMenu.menuType;
+}
+
+void Task_HandleChooseMonInput(u8 taskId)
+{
+ if (!gPaletteFade.active && sub_80BF748() != TRUE)
+ {
+ s8 *slotPtr = GetCurrentPartySlotPtr();
+
+ switch (PartyMenuButtonHandler(slotPtr))
+ {
+ case 1: // Selected mon
+ HandleChooseMonSelection(taskId, slotPtr);
+ break;
+ case 2: // Selected Cancel
+ HandleChooseMonCancel(taskId, slotPtr);
+ break;
+ case 8: // Start button
+ if (sPartyMenuInternal->chooseHalf)
+ {
+ PlaySE(SE_SELECT);
+ MoveCursorToConfirm();
+ }
+ break;
+ }
+ }
+}
+
+static s8 *GetCurrentPartySlotPtr(void)
+{
+ if (gPartyMenu.action == PARTY_ACTION_SWITCH || gPartyMenu.action == PARTY_ACTION_SOFTBOILED)
+ return &gPartyMenu.slotId2;
+ else
+ return &gPartyMenu.slotId;
+}
+
+static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr)
+{
+ if (*slotPtr == PARTY_SIZE)
+ {
+ gPartyMenu.task(taskId);
+ }
+ else
+ {
+ switch (gPartyMenu.action)
+ {
+ case PARTY_ACTION_SOFTBOILED:
+ if (IsSelectedMonNotEgg((u8 *)slotPtr))
+ Task_TryUseSoftboiledOnPartyMon(taskId);
+ break;
+ case PARTY_ACTION_USE_ITEM:
+ if (IsSelectedMonNotEgg((u8 *)slotPtr))
+ {
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
+ sPartyMenuInternal->exitCallback = CB2_SetUpExitToBattleScreen;
+ gItemUseCB(taskId, Task_ClosePartyMenuAfterText);
+ }
+ break;
+ case PARTY_ACTION_MOVE_TUTOR:
+ if (IsSelectedMonNotEgg((u8 *)slotPtr))
+ {
+ PlaySE(SE_SELECT);
+ TryTutorSelectedMon(taskId);
+ }
+ break;
+ case PARTY_ACTION_GIVE_MAILBOX_MAIL:
+ if (IsSelectedMonNotEgg((u8 *)slotPtr))
+ {
+ PlaySE(SE_SELECT);
+ TryGiveMailToSelectedMon(taskId);
+ }
+ break;
+ case PARTY_ACTION_GIVE_ITEM:
+ case PARTY_ACTION_GIVE_PC_ITEM:
+ if (IsSelectedMonNotEgg((u8 *)slotPtr))
+ {
+ PlaySE(SE_SELECT);
+ TryGiveItemOrMailToSelectedMon(taskId);
+ }
+ break;
+ case PARTY_ACTION_SWITCH:
+ PlaySE(SE_SELECT);
+ SwitchSelectedMons(taskId);
+ break;
+ case PARTY_ACTION_CHOOSE_AND_CLOSE:
+ PlaySE(SE_SELECT);
+ gSpecialVar_0x8004 = *slotPtr;
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_MOVE_RELEARNER)
+ gSpecialVar_0x8005 = GetNumberOfRelearnableMoves(&gPlayerParty[*slotPtr]);
+ Task_ClosePartyMenu(taskId);
+ break;
+ case PARTY_ACTION_MINIGAME:
+ if (IsSelectedMonNotEgg((u8 *)slotPtr))
+ TryEnterMonForMinigame(taskId, (u8)*slotPtr);
+ break;
+ default:
+ case PARTY_ACTION_ABILITY_PREVENTS:
+ case PARTY_ACTION_SWITCHING:
+ PlaySE(SE_SELECT);
+ Task_TryCreateSelectionWindow(taskId);
+ break;
+ }
+ }
+}
+
+static bool8 IsSelectedMonNotEgg(u8 *slotPtr)
+{
+ if (GetMonData(&gPlayerParty[*slotPtr], MON_DATA_IS_EGG) == TRUE)
+ {
+ PlaySE(SE_HAZURE);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void HandleChooseMonCancel(u8 taskId, s8 *slotPtr)
+{
+ switch (gPartyMenu.action)
+ {
+ case PARTY_ACTION_SEND_OUT:
+ PlaySE(SE_HAZURE);
+ break;
+ case PARTY_ACTION_SWITCH:
+ case PARTY_ACTION_SOFTBOILED:
+ PlaySE(SE_SELECT);
+ FinishTwoMonAction(taskId);
+ break;
+ case PARTY_ACTION_MINIGAME:
+ PlaySE(SE_SELECT);
+ CancelParticipationPrompt(taskId);
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_CHOOSE_HALF)
+ {
+ DisplayCancelChooseMonYesNo(taskId);
+ }
+ else
+ {
+ if (!MenuHelpers_LinkSomething())
+ gSpecialVar_0x8004 = PARTY_SIZE + 1;
+ gPartyMenuUseExitCallback = FALSE;
+ *slotPtr = PARTY_SIZE + 1;
+ Task_ClosePartyMenu(taskId);
+ }
+ break;
+ }
+}
+
+static void DisplayCancelChooseMonYesNo(u8 taskId)
+{
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ StringExpandPlaceholders(gStringVar4, gUnknown_84176CF);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ gTasks[taskId].func = Task_CancelChooseMonYesNo;
+}
+
+static void Task_CancelChooseMonYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleCancelChooseMonYesNoInput;
+ }
+}
+
+static void Task_HandleCancelChooseMonYesNoInput(u8 taskId)
+{
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ gPartyMenuUseExitCallback = FALSE;
+ gPartyMenu.slotId = PARTY_SIZE + 1;
+ ClearSelectedPartyOrder();
+ Task_ClosePartyMenu(taskId);
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1:
+ Task_ReturnToChooseMonAfterText(taskId);
+ break;
+ }
+}
+
+static u16 PartyMenuButtonHandler(s8 *slotPtr)
+{
+ s8 movementDir;
+
+ switch (gMain.newAndRepeatedKeys)
+ {
+ case DPAD_UP:
+ movementDir = MENU_DIR_UP;
+ break;
+ case DPAD_DOWN:
+ movementDir = MENU_DIR_DOWN;
+ break;
+ case DPAD_LEFT:
+ movementDir = MENU_DIR_LEFT;
+ break;
+ case DPAD_RIGHT:
+ movementDir = MENU_DIR_RIGHT;
+ break;
+ default:
+ switch (GetLRKeysPressedAndHeld())
+ {
+ case MENU_L_PRESSED:
+ movementDir = MENU_DIR_UP;
+ break;
+ case MENU_R_PRESSED:
+ movementDir = MENU_DIR_DOWN;
+ break;
+ default:
+ movementDir = 0;
+ break;
+ }
+ break;
+ }
+ if (JOY_NEW(START_BUTTON))
+ return 8;
+ if (movementDir)
+ {
+ UpdateCurrentPartySelection(slotPtr, movementDir);
+ return 0;
+ }
+ // Pressed Cancel
+ if (JOY_NEW(A_BUTTON) && *slotPtr == PARTY_SIZE + 1)
+ return 2;
+ return JOY_NEW(A_BUTTON | B_BUTTON);
+}
+
+static void UpdateCurrentPartySelection(s8 *slotPtr, s8 movementDir)
+{
+ s8 newSlotId = *slotPtr;
+ u8 layout = gPartyMenu.layout;
+
+ if (layout == PARTY_LAYOUT_SINGLE)
+ UpdatePartySelectionSingleLayout(slotPtr, movementDir);
+ else
+ UpdatePartySelectionDoubleLayout(slotPtr, movementDir);
+ if (*slotPtr != newSlotId)
+ {
+ PlaySE(SE_SELECT);
+ AnimatePartySlot(newSlotId, 0);
+ AnimatePartySlot(*slotPtr, 1);
+ }
+}
+
+static void UpdatePartySelectionSingleLayout(s8 *slotPtr, s8 movementDir)
+{
+ // PARTY_SIZE + 1 is Cancel, PARTY_SIZE is Confirm
+ switch (movementDir)
+ {
+ case MENU_DIR_UP:
+ if (*slotPtr == 0)
+ {
+ *slotPtr = PARTY_SIZE + 1;
+ }
+ else if (*slotPtr == PARTY_SIZE)
+ {
+ *slotPtr = gPlayerPartyCount - 1;
+ }
+ else if (*slotPtr == PARTY_SIZE + 1)
+ {
+ if (sPartyMenuInternal->chooseHalf)
+ *slotPtr = PARTY_SIZE;
+ else
+ *slotPtr = gPlayerPartyCount - 1;
+ }
+ else
+ {
+ --*slotPtr;
+ }
+ break;
+ case MENU_DIR_DOWN:
+ if (*slotPtr == PARTY_SIZE + 1)
+ {
+ *slotPtr = 0;
+ }
+ else
+ {
+ if (*slotPtr == gPlayerPartyCount - 1)
+ {
+ if (sPartyMenuInternal->chooseHalf)
+ *slotPtr = PARTY_SIZE;
+ else
+ *slotPtr = PARTY_SIZE + 1;
+ }
+ else
+ {
+ ++*slotPtr;
+ }
+ }
+ break;
+ case MENU_DIR_RIGHT:
+ if (gPlayerPartyCount != 1 && *slotPtr == 0)
+ {
+ if (sPartyMenuInternal->lastSelectedSlot == 0)
+ *slotPtr = 1;
+ else
+ *slotPtr = sPartyMenuInternal->lastSelectedSlot;
+ }
+ break;
+ case MENU_DIR_LEFT:
+ if (*slotPtr != 0 && *slotPtr != PARTY_SIZE && *slotPtr != PARTY_SIZE + 1)
+ {
+ sPartyMenuInternal->lastSelectedSlot = *slotPtr;
+ *slotPtr = 0;
+ }
+ break;
+ }
+}
+
+static void UpdatePartySelectionDoubleLayout(s8 *slotPtr, s8 movementDir)
+{
+ // PARTY_SIZE + 1 is Cancel, PARTY_SIZE is Confirm
+ // newSlot is used temporarily as a movement direction during its later assignment
+ s8 newSlot = movementDir;
+
+ switch (movementDir)
+ {
+ case MENU_DIR_UP:
+ if (*slotPtr == 0)
+ {
+ *slotPtr = PARTY_SIZE + 1;
+ break;
+ }
+ else if (*slotPtr == PARTY_SIZE)
+ {
+ *slotPtr = gPlayerPartyCount - 1;
+ break;
+ }
+ else if (*slotPtr == PARTY_SIZE + 1)
+ {
+ if (sPartyMenuInternal->chooseHalf)
+ {
+ *slotPtr = PARTY_SIZE;
+ break;
+ }
+ --*slotPtr;
+ }
+ newSlot = GetNewSlotDoubleLayout(*slotPtr, newSlot);
+ if (newSlot != -1)
+ *slotPtr = newSlot;
+ break;
+ case MENU_DIR_DOWN:
+ if (*slotPtr == PARTY_SIZE)
+ {
+ *slotPtr = PARTY_SIZE + 1;
+ }
+ else if (*slotPtr == PARTY_SIZE + 1)
+ {
+ *slotPtr = 0;
+ }
+ else
+ {
+ newSlot = GetNewSlotDoubleLayout(*slotPtr, MENU_DIR_DOWN);
+ if (newSlot == -1)
+ {
+ if (sPartyMenuInternal->chooseHalf)
+ *slotPtr = PARTY_SIZE;
+ else
+ *slotPtr = PARTY_SIZE + 1;
+ }
+ else
+ {
+ *slotPtr = newSlot;
+ }
+ }
+ break;
+ case MENU_DIR_RIGHT:
+ if (*slotPtr == 0)
+ {
+ if (sPartyMenuInternal->lastSelectedSlot == 3)
+ {
+ if (GetMonData(&gPlayerParty[3], MON_DATA_SPECIES) != SPECIES_NONE)
+ *slotPtr = 3;
+ }
+ else if (GetMonData(&gPlayerParty[2], MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ *slotPtr = 2;
+ }
+ }
+ else if (*slotPtr == 1)
+ {
+ if (sPartyMenuInternal->lastSelectedSlot == 5)
+ {
+ if (GetMonData(&gPlayerParty[5], MON_DATA_SPECIES) != SPECIES_NONE)
+ *slotPtr = 5;
+ }
+ else if (GetMonData(&gPlayerParty[4], MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ *slotPtr = 4;
+ }
+ }
+ break;
+ case MENU_DIR_LEFT:
+ if (*slotPtr == 2 || *slotPtr == 3)
+ {
+ sPartyMenuInternal->lastSelectedSlot = *slotPtr;
+ *slotPtr = 0;
+ }
+ else if (*slotPtr == 4 || *slotPtr == 5)
+ {
+ sPartyMenuInternal->lastSelectedSlot = *slotPtr;
+ *slotPtr = 1;
+ }
+ break;
+ }
+}
+
+static s8 GetNewSlotDoubleLayout(s8 slotId, s8 movementDir)
+{
+ while (TRUE)
+ {
+ slotId += movementDir;
+ if ((u8)slotId >= PARTY_SIZE)
+ return -1;
+ if (GetMonData(&gPlayerParty[slotId], MON_DATA_SPECIES) != SPECIES_NONE)
+ return slotId;
+ }
+}
+
+u8 *GetMonNickname(struct Pokemon *mon, u8 *dest)
+{
+ GetMonData(mon, MON_DATA_NICKNAME, dest);
+ return StringGetEnd10(dest);
+}
+
+#define tKeepOpen data[0]
+
+u8 DisplayPartyMenuMessage(const u8 *str, bool8 keepOpen)
+{
+ u8 taskId;
+
+ PartyMenuPrintText(str);
+ taskId = CreateTask(Task_PrintAndWaitForText, 1);
+ gTasks[taskId].tKeepOpen = keepOpen;
+ return taskId;
+}
+
+static void Task_PrintAndWaitForText(u8 taskId)
+{
+ if (RunTextPrinters_CheckActive(6) != TRUE)
+ {
+ if (gTasks[taskId].tKeepOpen == FALSE)
+ {
+ ClearStdWindowAndFrameToTransparent(6, 0);
+ ClearWindowTilemap(6);
+ }
+ DestroyTask(taskId);
+ }
+}
+
+#undef tKeepOpen
+
+bool8 IsPartyMenuTextPrinterActive(void)
+{
+ return FuncIsActiveTask(Task_PrintAndWaitForText);
+}
+
+static void Task_WaitForLinkAndReturnToChooseMon(u8 taskId)
+{
+ if (sub_80BF748() != TRUE)
+ {
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+ }
+}
+
+static void Task_ReturnToChooseMonAfterText(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ ClearStdWindowAndFrameToTransparent(6, 0);
+ ClearWindowTilemap(6);
+ if (MenuHelpers_LinkSomething() == TRUE)
+ {
+ gTasks[taskId].func = Task_WaitForLinkAndReturnToChooseMon;
+ }
+ else
+ {
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+ }
+ }
+}
+
+static void DisplayGaveHeldItemMessage(struct Pokemon *mon, u16 item, bool8 keepOpen, u8 a4)
+{
+ if (!a4)
+ ItemUse_SetQuestLogEvent(5, mon, item, 0xFFFF);
+ else if (gPartyMenu.action == PARTY_ACTION_GIVE_PC_ITEM)
+ ItemUse_SetQuestLogEvent(7, mon, item, 0xFFFF);
+ else
+ ItemUse_SetQuestLogEvent(6, mon, item, 0xFFFF);
+ GetMonNickname(mon, gStringVar1);
+ CopyItemName(item, gStringVar2);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnWasGivenItem);
+ DisplayPartyMenuMessage(gStringVar4, keepOpen);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void DisplayTookHeldItemMessage(struct Pokemon *mon, u16 item, bool8 keepOpen)
+{
+ ItemUse_SetQuestLogEvent(8, mon, item, 0xFFFF);
+ GetMonNickname(mon, gStringVar1);
+ CopyItemName(item, gStringVar2);
+ StringExpandPlaceholders(gStringVar4, gText_ReceivedItemFromPkmn);
+ DisplayPartyMenuMessage(gStringVar4, keepOpen);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void DisplayAlreadyHoldingItemSwitchMessage(struct Pokemon *mon, u16 item, bool8 keepOpen)
+{
+ GetMonNickname(mon, gStringVar1);
+ CopyItemName(item, gStringVar2);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnAlreadyHoldingItemSwitch);
+ DisplayPartyMenuMessage(gStringVar4, keepOpen);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void DisplaySwitchedHeldItemMessage(u16 item, u16 item2, bool8 keepOpen)
+{
+ sub_8124B60(&gPlayerParty[gPartyMenu.slotId], item2, item);
+ CopyItemName(item, gStringVar1);
+ CopyItemName(item2, gStringVar2);
+ StringExpandPlaceholders(gStringVar4, gText_SwitchedPkmnItem);
+ DisplayPartyMenuMessage(gStringVar4, keepOpen);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void GiveItemToMon(struct Pokemon *mon, u16 item)
+{
+ u8 itemBytes[2];
+
+ if (ItemIsMail(item) == TRUE)
+ {
+ if (GiveMailToMon(mon, item) == 0xFF)
+ return;
+ }
+ itemBytes[0] = item;
+ itemBytes[1] = item >> 8;
+ SetMonData(mon, MON_DATA_HELD_ITEM, itemBytes);
+}
+
+static u8 TryTakeMonItem(struct Pokemon *mon)
+{
+ u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
+
+ if (item == ITEM_NONE)
+ return 0;
+ if (AddBagItem(item, 1) == FALSE)
+ return 1;
+ item = ITEM_NONE;
+ SetMonData(mon, MON_DATA_HELD_ITEM, &item);
+ return 2;
+}
+
+static void BufferBagFullCantTakeItemMessage(u16 itemId)
+{
+ const u8 *string;
+
+ switch (ItemId_GetPocket(itemId))
+ {
+ default:
+ string = gStartMenuText_Bag;
+ break;
+ case POCKET_TM_CASE:
+ string = ItemId_GetName(ITEM_TM_CASE);
+ break;
+ case POCKET_BERRY_POUCH:
+ string = ItemId_GetName(ITEM_BERRY_POUCH);
+ break;
+ }
+ StringCopy(gStringVar1, string);
+ StringExpandPlaceholders(gStringVar4, gText_BagFullCouldNotRemoveItem);
+}
+
+#define tHP data[0]
+#define tMaxHP data[1]
+#define tHPIncrement data[2]
+#define tHPToAdd data[3]
+#define tPartyId data[4]
+#define tStartHP data[5]
+
+static void Task_PartyMenuModifyHP(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ tHP += tHPIncrement;
+ --tHPToAdd;
+ SetMonData(&gPlayerParty[tPartyId], MON_DATA_HP, &tHP);
+ DisplayPartyPokemonHPCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartyId], 1);
+ DisplayPartyPokemonHPBarCheck(&gPlayerParty[tPartyId], &sPartyMenuBoxes[tPartyId]);
+ if (tHPToAdd == 0 || tHP == 0 || tHP == tMaxHP)
+ {
+ // If HP was recovered, buffer the amount recovered
+ if (tHP > tStartHP)
+ ConvertIntToDecimalStringN(gStringVar2, tHP - tStartHP, STR_CONV_MODE_LEFT_ALIGN, 3);
+ SwitchTaskToFollowupFunc(taskId);
+ }
+}
+
+void PartyMenuModifyHP(u8 taskId, u8 slot, s8 hpIncrement, s16 hpDifference, TaskFunc task)
+{
+ struct Pokemon *mon = &gPlayerParty[slot];
+ s16 *data = gTasks[taskId].data;
+
+ tHP = GetMonData(mon, MON_DATA_HP);
+ tMaxHP = GetMonData(mon, MON_DATA_MAX_HP);
+ tHPIncrement = hpIncrement;
+ tHPToAdd = hpDifference;
+ tPartyId = slot;
+ tStartHP = tHP;
+ SetTaskFuncWithFollowupFunc(taskId, Task_PartyMenuModifyHP, task);
+}
+
+// The usage of hp in this function is mostly nonsense
+// Because caseId is always passed 0, none of the other cases ever occur
+static void ResetHPTaskData(u8 taskId, u8 caseId, u32 hp)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (caseId) // always zero
+ {
+ case 0:
+ tHP = hp;
+ tStartHP = hp;
+ break;
+ case 1:
+ tMaxHP = hp;
+ break;
+ case 2:
+ tHPIncrement = hp;
+ break;
+ case 3:
+ tHPToAdd = hp;
+ break;
+ case 4:
+ tPartyId = hp;
+ break;
+ case 5:
+ SetTaskFuncWithFollowupFunc(taskId, Task_PartyMenuModifyHP, (TaskFunc)hp); // >casting hp as a taskfunc
+ break;
+ }
+}
+
+#undef tHP
+#undef tMaxHP
+#undef tHPIncrement
+#undef tHPToAdd
+#undef tPartyId
+#undef tStartHP
+
+u8 GetAilmentFromStatus(u32 status)
+{
+ if (status & STATUS1_PSN_ANY)
+ return AILMENT_PSN;
+ if (status & STATUS1_PARALYSIS)
+ return AILMENT_PRZ;
+ if (status & STATUS1_SLEEP)
+ return AILMENT_SLP;
+ if (status & STATUS1_FREEZE)
+ return AILMENT_FRZ;
+ if (status & STATUS1_BURN)
+ return AILMENT_BRN;
+ return AILMENT_NONE;
+}
+
+u8 GetMonAilment(struct Pokemon *mon)
+{
+ u8 ailment;
+
+ if (GetMonData(mon, MON_DATA_HP) == 0)
+ return AILMENT_FNT;
+ ailment = GetAilmentFromStatus(GetMonData(mon, MON_DATA_STATUS));
+ if (ailment != AILMENT_NONE)
+ return ailment;
+ if (CheckPartyPokerus(mon, 0))
+ return AILMENT_PKRS;
+ return AILMENT_NONE;
+}
+
+static void SetPartyMonsAllowedInMinigame(void)
+{
+ u16 *ptr;
+
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_MINIGAME)
+ {
+ u8 i;
+
+ ptr = &gPartyMenu.data1;
+ gPartyMenu.data1 = 0;
+ if (gSpecialVar_0x8005 == 0)
+ {
+ for (i = 0; i < gPlayerPartyCount; ++i)
+ *ptr += IsMonAllowedInPokemonJump(&gPlayerParty[i]) << i;
+ }
+ else
+ {
+ for (i = 0; i < gPlayerPartyCount; ++i)
+ *ptr += IsMonAllowedInDodrioBerryPicking(&gPlayerParty[i]) << i;
+ }
+ }
+}
+
+static bool16 IsMonAllowedInPokemonJump(struct Pokemon *mon)
+{
+ if (GetMonData(mon, MON_DATA_IS_EGG) != TRUE && IsSpeciesAllowedInPokemonJump(GetMonData(mon, MON_DATA_SPECIES)))
+ return TRUE;
+ return FALSE;
+}
+
+
+static bool16 IsMonAllowedInDodrioBerryPicking(struct Pokemon *mon)
+{
+ if (GetMonData(mon, MON_DATA_IS_EGG) != TRUE && GetMonData(mon, MON_DATA_SPECIES) == SPECIES_DODRIO)
+ return TRUE;
+ return FALSE;
+}
+
+static bool8 IsMonAllowedInMinigame(u8 slot)
+{
+ if (!((gPartyMenu.data1 >> slot) & 1))
+ return FALSE;
+ return TRUE;
+}
+
+static void TryEnterMonForMinigame(u8 taskId, u8 slot)
+{
+ if (IsMonAllowedInMinigame(slot) == TRUE)
+ {
+ PlaySE(SE_SELECT);
+ gSpecialVar_0x8004 = slot;
+ Task_ClosePartyMenu(taskId);
+ }
+ else
+ {
+ PlaySE(SE_HAZURE);
+ DisplayPartyMenuMessage(gText_PkmnCantParticipate, FALSE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ }
+}
+
+static void CancelParticipationPrompt(u8 taskId)
+{
+ DisplayPartyMenuMessage(gText_CancelParticipation, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_CancelParticipationYesNo;
+}
+
+static void Task_CancelParticipationYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleCancelParticipationYesNoInput;
+ }
+}
+
+static void Task_HandleCancelParticipationYesNoInput(u8 taskId)
+{
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ gSpecialVar_0x8004 = PARTY_SIZE + 1;
+ Task_ClosePartyMenu(taskId);
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1:
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ break;
+ }
+}
+
+static u8 CanMonLearnTMTutor(struct Pokemon *mon, u16 item, u8 tutor)
+{
+ u16 move;
+
+ if (GetMonData(mon, MON_DATA_IS_EGG))
+ return CANNOT_LEARN_MOVE_IS_EGG;
+
+ if (item >= ITEM_TM01_FOCUS_PUNCH)
+ {
+ if (CanMonLearnTMHM(mon, item - ITEM_TM01_FOCUS_PUNCH))
+ move = ItemIdToBattleMoveId(item);
+ else
+ return CANNOT_LEARN_MOVE;
+ do
+ {
+ } while (0);
+ }
+ else if (CanLearnTutorMove(GetMonData(mon, MON_DATA_SPECIES), tutor) == FALSE)
+ {
+ return CANNOT_LEARN_MOVE;
+ }
+ else
+ {
+ move = GetTutorMove(tutor);
+ }
+ if (MonKnowsMove(mon, move) == TRUE)
+ return ALREADY_KNOWS_MOVE;
+ else
+ return CAN_LEARN_MOVE;
+}
+
+static u16 GetTutorMove(u8 tutor)
+{
+ switch (tutor)
+ {
+ case TUTOR_MOVE_FRENZY_PLANT:
+ return MOVE_FRENZY_PLANT;
+ case TUTOR_MOVE_BLAST_BURN:
+ return MOVE_BLAST_BURN;
+ case TUTOR_MOVE_HYDRO_CANNON:
+ return MOVE_HYDRO_CANNON;
+ default:
+ return sTutorMoves[tutor];
+ }
+}
+
+static bool8 CanLearnTutorMove(u16 species, u8 tutor)
+{
+ switch (tutor)
+ {
+ case TUTOR_MOVE_FRENZY_PLANT:
+ if (species == SPECIES_VENUSAUR)
+ return TRUE;
+ else
+ return FALSE;
+ case TUTOR_MOVE_BLAST_BURN:
+ if (species == SPECIES_CHARIZARD)
+ return TRUE;
+ else
+ return FALSE;
+ case TUTOR_MOVE_HYDRO_CANNON:
+ if (species == SPECIES_BLASTOISE)
+ return TRUE;
+ else
+ return FALSE;
+ default:
+ if (sTutorLearnsets[species] & (1 << tutor))
+ return TRUE;
+ else
+ return FALSE;
+ }
+}
+
+static void sub_8120C3C(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ gTasks[taskId].func = sub_8120C6C;
+}
+
+static void sub_8120C6C(u8 taskId)
+{
+ BeginNormalPaletteFade(0xFFFF1FFF, 4, 0, 6, RGB_BLACK);
+ gTasks[taskId].func = sub_8120CA8;
+}
+
+static void sub_8120CA8(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ gTasks[taskId].func = sub_8120CD8;
+}
+
+static void sub_8120CD8(u8 taskId)
+{
+ gTasks[taskId].data[0] = sub_81220D4();
+ gTasks[taskId].func = sub_8120D08;
+}
+
+static void sub_8120D08(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ if (RunTextPrinters_CheckActive((u8)data[0]) != TRUE)
+ gTasks[taskId].func = sub_8120D40;
+}
+
+static void sub_8120D40(u8 taskId)
+{
+ BeginNormalPaletteFade(0xFFFF0008, 4, 6, 0, RGB_BLACK);
+ gTasks[taskId].func = sub_8120D7C;
+}
+
+static void sub_8120D7C(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ gTasks[taskId].func = sub_8120DAC;
+}
+
+static void sub_8120DAC(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ sub_8122084(data[0], gUnknown_8417494);
+ gTasks[taskId].func = sub_8120DE0;
+}
+
+static void sub_8120DE0(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ if (RunTextPrinters_CheckActive((u8)data[0]) != TRUE)
+ {
+ sub_8122110((u8)data[0]);
+ gTasks[taskId].func = sub_8120E1C;
+ }
+}
+
+static void sub_8120E1C(u8 taskId)
+{
+ BeginNormalPaletteFade(0x0000FFF7, 4, 6, 0, RGB_BLACK);
+ gTasks[taskId].func = sub_8120E58;
+}
+
+static void sub_8120E58(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ TextWindow_SetUserSelectedFrame(0, 0x4F, 0xD0);
+ TextWindow_SetStdFrame0_WithPal(0, 0x58, 0xF0);
+ if (gPartyMenu.action == PARTY_ACTION_USE_ITEM)
+ DisplayPartyMenuStdMessage(PARTY_MSG_USE_ON_WHICH_MON);
+ else
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+ }
+}
+
+static void sub_8120EBC(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ data[0] = 0;
+ gTasks[taskId].func = sub_8120EE0;
+}
+
+static void sub_8120EE0(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active && sub_8120F78(taskId) != TRUE)
+ {
+ switch (data[0])
+ {
+ case 80:
+ UpdateCurrentPartySelection(&gPartyMenu.slotId, 2);
+ break;
+ case 160:
+ PlaySE(SE_SELECT);
+ CreateSelectionWindow();
+ break;
+ case 240:
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[2]);
+ sCursorOptions[sPartyMenuInternal->actions[0]].func(taskId);
+ break;
+ }
+ ++data[0];
+ }
+}
+
+static bool8 sub_8120F78(u8 taskId)
+{
+ if (JOY_NEW(B_BUTTON))
+ {
+ sPartyMenuInternal->exitCallback = sub_8120FB0;
+ Task_ClosePartyMenu(taskId);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void sub_8120FB0(void)
+{
+ FreeRestoreBattleData();
+ LoadPlayerParty();
+ SetTeachyTvControllerModeToResume();
+ SetMainCallback2(CB2_ReturnToTeachyTV);
+}
+
+static void sub_8120FCC(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ data[0] = 0;
+ gTasks[taskId].func = sub_8120FF0;
+}
+
+static void sub_8120FF0(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ if (!gPaletteFade.active && sub_8120F78(taskId) != TRUE)
+ {
+ if (data[0] != 80)
+ {
+ ++data[0];
+ }
+ else
+ {
+ sPartyMenuInternal->exitCallback = CB2_SetUpExitToBattleScreen;
+ gItemUseCB(taskId, Task_ClosePartyMenuAfterText);
+ }
+ }
+}
+
+static void InitPartyMenuWindows(u8 layout)
+{
+ u8 i;
+
+ switch (layout)
+ {
+ case PARTY_LAYOUT_SINGLE:
+ InitWindows(sSinglePartyMenuWindowTemplate);
+ break;
+ case PARTY_LAYOUT_DOUBLE:
+ InitWindows(sDoublePartyMenuWindowTemplate);
+ break;
+ case PARTY_LAYOUT_MULTI:
+ InitWindows(sMultiPartyMenuWindowTemplate);
+ break;
+ default: // PARTY_LAYOUT_MULTI_SHOWCASE
+ InitWindows(sShowcaseMultiPartyMenuWindowTemplate);
+ break;
+ }
+ DeactivateAllTextPrinters();
+ for (i = 0; i < PARTY_SIZE; ++i)
+ FillWindowPixelBuffer(i, PIXEL_FILL(0));
+ TextWindow_SetUserSelectedFrame(0, 0x4F, 0xD0);
+ TextWindow_SetStdFrame0_WithPal(0, 0x58, 0xF0);
+ LoadPalette(stdpal_get(2), 0xC0, 0x20);
+ LoadPalette(stdpal_get(0), 0xE0, 0x20);
+}
+
+static void CreateCancelConfirmWindows(bool8 chooseHalf)
+{
+ u8 confirmWindowId;
+ u8 cancelWindowId;
+ u8 offset;
+
+ if (gPartyMenu.menuType != PARTY_MENU_TYPE_MULTI_SHOWCASE)
+ {
+ if (chooseHalf == TRUE)
+ {
+ confirmWindowId = AddWindow(&sConfirmButtonWindowTemplate);
+ FillWindowPixelBuffer(confirmWindowId, PIXEL_FILL(0));
+ AddTextPrinterParameterized4(confirmWindowId, 0, (48 - GetStringWidth(0, gMenuText_Confirm, 0)) / 2u, 1, 0, 0, sFontColorTable[0], -1, gMenuText_Confirm);
+ PutWindowTilemap(confirmWindowId);
+ CopyWindowToVram(confirmWindowId, 2);
+ cancelWindowId = AddWindow(&sMultiCancelButtonWindowTemplate);
+ offset = 0;
+ }
+ else
+ {
+ cancelWindowId = AddWindow(&sCancelButtonWindowTemplate);
+ offset = 3;
+ }
+ FillWindowPixelBuffer(cancelWindowId, PIXEL_FILL(0));
+ // Branches are functionally identical. Second branch is never reached, Spin Trade wasnt fully implemented
+ if (gPartyMenu.menuType != PARTY_MENU_TYPE_SPIN_TRADE)
+ {
+ offset += (48 - GetStringWidth(0, gFameCheckerText_Cancel, 0)) / 2;
+ AddTextPrinterParameterized3(cancelWindowId, 0, offset, 1, sFontColorTable[0], -1, gFameCheckerText_Cancel);
+ }
+ else
+ {
+ offset += (48 - GetStringWidth(0, gOtherText_Exit, 0)) / 2;
+ AddTextPrinterParameterized3(cancelWindowId, 0, offset, 1, sFontColorTable[0], -1, gOtherText_Exit);
+ }
+ PutWindowTilemap(cancelWindowId);
+ CopyWindowToVram(cancelWindowId, 2);
+ ScheduleBgCopyTilemapToVram(0);
+ }
+}
+
+static u16 *GetPartyMenuPalBufferPtr(u8 paletteId)
+{
+ return &sPartyMenuInternal->palBuffer[paletteId];
+}
+
+static void BlitBitmapToPartyWindow(u8 windowId, const u8 *b, u8 c, u8 x, u8 y, u8 width, u8 height)
+{
+ u8 *pixels = AllocZeroed(height * width * 32);
+ u8 i, j;
+
+ if (pixels != NULL)
+ {
+ for (i = 0; i < height; ++i)
+ for (j = 0; j < width; ++j)
+ CpuCopy16(GetPartyMenuBgTile(b[x + j + ((y + i) * c)]), &pixels[(i * width + j) * 32], 32);
+ BlitBitmapToWindow(windowId, pixels, x * 8, y * 8, width * 8, height * 8);
+ Free(pixels);
+ }
+}
+
+static void BlitBitmapToPartyWindow_LeftColumn(u8 windowId, u8 x, u8 y, u8 width, u8 height, u8 isEgg)
+{
+ if (width == 0 && height == 0)
+ {
+ width = 10;
+ height = 7;
+ }
+ if (!isEgg)
+ BlitBitmapToPartyWindow(windowId, sMainSlotTileNums, 10, x, y, width, height);
+ else
+ BlitBitmapToPartyWindow(windowId, sMainSlotTileNums_Egg, 10, x, y, width, height);
+}
+
+static void BlitBitmapToPartyWindow_RightColumn(u8 windowId, u8 x, u8 y, u8 width, u8 height, u8 isEgg)
+{
+ if (width == 0 && height == 0)
+ {
+ width = 18;
+ height = 3;
+ }
+ if (!isEgg)
+ BlitBitmapToPartyWindow(windowId, sOtherSlotsTileNums, 18, x, y, width, height);
+ else
+ BlitBitmapToPartyWindow(windowId, sOtherSlotsTileNums_Egg, 18, x, y, width, height);
+}
+
+static void DrawEmptySlot(u8 windowId)
+{
+ BlitBitmapToPartyWindow(windowId, sEmptySlotTileNums, 18, 0, 0, 18, 3);
+}
+
+#define LOAD_PARTY_BOX_PAL(paletteIds, paletteOffsets) \
+{ \
+ LoadPalette(GetPartyMenuPalBufferPtr(paletteIds[0]), paletteOffsets[0] + palNum, 2); \
+ LoadPalette(GetPartyMenuPalBufferPtr(paletteIds[1]), paletteOffsets[1] + palNum, 2); \
+ LoadPalette(GetPartyMenuPalBufferPtr(paletteIds[2]), paletteOffsets[2] + palNum, 2); \
+}
+
+static void LoadPartyBoxPalette(struct PartyMenuBox *menuBox, u8 palFlags)
+{
+ u8 palNum = GetWindowAttribute(menuBox->windowId, WINDOW_PALETTE_NUM) * 16;
+
+ if (palFlags & PARTY_PAL_TO_SOFTBOIL)
+ {
+ if (palFlags & PARTY_PAL_SELECTED)
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
+ }
+ else
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds2, sPartyBoxPalOffsets2);
+ }
+ }
+ else if (palFlags & PARTY_PAL_SWITCHING)
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds2, sPartyBoxPalOffsets2);
+ }
+ else if (palFlags & PARTY_PAL_TO_SWITCH)
+ {
+ if (palFlags & PARTY_PAL_SELECTED)
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
+ }
+ else
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxSelectedForActionPalIds2, sPartyBoxPalOffsets2);
+ }
+ }
+ else if (palFlags & PARTY_PAL_FAINTED)
+ {
+ if (palFlags & PARTY_PAL_SELECTED)
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionFaintedPalIds, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
+ }
+ else
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxFaintedPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxFaintedPalIds2, sPartyBoxPalOffsets2);
+ }
+ }
+ else if (palFlags & PARTY_PAL_MULTI_ALT)
+ {
+ if (palFlags & PARTY_PAL_SELECTED)
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionMultiPalIds, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
+ }
+ else
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxMultiPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxMultiPalIds2, sPartyBoxPalOffsets2);
+ }
+ }
+ else if (palFlags & PARTY_PAL_SELECTED)
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxCurrSelectionPalIds2, sPartyBoxPalOffsets2);
+ }
+ else
+ {
+ LOAD_PARTY_BOX_PAL(sPartyBoxEmptySlotPalIds1, sPartyBoxPalOffsets1);
+ LOAD_PARTY_BOX_PAL(sPartyBoxEmptySlotPalIds2, sPartyBoxPalOffsets2);
+ }
+}
+
+static void DisplayPartyPokemonBarDetail(u8 windowId, const u8 *str, u8 color, const u8 *align)
+{
+ AddTextPrinterParameterized3(windowId, 0, align[0], align[1], sFontColorTable[color], 0, str);
+}
+
+static void DisplayPartyPokemonNickname(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
+{
+ u8 nickname[POKEMON_NAME_LENGTH + 1];
+
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ if (c == 1)
+ menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[0] >> 3, menuBox->infoRects->dimensions[1] >> 3, menuBox->infoRects->dimensions[2] >> 3, menuBox->infoRects->dimensions[3] >> 3, FALSE);
+ GetMonNickname(mon, nickname);
+ DisplayPartyPokemonBarDetail(menuBox->windowId, nickname, 0, menuBox->infoRects->dimensions);
+ }
+}
+
+static void DisplayPartyPokemonLevelCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
+{
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ u8 ailment = GetMonAilment(mon);
+
+ if (ailment == AILMENT_NONE || ailment == AILMENT_PKRS)
+ {
+ if (c != 0)
+ menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[4] >> 3, (menuBox->infoRects->dimensions[5] >> 3) + 1, menuBox->infoRects->dimensions[6] >> 3, menuBox->infoRects->dimensions[7] >> 3, FALSE);
+ if (c != 2)
+ DisplayPartyPokemonLevel(GetMonData(mon, MON_DATA_LEVEL), menuBox);
+ }
+ }
+}
+
+static void DisplayPartyPokemonLevel(u8 level, struct PartyMenuBox *menuBox)
+{
+ ConvertIntToDecimalStringN(gStringVar2, level, STR_CONV_MODE_LEFT_ALIGN, 3);
+ StringCopy(gStringVar1, gText_Lv);
+ StringAppend(gStringVar1, gStringVar2);
+ DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, &menuBox->infoRects->dimensions[4]);
+}
+
+static void DisplayPartyPokemonGenderNidoranCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
+{
+ u8 nickname[POKEMON_NAME_LENGTH + 1];
+
+ if (c == 1)
+ menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[8] >> 3, (menuBox->infoRects->dimensions[9] >> 3) + 1, menuBox->infoRects->dimensions[10] >> 3, menuBox->infoRects->dimensions[11] >> 3, FALSE);
+ GetMonNickname(mon, nickname);
+ DisplayPartyPokemonGender(GetMonGender(mon), GetMonData(mon, MON_DATA_SPECIES), nickname, menuBox);
+}
+
+static void DisplayPartyPokemonGender(u8 gender, u16 species, u8 *nickname, struct PartyMenuBox *menuBox)
+{
+ u8 palNum = GetWindowAttribute(menuBox->windowId, WINDOW_PALETTE_NUM) * 16;
+
+ if (species == SPECIES_NONE)
+ return;
+ if ((species == SPECIES_NIDORAN_M || species == SPECIES_NIDORAN_F) && StringCompare(nickname, gSpeciesNames[species]) == 0)
+ return;
+ switch (gender)
+ {
+ case MON_MALE:
+ LoadPalette(GetPartyMenuPalBufferPtr(sGenderMalePalIds[0]), sGenderPalOffsets[0] + palNum, 2);
+ LoadPalette(GetPartyMenuPalBufferPtr(sGenderMalePalIds[1]), sGenderPalOffsets[1] + palNum, 2);
+ DisplayPartyPokemonBarDetail(menuBox->windowId, gText_MaleSymbol, 2, &menuBox->infoRects->dimensions[8]);
+ break;
+ case MON_FEMALE:
+ LoadPalette(GetPartyMenuPalBufferPtr(sGenderFemalePalIds[0]), sGenderPalOffsets[0] + palNum, 2);
+ LoadPalette(GetPartyMenuPalBufferPtr(sGenderFemalePalIds[1]), sGenderPalOffsets[1] + palNum, 2);
+ DisplayPartyPokemonBarDetail(menuBox->windowId, gText_FemaleSymbol, 2, &menuBox->infoRects->dimensions[8]);
+ break;
+ }
+}
+
+static void DisplayPartyPokemonHPCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
+{
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ if (c != 0)
+ menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->dimensions[12] >> 3, (menuBox->infoRects->dimensions[13] >> 3) + 1, menuBox->infoRects->dimensions[14] >> 3, menuBox->infoRects->dimensions[15] >> 3, FALSE);
+ if (c != 2)
+ DisplayPartyPokemonHP(GetMonData(mon, MON_DATA_HP), menuBox);
+ }
+}
+
+static void DisplayPartyPokemonHP(u16 hp, struct PartyMenuBox *menuBox)
+{
+ u8 *strOut = ConvertIntToDecimalStringN(gStringVar1, hp, STR_CONV_MODE_RIGHT_ALIGN, 3);
+
+ strOut[0] = CHAR_SLASH;
+ strOut[1] = EOS;
+ DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, &menuBox->infoRects->dimensions[12]);
+}
+
+static void DisplayPartyPokemonMaxHPCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox, u8 c)
+{
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ if (c != 0)
+ menuBox->infoRects->blitFunc(menuBox->windowId, (menuBox->infoRects->dimensions[16] >> 3) + 1, (menuBox->infoRects->dimensions[17] >> 3) + 1, menuBox->infoRects->dimensions[18] >> 3, menuBox->infoRects->dimensions[19] >> 3, FALSE);
+ if (c != 2)
+ DisplayPartyPokemonMaxHP(GetMonData(mon, MON_DATA_MAX_HP), menuBox);
+ }
+}
+
+static void DisplayPartyPokemonMaxHP(u16 maxhp, struct PartyMenuBox *menuBox)
+{
+ ConvertIntToDecimalStringN(gStringVar2, maxhp, STR_CONV_MODE_RIGHT_ALIGN, 3);
+ StringCopy(gStringVar1, gText_Slash);
+ StringAppend(gStringVar1, gStringVar2);
+ DisplayPartyPokemonBarDetail(menuBox->windowId, gStringVar1, 0, &menuBox->infoRects->dimensions[16]);
+}
+
+static void DisplayPartyPokemonHPBarCheck(struct Pokemon *mon, struct PartyMenuBox *menuBox)
+{
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ DisplayPartyPokemonHPBar(GetMonData(mon, MON_DATA_HP), GetMonData(mon, MON_DATA_MAX_HP), menuBox);
+}
+
+static void DisplayPartyPokemonHPBar(u16 hp, u16 maxhp, struct PartyMenuBox *menuBox)
+{
+ u8 palNum = GetWindowAttribute(menuBox->windowId, WINDOW_PALETTE_NUM) * 16;
+ u8 hpFraction;
+
+ switch (GetHPBarLevel(hp, maxhp))
+ {
+ case HP_BAR_GREEN:
+ case HP_BAR_FULL:
+ LoadPalette(GetPartyMenuPalBufferPtr(sHPBarGreenPalIds[0]), sHPBarPalOffsets[0] + palNum, 2);
+ LoadPalette(GetPartyMenuPalBufferPtr(sHPBarGreenPalIds[1]), sHPBarPalOffsets[1] + palNum, 2);
+ break;
+ case HP_BAR_YELLOW:
+ LoadPalette(GetPartyMenuPalBufferPtr(sHPBarYellowPalIds[0]), sHPBarPalOffsets[0] + palNum, 2);
+ LoadPalette(GetPartyMenuPalBufferPtr(sHPBarYellowPalIds[1]), sHPBarPalOffsets[1] + palNum, 2);
+ break;
+ default:
+ LoadPalette(GetPartyMenuPalBufferPtr(sHPBarRedPalIds[0]), sHPBarPalOffsets[0] + palNum, 2);
+ LoadPalette(GetPartyMenuPalBufferPtr(sHPBarRedPalIds[1]), sHPBarPalOffsets[1] + palNum, 2);
+ break;
+ }
+ hpFraction = GetScaledHPFraction(hp, maxhp, menuBox->infoRects->dimensions[22]);
+ FillWindowPixelRect(menuBox->windowId, sHPBarPalOffsets[1], menuBox->infoRects->dimensions[20], menuBox->infoRects->dimensions[21], hpFraction, 1);
+ FillWindowPixelRect(menuBox->windowId, sHPBarPalOffsets[0], menuBox->infoRects->dimensions[20], menuBox->infoRects->dimensions[21] + 1, hpFraction, 2);
+ if (hpFraction != menuBox->infoRects->dimensions[22])
+ {
+ // This appears to be an alternating fill
+ FillWindowPixelRect(menuBox->windowId, 0x0D, menuBox->infoRects->dimensions[20] + hpFraction, menuBox->infoRects->dimensions[21], menuBox->infoRects->dimensions[22] - hpFraction, 1);
+ FillWindowPixelRect(menuBox->windowId, 0x02, menuBox->infoRects->dimensions[20] + hpFraction, menuBox->infoRects->dimensions[21] + 1, menuBox->infoRects->dimensions[22] - hpFraction, 2);
+ }
+ CopyWindowToVram(menuBox->windowId, 2);
+}
+
+static void DisplayPartyPokemonDescriptionText(u8 stringId, struct PartyMenuBox *menuBox, u8 c)
+{
+ if (c != 0)
+ menuBox->infoRects->blitFunc(menuBox->windowId, menuBox->infoRects->descTextLeft >> 3, menuBox->infoRects->descTextTop >> 3, menuBox->infoRects->descTextWidth >> 3, menuBox->infoRects->descTextHeight >> 3, TRUE);
+ if (c != 2)
+ AddTextPrinterParameterized3(menuBox->windowId, 1, menuBox->infoRects->descTextLeft, menuBox->infoRects->descTextTop, sFontColorTable[0], 0, sDescriptionStringTable[stringId]);
+}
+
+static void PartyMenuRemoveWindow(u8 *ptr)
+{
+ if (*ptr != 0xFF)
+ {
+ ClearStdWindowAndFrameToTransparent(*ptr, 0);
+ RemoveWindow(*ptr);
+ *ptr = 0xFF;
+ ScheduleBgCopyTilemapToVram(2);
+ }
+}
+
+void DisplayPartyMenuStdMessage(u32 stringId)
+{
+ u8 *windowPtr = &sPartyMenuInternal->windowId[1];
+
+ if (*windowPtr != 0xFF)
+ PartyMenuRemoveWindow(windowPtr);
+
+ if (stringId != PARTY_MSG_NONE)
+ {
+ switch (stringId)
+ {
+ case PARTY_MSG_DO_WHAT_WITH_MON:
+ *windowPtr = AddWindow(&sDoWhatWithMonMsgWindowTemplate);
+ break;
+ case PARTY_MSG_DO_WHAT_WITH_ITEM:
+ *windowPtr = AddWindow(&sDoWhatWithItemMsgWindowTemplate);
+ break;
+ case PARTY_MSG_DO_WHAT_WITH_MAIL:
+ *windowPtr = AddWindow(&sDoWhatWithMailMsgWindowTemplate);
+ break;
+ case PARTY_MSG_RESTORE_WHICH_MOVE:
+ case PARTY_MSG_BOOST_PP_WHICH_MOVE:
+ *windowPtr = AddWindow(&sWhichMoveMsgWindowTemplate);
+ break;
+ default:
+ *windowPtr = AddWindow(&sDefaultPartyMsgWindowTemplate);
+ break;
+ }
+
+ if (stringId == PARTY_MSG_CHOOSE_MON)
+ {
+ if (sPartyMenuInternal->chooseHalf)
+ stringId = PARTY_MSG_CHOOSE_MON_AND_CONFIRM;
+ else if (!ShouldUseChooseMonText())
+ stringId = PARTY_MSG_CHOOSE_MON_OR_CANCEL;
+ }
+ DrawStdFrameWithCustomTileAndPalette(*windowPtr, FALSE, 0x58, 0xF);
+ StringExpandPlaceholders(gStringVar4, sActionStringTable[stringId]);
+ AddTextPrinterParameterized(*windowPtr, 2, gStringVar4, 0, 2, 0, 0);
+ ScheduleBgCopyTilemapToVram(2);
+ }
+}
+
+static bool8 ShouldUseChooseMonText(void)
+{
+ struct Pokemon *party = gPlayerParty;
+ u8 i;
+ u8 numAliveMons = 0;
+
+ if (gPartyMenu.action == PARTY_ACTION_SEND_OUT)
+ return TRUE;
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE && (GetMonData(&party[i], MON_DATA_HP) != 0 || GetMonData(&party[i], MON_DATA_IS_EGG)))
+ ++numAliveMons;
+ if (numAliveMons > 1)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static u8 DisplaySelectionWindow(u8 windowType)
+{
+ struct WindowTemplate window;
+ u8 cursorDimension;
+ u8 fontAttribute;
+ u8 i;
+
+ switch (windowType)
+ {
+ case SELECTWINDOW_ACTIONS:
+ window = SetWindowTemplateFields(2, 19, 19 - (sPartyMenuInternal->numActions * 2), 10, sPartyMenuInternal->numActions * 2, 14, 0x2BF);
+ break;
+ case SELECTWINDOW_ITEM:
+ window = sItemGiveTakeWindowTemplate;
+ break;
+ case SELECTWINDOW_MAIL:
+ window = sMailReadTakeWindowTemplate;
+ break;
+ default: // SELECTWINDOW_MOVES
+ window = sMoveSelectWindowTemplate;
+ break;
+ }
+ sPartyMenuInternal->windowId[0] = AddWindow(&window);
+ DrawStdFrameWithCustomTileAndPalette(sPartyMenuInternal->windowId[0], FALSE, 0x4F, 13);
+ if (windowType == SELECTWINDOW_MOVES)
+ return sPartyMenuInternal->windowId[0];
+ cursorDimension = GetMenuCursorDimensionByFont(2, 0);
+ fontAttribute = GetFontAttribute(2, FONTATTR_LETTER_SPACING);
+ for (i = 0; i < sPartyMenuInternal->numActions; ++i)
+ {
+ u8 fontColorsId = (sPartyMenuInternal->actions[i] >= MENU_FIELD_MOVES) ? 4 : 3;
+
+ AddTextPrinterParameterized4(sPartyMenuInternal->windowId[0], 2, cursorDimension, (i * 16) + 2, fontAttribute, 0, sFontColorTable[fontColorsId], 0, sCursorOptions[sPartyMenuInternal->actions[i]].text);
+ }
+ Menu_InitCursorInternal(sPartyMenuInternal->windowId[0], 2, 0, 2, 16, sPartyMenuInternal->numActions, 0, 1);
+ ScheduleBgCopyTilemapToVram(2);
+ return sPartyMenuInternal->windowId[0];
+}
+
+static void PartyMenuPrintText(const u8 *text)
+{
+ DrawStdFrameWithCustomTileAndPalette(6, FALSE, 0x4F, 13);
+ gTextFlags.canABSpeedUpPrint = TRUE;
+ AddTextPrinterParameterized2(6, 2, text, GetTextSpeedSetting(), 0, 2, 1, 3);
+}
+
+static void PartyMenuDisplayYesNoMenu(void)
+{
+ CreateYesNoMenu(&sPartyMenuYesNoWindowTemplate, 2, 0, 2, 0x4F, 13, 0);
+}
+
+static u8 CreateLevelUpStatsWindow(void)
+{
+ sPartyMenuInternal->windowId[0] = AddWindow(&sLevelUpStatsWindowTemplate);
+ DrawStdFrameWithCustomTileAndPalette(sPartyMenuInternal->windowId[0], FALSE, 0x4F, 13);
+ return sPartyMenuInternal->windowId[0];
+}
+
+static void RemoveLevelUpStatsWindow(void)
+{
+ ClearWindowTilemap(sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+}
+
+static void sub_8122084(u8 windowId, const u8 *str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ gTextFlags.canABSpeedUpPrint = TRUE;
+ AddTextPrinterParameterized2(windowId, 4, gStringVar4, GetTextSpeedSetting(), 0, 2, 1, 3);
+}
+
+static bool8 sub_81220D4(void)
+{
+ u8 windowId = AddWindow(&gUnknown_845A170);
+
+ TextWindow_LoadResourcesStdFrame0(windowId, 0x4F, 0xE0);
+ DrawDialogFrameWithCustomTileAndPalette(windowId, 1, 0x4F, 0xE);
+ sub_8122084(windowId, gUnknown_8417457);
+ return windowId;
+}
+
+static void sub_8122110(u8 windowId)
+{
+ ClearWindowTilemap(windowId);
+ ClearDialogWindowAndFrameToTransparent(windowId, FALSE);
+ RemoveWindow(windowId);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void sub_8122138(u8 action)
+{
+ u8 attr;
+ struct PartyMenuInternal *ptr = sPartyMenuInternal;
+
+ if (action <= 17)
+ {
+ if (ptr->windowId[2] != 0xFF)
+ {
+ ClearWindowTilemap(ptr->windowId[2]);
+ RemoveWindow(ptr->windowId[2]);
+ ptr->windowId[2] = 0xFF;
+ ScheduleBgCopyTilemapToVram(2);
+ }
+ }
+ else
+ {
+ if (ptr->windowId[2] == 0xFF)
+ ptr->windowId[2] = AddWindow(&gUnknown_845A178);
+ sub_8112F18(ptr->windowId[2]);
+ attr = GetFontAttribute(2, FONTATTR_LETTER_SPACING);
+ AddTextPrinterParameterized4(ptr->windowId[2], 2, 3, 6, attr, 0, sFontColorTable[5], 0, sHMDescriptionTable[action - MENU_FIELD_MOVES]);
+ PutWindowTilemap(ptr->windowId[2]);
+ ScheduleBgCopyTilemapToVram(2);
+ }
+}
+
+static void CreatePartyMonIconSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox, u32 slot)
+{
+ bool32 handleDeoxys = TRUE;
+ u16 species2;
+
+ // If in a multi battle, show partners Deoxys icon as Normal forme
+ if (IsMultiBattle() == TRUE && gMain.inBattle)
+ handleDeoxys = (sMultiBattlePartnersPartyMask[slot] ^ handleDeoxys) ? TRUE : FALSE;
+ species2 = GetMonData(mon, MON_DATA_SPECIES2);
+ CreatePartyMonIconSpriteParameterized(species2, GetMonData(mon, MON_DATA_PERSONALITY), menuBox, 1, handleDeoxys);
+ UpdatePartyMonHPBar(menuBox->monSpriteId, mon);
+}
+
+static void CreatePartyMonIconSpriteParameterized(u16 species, u32 pid, struct PartyMenuBox *menuBox, u8 priority, bool32 handleDeoxys)
+{
+ if (species != SPECIES_NONE)
+ {
+ menuBox->monSpriteId = CreateMonIcon(species, SpriteCB_MonIcon, menuBox->spriteCoords[0], menuBox->spriteCoords[1], 4, pid, handleDeoxys);
+ gSprites[menuBox->monSpriteId].oam.priority = priority;
+ }
+}
+
+static void UpdateHPBar(u8 spriteId, u16 hp, u16 maxhp)
+{
+ switch (GetHPBarLevel(hp, maxhp))
+ {
+ case HP_BAR_FULL:
+ SetPartyHPBarSprite(&gSprites[spriteId], 0);
+ break;
+ case HP_BAR_GREEN:
+ SetPartyHPBarSprite(&gSprites[spriteId], 1);
+ break;
+ case HP_BAR_YELLOW:
+ SetPartyHPBarSprite(&gSprites[spriteId], 2);
+ break;
+ case HP_BAR_RED:
+ SetPartyHPBarSprite(&gSprites[spriteId], 3);
+ break;
+ default:
+ SetPartyHPBarSprite(&gSprites[spriteId], 4);
+ break;
+ }
+}
+
+static void UpdatePartyMonHPBar(u8 spriteId, struct Pokemon *mon)
+{
+ UpdateHPBar(spriteId, GetMonData(mon, MON_DATA_HP), GetMonData(mon, MON_DATA_MAX_HP));
+}
+
+static void AnimateSelectedPartyIcon(u8 spriteId, u8 animNum)
+{
+ gSprites[spriteId].data[0] = 0;
+ if (animNum == 0)
+ {
+ if (gSprites[spriteId].pos1.x == 16)
+ {
+ gSprites[spriteId].pos2.x = 0;
+ gSprites[spriteId].pos2.y = -4;
+ }
+ else
+ {
+ gSprites[spriteId].pos2.x = -4;
+ gSprites[spriteId].pos2.y = 0;
+ }
+ gSprites[spriteId].callback = SpriteCB_UpdatePartyMonIcon;
+ }
+ else
+ {
+ gSprites[spriteId].pos2.x = 0;
+ gSprites[spriteId].pos2.y = 0;
+ gSprites[spriteId].callback = SpriteCB_BouncePartyMonIcon;
+ }
+}
+
+static void SpriteCB_BouncePartyMonIcon(struct Sprite *sprite)
+{
+ u8 animCmd = UpdateMonIconFrame(sprite);
+
+ if (animCmd != 0)
+ {
+ if (animCmd & 1) // % 2 also matches
+ sprite->pos2.y = -3;
+ else
+ sprite->pos2.y = 1;
+ }
+}
+
+static void SpriteCB_UpdatePartyMonIcon(struct Sprite *sprite)
+{
+ UpdateMonIconFrame(sprite);
+}
+
+static void CreatePartyMonHeldItemSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
+{
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ menuBox->itemSpriteId = CreateSprite(&sSpriteTemplate_HeldItem, menuBox->spriteCoords[2], menuBox->spriteCoords[3], 0);
+ UpdatePartyMonHeldItemSprite(mon, menuBox);
+ }
+}
+
+static void CreatePartyMonHeldItemSpriteParameterized(u16 species, u16 item, struct PartyMenuBox *menuBox)
+{
+ if (species != SPECIES_NONE)
+ {
+ menuBox->itemSpriteId = CreateSprite(&sSpriteTemplate_HeldItem, menuBox->spriteCoords[2], menuBox->spriteCoords[3], 0);
+ gSprites[menuBox->itemSpriteId].oam.priority = 0;
+ ShowOrHideHeldItemSprite(item, menuBox);
+ }
+}
+
+static void UpdatePartyMonHeldItemSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
+{
+ ShowOrHideHeldItemSprite(GetMonData(mon, MON_DATA_HELD_ITEM), menuBox);
+}
+
+static void ShowOrHideHeldItemSprite(u16 item, struct PartyMenuBox *menuBox)
+{
+ if (item == ITEM_NONE)
+ {
+ gSprites[menuBox->itemSpriteId].invisible = TRUE;
+ }
+ else
+ {
+ if (ItemIsMail(item))
+ StartSpriteAnim(&gSprites[menuBox->itemSpriteId], 1);
+ else
+ StartSpriteAnim(&gSprites[menuBox->itemSpriteId], 0);
+ gSprites[menuBox->itemSpriteId].invisible = FALSE;
+ }
+}
+
+void LoadHeldItemIcons(void)
+{
+ LoadSpriteSheet(&sSpriteSheet_HeldItem);
+ LoadSpritePalette(&sSpritePalette_HeldItem);
+}
+
+void DrawHeldItemIconsForTrade(u8 *partyCounts, u8 *partySpriteIds, u8 whichParty)
+{
+ u16 i;
+ u16 item;
+
+ switch (whichParty)
+ {
+ case TRADE_PLAYER:
+ for (i = 0; i < partyCounts[TRADE_PLAYER]; ++i)
+ {
+ item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+ if (item != ITEM_NONE)
+ CreateHeldItemSpriteForTrade(partySpriteIds[i], ItemIsMail(item));
+ }
+ break;
+ case TRADE_PARTNER:
+ for (i = 0; i < partyCounts[TRADE_PARTNER]; ++i)
+ {
+ item = GetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM);
+ if (item != ITEM_NONE)
+ CreateHeldItemSpriteForTrade(partySpriteIds[i + PARTY_SIZE], ItemIsMail(item));
+ }
+ break;
+ }
+}
+
+static void CreateHeldItemSpriteForTrade(u8 spriteId, bool8 isMail)
+{
+ u8 subpriority = gSprites[spriteId].subpriority;
+ u8 newSpriteId = CreateSprite(&sSpriteTemplate_HeldItem, 250, 170, subpriority - 1);
+
+ gSprites[newSpriteId].pos2.x = 4;
+ gSprites[newSpriteId].pos2.y = 10;
+ gSprites[newSpriteId].callback = SpriteCB_HeldItem;
+ gSprites[newSpriteId].data[7] = spriteId;
+ StartSpriteAnim(&gSprites[newSpriteId], isMail);
+ gSprites[newSpriteId].callback(&gSprites[newSpriteId]);
+}
+
+static void SpriteCB_HeldItem(struct Sprite *sprite)
+{
+ u8 otherSpriteId = sprite->data[7];
+
+ if (gSprites[otherSpriteId].invisible)
+ {
+ sprite->invisible = TRUE;
+ }
+ else
+ {
+ sprite->invisible = FALSE;
+ sprite->pos1.x = gSprites[otherSpriteId].pos1.x + gSprites[otherSpriteId].pos2.x;
+ sprite->pos1.y = gSprites[otherSpriteId].pos1.y + gSprites[otherSpriteId].pos2.y;
+ }
+}
+
+static void CreatePartyMonPokeballSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
+{
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ menuBox->pokeballSpriteId = CreateSprite(&sSpriteTemplate_MenuPokeball, menuBox->spriteCoords[6], menuBox->spriteCoords[7], 8);
+}
+
+static void CreatePartyMonPokeballSpriteParameterized(u16 species, struct PartyMenuBox *menuBox)
+{
+ if (species != SPECIES_NONE)
+ {
+ menuBox->pokeballSpriteId = CreateSprite(&sSpriteTemplate_MenuPokeball, menuBox->spriteCoords[6], menuBox->spriteCoords[7], 8);
+ gSprites[menuBox->pokeballSpriteId].oam.priority = 0;
+ }
+}
+
+// For Cancel when Confirm isnt present
+static u8 CreatePokeballButtonSprite(u8 x, u8 y)
+{
+ u8 spriteId = CreateSprite(&sSpriteTemplate_MenuPokeball, x, y, 8);
+
+ gSprites[spriteId].oam.priority = 2;
+ return spriteId;
+}
+
+// For Confirm and Cancel when both are present
+static u8 CreateSmallPokeballButtonSprite(u8 x, u8 y)
+{
+ return CreateSprite(&sSpriteTemplate_MenuPokeballSmall, x, y, 8);
+}
+
+static void PartyMenuStartSpriteAnim(u8 spriteId, u8 animNum)
+{
+ StartSpriteAnim(&gSprites[spriteId], animNum);
+}
+
+// Unused. Might explain the large blank section in gPartyMenuPokeballSmall_Gfx
+// At the very least this is how the unused anim cmds for sSpriteAnimTable_MenuPokeballSmall were meant to be accessed
+void SpriteCB_BounceConfirmCancelButton(u8 spriteId, u8 spriteId2, u8 animNum)
+{
+ if (animNum == 0)
+ {
+ StartSpriteAnim(&gSprites[spriteId], 2);
+ StartSpriteAnim(&gSprites[spriteId2], 4);
+ gSprites[spriteId].pos2.y = 0;
+ gSprites[spriteId2].pos2.y = 0;
+ }
+ else
+ {
+ StartSpriteAnim(&gSprites[spriteId], 3);
+ StartSpriteAnim(&gSprites[spriteId2], 5);
+ gSprites[spriteId].pos2.y = -4;
+ gSprites[spriteId2].pos2.y = 4;
+ }
+}
+
+static void LoadPartyMenuPokeballGfx(void)
+{
+ LoadCompressedSpriteSheet(&sSpriteSheet_MenuPokeball);
+ LoadCompressedSpriteSheet(&sSpriteSheet_MenuPokeballSmall);
+ LoadCompressedSpritePalette(&sSpritePalette_MenuPokeball);
+}
+
+static void CreatePartyMonStatusSprite(struct Pokemon *mon, struct PartyMenuBox *menuBox)
+{
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE)
+ {
+ menuBox->statusSpriteId = CreateSprite(&sSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0);
+ SetPartyMonAilmentGfx(mon, menuBox);
+ }
+}
+
+static void CreatePartyMonStatusSpriteParameterized(u16 species, u8 status, struct PartyMenuBox *menuBox)
+{
+ if (species != SPECIES_NONE)
+ {
+ menuBox->statusSpriteId = CreateSprite(&sSpriteTemplate_StatusIcons, menuBox->spriteCoords[4], menuBox->spriteCoords[5], 0);
+ UpdatePartyMonAilmentGfx(status, menuBox);
+ gSprites[menuBox->statusSpriteId].oam.priority = 0;
+ }
+}
+
+static void SetPartyMonAilmentGfx(struct Pokemon *mon, struct PartyMenuBox *menuBox)
+{
+ UpdatePartyMonAilmentGfx(GetMonAilment(mon), menuBox);
+}
+
+static void UpdatePartyMonAilmentGfx(u8 status, struct PartyMenuBox *menuBox)
+{
+ switch (status)
+ {
+ case AILMENT_NONE:
+ case AILMENT_PKRS:
+ gSprites[menuBox->statusSpriteId].invisible = TRUE;
+ break;
+ default:
+ StartSpriteAnim(&gSprites[menuBox->statusSpriteId], status - 1);
+ gSprites[menuBox->statusSpriteId].invisible = FALSE;
+ break;
+ }
+}
+
+static void LoadPartyMenuAilmentGfx(void)
+{
+ LoadCompressedSpriteSheet(&sSpriteSheet_StatusIcons);
+ LoadCompressedSpritePalette(&sSpritePalette_StatusIcons);
+}
+
+static void SetPartyMonSelectionActions(struct Pokemon *mons, u8 slotId, u8 action)
+{
+ u8 i;
+
+ if (action == ACTIONS_NONE)
+ {
+ SetPartyMonFieldSelectionActions(mons, slotId);
+ }
+ else
+ {
+ sPartyMenuInternal->numActions = sPartyMenuActionCounts[action];
+ for (i = 0; i < sPartyMenuInternal->numActions; ++i)
+ sPartyMenuInternal->actions[i] = sPartyMenuActions[action][i];
+ }
+}
+
+static void SetPartyMonFieldSelectionActions(struct Pokemon *mons, u8 slotId)
+{
+ u8 i, j;
+
+ sPartyMenuInternal->numActions = 0;
+ AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SUMMARY);
+ // Add field moves to action list
+ for (i = 0; i < MAX_MON_MOVES; ++i)
+ {
+ for (j = 0; sFieldMoves[j] != FIELD_MOVE_END; ++j)
+ {
+ if (GetMonData(&mons[slotId], i + MON_DATA_MOVE1) == sFieldMoves[j])
+ {
+ AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, j + MENU_FIELD_MOVES);
+ break;
+ }
+ }
+ }
+ if (GetMonData(&mons[1], MON_DATA_SPECIES) != SPECIES_NONE)
+ AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_SWITCH);
+ if (ItemIsMail(GetMonData(&mons[slotId], MON_DATA_HELD_ITEM)))
+ AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_MAIL);
+ else
+ AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_ITEM);
+ AppendToList(sPartyMenuInternal->actions, &sPartyMenuInternal->numActions, MENU_CANCEL1);
+}
+
+static u8 GetPartyMenuActionsType(struct Pokemon *mon)
+{
+ u32 actionType;
+
+ switch (gPartyMenu.menuType)
+ {
+ case PARTY_MENU_TYPE_FIELD:
+ if (GetMonData(mon, MON_DATA_IS_EGG))
+ actionType = ACTIONS_SWITCH;
+ else
+ actionType = ACTIONS_NONE; // actions populated by SetPartyMonFieldSelectionActions
+ break;
+ case PARTY_MENU_TYPE_IN_BATTLE:
+ actionType = GetPartyMenuActionsTypeInBattle(mon);
+ break;
+ case PARTY_MENU_TYPE_CHOOSE_HALF:
+ switch (GetPartySlotEntryStatus(gPartyMenu.slotId))
+ {
+ default: // Not eligible
+ actionType = ACTIONS_SUMMARY_ONLY;
+ break;
+ case 0: // Eligible
+ actionType = ACTIONS_ENTER;
+ break;
+ case 1: // Already selected
+ actionType = ACTIONS_NO_ENTRY;
+ break;
+ }
+ break;
+ case PARTY_MENU_TYPE_DAYCARE:
+ actionType = (GetMonData(mon, MON_DATA_IS_EGG)) ? ACTIONS_SUMMARY_ONLY : ACTIONS_STORE;
+ break;
+ case PARTY_MENU_TYPE_UNION_ROOM_REGISTER:
+ actionType = ACTIONS_REGISTER;
+ break;
+ case PARTY_MENU_TYPE_UNION_ROOM_TRADE:
+ actionType = ACTIONS_TRADE;
+ break;
+ case PARTY_MENU_TYPE_SPIN_TRADE:
+ actionType = ACTIONS_SPIN_TRADE;
+ break;
+ // The following have no selection actions (i.e. they exit immediately upon selection)
+ // PARTY_MENU_TYPE_CONTEST
+ // PARTY_MENU_TYPE_CHOOSE_MON
+ // PARTY_MENU_TYPE_MULTI_SHOWCASE
+ // PARTY_MENU_TYPE_MOVE_RELEARNER
+ // PARTY_MENU_TYPE_MINIGAME
+ default:
+ actionType = ACTIONS_NONE;
+ break;
+ }
+ return actionType;
+}
+
+static void CreateSelectionWindow(void)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+
+ GetMonNickname(mon, gStringVar1);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, GetPartyMenuActionsType(mon));
+ DisplaySelectionWindow(SELECTWINDOW_ACTIONS);
+ DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_MON);
+}
+
+static void Task_TryCreateSelectionWindow(u8 taskId)
+{
+ CreateSelectionWindow();
+ gTasks[taskId].data[0] = 0xFF;
+ gTasks[taskId].func = Task_HandleSelectionMenuInput;
+}
+
+static void Task_HandleSelectionMenuInput(u8 taskId)
+{
+ if (!gPaletteFade.active && sub_80BF748() != TRUE)
+ {
+ s8 input;
+ s16 *data = gTasks[taskId].data;
+
+ if (sPartyMenuInternal->numActions <= 3)
+ input = Menu_ProcessInputNoWrapAround_other();
+ else
+ input = Menu_ProcessInput_other();
+ if (data[0] != Menu_GetCursorPos())
+ sub_8122138(sPartyMenuInternal->actions[Menu_GetCursorPos()]);
+ data[0] = Menu_GetCursorPos();
+ switch (input)
+ {
+ case MENU_NOTHING_CHOSEN:
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[2]);
+ sCursorOptions[sPartyMenuInternal->actions[sPartyMenuInternal->numActions - 1]].func(taskId);
+ break;
+ default:
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[2]);
+ sCursorOptions[sPartyMenuInternal->actions[input]].func(taskId);
+ break;
+ }
+ }
+}
+
+static void CursorCB_Summary(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ sPartyMenuInternal->exitCallback = CB2_ShowPokemonSummaryScreen;
+ Task_ClosePartyMenu(taskId);
+}
+
+static void CB2_ShowPokemonSummaryScreen(void)
+{
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
+ UpdatePartyToBattleOrder();
+ ShowPokemonSummaryScreen(gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuFromSummaryScreen, 0);
+}
+
+static void CB2_ReturnToPartyMenuFromSummaryScreen(void)
+{
+ gPaletteFade.bufferTransferDisabled = TRUE;
+ gPartyMenu.slotId = GetLastViewedMonIndex();
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_DO_WHAT_WITH_MON, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
+}
+
+static void CursorCB_Switch(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ gPartyMenu.action = PARTY_ACTION_SWITCH;
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ DisplayPartyMenuStdMessage(PARTY_MSG_MOVE_TO_WHERE);
+ AnimatePartySlot(gPartyMenu.slotId, 1);
+ gPartyMenu.slotId2 = gPartyMenu.slotId;
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+}
+
+#define tSlot1Left data[0]
+#define tSlot1Top data[1]
+#define tSlot1Width data[2]
+#define tSlot1Height data[3]
+#define tSlot2Left data[4]
+#define tSlot2Top data[5]
+#define tSlot2Width data[6]
+#define tSlot2Height data[7]
+#define tSlot1Offset data[8]
+#define tSlot2Offset data[9]
+#define tSlot1SlideDir data[10]
+#define tSlot2SlideDir data[11]
+
+static void SwitchSelectedMons(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ u8 windowIds[2];
+
+ if (gPartyMenu.slotId2 == gPartyMenu.slotId)
+ {
+ FinishTwoMonAction(taskId);
+ }
+ else
+ {
+ // Initialize switching party mons slide animation
+ sub_812358C();
+ windowIds[0] = sPartyMenuBoxes[gPartyMenu.slotId].windowId;
+ tSlot1Left = GetWindowAttribute(windowIds[0], WINDOW_TILEMAP_LEFT);
+ tSlot1Top = GetWindowAttribute(windowIds[0], WINDOW_TILEMAP_TOP);
+ tSlot1Width = GetWindowAttribute(windowIds[0], WINDOW_WIDTH);
+ tSlot1Height = GetWindowAttribute(windowIds[0], WINDOW_HEIGHT);
+ tSlot1Offset = 0;
+ if (tSlot1Width == 10)
+ tSlot1SlideDir = -1;
+ else
+ tSlot1SlideDir = 1;
+ windowIds[1] = sPartyMenuBoxes[gPartyMenu.slotId2].windowId;
+ tSlot2Left = GetWindowAttribute(windowIds[1], WINDOW_TILEMAP_LEFT);
+ tSlot2Top = GetWindowAttribute(windowIds[1], WINDOW_TILEMAP_TOP);
+ tSlot2Width = GetWindowAttribute(windowIds[1], WINDOW_WIDTH);
+ tSlot2Height = GetWindowAttribute(windowIds[1], WINDOW_HEIGHT);
+ tSlot2Offset = 0;
+ if (tSlot2Width == 10)
+ tSlot2SlideDir = -1;
+ else
+ tSlot2SlideDir = 1;
+ sSlot1TilemapBuffer = Alloc(tSlot1Width * (tSlot1Height << 1));
+ sSlot2TilemapBuffer = Alloc(tSlot2Width * (tSlot2Height << 1));
+ CopyToBufferFromBgTilemap(0, sSlot1TilemapBuffer, tSlot1Left, tSlot1Top, tSlot1Width, tSlot1Height);
+ CopyToBufferFromBgTilemap(0, sSlot2TilemapBuffer, tSlot2Left, tSlot2Top, tSlot2Width, tSlot2Height);
+ ClearWindowTilemap(windowIds[0]);
+ ClearWindowTilemap(windowIds[1]);
+ gPartyMenu.action = PARTY_ACTION_SWITCHING;
+ AnimatePartySlot(gPartyMenu.slotId, 1);
+ AnimatePartySlot(gPartyMenu.slotId2, 1);
+ SlidePartyMenuBoxOneStep(taskId);
+ gTasks[taskId].func = Task_SlideSelectedSlotsOffscreen;
+ }
+}
+
+// returns FALSE if the slot has slid fully offscreen / back onscreen
+static bool8 TryMovePartySlot(s16 x, s16 width, u8 *leftMove, u8 *newX, u8 *newWidth)
+{
+ if ((x + width) < 0)
+ return FALSE;
+ if (x > 31)
+ return FALSE;
+ if (x < 0)
+ {
+ *leftMove = x * -1;
+ *newX = 0;
+ *newWidth = width + x;
+ }
+ else
+ {
+ *leftMove = 0;
+ *newX = x;
+ if ((x + width) > 31)
+ *newWidth = 32 - x;
+ else
+ *newWidth = width;
+ }
+ return TRUE;
+}
+
+static void MoveAndBufferPartySlot(const void *rectSrc, s16 x, s16 y, s16 width, s16 height, s16 dir)
+{
+ // The use of the dimension parameters here is a mess
+ u8 leftMove, newX, newWidth; // leftMove is used as a srcX, newX is used as both x and srcHeight, newWidth is used as both width and destY
+
+ if (TryMovePartySlot(x, width, &leftMove, &newX, &newWidth))
+ {
+ FillBgTilemapBufferRect_Palette0(0, 0, newX, y, newWidth, height);
+ if (TryMovePartySlot(x + dir, width, &leftMove, &newX, &newWidth))
+ CopyRectToBgTilemapBufferRect(0, rectSrc, leftMove, 0, width, height, newX, y, newWidth, height, 17, 0, 0);
+ }
+}
+
+static void MovePartyMenuBoxSprites(struct PartyMenuBox *menuBox, s16 offset)
+{
+ gSprites[menuBox->pokeballSpriteId].pos2.x += offset * 8;
+ gSprites[menuBox->itemSpriteId].pos2.x += offset * 8;
+ gSprites[menuBox->monSpriteId].pos2.x += offset * 8;
+ gSprites[menuBox->statusSpriteId].pos2.x += offset * 8;
+}
+
+static void SlidePartyMenuBoxSpritesOneStep(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ if (tSlot1SlideDir != 0)
+ MovePartyMenuBoxSprites(&sPartyMenuBoxes[gPartyMenu.slotId], tSlot1SlideDir);
+ if (tSlot2SlideDir != 0)
+ MovePartyMenuBoxSprites(&sPartyMenuBoxes[gPartyMenu.slotId2], tSlot2SlideDir);
+}
+
+static void SlidePartyMenuBoxOneStep(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ if (tSlot1SlideDir != 0)
+ MoveAndBufferPartySlot(sSlot1TilemapBuffer, tSlot1Left + tSlot1Offset, tSlot1Top, tSlot1Width, tSlot1Height, tSlot1SlideDir);
+ if (tSlot2SlideDir != 0)
+ MoveAndBufferPartySlot(sSlot2TilemapBuffer, tSlot2Left + tSlot2Offset, tSlot2Top, tSlot2Width, tSlot2Height, tSlot2SlideDir);
+ ScheduleBgCopyTilemapToVram(0);
+}
+
+static void Task_SlideSelectedSlotsOffscreen(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ u16 slidingSlotPositions[2];
+
+ SlidePartyMenuBoxOneStep(taskId);
+ SlidePartyMenuBoxSpritesOneStep(taskId);
+ tSlot1Offset += tSlot1SlideDir;
+ tSlot2Offset += tSlot2SlideDir;
+ slidingSlotPositions[0] = tSlot1Left + tSlot1Offset;
+ slidingSlotPositions[1] = tSlot2Left + tSlot2Offset;
+ // Both slots have slid offscreen
+ if (slidingSlotPositions[0] > 33 && slidingSlotPositions[1] > 33)
+ {
+ tSlot1SlideDir *= -1;
+ tSlot2SlideDir *= -1;
+ SwitchPartyMon();
+ DisplayPartyPokemonData(gPartyMenu.slotId);
+ DisplayPartyPokemonData(gPartyMenu.slotId2);
+ PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId].windowId);
+ PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId2].windowId);
+ CopyToBufferFromBgTilemap(0, sSlot1TilemapBuffer, tSlot1Left, tSlot1Top, tSlot1Width, tSlot1Height);
+ CopyToBufferFromBgTilemap(0, sSlot2TilemapBuffer, tSlot2Left, tSlot2Top, tSlot2Width, tSlot2Height);
+ ClearWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId].windowId);
+ ClearWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId2].windowId);
+ gTasks[taskId].func = Task_SlideSelectedSlotsOnscreen;
+ }
+}
+
+static void Task_SlideSelectedSlotsOnscreen(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ SlidePartyMenuBoxOneStep(taskId);
+ SlidePartyMenuBoxSpritesOneStep(taskId);
+
+ // Both slots have slide back onscreen
+ if (tSlot1SlideDir == 0 && tSlot2SlideDir == 0)
+ {
+ PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId].windowId);
+ PutWindowTilemap(sPartyMenuBoxes[gPartyMenu.slotId2].windowId);
+ ScheduleBgCopyTilemapToVram(0);
+ // BUG: memory leak
+ // Free(sSlot1TilemapBuffer);
+ // Free(sSlot2TilemapBuffer);
+ FinishTwoMonAction(taskId);
+ }
+ // Continue sliding
+ else
+ {
+ tSlot1Offset += tSlot1SlideDir;
+ tSlot2Offset += tSlot2SlideDir;
+ if (tSlot1Offset == 0)
+ tSlot1SlideDir = 0;
+ if (tSlot2Offset == 0)
+ tSlot2SlideDir = 0;
+ }
+}
+
+static void SwitchMenuBoxSprites(u8 *spriteIdPtr1, u8 *spriteIdPtr2)
+{
+ u8 spriteIdBuffer = *spriteIdPtr1;
+ u16 xBuffer1, yBuffer1, xBuffer2, yBuffer2;
+
+ *spriteIdPtr1 = *spriteIdPtr2;
+ *spriteIdPtr2 = spriteIdBuffer;
+ xBuffer1 = gSprites[*spriteIdPtr1].pos1.x;
+ yBuffer1 = gSprites[*spriteIdPtr1].pos1.y;
+ xBuffer2 = gSprites[*spriteIdPtr1].pos2.x;
+ yBuffer2 = gSprites[*spriteIdPtr1].pos2.y;
+ gSprites[*spriteIdPtr1].pos1.x = gSprites[*spriteIdPtr2].pos1.x;
+ gSprites[*spriteIdPtr1].pos1.y = gSprites[*spriteIdPtr2].pos1.y;
+ gSprites[*spriteIdPtr1].pos2.x = gSprites[*spriteIdPtr2].pos2.x;
+ gSprites[*spriteIdPtr1].pos2.y = gSprites[*spriteIdPtr2].pos2.y;
+ gSprites[*spriteIdPtr2].pos1.x = xBuffer1;
+ gSprites[*spriteIdPtr2].pos1.y = yBuffer1;
+ gSprites[*spriteIdPtr2].pos2.x = xBuffer2;
+ gSprites[*spriteIdPtr2].pos2.y = yBuffer2;
+}
+
+static void SwitchPartyMon(void)
+{
+ struct PartyMenuBox *menuBoxes[2];
+ struct Pokemon *mon1, *mon2;
+ struct Pokemon *monBuffer;
+
+ menuBoxes[0] = &sPartyMenuBoxes[gPartyMenu.slotId];
+ menuBoxes[1] = &sPartyMenuBoxes[gPartyMenu.slotId2];
+ mon1 = &gPlayerParty[gPartyMenu.slotId];
+ mon2 = &gPlayerParty[gPartyMenu.slotId2];
+ monBuffer = Alloc(sizeof(struct Pokemon));
+ *monBuffer = *mon1;
+ *mon1 = *mon2;
+ *mon2 = *monBuffer;
+ Free(monBuffer);
+ SwitchMenuBoxSprites(&menuBoxes[0]->pokeballSpriteId, &menuBoxes[1]->pokeballSpriteId);
+ SwitchMenuBoxSprites(&menuBoxes[0]->itemSpriteId, &menuBoxes[1]->itemSpriteId);
+ SwitchMenuBoxSprites(&menuBoxes[0]->monSpriteId, &menuBoxes[1]->monSpriteId);
+ SwitchMenuBoxSprites(&menuBoxes[0]->statusSpriteId, &menuBoxes[1]->statusSpriteId);
+}
+
+static void sub_812358C(void)
+{
+ u16 *buffer = Alloc(2 * sizeof(u16));
+
+ buffer[0] = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES2);
+ buffer[1] = GetMonData(&gPlayerParty[gPartyMenu.slotId2], MON_DATA_SPECIES2);
+ sub_8113550(3, buffer);
+ Free(buffer);
+}
+
+// Finish switching mons or using Softboiled
+static void FinishTwoMonAction(u8 taskId)
+{
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ gPartyMenu.action = PARTY_ACTION_CHOOSE_MON;
+ AnimatePartySlot(gPartyMenu.slotId, 0);
+ gPartyMenu.slotId = gPartyMenu.slotId2;
+ AnimatePartySlot(gPartyMenu.slotId2, 1);
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+}
+
+#undef tSlot1Left
+#undef tSlot1Top
+#undef tSlot1Width
+#undef tSlot1Height
+#undef tSlot2Left
+#undef tSlot2Top
+#undef tSlot2Width
+#undef tSlot2Height
+#undef tSlot1Offset
+#undef tSlot2Offset
+#undef tSlot1SlideDir
+#undef tSlot2SlideDir
+
+static void CursorCB_Cancel1(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_DAYCARE)
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON_2);
+ else
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+}
+
+static void CursorCB_Item(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, ACTIONS_ITEM);
+ DisplaySelectionWindow(SELECTWINDOW_ITEM);
+ DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_ITEM);
+ gTasks[taskId].data[0] = 0xFF;
+ gTasks[taskId].func = Task_HandleSelectionMenuInput;
+}
+
+static void CursorCB_Give(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ sPartyMenuInternal->exitCallback = CB2_SelectBagItemToGive;
+ Task_ClosePartyMenu(taskId);
+}
+
+void CB2_SelectBagItemToGive(void)
+{
+ GoToBagMenu(1, 3, CB2_GiveHoldItem);
+}
+
+void CB2_GiveHoldItem(void)
+{
+ if (gSpecialVar_ItemId == ITEM_NONE)
+ {
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
+ }
+ else
+ {
+ sPartyMenuItemId = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
+ // Already holding item
+ if (sPartyMenuItemId != ITEM_NONE)
+ {
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_SwitchHoldItemsPrompt, gPartyMenu.exitCallback);
+ }
+ // Give mail
+ else if (ItemIsMail(gSpecialVar_ItemId))
+ {
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId);
+ CB2_WriteMailToGiveMon();
+ }
+ // Give item
+ else
+ {
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_GiveHoldItem, gPartyMenu.exitCallback);
+ }
+ }
+}
+
+static void Task_GiveHoldItem(u8 taskId)
+{
+ u16 item;
+
+ if (!gPaletteFade.active)
+ {
+ item = gSpecialVar_ItemId;
+ DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], item, FALSE, 0);
+ GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item);
+ RemoveBagItem(item, 1);
+ gTasks[taskId].func = Task_UpdateHeldItemSprite;
+ }
+}
+
+static void Task_SwitchHoldItemsPrompt(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ DisplayAlreadyHoldingItemSwitchMessage(&gPlayerParty[gPartyMenu.slotId], sPartyMenuItemId, TRUE);
+ gTasks[taskId].func = Task_SwitchItemsYesNo;
+ }
+}
+
+static void Task_SwitchItemsYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleSwitchItemsYesNoInput;
+ }
+}
+
+static void Task_HandleSwitchItemsYesNoInput(u8 taskId)
+{
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0: // Yes, switch items
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+
+ // No room to return held item to bag
+ if (AddBagItem(sPartyMenuItemId, 1) == FALSE)
+ {
+ AddBagItem(gSpecialVar_ItemId, 1);
+ BufferBagFullCantTakeItemMessage(sPartyMenuItemId);
+ DisplayPartyMenuMessage(gStringVar4, FALSE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ }
+ // Giving mail
+ else if (ItemIsMail(gSpecialVar_ItemId))
+ {
+ GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId);
+ gTasks[taskId].func = Task_WriteMailToGiveMonAfterText;
+ }
+ // Giving item
+ else
+ {
+ GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId);
+ DisplaySwitchedHeldItemMessage(gSpecialVar_ItemId, sPartyMenuItemId, TRUE);
+ gTasks[taskId].func = Task_UpdateHeldItemSprite;
+ }
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1: // No
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ break;
+ }
+}
+
+static void Task_WriteMailToGiveMonAfterText(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMon;
+ Task_ClosePartyMenu(taskId);
+ }
+}
+
+static void CB2_WriteMailToGiveMon(void)
+{
+ u8 mail = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_MAIL);
+
+ DoEasyChatScreen(EASY_CHAT_TYPE_MAIL,
+ gSaveBlock1Ptr->mail[mail].words,
+ CB2_ReturnToPartyMenuFromWritingMail);
+}
+
+static void CB2_ReturnToPartyMenuFromWritingMail(void)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
+
+ // Canceled writing mail
+ if (gSpecialVar_Result == FALSE)
+ {
+ TakeMailFromMon(mon);
+ SetMonData(mon, MON_DATA_HELD_ITEM, &sPartyMenuItemId);
+ RemoveBagItem(sPartyMenuItemId, 1);
+ AddBagItem(item, 1);
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_CHOOSE_MON, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
+ }
+ // Wrote mail
+ else
+ {
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_CHOOSE_MON, Task_DisplayGaveMailFromPartyMessage, gPartyMenu.exitCallback);
+ }
+}
+
+// Nearly redundant with Task_DisplayGaveMailFromBagMessgae
+static void Task_DisplayGaveMailFromPartyMessage(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ if (sPartyMenuItemId == ITEM_NONE)
+ DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId, FALSE, 0);
+ else
+ DisplaySwitchedHeldItemMessage(gSpecialVar_ItemId, sPartyMenuItemId, FALSE);
+ gTasks[taskId].func = Task_UpdateHeldItemSprite;
+ }
+}
+
+static void Task_UpdateHeldItemSprite(u8 taskId)
+{
+ s8 slotId = gPartyMenu.slotId;
+
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ UpdatePartyMonHeldItemSprite(&gPlayerParty[slotId], &sPartyMenuBoxes[slotId]);
+ Task_ReturnToChooseMonAfterText(taskId);
+ }
+}
+
+static void CursorCB_TakeItem(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
+
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ switch (TryTakeMonItem(mon))
+ {
+ case 0: // Not holding item
+ GetMonNickname(mon, gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnNotHolding);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ break;
+ case 1: // No room to take item
+ BufferBagFullCantTakeItemMessage(item);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ break;
+ default: // Took item
+ DisplayTookHeldItemMessage(mon, item, TRUE);
+ break;
+ }
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_UpdateHeldItemSprite;
+}
+
+static void CursorCB_Mail(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, ACTIONS_MAIL);
+ DisplaySelectionWindow(SELECTWINDOW_MAIL);
+ DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_MAIL);
+ gTasks[taskId].data[0] = 0xFF;
+ gTasks[taskId].func = Task_HandleSelectionMenuInput;
+}
+
+static void CursorCB_Read(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ sPartyMenuInternal->exitCallback = CB2_ReadHeldMail;
+ Task_ClosePartyMenu(taskId);
+}
+
+static void CB2_ReadHeldMail(void)
+{
+ ReadMail(&gSaveBlock1Ptr->mail[GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_MAIL)], CB2_ReturnToPartyMenuFromReadingMail, 1);
+}
+
+static void CB2_ReturnToPartyMenuFromReadingMail(void)
+{
+ gPaletteFade.bufferTransferDisabled = TRUE;
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_DO_WHAT_WITH_MON, Task_TryCreateSelectionWindow, gPartyMenu.exitCallback);
+}
+
+static void CursorCB_TakeMail(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ DisplayPartyMenuMessage(gText_SendMailToPC, TRUE);
+ gTasks[taskId].func = Task_SendMailToPCYesNo;
+}
+
+static void Task_SendMailToPCYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleSendMailToPCYesNoInput;
+ }
+}
+
+static void Task_HandleSendMailToPCYesNoInput(u8 taskId)
+{
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0: // Yes, send to PC
+ if (TakeMailFromMon2(&gPlayerParty[gPartyMenu.slotId]) != 0xFF)
+ {
+ DisplayPartyMenuMessage(gText_MailSentToPC, FALSE);
+ gTasks[taskId].func = Task_UpdateHeldItemSprite;
+ }
+ else
+ {
+ DisplayPartyMenuMessage(gText_PCMailboxFull, FALSE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ }
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1:
+ DisplayPartyMenuMessage(gText_MailMessageWillBeLost, TRUE);
+ gTasks[taskId].func = Task_LoseMailMessageYesNo;
+ break;
+ }
+}
+
+static void Task_LoseMailMessageYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleLoseMailMessageYesNoInput;
+ }
+}
+
+static void Task_HandleLoseMailMessageYesNoInput(u8 taskId)
+{
+ u16 item;
+
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0: // Yes, lose mail message
+ item = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
+ if (AddBagItem(item, 1) == TRUE)
+ {
+ TakeMailFromMon(&gPlayerParty[gPartyMenu.slotId]);
+ DisplayPartyMenuMessage(gText_MailTakenFromPkmn, FALSE);
+ gTasks[taskId].func = Task_UpdateHeldItemSprite;
+ }
+ else
+ {
+ BufferBagFullCantTakeItemMessage(item);
+ DisplayPartyMenuMessage(gStringVar4, FALSE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ }
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1:
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ break;
+ }
+}
+
+static void CursorCB_Cancel2(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ SetPartyMonSelectionActions(gPlayerParty, gPartyMenu.slotId, GetPartyMenuActionsType(mon));
+ DisplaySelectionWindow(SELECTWINDOW_ACTIONS);
+ DisplayPartyMenuStdMessage(PARTY_MSG_DO_WHAT_WITH_MON);
+ gTasks[taskId].data[0] = 0xFF;
+ gTasks[taskId].func = Task_HandleSelectionMenuInput;
+}
+
+static void CursorCB_SendMon(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ if (TrySwitchInPokemon() == TRUE)
+ {
+ Task_ClosePartyMenu(taskId);
+ }
+ else
+ {
+ // gStringVar4 below is the error message buffered by TrySwitchInPokemon
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ }
+}
+
+static void CursorCB_Enter(u8 taskId)
+{
+ u8 maxBattlers;
+ u8 i;
+ const u8 *str;
+
+ if (gPartyMenu.unk_8_6 == 2)
+ {
+ maxBattlers = 2;
+ str = gUnknown_8416B3E;
+ }
+ else
+ {
+ maxBattlers = 3;
+ str = gUnknown_8416B16;
+ }
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ for (i = 0; i < maxBattlers; ++i)
+ {
+ if (gSelectedOrderFromParty[i] == 0)
+ {
+ PlaySE(SE_SELECT);
+ gSelectedOrderFromParty[i] = gPartyMenu.slotId + 1;
+ DisplayPartyPokemonDescriptionText(i + PARTYBOX_DESC_FIRST, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
+ if (i == (maxBattlers - 1))
+ MoveCursorToConfirm();
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+ return;
+ }
+ }
+ PlaySE(SE_HAZURE);
+ DisplayPartyMenuMessage(str, TRUE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+}
+
+static void MoveCursorToConfirm(void)
+{
+ AnimatePartySlot(gPartyMenu.slotId, 0);
+ gPartyMenu.slotId = PARTY_SIZE;
+ AnimatePartySlot(gPartyMenu.slotId, 1);
+}
+
+static void CursorCB_NoEntry(u8 taskId)
+{
+ u8 i;
+
+ PlaySE(SE_SELECT);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ for (i = 0; i < 3; ++i)
+ {
+ if (gSelectedOrderFromParty[i] == gPartyMenu.slotId + 1)
+ {
+ gSelectedOrderFromParty[i] = 0;
+ switch (i)
+ {
+ case 0:
+ gSelectedOrderFromParty[0] = gSelectedOrderFromParty[1];
+ gSelectedOrderFromParty[1] = gSelectedOrderFromParty[2];
+ gSelectedOrderFromParty[2] = 0;
+ break;
+ case 1:
+ gSelectedOrderFromParty[1] = gSelectedOrderFromParty[2];
+ gSelectedOrderFromParty[2] = 0;
+ break;
+ }
+ break;
+ }
+ }
+ DisplayPartyPokemonDescriptionText(PARTYBOX_DESC_ABLE_3, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
+ if (gSelectedOrderFromParty[0] != 0)
+ DisplayPartyPokemonDescriptionText(PARTYBOX_DESC_FIRST, &sPartyMenuBoxes[gSelectedOrderFromParty[0] - 1], 1);
+ if (gSelectedOrderFromParty[1] != 0)
+ DisplayPartyPokemonDescriptionText(1 + PARTYBOX_DESC_FIRST, &sPartyMenuBoxes[gSelectedOrderFromParty[1] - 1], 1);
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+}
+
+static void CursorCB_Store(u8 taskId)
+{
+ PlaySE(SE_SELECT);
+ gSpecialVar_0x8004 = gPartyMenu.slotId;
+ Task_ClosePartyMenu(taskId);
+}
+
+// Register mon for the Trading Board in Union Room
+static void CursorCB_Register(u8 taskId)
+{
+ u16 species2 = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES2);
+ u16 species = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
+ u8 obedience = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_OBEDIENCE);
+
+ switch (CanRegisterMonForTradingBoard(*(struct UnkLinkRfuStruct_02022B14Substruct *)sub_80F9800(), species2, species, obedience))
+ {
+ case CANT_REGISTER_MON:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnCantBeTradedNow);
+ break;
+ case CANT_REGISTER_EGG:
+ StringExpandPlaceholders(gStringVar4, gText_EggCantBeTradedNow);
+ break;
+ default:
+ PlaySE(SE_SELECT);
+ Task_ClosePartyMenu(taskId);
+ return;
+ }
+ PlaySE(SE_HAZURE);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ StringAppend(gStringVar4, gText_PauseUntilPress);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+}
+
+static void CursorCB_Trade1(u8 taskId)
+{
+ u16 species2 = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES2);
+ u16 species = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
+ u8 obedience = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_OBEDIENCE);
+ u32 stringId = GetUnionRoomTradeMessageId(*(struct UnkLinkRfuStruct_02022B14Substruct *)sub_80F9800(), gUnknown_203B064, species2, gUnionRoomOfferedSpecies, gUnionRoomRequestedMonType, species, obedience);
+
+ if (stringId != UR_TRADE_MSG_NONE)
+ {
+ StringExpandPlaceholders(gStringVar4, sUnionRoomTradeMessages[stringId - 1]);
+ PlaySE(SE_HAZURE);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ StringAppend(gStringVar4, gText_PauseUntilPress);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ Task_ClosePartyMenu(taskId);
+ }
+}
+
+// Spin Trade (based on the translation of the Japanese trade prompt)
+// Not implemented, and normally unreachable because PARTY_MENU_TYPE_SPIN_TRADE is never used
+static void CursorCB_Trade2(u8 taskId)
+{
+}
+
+static void CursorCB_FieldMove(u8 taskId)
+{
+ u8 fieldMove = sPartyMenuInternal->actions[Menu_GetCursorPos()] - MENU_FIELD_MOVES;
+ const struct MapHeader *mapHeader;
+
+ PlaySE(SE_SELECT);
+ if (sFieldMoveCursorCallbacks[fieldMove].fieldMoveFunc == NULL)
+ return;
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
+ if (MenuHelpers_LinkSomething() == TRUE || InUnionRoom() == TRUE)
+ {
+ if (fieldMove == FIELD_MOVE_MILK_DRINK || fieldMove == FIELD_MOVE_SOFT_BOILED)
+ DisplayPartyMenuStdMessage(PARTY_MSG_CANT_USE_HERE);
+ else
+ DisplayPartyMenuStdMessage(sFieldMoveCursorCallbacks[fieldMove].msgId);
+ gTasks[taskId].func = Task_CancelAfterAorBPress;
+ }
+ else
+ {
+ // All field moves before WATERFALL are HMs.
+ if (fieldMove <= FIELD_MOVE_WATERFALL && FlagGet(FLAG_BADGE01_GET + fieldMove) != TRUE)
+ {
+ DisplayPartyMenuMessage(gText_CantUseUntilNewBadge, TRUE);
+ gTasks[taskId].func = Task_ReturnToChooseMonAfterText;
+ }
+ else if (sFieldMoveCursorCallbacks[fieldMove].fieldMoveFunc() == TRUE)
+ {
+ switch (fieldMove)
+ {
+ case FIELD_MOVE_MILK_DRINK:
+ case FIELD_MOVE_SOFT_BOILED:
+ ChooseMonForSoftboiled(taskId);
+ break;
+ case FIELD_MOVE_TELEPORT:
+ mapHeader = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->lastHealLocation.mapGroup, gSaveBlock1Ptr->lastHealLocation.mapNum);
+ GetMapNameGeneric(gStringVar1, mapHeader->regionMapSectionId);
+ StringExpandPlaceholders(gStringVar4, gText_ReturnToHealingSpot);
+ DisplayFieldMoveExitAreaMessage(taskId);
+ sPartyMenuInternal->data[0] = fieldMove;
+ break;
+ case FIELD_MOVE_DIG:
+ mapHeader = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->escapeWarp.mapGroup, gSaveBlock1Ptr->escapeWarp.mapNum);
+ GetMapNameGeneric(gStringVar1, mapHeader->regionMapSectionId);
+ StringExpandPlaceholders(gStringVar4, gText_EscapeFromHereAndReturnTo);
+ DisplayFieldMoveExitAreaMessage(taskId);
+ sPartyMenuInternal->data[0] = fieldMove;
+ break;
+ case FIELD_MOVE_FLY:
+ gPartyMenu.exitCallback = MCB2_FlyMap;
+ Task_ClosePartyMenu(taskId);
+ break;
+ default:
+ gPartyMenu.exitCallback = CB2_ReturnToField;
+ sub_8124BB0(&gPlayerParty[GetCursorSelectionMonId()], fieldMove);
+ Task_ClosePartyMenu(taskId);
+ break;
+ }
+ }
+ // Cant use Field Move
+ else
+ {
+ switch (fieldMove)
+ {
+ case FIELD_MOVE_SURF:
+ DisplayCantUseSurfMessage();
+ break;
+ case FIELD_MOVE_FLASH:
+ DisplayCantUseFlashMessage();
+ break;
+ default:
+ DisplayPartyMenuStdMessage(sFieldMoveCursorCallbacks[fieldMove].msgId);
+ break;
+ }
+ gTasks[taskId].func = Task_CancelAfterAorBPress;
+ }
+ }
+}
+
+static void DisplayFieldMoveExitAreaMessage(u8 taskId)
+{
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ gTasks[taskId].func = Task_FieldMoveExitAreaYesNo;
+}
+
+static void Task_FieldMoveExitAreaYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleFieldMoveExitAreaYesNoInput;
+ }
+}
+
+static void Task_HandleFieldMoveExitAreaYesNoInput(u8 taskId)
+{
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ gPartyMenu.exitCallback = CB2_ReturnToField;
+ sub_8124BB0(&gPlayerParty[GetCursorSelectionMonId()], sPartyMenuInternal->data[0]);
+ Task_ClosePartyMenu(taskId);
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1:
+ gFieldCallback2 = NULL;
+ gPostMenuFieldCallback = NULL;
+ Task_ReturnToChooseMonAfterText(taskId);
+ break;
+ }
+}
+
+bool8 FieldCallback_PrepareFadeInFromMenu(void)
+{
+ sub_807DC00();
+ CreateTask(Task_FieldMoveWaitForFade, 8);
+ return TRUE;
+}
+
+static void Task_FieldMoveWaitForFade(u8 taskId)
+{
+ if (IsWeatherNotFadingIn() == TRUE)
+ {
+ gFieldEffectArguments[0] = GetFieldMoveMonSpecies();
+ gPostMenuFieldCallback();
+ DestroyTask(taskId);
+ }
+}
+
+static u16 GetFieldMoveMonSpecies(void)
+{
+ return GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES);
+}
+
+static void Task_CancelAfterAorBPress(u8 taskId)
+{
+ if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON))
+ CursorCB_Cancel1(taskId);
+}
+
+static void DisplayCantUseFlashMessage(void)
+{
+ if (FlagGet(FLAG_SYS_FLASH_ACTIVE) == TRUE)
+ DisplayPartyMenuStdMessage(PARTY_MSG_ALREADY_IN_USE);
+ else
+ DisplayPartyMenuStdMessage(PARTY_MSG_CANT_USE_HERE);
+}
+
+static void FieldCallback_Surf(void)
+{
+ gFieldEffectArguments[0] = GetCursorSelectionMonId();
+ FieldEffectStart(FLDEFF_USE_SURF);
+}
+
+static bool8 SetUpFieldMove_Surf(void)
+{
+ s16 x, y;
+
+ GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
+ if (MetatileBehavior_IsSemiDeepWater(MapGridGetMetatileBehaviorAt(x, y)) != TRUE
+ && PartyHasMonWithSurf() == TRUE
+ && IsPlayerFacingSurfableFishableWater() == TRUE)
+ {
+ gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
+ gPostMenuFieldCallback = FieldCallback_Surf;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void DisplayCantUseSurfMessage(void)
+{
+ s16 x, y;
+
+ if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING))
+ {
+ DisplayPartyMenuStdMessage(PARTY_MSG_ALREADY_SURFING);
+ }
+ else
+ {
+ GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
+ if (MetatileBehavior_IsSemiDeepWater(MapGridGetMetatileBehaviorAt(x, y)) == TRUE)
+ DisplayPartyMenuStdMessage(PARTY_MSG_CURRENT_TOO_FAST);
+ else if ((gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE17))
+ && ((gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE17))
+ || (gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE18))))
+ DisplayPartyMenuStdMessage(PARTY_MSG_ENJOY_CYCLING);
+ else
+ DisplayPartyMenuStdMessage(PARTY_MSG_CANT_SURF_HERE);
+ }
+}
+
+static bool8 SetUpFieldMove_Fly(void)
+{
+ if (Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void CB2_ReturnToPartyMenuFromFlyMap(void)
+{
+ InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, TRUE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ReturnToFieldWithOpenMenu);
+}
+
+static void FieldCallback_Waterfall(void)
+{
+ gFieldEffectArguments[0] = GetCursorSelectionMonId();
+ FieldEffectStart(FLDEFF_USE_WATERFALL);
+}
+
+static bool8 SetUpFieldMove_Waterfall(void)
+{
+ s16 x, y;
+
+ GetXYCoordsOneStepInFrontOfPlayer(&x, &y);
+ if (MetatileBehavior_IsWaterfall(MapGridGetMetatileBehaviorAt(x, y)) == TRUE && IsPlayerSurfingNorth() == TRUE)
+ {
+ gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
+ gPostMenuFieldCallback = FieldCallback_Waterfall;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void sub_8124B60(struct Pokemon *mon, u16 item, u16 item2)
+{
+ u16 *ptr = Alloc(4 * sizeof(u16));
+
+ ptr[2] = GetMonData(mon, MON_DATA_SPECIES2);
+ ptr[0] = item;
+ ptr[1] = item2;
+ if (gPartyMenu.action == PARTY_ACTION_GIVE_PC_ITEM)
+ sub_8113550(10, ptr);
+ else
+ sub_8113550(9, ptr);
+ Free(ptr);
+}
+
+struct FieldMoveWarpParams
+{
+ u16 species;
+ u8 fieldMove;
+ u8 regionMapSectionId;
+};
+
+static void sub_8124BB0(struct Pokemon *mon, u8 fieldMove)
+{
+ struct FieldMoveWarpParams *ptr = Alloc(sizeof(*ptr));
+
+ ptr->species = GetMonData(mon, MON_DATA_SPECIES2);
+ ptr->fieldMove = fieldMove;
+ switch (ptr->fieldMove)
+ {
+ case FIELD_MOVE_TELEPORT:
+ ptr->regionMapSectionId = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->lastHealLocation.mapGroup, gSaveBlock1Ptr->lastHealLocation.mapNum)->regionMapSectionId;
+ break;
+ case FIELD_MOVE_DIG:
+ ptr->regionMapSectionId = gMapHeader.regionMapSectionId;
+ break;
+ default:
+ ptr->regionMapSectionId = 0xFF;
+ }
+ sub_8113550(36, (u16 *)ptr);
+ Free(ptr);
+}
+
+void sub_8124C1C(const u8 *healLocCtrlData) // TODO: confirm the type of data chunk at 0x83F2EE0
+{
+ const struct MapHeader *mapHeader;
+ struct FieldMoveWarpParams *ptr2;
+ struct
+ {
+ s8 mapGroup;
+ s8 mapNum;
+ u32 unk_4;
+ } *ptr = Alloc(sizeof(*ptr));
+
+ ptr->mapGroup = healLocCtrlData[0];
+ ptr->mapNum = healLocCtrlData[1];
+ mapHeader = Overworld_GetMapHeaderByGroupAndId(ptr->mapGroup, ptr->mapNum);
+ Free(ptr);
+ ptr2 = Alloc(4);
+ ptr2->species = GetMonData(&gPlayerParty[GetCursorSelectionMonId()], MON_DATA_SPECIES2);
+ ptr2->fieldMove = FIELD_MOVE_FLY;
+ ptr2->regionMapSectionId = mapHeader->regionMapSectionId;
+ sub_8113550(36, (u16 *)ptr2);
+ Free(ptr2);
+}
+
+void CB2_ShowPartyMenuForItemUse(void)
+{
+ MainCallback callback = CB2_ReturnToBagMenu;
+ u8 partyLayout;
+ u8 menuType;
+ u8 i;
+ u8 msgId;
+ TaskFunc task;
+
+ if (gMain.inBattle)
+ {
+ menuType = PARTY_MENU_TYPE_IN_BATTLE;
+ partyLayout = GetPartyLayoutFromBattleType();
+ }
+ else
+ {
+ menuType = PARTY_MENU_TYPE_FIELD;
+ partyLayout = PARTY_LAYOUT_SINGLE;
+ }
+
+ if (GetItemEffectType(gSpecialVar_ItemId) == ITEM_EFFECT_SACRED_ASH)
+ {
+ gPartyMenu.slotId = 0;
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != SPECIES_NONE && GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0)
+ {
+ gPartyMenu.slotId = i;
+ break;
+ }
+ }
+ if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_BERRY_POUCH)
+ callback = CB2_ReturnToBerryPouchMenu;
+ task = Task_SetSacredAshCB;
+ msgId = PARTY_MSG_NONE;
+ }
+ else
+ {
+ switch (GetPocketByItemId(gSpecialVar_ItemId))
+ {
+ default:
+ msgId = PARTY_MSG_USE_ON_WHICH_MON;
+ break;
+ case POCKET_TM_CASE:
+ msgId = PARTY_MSG_TEACH_WHICH_MON;
+ callback = CB2_ReturnToTMCaseMenu;
+ break;
+ case POCKET_BERRY_POUCH:
+ msgId = PARTY_MSG_USE_ON_WHICH_MON;
+ callback = CB2_ReturnToBerryPouchMenu;
+ break;
+ }
+ task = Task_HandleChooseMonInput;
+ }
+ InitPartyMenu(menuType, partyLayout, PARTY_ACTION_USE_ITEM, TRUE, msgId, task, callback);
+}
+
+static void CB2_ReturnToBagMenu(void)
+{
+ GoToBagMenu(11, 3, NULL);
+}
+
+static void CB2_ReturnToTMCaseMenu(void)
+{
+ InitTMCase(5, NULL, 0xFF);
+}
+
+static void CB2_ReturnToBerryPouchMenu(void)
+{
+ InitBerryPouch(BERRYPOUCH_NA, NULL, 0xFF);
+}
+
+static void sub_8124DC0(u8 taskId)
+{
+ sPartyMenuInternal->exitCallback = sub_8124DE0;
+ Task_ClosePartyMenu(taskId);
+}
+
+static void sub_8124DE0(void)
+{
+ if (CheckIfItemIsTMHMOrEvolutionStone(gSpecialVar_ItemId) == 2) // Evolution stone
+ {
+ if (sub_8126C24() == TRUE)
+ sub_811C540(gPartyMenu.slotId, gSpecialVar_ItemId, sub_8126BD4);
+ else
+ sub_811C5AC(gPartyMenu.slotId, gSpecialVar_ItemId, gPartyMenu.exitCallback);
+ }
+ else
+ {
+ sub_811C540(gPartyMenu.slotId, gSpecialVar_ItemId, sub_8124E48);
+ }
+}
+
+static void sub_8124E48(void)
+{
+ if (ItemId_GetPocket(gSpecialVar_ItemId) == POCKET_TM_CASE
+ && sub_811D178() == 1)
+ {
+ GiveMoveToMon(&gPlayerParty[gPartyMenu.slotId], ItemIdToBattleMoveId(gSpecialVar_ItemId));
+ AdjustFriendship(&gPlayerParty[gPartyMenu.slotId], 4);
+ if (gSpecialVar_ItemId <= ITEM_TM50)
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ SetMainCallback2(gPartyMenu.exitCallback);
+ }
+ else
+ {
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, PARTY_ACTION_CHOOSE_MON, gPartyMenu.slotId, PARTY_MSG_NONE, Task_SetSacredAshCB, gPartyMenu.exitCallback);
+ }
+}
+
+static void sub_8124EFC(void)
+{
+ if (sub_811D178() == 1)
+ {
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u8 moveIdx = GetMoveSlotToReplace();
+ u16 move = GetMonData(mon, moveIdx + MON_DATA_MOVE1);
+
+ RemoveMonPPBonus(mon, moveIdx);
+ SetMonMoveSlot(mon, ItemIdToBattleMoveId(gSpecialVar_ItemId), moveIdx);
+ AdjustFriendship(mon, 4);
+ ItemUse_SetQuestLogEvent(4, mon, gSpecialVar_ItemId, move);
+ if (gSpecialVar_ItemId <= ITEM_TM50)
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ SetMainCallback2(gPartyMenu.exitCallback);
+ }
+ else
+ {
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, gPartyMenu.slotId, PARTY_MSG_NONE, Task_SetSacredAshCB, gPartyMenu.exitCallback);
+ }
+}
+
+static void Task_SetSacredAshCB(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
+ sPartyMenuInternal->exitCallback = CB2_SetUpExitToBattleScreen;
+ gItemUseCB(taskId, Task_ClosePartyMenuAfterText); // ItemUseCB_SacredAsh in this case
+ }
+}
+
+static bool8 IsHPRecoveryItem(u16 item)
+{
+ const u8 *effect;
+
+ if (item == ITEM_ENIGMA_BERRY)
+ effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
+ else
+ effect = gItemEffectTable[item - ITEM_POTION];
+ if (effect[4] & ITEM4_HEAL_HP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void GetMedicineItemEffectMessage(u16 item)
+{
+ switch (GetItemEffectType(item))
+ {
+ case ITEM_EFFECT_CURE_POISON:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfPoison);
+ break;
+ case ITEM_EFFECT_CURE_SLEEP:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnWokeUp2);
+ break;
+ case ITEM_EFFECT_CURE_BURN:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBurnHealed);
+ break;
+ case ITEM_EFFECT_CURE_FREEZE:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnThawedOut);
+ break;
+ case ITEM_EFFECT_CURE_PARALYSIS:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnCuredOfParalysis);
+ break;
+ case ITEM_EFFECT_CURE_CONFUSION:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnSnappedOutOfConfusion);
+ break;
+ case ITEM_EFFECT_CURE_INFATUATION:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnGotOverInfatuation);
+ break;
+ case ITEM_EFFECT_CURE_ALL_STATUS:
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBecameHealthy);
+ break;
+ case ITEM_EFFECT_HP_EV:
+ StringCopy(gStringVar2, gText_HP3);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
+ break;
+ case ITEM_EFFECT_ATK_EV:
+ StringCopy(gStringVar2, gText_Attack3);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
+ break;
+ case ITEM_EFFECT_DEF_EV:
+ StringCopy(gStringVar2, gText_Defense3);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
+ break;
+ case ITEM_EFFECT_SPEED_EV:
+ StringCopy(gStringVar2, gText_Speed2);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
+ break;
+ case ITEM_EFFECT_SPATK_EV:
+ StringCopy(gStringVar2, gText_SpAtk3);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
+ break;
+ case ITEM_EFFECT_SPDEF_EV:
+ StringCopy(gStringVar2, gText_SpDef3);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnBaseVar2StatIncreased);
+ break;
+ case ITEM_EFFECT_PP_UP:
+ case ITEM_EFFECT_PP_MAX:
+ StringExpandPlaceholders(gStringVar4, gText_MovesPPIncreased);
+ break;
+ case ITEM_EFFECT_HEAL_PP:
+ StringExpandPlaceholders(gStringVar4, gText_PPWasRestored);
+ break;
+ default:
+ StringExpandPlaceholders(gStringVar4, gText_WontHaveEffect);
+ break;
+ }
+}
+
+static bool8 NotUsingHPEVItemOnShedinja(struct Pokemon *mon, u16 item)
+{
+ if (GetItemEffectType(item) == ITEM_EFFECT_HP_EV && GetMonData(mon, MON_DATA_SPECIES) == SPECIES_SHEDINJA)
+ return FALSE;
+ return TRUE;
+}
+
+static bool8 IsItemFlute(u16 item)
+{
+ if (item == ITEM_BLUE_FLUTE || item == ITEM_RED_FLUTE || item == ITEM_YELLOW_FLUTE)
+ return TRUE;
+ return FALSE;
+}
+
+static bool8 ExecuteTableBasedItemEffect_(u8 partyMonIndex, u16 item, u8 monMoveIndex)
+{
+ if (gMain.inBattle)
+ return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, GetPartyIdFromBattleSlot(partyMonIndex), monMoveIndex);
+ else
+ return ExecuteTableBasedItemEffect(&gPlayerParty[partyMonIndex], item, partyMonIndex, monMoveIndex);
+}
+
+void ItemUseCB_Medicine(u8 taskId, TaskFunc func)
+{
+ u16 hp;
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 item = gSpecialVar_ItemId;
+ bool8 canHeal;
+
+ if (!NotUsingHPEVItemOnShedinja(mon, item))
+ {
+ canHeal = TRUE;
+ }
+ else
+ {
+ if (IsHPRecoveryItem(item) == TRUE)
+ {
+ hp = GetMonData(mon, MON_DATA_HP);
+ if (hp == GetMonData(mon, MON_DATA_MAX_HP))
+ canHeal = FALSE;
+ }
+ canHeal = PokemonItemUseNoEffect(mon, item, gPartyMenu.slotId, 0);
+ }
+ PlaySE(SE_SELECT);
+ if (canHeal)
+ {
+ gPartyMenuUseExitCallback = FALSE;
+ DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = func;
+ }
+ else
+ {
+ ItemUse_SetQuestLogEvent(4, mon, item, 0xFFFF);
+ sub_8124DC0(taskId);
+ gItemUseCB = ItemUseCB_MedicineStep;
+ }
+}
+
+void ItemUseCB_MedicineStep(u8 taskId, TaskFunc func)
+{
+ u16 hp = 0;
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 item = gSpecialVar_ItemId;
+ bool8 canHeal;
+
+ if (NotUsingHPEVItemOnShedinja(mon, item))
+ {
+ canHeal = IsHPRecoveryItem(item);
+ if (canHeal == TRUE)
+ {
+ hp = GetMonData(mon, MON_DATA_HP);
+ if (hp == GetMonData(mon, MON_DATA_MAX_HP))
+ canHeal = FALSE;
+ }
+ if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0))
+ {
+ WONT_HAVE_EFFECT:
+ gPartyMenuUseExitCallback = FALSE;
+ PlaySE(SE_SELECT);
+ DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = func;
+ return;
+ }
+ }
+ else
+ {
+ goto WONT_HAVE_EFFECT; // even loop wrap won't work
+ }
+ gPartyMenuUseExitCallback = TRUE;
+ if (!IsItemFlute(item))
+ {
+ PlaySE(SE_KAIFUKU);
+ if (gPartyMenu.action != PARTY_ACTION_REUSABLE_ITEM)
+ RemoveBagItem(item, 1);
+ }
+ else
+ {
+ PlaySE(SE_BIDORO);
+ }
+ SetPartyMonAilmentGfx(mon, &sPartyMenuBoxes[gPartyMenu.slotId]);
+ if (gSprites[sPartyMenuBoxes[gPartyMenu.slotId].statusSpriteId].invisible)
+ DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
+ if (canHeal == TRUE)
+ {
+ if (hp == 0)
+ AnimatePartySlot(gPartyMenu.slotId, 1);
+ PartyMenuModifyHP(taskId, gPartyMenu.slotId, 1, GetMonData(mon, MON_DATA_HP) - hp, Task_DisplayHPRestoredMessage);
+ ResetHPTaskData(taskId, 0, hp);
+ return;
+ }
+ else
+ {
+ GetMonNickname(mon, gStringVar1);
+ GetMedicineItemEffectMessage(item);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = func;
+ }
+}
+
+static void Task_DisplayHPRestoredMessage(u8 taskId)
+{
+ GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnHPRestoredByVar2);
+ DisplayPartyMenuMessage(gStringVar4, FALSE);
+ ScheduleBgCopyTilemapToVram(2);
+ HandleBattleLowHpMusicChange();
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+}
+
+static void Task_ClosePartyMenuAfterText(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ if (gPartyMenuUseExitCallback == FALSE)
+ sPartyMenuInternal->exitCallback = NULL;
+ Task_ClosePartyMenu(taskId);
+ }
+}
+
+static void ShowMoveSelectWindow(u8 slot)
+{
+ u8 i;
+ u8 moveCount = 0;
+ u8 fontId = 2;
+ u8 windowId = DisplaySelectionWindow(SELECTWINDOW_MOVES);
+ u16 move;
+
+ for (i = 0; i < MAX_MON_MOVES; ++i)
+ {
+ move = GetMonData(&gPlayerParty[slot], MON_DATA_MOVE1 + i);
+ AddTextPrinterParameterized(windowId,
+ fontId,
+ gMoveNames[move],
+ GetFontAttribute(fontId, FONTATTR_MAX_LETTER_WIDTH) + GetFontAttribute(fontId, FONTATTR_LETTER_SPACING),
+ (i * 16) + 2,
+ TEXT_SPEED_FF,
+ NULL);
+ if (move != MOVE_NONE)
+ ++moveCount;
+ }
+ Menu_InitCursor(windowId, fontId, 0, 2, 16, moveCount, FALSE);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void Task_HandleWhichMoveInput(u8 taskId)
+{
+ s8 input = Menu_ProcessInput();
+
+ if (input != MENU_NOTHING_CHOSEN)
+ {
+ if (input == MENU_B_PRESSED)
+ {
+ PlaySE(SE_SELECT);
+ ReturnToUseOnWhichMon(taskId);
+ }
+ else
+ {
+ SetSelectedMoveForPPItem(taskId);
+ }
+ }
+}
+
+void ItemUseCB_PPRecovery(u8 taskId, UNUSED TaskFunc func)
+{
+ const u8 *effect;
+ u16 item = gSpecialVar_ItemId;
+
+ if (item == ITEM_ENIGMA_BERRY)
+ effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
+ else
+ effect = gItemEffectTable[item - ITEM_POTION];
+
+ if (!(effect[4] & ITEM4_HEAL_PP_ONE))
+ {
+ gPartyMenu.data1 = 0;
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
+ TryUsePPItem(taskId);
+ else
+ sub_812580C(taskId);
+ }
+ else
+ {
+ PlaySE(SE_SELECT);
+ DisplayPartyMenuStdMessage(PARTY_MSG_RESTORE_WHICH_MOVE);
+ ShowMoveSelectWindow(gPartyMenu.slotId);
+ gTasks[taskId].func = Task_HandleWhichMoveInput;
+ }
+}
+
+static void SetSelectedMoveForPPItem(u8 taskId)
+{
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ gPartyMenu.data1 = Menu_GetCursorPos();
+ if (gPartyMenu.menuType == PARTY_MENU_TYPE_IN_BATTLE)
+ TryUsePPItem(taskId);
+ else
+ sub_812580C(taskId);
+}
+
+static void ReturnToUseOnWhichMon(u8 taskId)
+{
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+ sPartyMenuInternal->exitCallback = NULL;
+ PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
+ DisplayPartyMenuStdMessage(PARTY_MSG_USE_ON_WHICH_MON);
+}
+
+static void sub_812580C(u8 taskId)
+{
+ bool8 noEffect = PokemonItemUseNoEffect(&gPlayerParty[gPartyMenu.slotId],
+ gSpecialVar_ItemId,
+ gPartyMenu.slotId,
+ gPartyMenu.data1);
+ PlaySE(SE_SELECT);
+ if (noEffect)
+ {
+ gPartyMenuUseExitCallback = FALSE;
+ DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+ }
+ else
+ {
+ sub_8124DC0(taskId);
+ gItemUseCB = sub_8125898;
+ }
+}
+
+static void sub_8125898(u8 taskId, UNUSED TaskFunc func)
+{
+ u16 move;
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+
+ ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, (u8)gPartyMenu.data1);
+ gPartyMenuUseExitCallback = TRUE;
+ ItemUse_SetQuestLogEvent(4, mon, gSpecialVar_ItemId, 0xFFFF);
+ PlaySE(SE_KAIFUKU);
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ move = GetMonData(mon, gPartyMenu.data1 + MON_DATA_MOVE1);
+ StringCopy(gStringVar1, gMoveNames[move]);
+ GetMedicineItemEffectMessage(gSpecialVar_ItemId);
+ DisplayPartyMenuMessage(gStringVar4, 1);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+}
+
+static void TryUsePPItem(u8 taskId)
+{
+ u16 move = MOVE_NONE;
+ s16 *moveSlot = &gPartyMenu.data1;
+ u16 item = gSpecialVar_ItemId;
+ struct PartyMenu *ptr = &gPartyMenu;
+ struct Pokemon *mon;
+
+ if (ExecuteTableBasedItemEffect_(ptr->slotId, item, *moveSlot))
+ {
+ gPartyMenuUseExitCallback = FALSE;
+ PlaySE(SE_SELECT);
+ DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+ }
+ else
+ {
+ gPartyMenuUseExitCallback = TRUE;
+ mon = &gPlayerParty[ptr->slotId];
+ ItemUse_SetQuestLogEvent(4, mon, item, 0xFFFF);
+ PlaySE(SE_KAIFUKU);
+ RemoveBagItem(item, 1);
+ move = GetMonData(mon, MON_DATA_MOVE1 + *moveSlot);
+ StringCopy(gStringVar1, gMoveNames[move]);
+ GetMedicineItemEffectMessage(item);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+ }
+}
+
+void ItemUseCB_PPUp(u8 taskId, UNUSED TaskFunc func)
+{
+ PlaySE(SE_SELECT);
+ DisplayPartyMenuStdMessage(PARTY_MSG_BOOST_PP_WHICH_MOVE);
+ ShowMoveSelectWindow(gPartyMenu.slotId);
+ gTasks[taskId].func = Task_HandleWhichMoveInput;
+}
+
+u16 ItemIdToBattleMoveId(u16 item)
+{
+ u16 tmNumber = item - ITEM_TM01_FOCUS_PUNCH;
+
+ return sTMHMMoves[tmNumber];
+}
+
+bool8 IsMoveHm(u16 move)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_HIDDEN_MACHINES - 1; ++i) // no dive
+ if (sTMHMMoves[i + NUM_TECHNICAL_MACHINES] == move)
+ return TRUE;
+ return FALSE;
+}
+
+bool8 MonKnowsMove(struct Pokemon *mon, u16 move)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_MON_MOVES; ++i)
+ {
+ if (GetMonData(mon, MON_DATA_MOVE1 + i) == move)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void DisplayLearnMoveMessage(const u8 *str)
+{
+ StringExpandPlaceholders(gStringVar4, str);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void DisplayLearnMoveMessageAndClose(u8 taskId, const u8 *str)
+{
+ DisplayLearnMoveMessage(str);
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+}
+
+void ItemUseCB_TMHM(u8 taskId, UNUSED TaskFunc func)
+{
+ struct Pokemon *mon;
+ s16 *move;
+ u16 item;
+
+ PlaySE(SE_SELECT);
+ mon = &gPlayerParty[gPartyMenu.slotId];
+ move = &gPartyMenu.data1;
+ item = gSpecialVar_ItemId;
+ GetMonNickname(mon, gStringVar1);
+ move[0] = ItemIdToBattleMoveId(item);
+ StringCopy(gStringVar2, gMoveNames[move[0]]);
+ move[1] = 0;
+ switch (CanMonLearnTMTutor(mon, item, 0))
+ {
+ case CANNOT_LEARN_MOVE:
+ DisplayLearnMoveMessageAndClose(taskId, gText_PkmnCantLearnMove);
+ return;
+ case ALREADY_KNOWS_MOVE:
+ DisplayLearnMoveMessageAndClose(taskId, gText_PkmnAlreadyKnows);
+ return;
+ }
+ if (GiveMoveToMon(mon, move[0]) != MON_HAS_MAX_MOVES)
+ {
+ ItemUse_SetQuestLogEvent(4, mon, item, 0xFFFF);
+ sub_8124DC0(taskId);
+ gItemUseCB = ItemUseCB_LearnedMove;
+ }
+ else
+ {
+ DisplayLearnMoveMessage(gText_PkmnNeedsToReplaceMove);
+ gTasks[taskId].func = Task_ReplaceMoveYesNo;
+ }
+}
+
+static void ItemUseCB_LearnedMove(u8 taskId, UNUSED TaskFunc func)
+{
+ Task_LearnedMove(taskId);
+}
+
+static void Task_LearnedMove(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ s16 *move = &gPartyMenu.data1;
+ u16 item = gSpecialVar_ItemId;
+
+ if (move[1] == 0)
+ {
+ AdjustFriendship(mon, 4);
+ if (item < ITEM_HM01_CUT)
+ RemoveBagItem(item, 1);
+ }
+ GetMonNickname(mon, gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[move[0]]);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnLearnedMove3);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_DoLearnedMoveFanfareAfterText;
+}
+
+static void Task_DoLearnedMoveFanfareAfterText(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PlayFanfare(MUS_FANFA1);
+ gTasks[taskId].func = Task_LearnNextMoveOrClosePartyMenu;
+ }
+}
+
+static void Task_LearnNextMoveOrClosePartyMenu(u8 taskId)
+{
+ if (IsFanfareTaskInactive() && ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)))
+ {
+ if (gPartyMenu.learnMoveState == 1)
+ Task_TryLearningNextMove(taskId);
+ else
+ {
+ if (gPartyMenu.learnMoveState == 2) // never occurs
+ gSpecialVar_Result = TRUE;
+ Task_ClosePartyMenu(taskId);
+ }
+ }
+}
+
+static void Task_ReplaceMoveYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleReplaceMoveYesNoInput;
+ }
+}
+
+static void Task_HandleReplaceMoveYesNoInput(u8 taskId)
+{
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ DisplayPartyMenuMessage(gText_WhichMoveToForget, TRUE);
+ gTasks[taskId].func = Task_ShowSummaryScreenToForgetMove;
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1:
+ StopLearningMovePrompt(taskId);
+ break;
+ }
+}
+
+static void Task_ShowSummaryScreenToForgetMove(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ sPartyMenuInternal->exitCallback = CB2_ShowSummaryScreenToForgetMove;
+ Task_ClosePartyMenu(taskId);
+ }
+}
+
+static void CB2_ShowSummaryScreenToForgetMove(void)
+{
+ ShowSelectMovePokemonSummaryScreen(gPlayerParty, gPartyMenu.slotId, gPlayerPartyCount - 1, CB2_ReturnToPartyMenuWhileLearningMove, gPartyMenu.data1);
+}
+
+static void CB2_ReturnToPartyMenuWhileLearningMove(void)
+{
+ u8 moveIdx = GetMoveSlotToReplace();
+ u16 move;
+ s32 learnMoveState = gPartyMenu.learnMoveState;
+
+ if (learnMoveState == 0 && moveIdx != MAX_MON_MOVES)
+ {
+ move = GetMonData(&gPlayerParty[gPartyMenu.slotId], moveIdx + MON_DATA_MOVE1);
+ sub_811C568(gPartyMenu.slotId, gSpecialVar_ItemId, move, sub_8124EFC);
+ gItemUseCB = sub_8125F4C;
+ gPartyMenu.action = learnMoveState;
+ }
+ else
+ {
+ InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, TRUE, PARTY_MSG_NONE, Task_ReturnToPartyMenuWhileLearningMove, gPartyMenu.exitCallback);
+ }
+}
+
+static void Task_ReturnToPartyMenuWhileLearningMove(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ if (GetMoveSlotToReplace() != MAX_MON_MOVES)
+ DisplayPartyMenuForgotMoveMessage(taskId);
+ else
+ StopLearningMovePrompt(taskId);
+ }
+}
+
+static void sub_8125F4C(u8 taskId, UNUSED TaskFunc func)
+{
+ sub_8125F5C(taskId);
+}
+
+static void sub_8125F5C(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u8 moveIdx = GetMoveSlotToReplace();
+ u16 move = GetMonData(mon, moveIdx + MON_DATA_MOVE1);
+
+ ItemUse_SetQuestLogEvent(4, mon, gSpecialVar_ItemId, move);
+ GetMonNickname(mon, gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[move]);
+ RemoveMonPPBonus(mon, moveIdx);
+ SetMonMoveSlot(mon, gPartyMenu.data1, moveIdx);
+ Task_LearnedMove(taskId);
+}
+
+static void DisplayPartyMenuForgotMoveMessage(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 move = GetMonData(mon, MON_DATA_MOVE1 + GetMoveSlotToReplace());
+
+ GetMonNickname(mon, gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[move]);
+ DisplayLearnMoveMessage(gText_12PoofForgotMove);
+ gTasks[taskId].func = Task_PartyMenuReplaceMove;
+}
+
+static void Task_PartyMenuReplaceMove(u8 taskId)
+{
+ struct Pokemon *mon;
+ u16 move;
+
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ mon = &gPlayerParty[gPartyMenu.slotId];
+ RemoveMonPPBonus(mon, GetMoveSlotToReplace());
+ move = gPartyMenu.data1;
+ SetMonMoveSlot(mon, move, GetMoveSlotToReplace());
+ Task_LearnedMove(taskId);
+ }
+}
+
+static void StopLearningMovePrompt(u8 taskId)
+{
+ StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
+ StringExpandPlaceholders(gStringVar4, gText_StopLearningMove2);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_StopLearningMoveYesNo;
+}
+
+static void Task_StopLearningMoveYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleStopLearningMoveYesNoInput;
+ }
+}
+
+static void Task_HandleStopLearningMoveYesNoInput(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ GetMonNickname(mon, gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
+ StringExpandPlaceholders(gStringVar4, gText_MoveNotLearned);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ if (gPartyMenu.learnMoveState == 1)
+ {
+ gTasks[taskId].func = Task_TryLearningNextMoveAfterText;
+ }
+ else
+ {
+ if (gPartyMenu.learnMoveState == 2) // never occurs
+ gSpecialVar_Result = FALSE;
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+ }
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1:
+ GetMonNickname(mon, gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
+ DisplayLearnMoveMessage(gText_PkmnNeedsToReplaceMove);
+ gTasks[taskId].func = Task_ReplaceMoveYesNo;
+ break;
+ }
+}
+
+static void Task_TryLearningNextMoveAfterText(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ Task_TryLearningNextMove(taskId);
+}
+
+void ItemUseCB_RareCandy(u8 taskId, TaskFunc func)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 item = gSpecialVar_ItemId;
+ bool8 noEffect;
+
+ if (GetMonData(mon, MON_DATA_LEVEL) != MAX_LEVEL)
+ noEffect = PokemonItemUseNoEffect(mon, item, gPartyMenu.slotId, 0);
+ else
+ noEffect = TRUE;
+ PlaySE(SE_SELECT);
+ if (noEffect)
+ {
+ gPartyMenuUseExitCallback = FALSE;
+ DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = func;
+ }
+ else
+ {
+ sub_8124DC0(taskId);
+ gItemUseCB = ItemUseCB_RareCandyStep;
+ }
+}
+
+static void ItemUseCB_RareCandyStep(u8 taskId, UNUSED TaskFunc func)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ struct PartyMenuInternal *ptr = sPartyMenuInternal;
+ s16 *arrayPtr = ptr->data;
+ u8 level;
+
+ BufferMonStatsToTaskData(mon, arrayPtr);
+ ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0);
+ BufferMonStatsToTaskData(mon, &ptr->data[NUM_STATS]);
+ gPartyMenuUseExitCallback = TRUE;
+ ItemUse_SetQuestLogEvent(4, mon, gSpecialVar_ItemId, 0xFFFF);
+ PlayFanfareByFanfareNum(0);
+ UpdateMonDisplayInfoAfterRareCandy(gPartyMenu.slotId, mon);
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ GetMonNickname(mon, gStringVar1);
+ level = GetMonData(mon, MON_DATA_LEVEL);
+ ConvertIntToDecimalStringN(gStringVar2, level, STR_CONV_MODE_LEFT_ALIGN, 3);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnElevatedToLvVar2);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_DisplayLevelUpStatsPg1;
+}
+
+static void UpdateMonDisplayInfoAfterRareCandy(u8 slot, struct Pokemon *mon)
+{
+ SetPartyMonAilmentGfx(mon, &sPartyMenuBoxes[slot]);
+ if (gSprites[sPartyMenuBoxes[slot].statusSpriteId].invisible)
+ DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[slot], 1);
+ DisplayPartyPokemonHPCheck(mon, &sPartyMenuBoxes[slot], 1);
+ DisplayPartyPokemonMaxHPCheck(mon, &sPartyMenuBoxes[slot], 1);
+ DisplayPartyPokemonHPBarCheck(mon, &sPartyMenuBoxes[slot]);
+ UpdatePartyMonHPBar(sPartyMenuBoxes[slot].monSpriteId, mon);
+ AnimatePartySlot(slot, 1);
+ ScheduleBgCopyTilemapToVram(0);
+}
+
+static void Task_DisplayLevelUpStatsPg1(u8 taskId)
+{
+ if (WaitFanfare(FALSE) && IsPartyMenuTextPrinterActive() != TRUE && (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON)))
+ {
+ PlaySE(SE_SELECT);
+ DisplayLevelUpStatsPg1(taskId);
+ gTasks[taskId].func = Task_DisplayLevelUpStatsPg2;
+ }
+}
+
+static void Task_DisplayLevelUpStatsPg2(u8 taskId)
+{
+ if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ DisplayLevelUpStatsPg2(taskId);
+ gTasks[taskId].func = Task_TryLearnNewMoves;
+ }
+}
+
+static void DisplayLevelUpStatsPg1(u8 taskId)
+{
+ s16 *arrayPtr = sPartyMenuInternal->data;
+
+ arrayPtr[12] = CreateLevelUpStatsWindow();
+ DrawLevelUpWindowPg1(arrayPtr[12], arrayPtr, &arrayPtr[6], 1, 2, 3);
+ CopyWindowToVram(arrayPtr[12], 2);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void DisplayLevelUpStatsPg2(u8 taskId)
+{
+ s16 *arrayPtr = sPartyMenuInternal->data;
+
+ DrawLevelUpWindowPg2(arrayPtr[12], &arrayPtr[6], 1, 2, 3);
+ CopyWindowToVram(arrayPtr[12], 2);
+ ScheduleBgCopyTilemapToVram(2);
+}
+
+static void Task_TryLearnNewMoves(u8 taskId)
+{
+ u16 learnMove;
+
+ if (WaitFanfare(0) && (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON)))
+ {
+ RemoveLevelUpStatsWindow();
+ learnMove = MonTryLearningNewMove(&gPlayerParty[gPartyMenu.slotId], TRUE);
+ gPartyMenu.learnMoveState = 1;
+ switch (learnMove)
+ {
+ case 0: // No moves to learn
+ PartyMenuTryEvolution(taskId);
+ break;
+ case MON_HAS_MAX_MOVES:
+ DisplayMonNeedsToReplaceMove(taskId);
+ break;
+ case MON_ALREADY_KNOWS_MOVE:
+ gTasks[taskId].func = Task_TryLearningNextMove;
+ break;
+ default:
+ DisplayMonLearnedMove(taskId, learnMove);
+ break;
+ }
+ }
+}
+
+static void Task_TryLearningNextMove(u8 taskId)
+{
+ u16 result = MonTryLearningNewMove(&gPlayerParty[gPartyMenu.slotId], FALSE);
+
+ switch (result)
+ {
+ case 0: // No moves to learn
+ PartyMenuTryEvolution(taskId);
+ break;
+ case MON_HAS_MAX_MOVES:
+ DisplayMonNeedsToReplaceMove(taskId);
+ break;
+ case MON_ALREADY_KNOWS_MOVE:
+ return;
+ default:
+ DisplayMonLearnedMove(taskId, result);
+ break;
+ }
+}
+
+static void PartyMenuTryEvolution(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 targetSpecies = GetEvolutionTargetSpecies(mon, 0, 0);
+
+ if (targetSpecies != SPECIES_NONE)
+ {
+ FreePartyPointers();
+ gCB2_AfterEvolution = gPartyMenu.exitCallback;
+ BeginEvolutionScene(mon, targetSpecies, 1, gPartyMenu.slotId);
+ DestroyTask(taskId);
+ }
+ else
+ {
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+ }
+}
+
+static void DisplayMonNeedsToReplaceMove(u8 taskId)
+{
+ GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[gMoveToLearn]);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnNeedsToReplaceMove);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gPartyMenu.data1 = gMoveToLearn;
+ gTasks[taskId].func = Task_ReplaceMoveYesNo;
+}
+
+static void DisplayMonLearnedMove(u8 taskId, u16 move)
+{
+ GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
+ StringCopy(gStringVar2, gMoveNames[move]);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnLearnedMove3);
+ DisplayPartyMenuMessage(gStringVar4, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gPartyMenu.data1 = move;
+ gTasks[taskId].func = Task_DoLearnedMoveFanfareAfterText;
+}
+
+#define tUsedOnSlot data[0]
+#define tHadEffect data[1]
+#define tLastSlotUsed data[2]
+
+void ItemUseCB_SacredAsh(u8 taskId, UNUSED TaskFunc func)
+{
+ sPartyMenuInternal->tUsedOnSlot = FALSE;
+ sPartyMenuInternal->tHadEffect = FALSE;
+ sPartyMenuInternal->tLastSlotUsed = gPartyMenu.slotId;
+ UseSacredAsh(taskId);
+}
+
+static void UseSacredAsh(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 hp;
+
+ if (GetMonData(mon, MON_DATA_SPECIES) == SPECIES_NONE)
+ {
+ gTasks[taskId].func = Task_SacredAshLoop;
+ return;
+ }
+ hp = GetMonData(mon, MON_DATA_HP);
+ if (ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0))
+ {
+ gTasks[taskId].func = Task_SacredAshLoop;
+ return;
+ }
+ PlaySE(SE_KAIFUKU);
+ if (sPartyMenuInternal->tHadEffect == 0)
+ sSacredAshQuestLogMonBackup = mon;
+ SetPartyMonAilmentGfx(mon, &sPartyMenuBoxes[gPartyMenu.slotId]);
+ if (gSprites[sPartyMenuBoxes[gPartyMenu.slotId].statusSpriteId].invisible)
+ DisplayPartyPokemonLevelCheck(mon, &sPartyMenuBoxes[gPartyMenu.slotId], 1);
+ AnimatePartySlot(sPartyMenuInternal->tLastSlotUsed, 0);
+ AnimatePartySlot(gPartyMenu.slotId, 1);
+ PartyMenuModifyHP(taskId, gPartyMenu.slotId, 1, GetMonData(mon, MON_DATA_HP) - hp, Task_SacredAshDisplayHPRestored);
+ ResetHPTaskData(taskId, 0, hp);
+ sPartyMenuInternal->tUsedOnSlot = TRUE;
+ sPartyMenuInternal->tHadEffect = TRUE;
+}
+
+static void Task_SacredAshLoop(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ if (sPartyMenuInternal->tUsedOnSlot == TRUE)
+ {
+ sPartyMenuInternal->tUsedOnSlot = FALSE;
+ sPartyMenuInternal->tLastSlotUsed = gPartyMenu.slotId;
+ }
+ if (++(gPartyMenu.slotId) == PARTY_SIZE)
+ {
+ if (sPartyMenuInternal->tHadEffect == FALSE)
+ {
+ gPartyMenuUseExitCallback = FALSE;
+ DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ }
+ else
+ {
+ gPartyMenuUseExitCallback = TRUE;
+ if (gPartyMenu.menuType != PARTY_MENU_TYPE_IN_BATTLE)
+ ItemUse_SetQuestLogEvent(4, sSacredAshQuestLogMonBackup, gSpecialVar_ItemId, 0xFFFF);
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+ }
+ gTasks[taskId].func = Task_ClosePartyMenuAfterText;
+ gPartyMenu.slotId = 0;
+ }
+ else
+ {
+ UseSacredAsh(taskId);
+ }
+ }
+}
+
+static void Task_SacredAshDisplayHPRestored(u8 taskId)
+{
+ GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnHPRestoredByVar2);
+ DisplayPartyMenuMessage(gStringVar4, FALSE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_SacredAshLoop;
+}
+
+#undef tUsedOnSlot
+#undef tHadEffect
+#undef tLastSlotUsed
+
+void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc func)
+{
+ bool8 noEffect;
+
+ PlaySE(SE_SELECT);
+ noEffect = PokemonItemUseNoEffect(&gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId, gPartyMenu.slotId, 0);
+ if (noEffect)
+ {
+ gPartyMenuUseExitCallback = FALSE;
+ DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = func;
+ }
+ else
+ {
+ sub_8124DC0(taskId);
+ }
+}
+
+static void sub_8126BD4(void)
+{
+ gCB2_AfterEvolution = gPartyMenu.exitCallback;
+ ExecuteTableBasedItemEffect_(gPartyMenu.slotId, gSpecialVar_ItemId, 0);
+ ItemUse_SetQuestLogEvent(4, &gPlayerParty[gPartyMenu.slotId], gSpecialVar_ItemId, 0xFFFF);
+ RemoveBagItem(gSpecialVar_ItemId, 1);
+}
+
+static bool8 sub_8126C24(void)
+{
+ if (!IsNationalPokedexEnabled()
+ && GetEvolutionTargetSpecies(&gPlayerParty[gPartyMenu.slotId], 2, gSpecialVar_ItemId) > KANTO_DEX_COUNT)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+u8 GetItemEffectType(u16 item)
+{
+ const u8 *itemEffect;
+ u32 statusCure;
+
+ if (!IS_POKEMON_ITEM(item))
+ return ITEM_EFFECT_NONE;
+ // Read the item's effect properties.
+ if (item == ITEM_ENIGMA_BERRY)
+ itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
+ else
+ itemEffect = gItemEffectTable[item - ITEM_POTION];
+ if ((itemEffect[0] & (ITEM0_HIGH_CRIT | ITEM0_X_ATTACK)) || itemEffect[1] || itemEffect[2] || (itemEffect[3] & ITEM3_MIST))
+ return ITEM_EFFECT_X_ITEM;
+ else if (itemEffect[0] & ITEM0_SACRED_ASH)
+ return ITEM_EFFECT_SACRED_ASH;
+ else if (itemEffect[3] & ITEM3_LEVEL_UP)
+ return ITEM_EFFECT_RAISE_LEVEL;
+ statusCure = itemEffect[3] & ITEM3_STATUS_ALL;
+ if (statusCure || (itemEffect[0] >> 7))
+ {
+ if (statusCure == ITEM3_SLEEP)
+ return ITEM_EFFECT_CURE_SLEEP;
+ else if (statusCure == ITEM3_POISON)
+ return ITEM_EFFECT_CURE_POISON;
+ else if (statusCure == ITEM3_BURN)
+ return ITEM_EFFECT_CURE_BURN;
+ else if (statusCure == ITEM3_FREEZE)
+ return ITEM_EFFECT_CURE_FREEZE;
+ else if (statusCure == ITEM3_PARALYSIS)
+ return ITEM_EFFECT_CURE_PARALYSIS;
+ else if (statusCure == ITEM3_CONFUSION)
+ return ITEM_EFFECT_CURE_CONFUSION;
+ else if (itemEffect[0] >> 7 && !statusCure)
+ return ITEM_EFFECT_CURE_INFATUATION;
+ else
+ return ITEM_EFFECT_CURE_ALL_STATUS;
+ }
+ if (itemEffect[4] & (ITEM4_REVIVE | ITEM4_HEAL_HP))
+ return ITEM_EFFECT_HEAL_HP;
+ else if (itemEffect[4] & ITEM4_EV_ATK)
+ return ITEM_EFFECT_ATK_EV;
+ else if (itemEffect[4] & ITEM4_EV_HP)
+ return ITEM_EFFECT_HP_EV;
+ else if (itemEffect[5] & ITEM5_EV_SPATK)
+ return ITEM_EFFECT_SPATK_EV;
+ else if (itemEffect[5] & ITEM5_EV_SPDEF)
+ return ITEM_EFFECT_SPDEF_EV;
+ else if (itemEffect[5] & ITEM5_EV_SPEED)
+ return ITEM_EFFECT_SPEED_EV;
+ else if (itemEffect[5] & ITEM5_EV_DEF)
+ return ITEM_EFFECT_DEF_EV;
+ else if (itemEffect[4] & ITEM4_EVO_STONE)
+ return ITEM_EFFECT_EVO_STONE;
+ else if (itemEffect[4] & ITEM4_PP_UP)
+ return ITEM_EFFECT_PP_UP;
+ else if (itemEffect[5] & ITEM5_PP_MAX)
+ return ITEM_EFFECT_PP_MAX;
+ else if (itemEffect[4] & (ITEM4_HEAL_PP_ALL | ITEM4_HEAL_PP_ONE))
+ return ITEM_EFFECT_HEAL_PP;
+ else
+ return ITEM_EFFECT_NONE;
+}
+
+static void TryTutorSelectedMon(u8 taskId)
+{
+ struct Pokemon *mon;
+ s16 *move;
+
+ if (!gPaletteFade.active)
+ {
+ mon = &gPlayerParty[gPartyMenu.slotId];
+ move = &gPartyMenu.data1;
+ GetMonNickname(mon, gStringVar1);
+ gPartyMenu.data1 = GetTutorMove(gSpecialVar_0x8005);
+ StringCopy(gStringVar2, gMoveNames[gPartyMenu.data1]);
+ move[1] = 2;
+ switch (CanMonLearnTMTutor(mon, 0, gSpecialVar_0x8005))
+ {
+ case CANNOT_LEARN_MOVE:
+ DisplayLearnMoveMessageAndClose(taskId, gText_PkmnCantLearnMove);
+ return;
+ case ALREADY_KNOWS_MOVE:
+ DisplayLearnMoveMessageAndClose(taskId, gText_PkmnAlreadyKnows);
+ return;
+ default:
+ if (GiveMoveToMon(mon, gPartyMenu.data1) != MON_HAS_MAX_MOVES)
+ {
+ Task_LearnedMove(taskId);
+ return;
+ }
+ break;
+ }
+ DisplayLearnMoveMessage(gText_PkmnNeedsToReplaceMove);
+ gTasks[taskId].func = Task_ReplaceMoveYesNo;
+ }
+}
+
+void CB2_PartyMenuFromStartMenu(void)
+{
+ InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ReturnToFieldWithOpenMenu);
+}
+
+// Giving an item by selecting Give from the bag menu
+// As opposted to by selecting Give in the party menu, which is handled by CursorCB_Give
+void CB2_ChooseMonToGiveItem(void)
+{
+ MainCallback callback;
+
+ switch (GetPocketByItemId(gSpecialVar_ItemId))
+ {
+ default:
+ callback = CB2_ReturnToBagMenu;
+ break;
+ case POCKET_TM_CASE:
+ callback = CB2_ReturnToTMCaseMenu;
+ break;
+ case POCKET_BERRY_POUCH:
+ callback = CB2_ReturnToBerryPouchMenu;
+ break;
+ }
+ InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_ITEM, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, callback);
+ gPartyMenu.bagItem = gSpecialVar_ItemId;
+}
+
+static void TryGiveItemOrMailToSelectedMon(u8 taskId)
+{
+ sPartyMenuItemId = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
+ if (sPartyMenuItemId == ITEM_NONE)
+ {
+ GiveItemOrMailToSelectedMon(taskId);
+ }
+ else if (ItemIsMail(sPartyMenuItemId))
+ {
+ DisplayItemMustBeRemovedFirstMessage(taskId);
+ }
+ else
+ {
+ DisplayAlreadyHoldingItemSwitchMessage(&gPlayerParty[gPartyMenu.slotId], sPartyMenuItemId, TRUE);
+ gTasks[taskId].func = Task_SwitchItemsFromBagYesNo;
+ }
+}
+
+static void GiveItemOrMailToSelectedMon(u8 taskId)
+{
+ if (ItemIsMail(gPartyMenu.bagItem))
+ {
+ RemoveItemToGiveFromBag(gPartyMenu.bagItem);
+ sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMonFromBag;
+ Task_ClosePartyMenu(taskId);
+ }
+ else
+ {
+ GiveItemToSelectedMon(taskId);
+ }
+}
+
+static void GiveItemToSelectedMon(u8 taskId)
+{
+ u16 item;
+
+ if (!gPaletteFade.active)
+ {
+ item = gPartyMenu.bagItem;
+ DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], item, FALSE, 1);
+ GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item);
+ RemoveItemToGiveFromBag(item);
+ gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
+ }
+}
+
+static void Task_UpdateHeldItemSpriteAndClosePartyMenu(u8 taskId)
+{
+ s8 slot = gPartyMenu.slotId;
+
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ UpdatePartyMonHeldItemSprite(&gPlayerParty[slot], &sPartyMenuBoxes[slot]);
+ Task_ClosePartyMenu(taskId);
+ }
+}
+
+static void CB2_WriteMailToGiveMonFromBag(void)
+{
+ u8 mail;
+
+ GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], gPartyMenu.bagItem);
+ mail = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_MAIL);
+ DoEasyChatScreen(EASY_CHAT_TYPE_MAIL, gSaveBlock1Ptr->mail[mail].words, CB2_ReturnToPartyOrBagMenuFromWritingMail);
+}
+
+static void CB2_ReturnToPartyOrBagMenuFromWritingMail(void)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ u16 item = GetMonData(mon, MON_DATA_HELD_ITEM);
+
+ // Canceled writing mail
+ if (gSpecialVar_Result == FALSE)
+ {
+ TakeMailFromMon(mon);
+ SetMonData(mon, MON_DATA_HELD_ITEM, &sPartyMenuItemId);
+ RemoveBagItem(sPartyMenuItemId, 1);
+ ReturnGiveItemToBagOrPC(item);
+ SetMainCallback2(gPartyMenu.exitCallback);
+ }
+ // Wrote mail
+ else
+ {
+ InitPartyMenu(gPartyMenu.menuType, KEEP_PARTY_LAYOUT, gPartyMenu.action, TRUE, PARTY_MSG_NONE, Task_DisplayGaveMailFromBagMessage, gPartyMenu.exitCallback);
+ }
+}
+
+static void Task_DisplayGaveMailFromBagMessage(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ if (sPartyMenuItemId != ITEM_NONE)
+ DisplaySwitchedHeldItemMessage(gPartyMenu.bagItem, sPartyMenuItemId, FALSE);
+ else
+ DisplayGaveHeldItemMessage(&gPlayerParty[gPartyMenu.slotId], gPartyMenu.bagItem, FALSE, 1);
+ gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
+ }
+}
+
+static void Task_SwitchItemsFromBagYesNo(u8 taskId)
+{
+ if (IsPartyMenuTextPrinterActive() != TRUE)
+ {
+ PartyMenuDisplayYesNoMenu();
+ gTasks[taskId].func = Task_HandleSwitchItemsFromBagYesNoInput;
+ }
+}
+
+static void Task_HandleSwitchItemsFromBagYesNoInput(u8 taskId)
+{
+ u16 item;
+
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0: // Yes, switch items
+ item = gPartyMenu.bagItem;
+ RemoveItemToGiveFromBag(item);
+ if (AddBagItem(sPartyMenuItemId, 1) == FALSE)
+ {
+ ReturnGiveItemToBagOrPC(item);
+ BufferBagFullCantTakeItemMessage(sPartyMenuItemId);
+ DisplayPartyMenuMessage(gStringVar4, FALSE);
+ gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
+ }
+ else if (ItemIsMail(item))
+ {
+ sPartyMenuInternal->exitCallback = CB2_WriteMailToGiveMonFromBag;
+ Task_ClosePartyMenu(taskId);
+ }
+ else
+ {
+ GiveItemToMon(&gPlayerParty[gPartyMenu.slotId], item);
+ DisplaySwitchedHeldItemMessage(item, sPartyMenuItemId, TRUE);
+ gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
+ }
+ break;
+ case MENU_B_PRESSED:
+ PlaySE(SE_SELECT);
+ // fallthrough
+ case 1: // No, dont switch items
+ gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
+ break;
+ }
+}
+
+static void DisplayItemMustBeRemovedFirstMessage(u8 taskId)
+{
+ DisplayPartyMenuMessage(gText_RemoveMailBeforeItem, TRUE);
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
+}
+
+static void RemoveItemToGiveFromBag(u16 item)
+{
+ if (gPartyMenu.action == PARTY_ACTION_GIVE_PC_ITEM) // Unused, never occurs
+ RemovePCItem(item, 1);
+ else
+ RemoveBagItem(item, 1);
+}
+
+// Returns FALSE if there was no space to return the item
+// but there always should be, and the return is ignored in all uses
+static bool8 ReturnGiveItemToBagOrPC(u16 item)
+{
+ if (gPartyMenu.action == PARTY_ACTION_GIVE_ITEM)
+ return AddBagItem(item, 1);
+ else
+ return AddPCItem(item, 1);
+}
+
+void ChooseMonToGiveMailFromMailbox(void)
+{
+ InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_MAILBOX_MAIL, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, Mailbox_ReturnToMailListAfterDeposit);
+}
+
+static void TryGiveMailToSelectedMon(u8 taskId)
+{
+ struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
+ struct MailStruct *mail;
+
+ gPartyMenuUseExitCallback = FALSE;
+ mail = &gSaveBlock1Ptr->mail[gPlayerPcMenuManager.itemsAbove + 6 + gPlayerPcMenuManager.cursorPos];
+ if (GetMonData(mon, MON_DATA_HELD_ITEM) != ITEM_NONE)
+ {
+ DisplayPartyMenuMessage(gText_PkmnHoldingItemCantHoldMail, TRUE);
+ }
+ else
+ {
+ GiveMailToMon2(mon, mail);
+ ClearMailStruct(mail);
+ DisplayPartyMenuMessage(gText_MailTransferredFromMailbox, TRUE);
+ }
+ ScheduleBgCopyTilemapToVram(2);
+ gTasks[taskId].func = Task_UpdateHeldItemSpriteAndClosePartyMenu;
+}
+
+void InitChooseHalfPartyForBattle(u8 a1)
+{
+ ClearSelectedPartyOrder();
+ InitPartyMenu(PARTY_MENU_TYPE_CHOOSE_HALF, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, gMain.savedCallback);
+ gPartyMenu.unk_8_6 = a1;
+ gPartyMenu.task = Task_ValidateChosenHalfParty;
+}
+
+void ClearSelectedPartyOrder(void)
+{
+ memset(gSelectedOrderFromParty, 0, sizeof(gSelectedOrderFromParty));
+}
+
+static u8 GetPartySlotEntryStatus(s8 slot)
+{
+ if (GetBattleEntryEligibility(&gPlayerParty[slot]) == FALSE)
+ return 2;
+ if (HasPartySlotAlreadyBeenSelected(slot + 1) == TRUE)
+ return 1;
+ return 0;
+}
+
+static bool8 GetBattleEntryEligibility(struct Pokemon *mon)
+{
+ u16 species;
+ u16 i = 0;
+
+ if (GetMonData(mon, MON_DATA_IS_EGG))
+ return FALSE;
+ switch (gPartyMenu.unk_8_6)
+ {
+ default:
+ if (GetMonData(mon, MON_DATA_LEVEL) > 30)
+ return FALSE;
+ break;
+ case 0:
+ if (GetMonData(mon, MON_DATA_HP) == 0)
+ return FALSE;
+ break;
+ case 1:
+ if (gSaveBlock2Ptr->battleTower.battleTowerLevelType == 0 // level 50
+ && GetMonData(mon, MON_DATA_LEVEL) > 50)
+ return FALSE;
+ species = GetMonData(mon, MON_DATA_SPECIES);
+ for (; gBattleTowerBannedSpecies[i] != 0xFFFF; ++i)
+ if (gBattleTowerBannedSpecies[i] == species)
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static u8 CheckBattleEntriesAndGetMessage(void)
+{
+ u8 i, j;
+ struct Pokemon *party = gPlayerParty;
+ u8 *order = gSelectedOrderFromParty;
+
+ switch (gPartyMenu.unk_8_6)
+ {
+ case 1:
+ if (order[2] == 0)
+ return PARTY_MSG_THREE_MONS_ARE_NEEDED;
+ for (i = 0; i < 2; ++i)
+ {
+ sPartyMenuInternal->data[15] = GetMonData(&party[order[i] - 1], MON_DATA_SPECIES);
+ sPartyMenuInternal->data[14] = GetMonData(&party[order[i] - 1], MON_DATA_HELD_ITEM);
+ for (j = i + 1; j < 3; ++j)
+ {
+ if (sPartyMenuInternal->data[15] == GetMonData(&party[order[j] - 1], MON_DATA_SPECIES))
+ return PARTY_MSG_MONS_CANT_BE_SAME;
+ if (sPartyMenuInternal->data[14] != ITEM_NONE && sPartyMenuInternal->data[14] == GetMonData(&party[order[j] - 1], MON_DATA_HELD_ITEM))
+ return PARTY_MSG_NO_SAME_HOLD_ITEMS;
+ }
+ }
+ break;
+ case 2:
+ if (order[1] == 0)
+ return PARTY_MSG_TWO_MONS_ARE_NEEDED;
+ break;
+ }
+ return 0xFF;
+}
+
+static bool8 HasPartySlotAlreadyBeenSelected(u8 slot)
+{
+ u8 i;
+
+ for (i = 0; i < NELEMS(gSelectedOrderFromParty); ++i)
+ if (gSelectedOrderFromParty[i] == slot)
+ return TRUE;
+ return FALSE;
+}
+
+static void Task_ValidateChosenHalfParty(u8 taskId)
+{
+ u8 msgId = CheckBattleEntriesAndGetMessage();
+
+ if (msgId != 0xFF)
+ {
+ PlaySE(SE_HAZURE);
+ DisplayPartyMenuStdMessage(msgId);
+ gTasks[taskId].func = Task_ContinueChoosingHalfParty;
+ }
+ else
+ {
+ if (gSelectedOrderFromParty[0] != 0)
+ {
+ PlaySE(SE_SELECT);
+ Task_ClosePartyMenu(taskId);
+ }
+ else
+ {
+ PlaySE(SE_HAZURE);
+ DisplayPartyMenuStdMessage(PARTY_MSG_NO_MON_FOR_BATTLE);
+ gTasks[taskId].func = Task_ContinueChoosingHalfParty;
+ }
+ }
+}
+
+static void Task_ContinueChoosingHalfParty(u8 taskId)
+{
+ if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+ DisplayPartyMenuStdMessage(PARTY_MSG_CHOOSE_MON);
+ gTasks[taskId].func = Task_HandleChooseMonInput;
+ }
+}
+
+void sub_81277F4(u8 menuType, MainCallback callback)
+{
+ InitPartyMenu(menuType,
+ PARTY_LAYOUT_SINGLE,
+ PARTY_ACTION_CHOOSE_MON,
+ FALSE,
+ PARTY_MSG_CHOOSE_MON,
+ Task_HandleChooseMonInput,
+ callback);
+}
+
+void ChooseMonForMoveTutor(void)
+{
+ if (gSpecialVar_0x8005 < TUTOR_MOVE_COUNT)
+ {
+ InitPartyMenu(PARTY_MENU_TYPE_FIELD,
+ PARTY_LAYOUT_SINGLE,
+ PARTY_ACTION_MOVE_TUTOR,
+ FALSE,
+ PARTY_MSG_TEACH_WHICH_MON,
+ Task_HandleChooseMonInput,
+ CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ }
+ else
+ {
+ InitPartyMenu(PARTY_MENU_TYPE_FIELD,
+ PARTY_LAYOUT_SINGLE,
+ PARTY_ACTION_MOVE_TUTOR,
+ FALSE,
+ PARTY_MSG_NONE,
+ TryTutorSelectedMon,
+ CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ gPartyMenu.slotId = gSpecialVar_0x8007;
+ }
+}
+
+void ChooseMonForWirelessMinigame(void)
+{
+ InitPartyMenu(PARTY_MENU_TYPE_MINIGAME, PARTY_LAYOUT_SINGLE, PARTY_ACTION_MINIGAME, FALSE, PARTY_MSG_CHOOSE_MON_OR_CANCEL, Task_HandleChooseMonInput, CB2_ReturnToFieldContinueScriptPlayMapMusic);
+}
+
+static u8 GetPartyLayoutFromBattleType(void)
+{
+ if (IsDoubleBattle() == FALSE)
+ return PARTY_LAYOUT_SINGLE;
+ if (IsMultiBattle() == TRUE)
+ return PARTY_LAYOUT_MULTI;
+ return PARTY_LAYOUT_DOUBLE;
+}
+
+void OpenPartyMenuInTutorialBattle(u8 partyAction)
+{
+ if (!sub_80EB2E0(8) && (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE))
+ {
+ InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE,
+ GetPartyLayoutFromBattleType(),
+ partyAction,
+ FALSE,
+ PARTY_MSG_NONE,
+ sub_8120C3C,
+ SetCB2ToReshowScreenAfterMenu);
+ sub_80EB2F4(8);
+ }
+ else
+ {
+ InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE,
+ GetPartyLayoutFromBattleType(),
+ partyAction,
+ FALSE,
+ PARTY_MSG_CHOOSE_MON,
+ Task_HandleChooseMonInput,
+ SetCB2ToReshowScreenAfterMenu);
+ }
+ nullsub_44();
+ UpdatePartyToBattleOrder();
+}
+
+void OpenPartyMenuInBattle(void)
+{
+ InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON, sub_8120EBC, SetCB2ToReshowScreenAfterMenu);
+ nullsub_44();
+ UpdatePartyToBattleOrder();
+}
+
+void ChooseMonForInBattleItem(void)
+{
+ InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE, GetPartyLayoutFromBattleType(), PARTY_ACTION_REUSABLE_ITEM, FALSE, PARTY_MSG_USE_ON_WHICH_MON, sub_8120FCC, sub_8107ECC);
+ nullsub_44();
+ UpdatePartyToBattleOrder();
+}
+
+void sub_81279E0(void)
+{
+ if (!sub_80EB2E0(8) && (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE))
+ {
+ InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE,
+ GetPartyLayoutFromBattleType(),
+ PARTY_ACTION_USE_ITEM,
+ FALSE,
+ PARTY_MSG_NONE,
+ sub_8120C3C,
+ sub_8107ECC);
+ sub_80EB2F4(8);
+ }
+ else
+ {
+ MainCallback callback;
+
+ if (GetPocketByItemId(gSpecialVar_ItemId) == POCKET_BERRY_POUCH)
+ callback = CB2_ReturnToBerryPouchMenu;
+ else
+ callback = sub_8107ECC;
+ InitPartyMenu(PARTY_MENU_TYPE_IN_BATTLE,
+ GetPartyLayoutFromBattleType(),
+ PARTY_ACTION_USE_ITEM,
+ FALSE,
+ PARTY_MSG_USE_ON_WHICH_MON,
+ Task_HandleChooseMonInput,
+ callback);
+ }
+ nullsub_44();
+ UpdatePartyToBattleOrder();
+}
+
+static u8 GetPartyMenuActionsTypeInBattle(struct Pokemon *mon)
+{
+ if (GetMonData(&gPlayerParty[1], MON_DATA_SPECIES) == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG))
+ return ACTIONS_SUMMARY_ONLY;
+ else if (gPartyMenu.action == PARTY_ACTION_SEND_OUT)
+ return ACTIONS_SEND_OUT;
+ else
+ return ACTIONS_SHIFT;
+}
+
+static bool8 TrySwitchInPokemon(void)
+{
+ u8 slot = GetCursorSelectionMonId();
+ u8 newSlot;
+ u8 i;
+
+ // In a multi battle, slots 1, 4, and 5 are the partner's pokemon
+ if (IsMultiBattle() == TRUE && (slot == 1 || slot == 4 || slot == 5))
+ {
+ StringCopy(gStringVar1, GetTrainerPartnerName());
+ StringExpandPlaceholders(gStringVar4, gText_CantSwitchWithAlly);
+ return FALSE;
+ }
+ if (GetMonData(&gPlayerParty[slot], MON_DATA_HP) == 0)
+ {
+ GetMonNickname(&gPlayerParty[slot], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnHasNoEnergy);
+ return FALSE;
+ }
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if (GetBattlerSide(i) == B_SIDE_PLAYER && GetPartyIdFromBattleSlot(slot) == gBattlerPartyIndexes[i])
+ {
+ GetMonNickname(&gPlayerParty[slot], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnAlreadyInBattle);
+ return FALSE;
+ }
+ }
+ if (GetMonData(&gPlayerParty[slot], MON_DATA_IS_EGG))
+ {
+ StringExpandPlaceholders(gStringVar4, gText_EggCantBattle);
+ return FALSE;
+ }
+ if (GetPartyIdFromBattleSlot(slot) == gBattleStruct->field_8B)
+ {
+ GetMonNickname(&gPlayerParty[slot], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnAlreadySelected);
+ return FALSE;
+ }
+ if (gPartyMenu.action == PARTY_ACTION_ABILITY_PREVENTS)
+ {
+ SetMonPreventsSwitchingString();
+ return FALSE;
+ }
+ if (gPartyMenu.action == PARTY_ACTION_CANT_SWITCH)
+ {
+ u8 currBattler = gBattlerInMenuId;
+
+ GetMonNickname(&gPlayerParty[GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[currBattler])], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_PkmnCantSwitchOut);
+ return FALSE;
+ }
+ gSelectedMonPartyId = GetPartyIdFromBattleSlot(slot);
+ gPartyMenuUseExitCallback = TRUE;
+ newSlot = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[gBattlerInMenuId]);
+ SwitchPartyMonSlots(newSlot, slot);
+ SwapPartyPokemon(&gPlayerParty[newSlot], &gPlayerParty[slot]);
+ return TRUE;
+}
+
+void BufferBattlePartyCurrentOrder(void)
+{
+ BufferBattlePartyOrder(gBattlePartyCurrentOrder, GetPlayerFlankId());
+}
+
+static void BufferBattlePartyOrder(u8 *partyBattleOrder, u8 flankId)
+{
+ u8 partyIds[PARTY_SIZE];
+ s32 i, j;
+
+ if (IsMultiBattle() == TRUE)
+ {
+ // Party ids are packed in 4 bits at a time
+ // i.e. the party id order below would be 0, 3, 5, 4, 2, 1, and the two parties would be 0,5,4 and 3,2,1
+ if (flankId != 0)
+ {
+ partyBattleOrder[0] = 0 | (3 << 4);
+ partyBattleOrder[1] = 5 | (4 << 4);
+ partyBattleOrder[2] = 2 | (1 << 4);
+ }
+ else
+ {
+ partyBattleOrder[0] = 3 | (0 << 4);
+ partyBattleOrder[1] = 2 | (1 << 4);
+ partyBattleOrder[2] = 5 | (4 << 4);
+ }
+ return;
+ }
+ else if (IsDoubleBattle() == FALSE)
+ {
+ j = 1;
+ partyIds[0] = gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)];
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (i != partyIds[0])
+ {
+ partyIds[j] = i;
+ ++j;
+ }
+ }
+ }
+ else
+ {
+ j = 2;
+ partyIds[0] = gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)];
+ partyIds[1] = gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)];
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (i != partyIds[0] && i != partyIds[1])
+ {
+ partyIds[j] = i;
+ ++j;
+ }
+ }
+ }
+ for (i = 0; i < (s32)NELEMS(gBattlePartyCurrentOrder); ++i)
+ partyBattleOrder[i] = (partyIds[0 + (i * 2)] << 4) | partyIds[1 + (i * 2)];
+}
+
+void BufferBattlePartyCurrentOrderBySide(u8 battlerId, u8 flankId)
+{
+ BufferBattlePartyOrderBySide(gBattleStruct->field_60[battlerId], flankId, battlerId);
+}
+
+// when GetBattlerSide(battlerId) == B_SIDE_PLAYER, this function is identical the one above
+static void BufferBattlePartyOrderBySide(u8 *partyBattleOrder, u8 flankId, u8 battlerId)
+{
+ u8 partyIndexes[PARTY_SIZE];
+ s32 i, j;
+ u8 leftBattler;
+ u8 rightBattler;
+
+ if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
+ {
+ leftBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
+ rightBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
+ }
+ else
+ {
+ leftBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
+ rightBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
+ }
+ if (IsMultiBattle() == TRUE)
+ {
+ if (flankId != 0)
+ {
+ partyBattleOrder[0] = 0 | (3 << 4);
+ partyBattleOrder[1] = 5 | (4 << 4);
+ partyBattleOrder[2] = 2 | (1 << 4);
+ }
+ else
+ {
+ partyBattleOrder[0] = 3 | (0 << 4);
+ partyBattleOrder[1] = 2 | (1 << 4);
+ partyBattleOrder[2] = 5 | (4 << 4);
+ }
+ return;
+ }
+ else if (IsDoubleBattle() == FALSE)
+ {
+ j = 1;
+ partyIndexes[0] = gBattlerPartyIndexes[leftBattler];
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (i != partyIndexes[0])
+ {
+ partyIndexes[j] = i;
+ ++j;
+ }
+ }
+ }
+ else
+ {
+ j = 2;
+ partyIndexes[0] = gBattlerPartyIndexes[leftBattler];
+ partyIndexes[1] = gBattlerPartyIndexes[rightBattler];
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (i != partyIndexes[0] && i != partyIndexes[1])
+ {
+ partyIndexes[j] = i;
+ ++j;
+ }
+ }
+ }
+ for (i = 0; i < 3; ++i)
+ partyBattleOrder[i] = (partyIndexes[0 + (i * 2)] << 4) | partyIndexes[1 + (i * 2)];
+}
+
+void SwitchPartyOrderLinkMulti(u8 battlerId, u8 slot, u8 slot2)
+{
+ u8 partyIds[PARTY_SIZE];
+ u8 tempSlot = 0;
+ s32 i, j;
+ u8 *partyBattleOrder;
+ u8 partyIdBuffer;
+
+ if (IsMultiBattle())
+ {
+ partyBattleOrder = gBattleStruct->field_60[battlerId];
+ for (i = j = 0; i < 3; ++j, ++i)
+ {
+ partyIds[j] = partyBattleOrder[i] >> 4;
+ ++j;
+ partyIds[j] = partyBattleOrder[i] & 0xF;
+ }
+ partyIdBuffer = partyIds[slot2];
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (partyIds[i] == slot)
+ {
+ tempSlot = partyIds[i];
+ partyIds[i] = partyIdBuffer;
+ break;
+ }
+ }
+ if (i != PARTY_SIZE)
+ {
+ partyIds[slot2] = tempSlot;
+ partyBattleOrder[0] = (partyIds[0] << 4) | partyIds[1];
+ partyBattleOrder[1] = (partyIds[2] << 4) | partyIds[3];
+ partyBattleOrder[2] = (partyIds[4] << 4) | partyIds[5];
+ }
+ }
+}
+
+static u8 GetPartyIdFromBattleSlot(u8 slot)
+{
+ u8 modResult = slot & 1;
+ u8 retVal;
+
+ slot /= 2;
+ if (modResult != 0)
+ retVal = gBattlePartyCurrentOrder[slot] & 0xF;
+ else
+ retVal = gBattlePartyCurrentOrder[slot] >> 4;
+ return retVal;
+}
+
+static void SetPartyIdAtBattleSlot(u8 slot, u8 setVal)
+{
+ bool32 modResult = slot & 1;
+
+ slot /= 2;
+ if (modResult != 0)
+ gBattlePartyCurrentOrder[slot] = (gBattlePartyCurrentOrder[slot] & 0xF0) | setVal;
+ else
+ gBattlePartyCurrentOrder[slot] = (gBattlePartyCurrentOrder[slot] & 0xF) | (setVal << 4);
+}
+
+void SwitchPartyMonSlots(u8 slot, u8 slot2)
+{
+ u8 partyId = GetPartyIdFromBattleSlot(slot);
+
+ SetPartyIdAtBattleSlot(slot, GetPartyIdFromBattleSlot(slot2));
+ SetPartyIdAtBattleSlot(slot2, partyId);
+}
+
+u8 GetPartyIdFromBattlePartyId(u8 battlePartyId)
+{
+ u8 i, j;
+
+ for (j = i = 0; i < (s32)NELEMS(gBattlePartyCurrentOrder); ++j, ++i)
+ {
+ if ((gBattlePartyCurrentOrder[i] >> 4) != battlePartyId)
+ {
+ ++j;
+ if ((gBattlePartyCurrentOrder[i] & 0xF) == battlePartyId)
+ return j;
+ }
+ else
+ {
+ return j;
+ }
+ }
+ return 0;
+}
+
+static void UpdatePartyToBattleOrder(void)
+{
+ struct Pokemon *partyBuffer = Alloc(sizeof(gPlayerParty));
+ u8 i;
+
+ memcpy(partyBuffer, gPlayerParty, sizeof(gPlayerParty));
+ for (i = 0; i < PARTY_SIZE; ++i)
+ memcpy(&gPlayerParty[GetPartyIdFromBattlePartyId(i)], &partyBuffer[i], sizeof(struct Pokemon));
+ Free(partyBuffer);
+}
+
+static void UpdatePartyToFieldOrder(void)
+{
+ struct Pokemon *partyBuffer = Alloc(sizeof(gPlayerParty));
+ u8 i;
+
+ memcpy(partyBuffer, gPlayerParty, sizeof(gPlayerParty));
+ for (i = 0; i < PARTY_SIZE; ++i)
+ memcpy(&gPlayerParty[GetPartyIdFromBattleSlot(i)], &partyBuffer[i], sizeof(struct Pokemon));
+ Free(partyBuffer);
+}
+
+// not used
+static void SwitchAliveMonIntoLeadSlot(void)
+{
+ u8 i;
+ struct Pokemon *mon;
+ u8 partyId;
+
+ for (i = 1; i < PARTY_SIZE; ++i)
+ {
+ mon = &gPlayerParty[GetPartyIdFromBattleSlot(i)];
+ if (GetMonData(mon, MON_DATA_SPECIES) != SPECIES_NONE && GetMonData(mon, MON_DATA_HP) != 0)
+ {
+ partyId = GetPartyIdFromBattleSlot(0);
+ SwitchPartyMonSlots(0, i);
+ SwapPartyPokemon(&gPlayerParty[partyId], mon);
+ break;
+ }
+ }
+}
+
+static void CB2_SetUpExitToBattleScreen(void)
+{
+ CB2_SetUpReshowBattleScreenAfterMenu();
+ SetMainCallback2(SetCB2ToReshowScreenAfterMenu);
+}
+
+void ShowPartyMenuToShowcaseMultiBattleParty(void)
+{
+ InitPartyMenu(PARTY_MENU_TYPE_MULTI_SHOWCASE, PARTY_LAYOUT_MULTI_SHOWCASE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_NONE, Task_InitMultiPartnerPartySlideIn, gMain.savedCallback);
+}
+
+#define tXPos data[0]
+
+static void Task_InitMultiPartnerPartySlideIn(u8 taskId)
+{
+ // The first slide step also sets the sprites offscreen
+ gTasks[taskId].tXPos = 256;
+ SlideMultiPartyMenuBoxSpritesOneStep(taskId);
+ ChangeBgX(2, 0x10000, 0);
+ gTasks[taskId].func = Task_MultiPartnerPartySlideIn;
+}
+
+static void Task_MultiPartnerPartySlideIn(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ u8 i;
+
+ if (!gPaletteFade.active)
+ {
+ tXPos -= 8;
+ SlideMultiPartyMenuBoxSpritesOneStep(taskId);
+ if (tXPos == 0)
+ {
+ for (i = 3; i < PARTY_SIZE; ++i)
+ {
+ if (gMultiPartnerParty[i - MULTI_PARTY_SIZE].species != SPECIES_NONE)
+ AnimateSelectedPartyIcon(sPartyMenuBoxes[i].monSpriteId, 0);
+ }
+ PlaySE(SE_W231); // The Harden SE plays once the partners party mons have slid on screen
+ gTasks[taskId].func = Task_WaitAfterMultiPartnerPartySlideIn;
+ }
+ }
+}
+
+static void Task_WaitAfterMultiPartnerPartySlideIn(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ // data[0] used as a timer afterwards rather than the x pos
+ if (++data[0] == 256)
+ Task_ClosePartyMenu(taskId);
+}
+
+static void MoveMultiPartyMenuBoxSprite(u8 spriteId, s16 x)
+{
+ if (x >= 0)
+ gSprites[spriteId].pos2.x = x;
+}
+
+static void SlideMultiPartyMenuBoxSpritesOneStep(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ u8 i;
+
+ for (i = 3; i < PARTY_SIZE; ++i)
+ {
+ if (gMultiPartnerParty[i - MULTI_PARTY_SIZE].species != SPECIES_NONE)
+ {
+ MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].monSpriteId, tXPos - 8);
+ MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].itemSpriteId, tXPos - 8);
+ MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].pokeballSpriteId, tXPos - 8);
+ MoveMultiPartyMenuBoxSprite(sPartyMenuBoxes[i].statusSpriteId, tXPos - 8);
+ }
+ }
+ ChangeBgX(2, 0x800, 1);
+}
+
+#undef tXpos
+
+void ChooseMonForDaycare(void)
+{
+ gFieldCallback2 = CB2_FadeFromPartyMenu;
+ InitPartyMenu(PARTY_MENU_TYPE_DAYCARE, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_MON, FALSE, PARTY_MSG_CHOOSE_MON_2, Task_HandleChooseMonInput, CB2_ReturnToField);
+}
+
+void ChoosePartyMonByMenuType(u8 menuType)
+{
+ gFieldCallback2 = CB2_FadeFromPartyMenu;
+ InitPartyMenu(menuType, PARTY_LAYOUT_SINGLE, PARTY_ACTION_CHOOSE_AND_CLOSE, FALSE, PARTY_MSG_CHOOSE_MON, Task_HandleChooseMonInput, CB2_ReturnToField);
+}
+
+static bool8 CB2_FadeFromPartyMenu(void)
+{
+ sub_807DC00();
+ CreateTask(Task_PartyMenuWaitForFade, 10);
+ return TRUE;
+}
+
+static void Task_PartyMenuWaitForFade(u8 taskId)
+{
+ if (IsWeatherNotFadingIn())
+ {
+ DestroyTask(taskId);
+ ScriptContext2_Disable();
+ EnableBothScriptContexts();
+ }
+}
diff --git a/src/player_pc.c b/src/player_pc.c
index f454cd07f..00d41abe6 100644
--- a/src/player_pc.c
+++ b/src/player_pc.c
@@ -38,7 +38,7 @@ static EWRAM_DATA const u8 *sItemOrder = NULL;
static EWRAM_DATA u8 sTopMenuItemCount = 0;
EWRAM_DATA struct PlayerPCItemPageStruct gPlayerPcMenuManager = {};
-#define SELECTED_MAIL (gSaveBlock1Ptr->mail[PC_MAIL_NUM(gPlayerPcMenuManager.scrollOffset) + gPlayerPcMenuManager.selectedRow])
+#define SELECTED_MAIL (gSaveBlock1Ptr->mail[PC_MAIL_NUM(gPlayerPcMenuManager.itemsAbove) + gPlayerPcMenuManager.cursorPos])
static void Task_DrawPlayerPcTopMenu(u8 taskId);
static void Task_TopMenuHandleInput(u8 taskId);
@@ -234,8 +234,8 @@ static void Task_PlayerPcMailbox(u8 taskId)
}
else
{
- gPlayerPcMenuManager.selectedRow = 0;
- gPlayerPcMenuManager.scrollOffset = 0;
+ gPlayerPcMenuManager.cursorPos = 0;
+ gPlayerPcMenuManager.itemsAbove = 0;
PCMailCompaction();
Task_SetPageItemVars(taskId);
if (gPlayerPcMenuManager.unk_9 == 0)
@@ -322,7 +322,7 @@ static void Task_DepositItem_WaitFadeAndGoToBag(u8 taskId)
if (!gPaletteFade.active)
{
CleanupOverworldWindowsAndTilemaps();
- sub_8107DB4(3, POCKET_ITEMS - 1, CB2_ReturnToField);
+ GoToBagMenu(3, POCKET_ITEMS - 1, CB2_ReturnToField);
gFieldCallback = CB2_ReturnFromDepositMenu;
DestroyTask(taskId);
}
@@ -336,7 +336,7 @@ static void Task_PlayerPcDepositItem(u8 taskId)
static void Task_ReturnToItemStorageSubmenu(u8 taskId)
{
- if (field_weather_is_fade_finished() == TRUE)
+ if (IsWeatherNotFadingIn() == TRUE)
gTasks[taskId].func = Task_TopMenu_ItemStorageSubmenu_HandleInput;
}
@@ -469,7 +469,7 @@ static void Task_MailboxPcHandleInput(u8 taskId)
if (!gPaletteFade.active)
{
input = ListMenu_ProcessInput(tListMenuTaskId);
- ListMenuGetScrollAndRow(tListMenuTaskId, &gPlayerPcMenuManager.scrollOffset, &gPlayerPcMenuManager.selectedRow);
+ ListMenuGetScrollAndRow(tListMenuTaskId, &gPlayerPcMenuManager.itemsAbove, &gPlayerPcMenuManager.cursorPos);
switch (input)
{
case -1:
@@ -483,7 +483,7 @@ static void Task_MailboxPcHandleInput(u8 taskId)
PlaySE(SE_SELECT);
MailboxPC_RemoveWindow(0);
MailboxPC_RemoveWindow(1);
- DestroyListMenuTask(tListMenuTaskId, &gPlayerPcMenuManager.scrollOffset, &gPlayerPcMenuManager.selectedRow);
+ DestroyListMenuTask(tListMenuTaskId, &gPlayerPcMenuManager.itemsAbove, &gPlayerPcMenuManager.cursorPos);
ScheduleBgCopyTilemapToVram(0);
RemoveScrollIndicatorArrowPair(gPlayerPcMenuManager.scrollIndicatorId);
gTasks[taskId].func = Task_PrintWhatToDoWithSelectedMail;
@@ -573,7 +573,7 @@ static void Task_WaitFadeAndReadSelectedMail(u8 taskId)
static void Task_WaitFadeAndReturnToMailboxPcInputHandler(u8 taskId)
{
- if (field_weather_is_fade_finished() == TRUE)
+ if (IsWeatherNotFadingIn() == TRUE)
gTasks[taskId].func = Task_MailboxPcHandleInput;
}
@@ -641,10 +641,10 @@ static void Task_TryPutMailInBag_DestroyMsgIfSuccessful(u8 taskId)
ClearMailStruct(mail);
PCMailCompaction();
gPlayerPcMenuManager.count--;
- if (gPlayerPcMenuManager.count < gPlayerPcMenuManager.pageItems + gPlayerPcMenuManager.scrollOffset)
+ if (gPlayerPcMenuManager.count < gPlayerPcMenuManager.pageItems + gPlayerPcMenuManager.itemsAbove)
{
- if (gPlayerPcMenuManager.scrollOffset != 0)
- gPlayerPcMenuManager.scrollOffset--;
+ if (gPlayerPcMenuManager.itemsAbove != 0)
+ gPlayerPcMenuManager.itemsAbove--;
}
Task_SetPageItemVars(taskId);
}
@@ -674,7 +674,7 @@ static void Task_WaitFadeAndGoToPartyMenu(u8 taskId)
{
MailboxPC_DestroyListMenuBuffer();
CleanupOverworldWindowsAndTilemaps();
- PartyMenuInit_FromPlayerPc();
+ ChooseMonToGiveMailFromMailbox();
DestroyTask(taskId);
}
}
@@ -693,10 +693,10 @@ static void CB2_ReturnToMailboxPc_UpdateScrollVariables(void)
PCMailCompaction();
if (count != gPlayerPcMenuManager.count)
{
- if (gPlayerPcMenuManager.count < gPlayerPcMenuManager.pageItems + gPlayerPcMenuManager.scrollOffset)
+ if (gPlayerPcMenuManager.count < gPlayerPcMenuManager.pageItems + gPlayerPcMenuManager.itemsAbove)
{
- if (gPlayerPcMenuManager.scrollOffset != 0)
- gPlayerPcMenuManager.scrollOffset--;
+ if (gPlayerPcMenuManager.itemsAbove != 0)
+ gPlayerPcMenuManager.itemsAbove--;
}
}
Task_SetPageItemVars(taskId);
@@ -708,7 +708,7 @@ static void CB2_ReturnToMailboxPc_UpdateScrollVariables(void)
sub_807DC00();
}
-void CB2_PlayerPC_ReturnFromPartyMenu(void)
+void Mailbox_ReturnToMailListAfterDeposit(void)
{
gFieldCallback = CB2_ReturnToMailboxPc_UpdateScrollVariables;
SetMainCallback2(CB2_ReturnToField);
diff --git a/src/pokemon.c b/src/pokemon.c
index 8f9fe192c..9f5a6967e 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -4117,7 +4117,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
if (sp34 != 4)
{
gAbsentBattlerFlags &= ~gBitTable[sp34];
- CopyPlayerPartyMonToBattleData(sp34, pokemon_order_func(gBattlerPartyIndexes[sp34]));
+ CopyPlayerPartyMonToBattleData(sp34, GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[sp34]));
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255)
gBattleResults.numRevivesUsed++;
}
@@ -4405,7 +4405,7 @@ static bool8 HealStatusConditions(struct Pokemon *mon, u32 unused, u32 healMask,
}
}
-bool8 PokemonUseItemEffects2(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex)
+bool8 PokemonItemUseNoEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex)
{
u32 data;
s32 tmp;
@@ -5179,7 +5179,7 @@ void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)
SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]);
}
-bool8 sub_80435E0(void)
+bool8 GetPlayerFlankId(void)
{
bool8 retVal = FALSE;
switch (gLinkPlayers[GetMultiplayerId()].id)
@@ -5813,11 +5813,11 @@ void SetMonPreventsSwitchingString(void)
gBattleTextBuff1[4] = B_BUFF_EOS;
if (GetBattlerSide(gBattleStruct->battlerPreventingSwitchout) == B_SIDE_PLAYER)
- gBattleTextBuff1[3] = pokemon_order_func(gBattlerPartyIndexes[gBattleStruct->battlerPreventingSwitchout]);
+ gBattleTextBuff1[3] = GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[gBattleStruct->battlerPreventingSwitchout]);
else
gBattleTextBuff1[3] = gBattlerPartyIndexes[gBattleStruct->battlerPreventingSwitchout];
- PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBattlerInMenuId, pokemon_order_func(gBattlerPartyIndexes[gBattlerInMenuId]))
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBattlerInMenuId, GetPartyIdFromBattlePartyId(gBattlerPartyIndexes[gBattlerInMenuId]))
BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
}
diff --git a/src/pokemon_icon.c b/src/pokemon_icon.c
index f3492593c..4c7681231 100644
--- a/src/pokemon_icon.c
+++ b/src/pokemon_icon.c
@@ -1276,7 +1276,7 @@ static void DestroyMonIconInternal(struct Sprite * sprite)
DestroySprite(sprite);
}
-void MonIcon_SetAnim(struct Sprite * sprite, u8 animNum)
+void SetPartyHPBarSprite(struct Sprite * sprite, u8 animNum)
{
sprite->animNum = animNum;
sprite->animDelayCounter = 0;
diff --git a/src/quest_log.c b/src/quest_log.c
index d7b544882..04369f1c2 100644
--- a/src/quest_log.c
+++ b/src/quest_log.c
@@ -987,7 +987,7 @@ void sub_8111708(void)
gSaveBlock1Ptr->mapDataId = VarGet(VAR_0x40AE);
if (gSaveBlock1Ptr->mapDataId == 0)
{
- sp0 = *get_mapheader_by_bank_and_number(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum);
+ sp0 = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum);
gSaveBlock1Ptr->mapDataId = sp0.mapDataId;
}
}
@@ -1363,7 +1363,7 @@ static void sub_8111FCC(u8 taskId)
{
if (gUnknown_203AE94.unk_0_6 != 1)
{
- sub_80C4DF8(gStringVar1, gMapHeader.regionMapSectionId);
+ GetMapNameGeneric(gStringVar1, gMapHeader.regionMapSectionId);
StringExpandPlaceholders(gStringVar4, gUnknown_841B073);
sub_8111D10();
}
@@ -1972,15 +1972,15 @@ void DestroyHelpMessageWindow(u8 a0)
}
#ifdef NONMATCHING
-void sub_8112F18(u8 a0)
+void sub_8112F18(u8 windowId)
{
- u8 width = GetWindowAttribute(a0, WINDOW_WIDTH);
- u8 height = GetWindowAttribute(a0, WINDOW_HEIGHT);
+ u8 width = GetWindowAttribute(windowId, WINDOW_WIDTH);
+ u8 height = GetWindowAttribute(windowId, WINDOW_HEIGHT);
u8 *buffer = Alloc(32 * width * height);
u8 i, j;
u8 k;
- if (buffer)
+ if (buffer != NULL)
{
for (i = 0; i < height; i++)
{
@@ -1999,13 +1999,13 @@ void sub_8112F18(u8 a0)
);
}
}
- CopyToWindowPixelBuffer(a0, buffer, width * height * 32, 0);
+ CopyToWindowPixelBuffer(windowId, buffer, width * height * 32, 0);
Free(buffer);
}
}
#else
NAKED
-void sub_8112F18(u8 a0)
+void sub_8112F18(u8 windowId)
{
asm_unified("\tpush {r4-r7,lr}\n"
"\tmov r7, r10\n"
@@ -3166,7 +3166,7 @@ static const u16 *sub_8113FBC(const u16 *a0)
StringCopy(gStringVar1, ItemId_GetName(r5[0]));
if (r5[0] == ITEM_ESCAPE_ROPE)
{
- sub_80C4DF8(gStringVar2, r5[2]);
+ GetMapNameGeneric(gStringVar2, r5[2]);
StringExpandPlaceholders(gStringVar4, gUnknown_841AFA6);
}
else if (r5[1] != 0xFFFF)
@@ -3814,7 +3814,7 @@ static const u16 *sub_8114D68(const u16 *a0)
a0 = sub_8113E88(30, a0);
r6 = (const u8 *)a0 + 6;
DynamicPlaceholderTextUtil_Reset();
- sub_80C4DF8(gStringVar1, r6[0]);
+ GetMapNameGeneric(gStringVar1, r6[0]);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(1, gTrainers[a0[2]].trainerName);
QuestLog_AutoGetSpeciesName(a0[0], 0, 2);
@@ -3855,7 +3855,7 @@ static const u16 *sub_8114E68(const u16 *a0)
r6 = (const u8 *)a0 + 8;
DynamicPlaceholderTextUtil_Reset();
- sub_80C4DF8(gStringVar1, r6[2]);
+ GetMapNameGeneric(gStringVar1, r6[2]);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1);
QuestLog_AutoGetSpeciesName(a0[2], NULL, 1);
ConvertIntToDecimalStringN(gStringVar2, r6[0], STR_CONV_MODE_LEFT_ALIGN, 3);
@@ -3983,7 +3983,7 @@ static const u16 *sub_81151DC(const u16 *a0)
const u16 *r5 = sub_8113E88(34, a0);
const u8 *r6 = (const u8 *)r5 + 6;
DynamicPlaceholderTextUtil_Reset();
- sub_80C4DF8(gStringVar1, r6[0]);
+ GetMapNameGeneric(gStringVar1, r6[0]);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1);
if (
gTrainers[r5[2]].trainerClass == 0x51
@@ -4164,7 +4164,7 @@ static const u16 *sub_81152BC(const u16 *a0)
const u16 *r5 = sub_8113E88(35, a0);
const u8 *r5_2 = (const u8 *)r5 + 0;
r6 = r5_2[1];
- sub_80C4DF8(gStringVar1, r5_2[0]);
+ GetMapNameGeneric(gStringVar1, r5_2[0]);
StringCopy(gStringVar2, gUnknown_8456AF0[r6]);
if (gUnknown_8456BE4[r6] == 5)
{
@@ -4238,7 +4238,7 @@ static const u16 *sub_8115460(const u16 *a0)
const u8 *r5 = (const u8 *)r4 + 2;
QuestLog_AutoGetSpeciesName(r4[0], gStringVar1, 0);
if (r5[1] != 0xFF)
- sub_80C4DF8(gStringVar2, r5[1]);
+ GetMapNameGeneric(gStringVar2, r5[1]);
if (r5[0] == 7)
{
if (r5[1] == 0x58)
@@ -4270,7 +4270,7 @@ static const u16 *sub_8115518(const u16 *a0)
const u8 *r7 = (const u8 *)r4 + 8;
u32 r6 = (r4[2] << 16) + r4[3];
DynamicPlaceholderTextUtil_Reset();
- sub_80C4DF8(gStringVar1, r7[0]);
+ GetMapNameGeneric(gStringVar1, r7[0]);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(1, ItemId_GetName(r4[0]));
if (r4[1] < 2)
@@ -4303,7 +4303,7 @@ static const u16 *sub_81155E0(const u16 *a0) {
const u8 *r7 = (const u8 *) r5 + 8;
u32 r6 = (r5[2] << 16) + r5[3];
DynamicPlaceholderTextUtil_Reset();
- sub_80C4DF8(gStringVar1, r7[0]);
+ GetMapNameGeneric(gStringVar1, r7[0]);
if (r7[1] == 0) {
DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gSaveBlock2Ptr->playerName);
DynamicPlaceholderTextUtil_SetPlaceholderPtr(1, gStringVar1);
@@ -4344,7 +4344,7 @@ static const u16 *sub_8115700(const u16 *a0)
{
const u16 *r4 = sub_8113E88(40, a0);
const u8 *r5 = (const u8 *)r4 + 2;
- sub_80C4DF8(gStringVar1, r5[0]);
+ GetMapNameGeneric(gStringVar1, r5[0]);
StringCopy(gStringVar2, ItemId_GetName(r4[0]));
StringExpandPlaceholders(gStringVar4, gUnknown_841B03F);
return (const u16 *)(r5 + 2);
@@ -4420,7 +4420,7 @@ static u16 *sub_81157DC(u16 *a0, const u16 *a1)
static const u16 *sub_8115800(const u16 *a0)
{
const u16 *r4 = sub_8113E88(42, a0);
- sub_80C4DF8(gStringVar1, r4[0]);
+ GetMapNameGeneric(gStringVar1, r4[0]);
StringExpandPlaceholders(gStringVar4, gUnknown_841B064);
return r4 + 1;
}
diff --git a/src/roamer.c b/src/roamer.c
index b42855644..b3cc67f85 100644
--- a/src/roamer.c
+++ b/src/roamer.c
@@ -236,5 +236,5 @@ u16 GetRoamerLocationMapSectionId(void)
struct Roamer *roamer = &saveRoamer;
if (!saveRoamer.active)
return MAPSEC_NONE;
- return get_mapheader_by_bank_and_number(sRoamerLocation[MAP_GRP], sRoamerLocation[MAP_NUM])->regionMapSectionId;
+ return Overworld_GetMapHeaderByGroupAndId(sRoamerLocation[MAP_GRP], sRoamerLocation[MAP_NUM])->regionMapSectionId;
}
diff --git a/src/save_menu_util.c b/src/save_menu_util.c
index 195b29b0c..54073785e 100644
--- a/src/save_menu_util.c
+++ b/src/save_menu_util.c
@@ -41,7 +41,7 @@ void SaveStatToString(u8 gameStatId, u8 *dest0, u8 color)
dest = ConvertIntToDecimalStringN(dest, gSaveBlock2Ptr->playTimeMinutes, STR_CONV_MODE_LEADING_ZEROS, 2);
break;
case SAVE_STAT_LOCATION:
- sub_80C4DF8(dest, gMapHeader.regionMapSectionId);
+ GetMapNameGeneric(dest, gMapHeader.regionMapSectionId);
break;
case SAVE_STAT_BADGES:
for (flagId = FLAG_BADGE01_GET, nBadges = 0; flagId < FLAG_BADGE01_GET + 8; flagId++)
diff --git a/src/start_menu.c b/src/start_menu.c
index 4a4fe52e3..2a1713902 100644
--- a/src/start_menu.c
+++ b/src/start_menu.c
@@ -504,7 +504,7 @@ static bool8 StartMenuPlayerCallback(void)
PlayRainStoppingSoundEffect();
DestroySafariZoneStatsWindow();
CleanupOverworldWindowsAndTilemaps();
- InitTrainerCard(CB2_ReturnToStartMenu);
+ InitTrainerCard(CB2_ReturnToFieldWithOpenMenu);
return TRUE;
}
return FALSE;
@@ -524,7 +524,7 @@ static bool8 StartMenuOptionCallback(void)
DestroySafariZoneStatsWindow();
CleanupOverworldWindowsAndTilemaps();
SetMainCallback2(CB2_OptionsMenuFromStartMenu);
- gMain.savedCallback = CB2_ReturnToStartMenu;
+ gMain.savedCallback = CB2_ReturnToFieldWithOpenMenu;
return TRUE;
}
return FALSE;
@@ -554,7 +554,7 @@ static bool8 StartMenuLinkPlayerCallback(void)
{
PlayRainStoppingSoundEffect();
CleanupOverworldWindowsAndTilemaps();
- InitLinkPartnerTrainerCard(gUnknown_300502C, CB2_ReturnToStartMenu);
+ InitLinkPartnerTrainerCard(gUnknown_300502C, CB2_ReturnToFieldWithOpenMenu);
return TRUE;
}
return FALSE;
diff --git a/src/tm_case.c b/src/tm_case.c
index 25fe9a72c..a9af2332e 100644
--- a/src/tm_case.c
+++ b/src/tm_case.c
@@ -595,7 +595,7 @@ static void TMCase_MoveCursor_UpdatePrintedDescription(s32 itemIndex)
static void FillBG2RowWithPalette_2timesNplus1(s32 a0)
{
- SetBgRectPal(2, 0, 12, 30, 8, 2 * a0 + 1);
+ SetBgTilemapPalette(2, 0, 12, 30, 8, 2 * a0 + 1);
ScheduleBgCopyTilemapToVram(2);
}
@@ -848,8 +848,8 @@ static void TMHMContextMenuAction_Use(u8 taskId)
}
else
{
- gUnknown_3005E98 = sub_8125B40;
- sTMCaseDynamicResources->savedCallback = sub_8124C8C;
+ gItemUseCB = ItemUseCB_TMHM;
+ sTMCaseDynamicResources->savedCallback = CB2_ShowPartyMenuForItemUse;
Task_BeginFadeOutFromTMCase(taskId);
}
}
@@ -874,7 +874,7 @@ static void TMHMContextMenuAction_Give(u8 taskId)
}
else
{
- sTMCaseDynamicResources->savedCallback = sub_8126EDC;
+ sTMCaseDynamicResources->savedCallback = CB2_ChooseMonToGiveItem;
Task_BeginFadeOutFromTMCase(taskId);
}
}
@@ -945,7 +945,7 @@ static void Task_SelectTMAction_Type1(u8 taskId)
if (!itemid_is_unique(BagGetItemIdByPocketPosition(POCKET_TM_CASE, data[1])))
{
- sTMCaseDynamicResources->savedCallback = c2_8123744;
+ sTMCaseDynamicResources->savedCallback = CB2_GiveHoldItem;
Task_BeginFadeOutFromTMCase(taskId);
}
else
@@ -1274,7 +1274,7 @@ static void Task_TMCaseDude_Playback(u8 taskId)
sTMCaseStaticResources.scrollOffset = sPokeDudePackBackup->unk_162;
Free(sPokeDudePackBackup);
CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
- sub_8108CF0();
+ CB2_SetUpReshowBattleScreenAfterMenu();
BeginNormalPaletteFade(0xFFFFFFFF, -2, 0, 16, 0);
data[8]++;
}
diff --git a/src/trade.c b/src/trade.c
index 5151ecedd..4921a1ba3 100644
--- a/src/trade.c
+++ b/src/trade.c
@@ -459,9 +459,9 @@ static const u8 *const sTradeErrorOrStatusMessagePtrs[] = {
gUnknown_8417094, // That's your only POKéMON for battle
gUnknown_841E199, // Waiting for your friend to finish
gUnknown_841E1C5, // Your friend wants to trade POKéMON
- gUnknown_84170BC, // That POKéMON can't be traded now
- gUnknown_84170E0, // An EGG can't be traded now
- gUnknown_84170FC // The other TRAINER's POKéMON can't be traded now
+ gText_PkmnCantBeTradedNow, // That POKéMON can't be traded now
+ gText_EggCantBeTradedNow, // An EGG can't be traded now
+ gText_OtherTrainersPkmnCantBeTraded // The other TRAINER's POKéMON can't be traded now
};
static const u8 gUnknown_8261F18[] = { 0, 1, 2 };
@@ -879,11 +879,11 @@ static void sub_804C728(void)
break;
case 8:
LoadHeldItemIcons();
- sub_812256C(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 0);
+ DrawHeldItemIconsForTrade(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 0);
gMain.state++;
break;
case 9:
- sub_812256C(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 1);
+ DrawHeldItemIconsForTrade(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 1);
gMain.state++;
break;
case 10:
@@ -1483,7 +1483,7 @@ static void sub_804C728(void)
"\tadds r0, 0x36\n"
"\tadds r1, 0x28\n"
"\tmovs r2, 0\n"
- "\tbl sub_812256C\n"
+ "\tbl DrawHeldItemIconsForTrade\n"
"\tldr r1, _0804CB74 @ =gMain\n"
"\tmovs r5, 0x87\n"
"\tlsls r5, 3\n"
@@ -1499,7 +1499,7 @@ static void sub_804C728(void)
"\tadds r0, 0x36\n"
"\tadds r1, 0x28\n"
"\tmovs r2, 0x1\n"
- "\tbl sub_812256C\n"
+ "\tbl DrawHeldItemIconsForTrade\n"
"\tldr r1, _0804CB98 @ =gMain\n"
"\tmovs r7, 0x87\n"
"\tlsls r7, 3\n"
@@ -1989,11 +1989,11 @@ void sub_804CF14(void)
break;
case 8:
LoadHeldItemIcons();
- sub_812256C(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 0);
+ DrawHeldItemIconsForTrade(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 0);
gMain.state++;
break;
case 9:
- sub_812256C(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 1);
+ DrawHeldItemIconsForTrade(sTradeMenuResourcesPtr->partyCounts, sTradeMenuResourcesPtr->partyIcons, 1);
gMain.state++;
break;
case 10:
@@ -2053,9 +2053,9 @@ void sub_804CF14(void)
}
if (sTradeMenuResourcesPtr->tradeMenuCursorPosition < 6)
- sTradeMenuResourcesPtr->tradeMenuCursorPosition = sub_8138B20();
+ sTradeMenuResourcesPtr->tradeMenuCursorPosition = GetLastViewedMonIndex();
else
- sTradeMenuResourcesPtr->tradeMenuCursorPosition = sub_8138B20() + 6;
+ sTradeMenuResourcesPtr->tradeMenuCursorPosition = GetLastViewedMonIndex() + 6;
sTradeMenuResourcesPtr->tradeMenuCursorSpriteIdx = CreateSprite(&sSpriteTemplate_TradeButtons, sTradeMonSpriteCoords[sTradeMenuResourcesPtr->tradeMenuCursorPosition][0] * 8 + 32, sTradeMonSpriteCoords[sTradeMenuResourcesPtr->tradeMenuCursorPosition][1] * 8, 2);
gMain.state = 16;
@@ -2365,7 +2365,7 @@ void sub_804CF14(void)
"\tadds r0, 0x36\n"
"\tadds r1, 0x28\n"
"\tmovs r2, 0\n"
- "\tbl sub_812256C\n"
+ "\tbl DrawHeldItemIconsForTrade\n"
"\tldr r1, _0804D174 @ =gMain\n"
"\tmovs r5, 0x87\n"
"\tlsls r5, 3\n"
@@ -2381,7 +2381,7 @@ void sub_804CF14(void)
"\tadds r0, 0x36\n"
"\tadds r1, 0x28\n"
"\tmovs r2, 0x1\n"
- "\tbl sub_812256C\n"
+ "\tbl DrawHeldItemIconsForTrade\n"
"\tldr r1, _0804D198 @ =gMain\n"
"\tmovs r7, 0x87\n"
"\tlsls r7, 3\n"
@@ -2633,14 +2633,14 @@ void sub_804CF14(void)
"\tldrb r0, [r0]\n"
"\tcmp r0, 0x5\n"
"\tbhi _0804D3B8\n"
- "\tbl sub_8138B20\n"
+ "\tbl GetLastViewedMonIndex\n"
"\tldr r1, [r4]\n"
"\tb _0804D3C0\n"
"\t.align 2, 0\n"
"_0804D3B0: .4byte sSpriteTemplate_Text\n"
"_0804D3B4: .4byte sTradeMenuResourcesPtr\n"
"_0804D3B8:\n"
- "\tbl sub_8138B20\n"
+ "\tbl GetLastViewedMonIndex\n"
"\tldr r1, [r4]\n"
"\tadds r0, 0x6\n"
"_0804D3C0:\n"
@@ -4243,7 +4243,7 @@ static void sub_804F964(void)
{
for (j = 0; j < sTradeMenuResourcesPtr->partyCounts[i]; j++)
{
- MonIcon_SetAnim(&gSprites[sTradeMenuResourcesPtr->partyIcons[i][j]], 4 - sTradeMenuResourcesPtr->unk_5D[i][j]);
+ SetPartyHPBarSprite(&gSprites[sTradeMenuResourcesPtr->partyIcons[i][j]], 4 - sTradeMenuResourcesPtr->unk_5D[i][j]);
}
}
}
@@ -4394,7 +4394,7 @@ static bool32 IsDeoxysOrMewUntradable(u16 species, bool8 isObedientBitSet)
return FALSE;
}
-int sub_804FBEC(struct UnkLinkRfuStruct_02022B14Substruct a0, struct UnkLinkRfuStruct_02022B14Substruct a1, u16 species1, u16 species2, u8 type, u16 species3, u8 isObedientBitSet)
+int GetUnionRoomTradeMessageId(struct UnkLinkRfuStruct_02022B14Substruct a0, struct UnkLinkRfuStruct_02022B14Substruct a1, u16 species1, u16 species2, u8 type, u16 species3, u8 isObedientBitSet)
{
u8 r9 = a0.unk_01_0;
u8 r4 = a0.unk_00_7;
@@ -4474,7 +4474,7 @@ int sub_804FBEC(struct UnkLinkRfuStruct_02022B14Substruct a0, struct UnkLinkRfuS
return 0;
}
-int Trade_CanTradeSelectedMon(struct UnkLinkRfuStruct_02022B14Substruct a0, u16 species, u16 a2, u8 a3)
+int CanRegisterMonForTradingBoard(struct UnkLinkRfuStruct_02022B14Substruct a0, u16 species, u16 a2, u8 a3)
{
u8 canTradeEggAndNational = a0.unk_01_0;
diff --git a/src/wild_pokemon_area.c b/src/wild_pokemon_area.c
index fc4df06ed..3c5afaf25 100644
--- a/src/wild_pokemon_area.c
+++ b/src/wild_pokemon_area.c
@@ -289,7 +289,7 @@ static bool32 PokemonInEncounterTable(const struct WildPokemonInfo * info, s32 s
static u16 GetMapSecIdFromWildMonHeader(const struct WildPokemonHeader * header)
{
- return get_mapheader_by_bank_and_number(header->mapGroup, header->mapNum)->regionMapSectionId;
+ return Overworld_GetMapHeaderByGroupAndId(header->mapGroup, header->mapNum)->regionMapSectionId;
}
static bool32 TryGetMapSecPokedexAreaEntry(u16 mapSecId, const u16 (*lut)[2], s32 count, s32 * lutIdx_p, u16 * tableIdx_p)