Alchemy
Loading...
Searching...
No Matches

item_picker.c

Go to the documentation of this file.
1/// @file
2/// The item picker: which member's item to drop when every bag is full.
3/// Part of shop.c, the shop object, compiled only through it.
4
5#include "../shop_internal.h"
6
7/// Lets the player choose a party member, then one of its items that may be
8/// dropped. Writes the member and inventory slot to `selectedUnit` and
9/// `selectedSlot` and returns 0, or writes -1 to both and returns -1 when
10/// cancelled. Holds the shop's work block while it runs. Reached through
11/// SHOP.S when an item is found with every bag full ("What will you drop?",
12/// PartyInventory_GiveItem), by the Elemental Star room's Mythril Bags and by
13/// the debug menu.
14s32 Shop_PickUnitItem(s32 *selectedUnit, s32 *selectedSlot) {
15 struct ShopRuntime *shop;
16 struct RenderOutput *cursorAnchor;
17 struct UiWindow *partyWindow;
18 s32 memberIndex = 0;
19 s32 redraw = 1;
20 s32 unitId = 0;
21 s32 itemSlot;
22 s32 result = 0;
23
25 shop = gMenuWork;
26 shop->itemWindow = UiWindow_CreateFar(16, 12, 14, 8, 2);
27 partyWindow = UiWindow_CreateFar(0, 14, 13, 3, 2);
28 cursorAnchor = RenderOutput_CreateFar(shop->cursorIcon, 0x40000000,
29 partyWindow, 0, result);
30 cursorAnchor->active = 4;
31 cursorAnchor->kind = result;
33 shop->cursor.anchor = cursorAnchor;
34 shop->mode = 12;
35 PsynergyMenu_InitializeEntryObjectsFar(partyWindow, 2, 0, 8, result);
36
37 while (1) {
38 if (redraw != 0) {
39 redraw = 0;
40 memberIndex =
41 (memberIndex + shop->partyMemberCount) % shop->partyMemberCount;
42 unitId = shop->partyMemberIds[memberIndex];
43 Shop_PlaceCursor(partyWindow, memberIndex * 24 - 12, 0);
44 shop->mode = 3;
45 Shop_DrawParty(partyWindow, memberIndex, 0);
46 Shop_DrawUnitGrid(shop->itemWindow, unitId);
47 }
48
49 WaitFrames(1);
50 if ((gKeysPressed & KEY_A) != 0) {
51 if (Inventory_CountFar(unitId) == 0) {
53 continue;
54 }
55
57 itemSlot = Shop_SelectUse(unitId);
58 if (itemSlot == -1) {
59 shop->cursor.anchor->active = 4;
60 shop->mode = 12;
61 redraw = 1;
62 continue;
63 }
64 *selectedUnit = unitId;
65 *selectedSlot = itemSlot;
66 result = 0;
67 break;
68 }
69
70 if ((gKeysPressed & KEY_B) != 0) {
72 *selectedUnit = -1;
73 *selectedSlot = -1;
74 result = -1;
75 break;
76 }
77
78 if ((gKeysRepeat & KEY_LEFT) != 0) {
80 memberIndex--;
81 redraw = 1;
82 }
83 if ((gKeysRepeat & KEY_RIGHT) != 0) {
85 memberIndex++;
86 redraw = 1;
87 }
88 }
89
91 UiWork_FinalizeFar(partyWindow, 2);
93 WaitFrames(1);
95 return result;
96}
97
98// The sale value line's label, number and coin word, placed for each
99// language's words; Japanese names its coins with a different message.
100#if LANGUAGE == LANGUAGE_ENGLISH || LANGUAGE == LANGUAGE_ITALIAN
101#define SHOP_USE_PRICE_LABEL_X 8
102#define SHOP_USE_PRICE_NUMBER_X 40
103#define SHOP_USE_COIN_LABEL_X 80
104#define SHOP_USE_COIN_MESSAGE_OFFSET 5
105#elif LANGUAGE == LANGUAGE_GERMAN
106#define SHOP_USE_PRICE_LABEL_X 0
107#define SHOP_USE_PRICE_NUMBER_X 32
108#define SHOP_USE_COIN_LABEL_X 72
109#define SHOP_USE_COIN_MESSAGE_OFFSET 5
110#elif LANGUAGE == LANGUAGE_SPANISH
111#define SHOP_USE_PRICE_LABEL_X 8
112#define SHOP_USE_PRICE_NUMBER_X 40
113#define SHOP_USE_COIN_LABEL_X 88
114#define SHOP_USE_COIN_MESSAGE_OFFSET 5
115#elif LANGUAGE == LANGUAGE_FRENCH
116#define SHOP_USE_PRICE_LABEL_X 8
117#define SHOP_USE_PRICE_NUMBER_X 32
118#define SHOP_USE_COIN_LABEL_X 72
119#define SHOP_USE_COIN_MESSAGE_OFFSET 5
120#else
121#define SHOP_USE_PRICE_LABEL_X 8
122#define SHOP_USE_PRICE_NUMBER_X 40
123#define SHOP_USE_COIN_LABEL_X 80
124#define SHOP_USE_COIN_MESSAGE_OFFSET 1
125#endif
126
127/// Lets the player choose one of the member's items to drop, refusing an
128/// indispensable or cursed equipped one with a message. Returns the slot, or
129/// -1 when cancelled. Called by Shop_PickUnitItem.
131 struct ShopRuntime *shop = gMenuWork;
132
133 struct UiWindow *descriptionWindow;
134 struct UiWindow *priceWindow;
135 struct BattleUnit *unit;
136 s32 slot;
137 s32 redraw;
138 s32 inventoryCount;
139 s32 selectionResult;
140 s32 discardStatus;
141 s32 itemId;
142 struct UiWindow *window;
143 s32 x;
144 s32 y;
145
146 unit = UnitGetFar(unitId);
147 inventoryCount = 1;
148 selectionResult = 0;
149 redraw = 1;
150 priceWindow =
152 descriptionWindow = UiWindow_CreateFar(0, 5, 30, 3, 2);
153 shop->cursor.anchor->active = 18;
154 shop->mode = 12;
155 slot = 0;
156
157 while (1) {
158 if (redraw != 0) {
159 redraw = 0;
160 inventoryCount = Inventory_CountFar(unitId);
161 if (slot > inventoryCount - 1)
162 slot = inventoryCount - 1;
163
164 itemId = unit->inventory[slot] & ITEM_ID_MASK;
165 window = shop->itemWindow;
166 x = slot % SHOP_INVENTORY_COLUMNS << 4;
167 y = (slot / SHOP_INVENTORY_COLUMNS << 4) + 8;
168 Shop_PlaceCursor(window, x, y);
169 shop->mode = 3;
170 Shop_DrawUseItem(priceWindow, unitId, slot);
171 Shop_DrawMsg(descriptionWindow, itemId + MsgItemPlainName);
172 }
173
174 WaitFrames(1);
175
176 if ((gKeysPressed & KEY_A) != 0) {
177 discardStatus = Inventory_CheckDiscardFar(unitId, slot);
178 if (discardStatus == 0) {
180 selectionResult = slot;
181 break;
182 }
183 // BUG: default code selects the error using selectionResult, still zero.
184 if (discardStatus == -4) {
185 UiText_OpenMessageWindowFar(MsgCannotDropIt, 8, 1, 2);
186 } else if (SHOP_CANNOT_REMOVE_STATUS(discardStatus, selectionResult) ==
187 -3) {
188 UiText_OpenMessageWindowFar(MsgCannotRemoveIt, 8, 1, 2);
189 }
191 while (UiWork_IsCompleteFar() == 0)
192 WaitFrames(1);
194 continue;
195 }
196
197 if ((gKeysPressed & KEY_B) != 0) {
199 selectionResult = -1;
200 break;
201 }
202
203 if ((gKeysRepeat & KEY_LEFT) != 0) {
205 slot -= 1;
206 slot = (slot + inventoryCount) % inventoryCount;
207 redraw = 1;
208 }
209 if ((gKeysRepeat & KEY_RIGHT) != 0) {
211 slot += 1;
212 slot = (slot + inventoryCount) % inventoryCount;
213 redraw = 1;
214 }
215 if ((gKeysRepeat & KEY_UP) != 0) {
217 if (slot < 0)
218 slot += INVENTORY_SLOTS;
219 while (slot >= inventoryCount)
222 redraw = 1;
223 }
224 if ((gKeysRepeat & KEY_DOWN) != 0) {
226 if (slot >= inventoryCount)
227 slot -= INVENTORY_SLOTS;
228 while (slot < 0)
231 redraw = 1;
232 }
233 }
234
235 UiWork_FinalizeFar(descriptionWindow, 2);
236 UiWork_FinalizeFar(priceWindow, 2);
237 WaitFrames(1);
238 return selectionResult;
239}
240
241/// Draws the slot's item name and, below it, why it cannot be dropped or what
242/// the whole stack would sell for. Called by Shop_SelectUse each time the
243/// cursor moves.
244void Shop_DrawUseItem(struct UiWindow *window, s32 unitId, s32 slot) {
245 struct BattleUnit *unit = UnitGetFar(unitId);
246 s32 itemId = unit->inventory[slot] & ITEM_ID_MASK;
247 u32 inventoryEntry = unit->inventory[slot];
248 s32 quantity = (inventoryEntry >> INVENTORY_QUANTITY_SHIFT) + 1;
249
250 if (window != 0) {
251 s32 discardStatus;
252
254 UiText_DrawCharacterAtOffsetFar(itemId + MsgItemName, window, 0, 0);
255
256 discardStatus = Inventory_CheckDiscardFar(unitId, slot);
257 if (discardStatus == -4) {
259 8);
260 } else if (discardStatus == -3) {
261 UiText_DrawCharacterAtOffsetFar(MsgCannotRemove, window, SHOP_ITEM_NOTE_X,
262 8);
263 } else {
264 s32 unitSalePrice;
265 s32 stackSalePrice;
266
267 unitSalePrice = Shop_SalePrice(unit->inventory[slot]);
268 stackSalePrice = quantity * unitSalePrice;
269
270 UiText_DrawCharacterAtOffsetFar(MsgPriceHeading, window,
272 UiText_DrawNumberInWindowFar(stackSalePrice, 5, window,
274 UiText_DrawCharacterAtOffsetFar(MsgPriceHeading -
276 window, SHOP_USE_COIN_LABEL_X, 8);
277 }
278 }
279}
280
281#undef SHOP_USE_PRICE_LABEL_X
282#undef SHOP_USE_PRICE_NUMBER_X
283#undef SHOP_USE_COIN_LABEL_X
284#undef SHOP_USE_COIN_MESSAGE_OFFSET
void Shop_DrawParty(struct UiWindow *window, s32 selected, s32 itemId)
Shows the chosen member walking and the others standing, and draws at four fifths of their size the m...
Definition buy.c:382
s32 Shop_SalePrice(s32 inventoryEntry)
Returns what the shops pay for an inventory entry: nothing for an indispensable item,...
Definition buy.c:803
void Shop_DrawMsg(struct UiWindow *window, s32 message)
Shows message, an item's description, in the help window; a NULL window is ignored.
Definition buy.c:367
void Shop_PlaceCursor(struct UiWindow *window, s32 x, s32 y)
Starts the hand cursor's glide to (x, y) pixels inside window (the screen when it is NULL),...
Definition cursor.c:273
void ShopCursor_SetPositionImmediate(struct ShopCursor *cursor, s32 x, s32 y)
Places the cursor and its sprite at (x, y) at once, with a one-frame glide that has already arrived.
Definition cursor.c:249
struct BattleUnit * UnitGetFar(u32 owner)
s32 Inventory_CountFar(s32 owner)
s32 Inventory_CheckDiscardFar(s32 owner, s32 slot)
void Menu_ReleaseEntryObjectsFar(void)
void PsynergyMenu_InitializeEntryObjectsFar(void *source, s32 originX, s32 originY, s32 spacing, s32 unused)
void AudioCommand_PlayFar(s32 id)
struct UiWindow * UiWindow_CreateFar(s32 x, s32 y, s32 width, s32 height, s32 attrs)
void UiText_DrawNumberInWindowFar(s32 arg0, s32 arg1, struct UiWindow *arg2, s32 arg3, s32 arg4)
void UiText_DrawCharacterAtOffsetFar(s32 character, const struct UiWindow *position, u32 offsetX, u32 offsetY)
struct RenderOutput * RenderOutput_CreateFar(s32 slot, s32 flags, struct UiWindow *input, s32 offsetX, s32 offsetY)
void UiWork_FinalizeFar(struct UiWindow *work, s32 release)
s32 UiWork_IsCompleteFar(void)
void RenderOutput_RedrawSavedRectFar(struct UiWindow *window)
struct UiWindow * UiText_OpenMessageWindowFar(s32 message, s32 x, s32 y, u32 packed)
void UiWork_FinalizePendingCoreFar(void)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
void * gMenuWork
@ KEY_UP
Definition io_reg.h:249
@ KEY_B
Definition io_reg.h:244
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_RIGHT
Definition io_reg.h:247
@ KEY_A
Definition io_reg.h:243
@ KEY_DOWN
Definition io_reg.h:250
@ INVENTORY_SLOTS
Definition item.h:23
@ ITEM_ID_MASK
Definition item.h:16
@ INVENTORY_QUANTITY_SHIFT
Definition item.h:20
#define SHOP_USE_PRICE_LABEL_X
s32 Shop_PickUnitItem(s32 *selectedUnit, s32 *selectedSlot)
Lets the player choose a party member, then one of its items that may be dropped.
Definition item_picker.c:14
#define SHOP_USE_COIN_MESSAGE_OFFSET
#define SHOP_USE_PRICE_NUMBER_X
#define SHOP_USE_COIN_LABEL_X
s32 Shop_SelectUse(s32 unitId)
Lets the player choose one of the member's items to drop, refusing an indispensable or cursed equippe...
void Shop_DrawUseItem(struct UiWindow *window, s32 unitId, s32 slot)
Draws the slot's item name and, below it, why it cannot be dropped or what the whole stack would sell...
volatile u32 gKeysPressed
Keys that went down this frame.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
void Shop_ReleaseCursorWork(void)
Stops the cursor task, frees the six cursor icons and the work block.
Definition run.c:79
void Shop_InitializeCursorWork(void)
Allocates and clears the work block in the menu's heap slot, lists the party, loads the six cursor ic...
Definition run.c:47
void Shop_DrawUnitGrid(struct UiWindow *window, s32 unitId)
Draws the member's items as icons in rows of five, or a line saying it has none.
Definition sell.c:190
What every part of the shop object shares: its includes, the shop actions and sanctum services,...
#define SHOP_ITEM_NOTE_X
#define SHOP_CANNOT_REMOVE_STATUS(discardStatus, selectionResult)
@ SHOP_INVENTORY_COLUMNS
#define SHOP_USE_WINDOW_WIDTH
#define SHOP_USE_WINDOW_X
#define SE_MENU_CANCEL
Definition songs.h:106
#define SE_MENU_CURSOR_MOVE
Definition songs.h:104
#define SE_MENU_CONFIRM
Definition songs.h:105
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u16 inventory[15]
Items held, one entry each: bits 15..11 quantity | 10 broken | 9 equipped | 8..0 item id (INVENTORY_*...
A render output: a sprite in a window's output list (a character, an icon or a portrait),...
s8 active
its UI_SPRITE_ motion; 0 while free
s8 kind
0 for a glyph; otherwise it owns VRAM cache slot index, freed with it, and 2 (a portrait) also its pa...
struct RenderOutput * anchor
the cursor's sprite, moved with its OAM
Definition cursor.h:14
A shop's work: its windows, the party members' icons, the stock, the cursor and its icons,...
Definition shop.h:18
s8 partyMemberCount
Definition shop.h:47
struct UiWindow * itemWindow
Definition shop.h:22
struct ShopCursor cursor
the hand cursor
Definition shop.h:31
s16 partyMemberIds[9]
the party in order (Party_ListActiveOwners)
Definition shop.h:30
u16 cursorIcon
VRAM cache slots of the six cursor icons, loaded when the work is set up and freed with it.
Definition shop.h:35
u8 mode
passed on as the hand cursor's kind; set to 12 at first
Definition shop.h:48
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
u16 y
tiles
Definition uiwindow.h:16
u16 x
tiles
Definition uiwindow.h:15
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15