Add "Move Item" option in party menu (#6758)

This commit is contained in:
Eduardo Quezada 2025-05-04 05:40:31 -04:00 committed by GitHub
parent e92d48aee9
commit 96650ffd27
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 156 additions and 36 deletions

View File

@ -83,6 +83,7 @@
#define PARTY_MSG_CHOOSE_SECOND_FUSION 28
#define PARTY_MSG_NO_POKEMON 29
#define PARTY_MSG_CHOOSE_MON_FOR_BOX 30
#define PARTY_MSG_MOVE_ITEM_WHERE 31
#define PARTY_MSG_NONE 127

View File

@ -1573,6 +1573,9 @@ extern const u8 gText_ChoosePokemon[];
extern const u8 gText_ChoosePokemonCancel[];
extern const u8 gText_ChoosePokemonConfirm[];
extern const u8 gText_SendWhichMonToPC[];
extern const u8 gText_MoveItemWhere[];
extern const u8 gText_XsYAnd[];
extern const u8 gText_XsYWereSwapped[];
extern const u8 gText_MoveToWhere[];
extern const u8 gText_TeachWhichPokemon[];
extern const u8 gText_UseOnWhichPokemon[];

View File

@ -497,9 +497,9 @@ static const struct WindowTemplate sItemGiveTakeWindowTemplate =
{
.bg = 2,
.tilemapLeft = 23,
.tilemapTop = 13,
.tilemapTop = 11,
.width = 6,
.height = 6,
.height = 8,
.paletteNum = 14,
.baseBlock = 0x39D,
};
@ -661,6 +661,7 @@ static const u8 *const sActionStringTable[] =
[PARTY_MSG_CHOOSE_SECOND_FUSION] = gText_NextFusionMon,
[PARTY_MSG_NO_POKEMON] = COMPOUND_STRING("You have no POKéMON."),
[PARTY_MSG_CHOOSE_MON_FOR_BOX] = gText_SendWhichMonToPC,
[PARTY_MSG_MOVE_ITEM_WHERE] = gText_MoveItemWhere,
};
static const u8 *const sDescriptionStringTable[] =
@ -696,33 +697,34 @@ struct
TaskFunc func;
} static const sCursorOptions[MENU_FIELD_MOVES] =
{
[MENU_SUMMARY] = {COMPOUND_STRING("SUMMARY"), CursorCb_Summary},
[MENU_SWITCH] = {COMPOUND_STRING("SWITCH"), CursorCb_Switch},
[MENU_CANCEL1] = {gText_Cancel2, CursorCb_Cancel1},
[MENU_ITEM] = {COMPOUND_STRING("ITEM"), CursorCb_Item},
[MENU_GIVE] = {gMenuText_Give, CursorCb_Give},
[MENU_TAKE_ITEM] = {COMPOUND_STRING("TAKE"), CursorCb_TakeItem},
[MENU_MAIL] = {COMPOUND_STRING("MAIL"), CursorCb_Mail},
[MENU_TAKE_MAIL] = {COMPOUND_STRING("TAKE"), CursorCb_TakeMail},
[MENU_READ] = {COMPOUND_STRING("READ"), CursorCb_Read},
[MENU_CANCEL2] = {gText_Cancel2, CursorCb_Cancel2},
[MENU_SHIFT] = {COMPOUND_STRING("SHIFT"), CursorCb_SendMon},
[MENU_SEND_OUT] = {COMPOUND_STRING("SEND OUT"), CursorCb_SendMon},
[MENU_ENTER] = {COMPOUND_STRING("ENTER"), CursorCb_Enter},
[MENU_NO_ENTRY] = {COMPOUND_STRING("NO ENTRY"), CursorCb_NoEntry},
[MENU_STORE] = {COMPOUND_STRING("STORE"), CursorCb_Store},
[MENU_REGISTER] = {gText_Register, CursorCb_Register},
[MENU_TRADE1] = {sText_Trade4, CursorCb_Trade1},
[MENU_TRADE2] = {sText_Trade4, CursorCb_Trade2},
[MENU_TOSS] = {gMenuText_Toss, CursorCb_Toss},
[MENU_CATALOG_BULB] = {COMPOUND_STRING("Light bulb"), CursorCb_CatalogBulb},
[MENU_CATALOG_OVEN] = {COMPOUND_STRING("Microwave oven"), CursorCb_CatalogOven},
[MENU_SUMMARY] = {COMPOUND_STRING("SUMMARY"), CursorCb_Summary},
[MENU_SWITCH] = {COMPOUND_STRING("SWITCH"), CursorCb_Switch},
[MENU_CANCEL1] = {gText_Cancel2, CursorCb_Cancel1},
[MENU_ITEM] = {COMPOUND_STRING("ITEM"), CursorCb_Item},
[MENU_GIVE] = {gMenuText_Give, CursorCb_Give},
[MENU_TAKE_ITEM] = {COMPOUND_STRING("TAKE"), CursorCb_TakeItem},
[MENU_MOVE_ITEM] = {COMPOUND_STRING("MOVE"), CursorCb_MoveItem},
[MENU_MAIL] = {COMPOUND_STRING("MAIL"), CursorCb_Mail},
[MENU_TAKE_MAIL] = {COMPOUND_STRING("TAKE"), CursorCb_TakeMail},
[MENU_READ] = {COMPOUND_STRING("READ"), CursorCb_Read},
[MENU_CANCEL2] = {gText_Cancel2, CursorCb_Cancel2},
[MENU_SHIFT] = {COMPOUND_STRING("SHIFT"), CursorCb_SendMon},
[MENU_SEND_OUT] = {COMPOUND_STRING("SEND OUT"), CursorCb_SendMon},
[MENU_ENTER] = {COMPOUND_STRING("ENTER"), CursorCb_Enter},
[MENU_NO_ENTRY] = {COMPOUND_STRING("NO ENTRY"), CursorCb_NoEntry},
[MENU_STORE] = {COMPOUND_STRING("STORE"), CursorCb_Store},
[MENU_REGISTER] = {gText_Register, CursorCb_Register},
[MENU_TRADE1] = {sText_Trade4, CursorCb_Trade1},
[MENU_TRADE2] = {sText_Trade4, CursorCb_Trade2},
[MENU_TOSS] = {gMenuText_Toss, CursorCb_Toss},
[MENU_CATALOG_BULB] = {COMPOUND_STRING("Light bulb"), CursorCb_CatalogBulb},
[MENU_CATALOG_OVEN] = {COMPOUND_STRING("Microwave oven"), CursorCb_CatalogOven},
[MENU_CATALOG_WASHING] = {COMPOUND_STRING("Washing machine"), CursorCb_CatalogWashing},
[MENU_CATALOG_FRIDGE] = {COMPOUND_STRING("Refrigerator"), CursorCb_CatalogFridge},
[MENU_CATALOG_FAN] = {COMPOUND_STRING("Electric fan"), CursorCb_CatalogFan},
[MENU_CATALOG_MOWER] = {COMPOUND_STRING("Lawn mower"), CursorCb_CatalogMower},
[MENU_CHANGE_FORM] = {COMPOUND_STRING("Change form"), CursorCb_ChangeForm},
[MENU_CHANGE_ABILITY] = {COMPOUND_STRING("Change Ability"), CursorCb_ChangeAbility},
[MENU_CATALOG_FRIDGE] = {COMPOUND_STRING("Refrigerator"), CursorCb_CatalogFridge},
[MENU_CATALOG_FAN] = {COMPOUND_STRING("Electric fan"), CursorCb_CatalogFan},
[MENU_CATALOG_MOWER] = {COMPOUND_STRING("Lawn mower"), CursorCb_CatalogMower},
[MENU_CHANGE_FORM] = {COMPOUND_STRING("Change form"), CursorCb_ChangeForm},
[MENU_CHANGE_ABILITY] = {COMPOUND_STRING("Change Ability"), CursorCb_ChangeAbility},
};
static const u8 sPartyMenuAction_SummarySwitchCancel[] = {MENU_SUMMARY, MENU_SWITCH, MENU_CANCEL1};
@ -732,7 +734,7 @@ 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_GiveTakeItemCancel[] = {MENU_GIVE, MENU_TAKE_ITEM, MENU_MOVE_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};

View File

@ -84,6 +84,7 @@ enum {
MENU_ITEM,
MENU_GIVE,
MENU_TAKE_ITEM,
MENU_MOVE_ITEM,
MENU_MAIL,
MENU_TAKE_MAIL,
MENU_READ,
@ -491,6 +492,7 @@ static void CursorCb_Cancel1(u8);
static void CursorCb_Item(u8);
static void CursorCb_Give(u8);
static void CursorCb_TakeItem(u8);
static void CursorCb_MoveItem(u8);
static void CursorCb_Mail(u8);
static void CursorCb_Read(u8);
static void CursorCb_TakeMail(u8);
@ -516,7 +518,7 @@ static bool8 SetUpFieldMove_Surf(void);
static bool8 SetUpFieldMove_Fly(void);
static bool8 SetUpFieldMove_Waterfall(void);
static bool8 SetUpFieldMove_Dive(void);
void TryItemHoldFormChange(struct Pokemon *mon);
void TryItemHoldFormChange(struct Pokemon *mon, s8 slotId);
static void ShowMoveSelectWindow(u8 slot);
static void Task_HandleWhichMoveInput(u8 taskId);
static void Task_HideFollowerNPCForTeleport(u8);
@ -2043,7 +2045,7 @@ static void GiveItemToMon(struct Pokemon *mon, u16 item)
itemBytes[0] = item;
itemBytes[1] = item >> 8;
SetMonData(mon, MON_DATA_HELD_ITEM, itemBytes);
TryItemHoldFormChange(&gPlayerParty[gPartyMenu.slotId]);
TryItemHoldFormChange(&gPlayerParty[gPartyMenu.slotId], gPartyMenu.slotId);
}
static u8 TryTakeMonItem(struct Pokemon *mon)
@ -2057,7 +2059,7 @@ static u8 TryTakeMonItem(struct Pokemon *mon)
item = ITEM_NONE;
SetMonData(mon, MON_DATA_HELD_ITEM, &item);
TryItemHoldFormChange(&gPlayerParty[gPartyMenu.slotId]);
TryItemHoldFormChange(&gPlayerParty[gPartyMenu.slotId], gPartyMenu.slotId);
return 2;
}
@ -6717,7 +6719,7 @@ static void CursorCb_ChangeAbility(u8 taskId)
TryMultichoiceFormChange(taskId);
}
void TryItemHoldFormChange(struct Pokemon *mon)
void TryItemHoldFormChange(struct Pokemon *mon, s8 slotId)
{
u32 currentSpecies = GetMonData(mon, MON_DATA_SPECIES);
u32 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_HOLD, 0);
@ -6725,10 +6727,10 @@ void TryItemHoldFormChange(struct Pokemon *mon)
{
PlayCry_NormalNoDucking(targetSpecies, 0, CRY_VOLUME_RS, CRY_VOLUME_RS);
SetMonData(mon, MON_DATA_SPECIES, &targetSpecies);
FreeAndDestroyMonIconSprite(&gSprites[sPartyMenuBoxes[gPartyMenu.slotId].monSpriteId]);
CreatePartyMonIconSpriteParameterized(targetSpecies, GetMonData(mon, MON_DATA_PERSONALITY, NULL), &sPartyMenuBoxes[gPartyMenu.slotId], 1);
FreeAndDestroyMonIconSprite(&gSprites[sPartyMenuBoxes[slotId].monSpriteId]);
CreatePartyMonIconSpriteParameterized(targetSpecies, GetMonData(mon, MON_DATA_PERSONALITY, NULL), &sPartyMenuBoxes[slotId], 1);
CalculateMonStats(mon);
UpdatePartyMonHeldItemSprite(mon, &sPartyMenuBoxes[gPartyMenu.slotId]);
UpdatePartyMonHeldItemSprite(mon, &sPartyMenuBoxes[slotId]);
}
}
@ -7916,3 +7918,112 @@ void IsLastMonThatKnowsSurf(void)
gSpecialVar_Result = !P_CAN_FORGET_HIDDEN_MOVE;
}
}
void CursorCb_MoveItemCallback(u8 taskId)
{
u16 item1, item2;
u8 buffer[100];
if (gPaletteFade.active || MenuHelpers_ShouldWaitForLinkRecv())
return;
switch (PartyMenuButtonHandler(&gPartyMenu.slotId2))
{
case 2: // User hit B or A while on Cancel
HandleChooseMonCancel(taskId, &gPartyMenu.slotId2);
break;
case 1: // User hit A on a Pokemon
// Pokemon can't give away items to eggs or themselves
if (GetMonData(&gPlayerParty[gPartyMenu.slotId2], MON_DATA_IS_EGG)
|| gPartyMenu.slotId == gPartyMenu.slotId2)
{
PlaySE(SE_FAILURE);
return;
}
PlaySE(SE_SELECT);
gPartyMenu.action = PARTY_ACTION_CHOOSE_MON;
// look up held items
item1 = GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM);
item2 = GetMonData(&gPlayerParty[gPartyMenu.slotId2], MON_DATA_HELD_ITEM);
// swap the held items
SetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_HELD_ITEM, &item2);
SetMonData(&gPlayerParty[gPartyMenu.slotId2], MON_DATA_HELD_ITEM, &item1);
TryItemHoldFormChange(&gPlayerParty[gPartyMenu.slotId], gPartyMenu.slotId);
TryItemHoldFormChange(&gPlayerParty[gPartyMenu.slotId2], gPartyMenu.slotId2);
// update the held item icons
UpdatePartyMonHeldItemSprite(&gPlayerParty[gPartyMenu.slotId], &sPartyMenuBoxes[gPartyMenu.slotId]);
UpdatePartyMonHeldItemSprite(&gPlayerParty[gPartyMenu.slotId2], &sPartyMenuBoxes[gPartyMenu.slotId2]);
// create the string describing the move
if (item2 == ITEM_NONE)
{
GetMonNickname(&gPlayerParty[gPartyMenu.slotId2], gStringVar1);
CopyItemName(item1, gStringVar2);
StringExpandPlaceholders(gStringVar4, gText_PkmnWasGivenItem);
}
else
{
GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1);
CopyItemName(item1, gStringVar2);
StringExpandPlaceholders(buffer, gText_XsYAnd);
StringAppend(buffer, gText_XsYWereSwapped);
GetMonNickname(&gPlayerParty[gPartyMenu.slotId2], gStringVar1);
CopyItemName(item2, gStringVar2);
StringExpandPlaceholders(gStringVar4, buffer);
}
// display the string
DisplayPartyMenuMessage(gStringVar4, TRUE);
// update colors of selected boxes
AnimatePartySlot(gPartyMenu.slotId2, 0);
AnimatePartySlot(gPartyMenu.slotId, 1);
// return to the main party menu
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_UpdateHeldItemSprite;
break;
}
}
void CursorCb_MoveItem(u8 taskId)
{
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
PlaySE(SE_SELECT);
// delete old windows
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]);
PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]);
if (GetMonData(mon, MON_DATA_HELD_ITEM) != ITEM_NONE)
{
gPartyMenu.action = PARTY_ACTION_SWITCH;
// show "Move item to where" in bottom left
DisplayPartyMenuStdMessage(PARTY_MSG_MOVE_ITEM_WHERE);
// update color of first selected box
AnimatePartySlot(gPartyMenu.slotId, 1);
// set up callback
gPartyMenu.slotId2 = gPartyMenu.slotId;
gTasks[taskId].func = CursorCb_MoveItemCallback;
}
else
{
// create and display string about lack of hold item
GetMonNickname(mon, gStringVar1);
StringExpandPlaceholders(gStringVar4, gText_PkmnNotHolding);
DisplayPartyMenuMessage(gStringVar4, TRUE);
// return to the main party menu
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = Task_UpdateHeldItemSprite;
}
}

View File

@ -320,6 +320,9 @@ const u8 gText_DoWhatWithMail[] = _("Do what with the MAIL?");
const u8 gText_ChoosePokemonCancel[] = _("Choose POKéMON or CANCEL.");
const u8 gText_ChoosePokemonConfirm[] = _("Choose POKéMON and confirm.");
const u8 gText_SendWhichMonToPC[] = _("Send which POKéMON to the PC?");
const u8 gText_MoveItemWhere[] = _("Move item to where?");
const u8 gText_XsYAnd[] = _("{STR_VAR_1}'s {STR_VAR_2} and\n");
const u8 gText_XsYWereSwapped[] = _("{STR_VAR_1}'s {STR_VAR_2} were swapped!{PAUSE_UNTIL_PRESS}");
const u8 gText_EnjoyCycling[] = _("Let's enjoy cycling!");
const u8 gText_InUseAlready_PM[] = _("This is in use already.");
const u8 gText_AlreadyHoldingOne[] = _("{STR_VAR_1} is already holding\none {STR_VAR_2}.");