Alchemy
Loading...
Searching...
No Matches

run.c

Go to the documentation of this file.
1/// @file
2/// Running a shop, its cursor work, and the message helpers every counter uses.
3/// Part of shop.c, the shop object, compiled only through it.
4
5#include "../shop_internal.h"
6
7/// Lists the current shop's artifacts: every item of the shop's type whose
8/// shared stock counter is above zero. Writes them to the work block's stock
9/// list and returns how many. Called by Shop_Run when the player picks
10/// Artifacts, and by Shop_SelectBuy to refresh the list after a purchase.
12 struct ShopRuntime *shop;
13 s16 *stockItems;
14 s32 itemId;
15 s32 count;
16 s8 equipmentGroup;
17
18 shop = gMenuWork;
19 count = 0;
20 itemId = 0;
21 stockItems = shop->stockItemIds;
22 do {
23 equipmentGroup = shop->shopType;
24 if (equipmentGroup == Item_GetEquipmentGroupFar(itemId) &&
25 Item_AdjustCounterFar(itemId, 0) != 0) {
26 *stockItems = itemId;
27 count++;
28 stockItems++;
29 }
30 itemId++;
31 } while (itemId <= ITEM_ID_MASK);
32 shop->stockItemIds[count] = 0;
33 shop->stockCount = count;
34 return count;
35}
36
37/// Advances the hand cursor one frame. Runs every frame as a scheduler task
38/// while a counter is open.
39void Shop_StepCursor(void) {
41}
42
43/// Allocates and clears the work block in the menu's heap slot, lists the
44/// party, loads the six cursor icons into the VRAM cache and starts the
45/// cursor's task. Every counter opens with it: Shop_Run, the inn, the
46/// sanctum and the item picker.
48 struct ShopRuntime *shop;
49 s32 resourceSlot;
50
53 Dma_Fill32(0, shop, sizeof(struct ShopRuntime));
54 shop->mode = 12;
56 resourceSlot = Resource_FindFreeEntry();
57 shop->cursorIcon = resourceSlot;
58 VramCache_Load(resourceSlot, 128, gShop_HandTiles);
59 resourceSlot = Resource_FindFreeEntry();
60 shop->previousPageIcon = resourceSlot;
61 VramCache_Load(resourceSlot, 128, gShop_UpArrowTiles);
62 resourceSlot = Resource_FindFreeEntry();
63 shop->nextPageIcon = resourceSlot;
64 VramCache_Load(resourceSlot, 128, gShop_DownArrowTiles);
65 resourceSlot = Resource_FindFreeEntry();
66 shop->gemIcon = resourceSlot;
67 VramCache_Load(resourceSlot, 128, gShop_GemTiles);
68 resourceSlot = Resource_FindFreeEntry();
69 shop->statDownIcon = resourceSlot;
70 VramCache_Load(resourceSlot, 128, gShop_SmallDownArrowTiles);
71 resourceSlot = Resource_FindFreeEntry();
72 shop->statUpIcon = resourceSlot;
73 VramCache_Load(resourceSlot, 128, gShop_SmallUpArrowTiles);
75}
76
77/// Stops the cursor task, frees the six cursor icons and the work block.
78/// Every counter closes with it.
80 struct ShopRuntime *state;
81
82 state = gMenuWork;
92}
93
94/// Runs a shop: the shopkeeper's welcome, then buy, sell, artifacts and repair
95/// until the player leaves. `stockRow` picks the row of sStockTable (0 for a
96/// row out of range) and `keeperId` the object whose portrait the messages
97/// show. Seeds the row's artifacts on the first visit and holds the work block
98/// while it runs. Called by the town scenes' shopkeepers through SHOP.S, and
99/// by the debug shop.
100s32 Shop_Run(s32 stockRow, s32 keeperId) {
101 struct ShopRuntime *shop;
102 struct RenderOutput *anchor;
103 struct UiWindow *window;
104 s32 action = 0;
105
106 if (stockRow >= EventTable_GetRowLimit() || stockRow < 0)
107 stockRow = 0;
108 // Seed this location's artifact stock before creating the shop UI.
111 shop = gMenuWork;
112 shop->shopType = EventTable_GetRowType(stockRow);
113 // Stock rows 16 to 18 are the warriors' shops, which greet differently.
114 if (stockRow == 16)
115 shop->warriorShop = 1;
116 if (stockRow == 17)
117 shop->warriorShop = 1;
118 if (stockRow == 18)
119 shop->warriorShop = 1;
120 shop->keeperResource =
121 ((struct AnimationObject *)((struct ObjectRuntime *)Object_GetByIdFar(
122 keeperId))
123 ->animation)
124 ->entries[0]
125 ->animId;
126 // The shopkeeper's portrait window, or an empty one off the left edge when
127 // there is no portrait.
128 window = UiWindow_CreateWithSideObjectFar(shop->keeperResource, 0, 0, 0);
129 if (window == 0)
130 window = UiWindow_CreateFar(-5, 0, 5, 5, 2);
131 anchor = RenderOutput_CreateFar(shop->cursorIcon, 0x40000000, window, 0, 0);
132 anchor->active = 1;
133 anchor->kind = 0;
134 ShopCursor_SetPositionImmediate(&shop->cursor, -32, 112);
135 shop->cursor.anchor = anchor;
136 UiMessage_ShowAndWait(MsgWeaponShopWelcome);
137 while (1) {
139 shop->partyAction = action;
140 if (action == SHOP_ACTION_BUY) {
141 shop->stockCount = EventTable_CopyRowHeader(stockRow, shop->stockItemIds);
142 UiMessage_ShowAndWait(MsgWhatWouldYouLike);
144 } else if (action == SHOP_ACTION_SELL) {
145 UiMessage_ShowAndWait(MsgWhatToSell);
147 } else if (action == SHOP_ACTION_ARTIFACTS) {
148 if (Shop_ListAvailableArtifacts() != 0) {
149 UiMessage_ShowAndWait(MsgConnoisseur);
151 } else {
152 UiMessage_ShowAndWait(MsgOutOfStock);
153 WaitFrames(1);
154 }
155 } else if (action == SHOP_ACTION_REPAIR) {
156 UiMessage_ShowAndWait(MsgFixDamaged);
158 } else {
159 break;
160 }
161 ShopCursor_SetPositionImmediate(&shop->cursor, -32, 112);
162 UiMessage_ShowAndWait(MsgAnythingElse);
163 }
164 UiMessage_ShowAndWait(MsgShopFarewell);
165 UiWork_FinalizeFar(window, 2);
167 return 0;
168}
169
170#if TBS_PATCH_1
171#define SHOP_DEBUG_STOCK_ROW 1
172#else
173#define SHOP_DEBUG_STOCK_ROW 2
174#endif
175
176/// Opens the debug shop with 200000 coins, the ticket counter at its cap,
177/// broken equipment for repairs and poisoned or haunted members for the
178/// sanctum. Called by DebugMenu_RunPresetShop.
180 gGameState.coins = 200000;
183 GARET,
188 UnitGetFar(MIA)->poison = 1;
189 UnitGetFar(JENNA)->poison = 1;
190 UnitGetFar(IVAN)->haunt = 1;
192 return 0;
193}
194
195/// Waits one frame at a time until the sound driver has finished the last
196/// command. Called by the inn's sleep, the sanctum and two scenes that wait
197/// for a fanfare.
199 while (AudioCommand_GetStateByteFar() != 0) {
200 WaitFrames(1);
201 }
202}
203
204/// Byte view of the six colour writes in a quantity-bar segment.
206 u8 filler0[4]; ///< bytes before the first coloured pixel
207 u8 values[21]; ///< palette bytes at indices 0, 4, 8, 12, 16 and 20
208};
209
210/// Shows a shopkeeper's line and waits for its window to finish, one more
211/// frame included. `messageId` is the weapon shop's line; the armor, item and
212/// warriors' shops say theirs, at the same distance from their own welcome.
213/// Called by every counter.
214void UiMessage_ShowAndWait(s32 messageId) {
215 // A shared message-resolution inline added four bytes to each dialogue caller
216 // in the English native build; both callers retain their direct resolution.
217 struct ShopRuntime *shop = gMenuWork;
218 s32 portraitResource = BattleFx_GetResourceIdFar(shop->keeperResource);
219 s32 resolvedMessage = messageId;
220 s8 shopType;
221
223 shopType = shop->shopType;
224 if (shopType == 2)
225 resolvedMessage += MsgArmorShopWelcome - MsgWeaponShopWelcome;
226 if (shopType == 0)
227 resolvedMessage += MsgItemShopWelcome - MsgWeaponShopWelcome;
228 if ((s8)shop->warriorShop != 0)
229 resolvedMessage += MsgWarriorShopWelcome - MsgWeaponShopWelcome;
230 UiText_OpenMessageWindowFar(resolvedMessage, 5, 0,
231 (portraitResource << 16) | 0x22);
232 while (UiWork_IsCompleteFar() == 0)
233 WaitFrames(1);
234 WaitFrames(1);
235}
236
237/// Shows a shopkeeper's line as UiMessage_ShowAndWait does, hiding the hand
238/// cursor while it shows and putting back its motion after.
240 s32 portraitResource;
241 s32 resolvedMessage;
242 s8 shopType;
244 u8 savedCursorMode;
245 struct ShopRuntime *shop;
246 struct RenderOutput **cursorSlot;
247
248 shop = gMenuWork;
249 cursorSlot = &shop->cursor.anchor;
250 savedCursorMode = (*cursorSlot)->active;
251 resolvedMessage = messageId;
252 portraitResource = BattleFx_GetResourceIdFar(shop->keeperResource);
253 shopType = shop->shopType;
254 if (shopType == 2) {
255 resolvedMessage += MsgArmorShopWelcome - MsgWeaponShopWelcome;
256 }
257 if (shopType == 0) {
258 resolvedMessage += MsgItemShopWelcome - MsgWeaponShopWelcome;
259 }
260 warriorShop = shop->warriorShop;
261 if (warriorShop != 0) {
262 resolvedMessage += MsgWarriorShopWelcome - MsgWeaponShopWelcome;
263 }
264 (*cursorSlot)->active = 13;
266 UiText_OpenMessageWindowFar(resolvedMessage, 5, 0,
267 (portraitResource << 0x10) | 0x22);
268 while (UiWork_IsCompleteFar() == 0) {
269 WaitFrames(1);
270 }
271 WaitFrames(1);
272 shop->cursor.anchor->active = savedCursorMode;
273}
274
275/// Runs the Yes or No choice beside the shopkeeper's line and returns it,
276/// keeping the hand cursor's motion. Called by the counters before they buy,
277/// sell, equip or repair, and by the inn.
279 struct RenderOutput **cursorSlot =
280 &((struct ShopRuntime *)gMenuWork)->cursor.anchor;
281 u8 savedCursorMode = (*cursorSlot)->active;
282 UiIcon_PrepareObjectFar(*cursorSlot);
284 (*cursorSlot)->active = savedCursorMode;
285 return choice;
286}
287
288/// Runs the Yes or No choice at the sanctum's place on the screen and
289/// returns it, keeping the hand cursor's motion. Called by
290/// Sanctum_RunPartyService.
292 struct RenderOutput **cursorSlot =
293 &((struct ShopRuntime *)gMenuWork)->cursor.anchor;
294 u8 savedCursorMode = (*cursorSlot)->active;
295 UiIcon_PrepareObjectFar(*cursorSlot);
296 choice = Menu_RunConfirmSelectionAtFar(7, 7, choice);
297 (*cursorSlot)->active = savedCursorMode;
298 return choice;
299}
300
301/// Unused original list walker: follows the requested number of next links.
302UNUSED struct NodeChainNode *
304 struct NodeChainNode *node = state->node;
305 s32 linkIndex;
306
307 for (linkIndex = 0; linkIndex != state->count; ++linkIndex) {
308 node = node->next;
309 }
310 return node;
311}
312
313#undef SHOP_DEBUG_STOCK_ROW
s32 EventTable_CopyRowHeader(s32 stockRow, s16 *output)
Copies the shop's ordinary stock, up to 24 items, to output with a 0 after, and returns how many.
Definition artifacts.c:338
s32 EventTable_GetRowType(s32 stockRow)
Returns the shop's type from the last column of its stock row: 0 items, 1 weapons,...
Definition artifacts.c:366
s32 EventTable_GetRowLimit(void)
Returns how many stock rows there are; Shop_Run refuses a row past them.
Definition artifacts.c:304
void EventTable_ApplyRowAbilities(s32 stockRow)
Adds a shop's artifacts to the shared stock counters once, on its first visit, and sets the shop's fl...
Definition artifacts.c:309
s32 Shop_SelectBuy(void)
Runs the Buy and Artifacts counters: the player browses the stock seven items a page,...
Definition buy.c:19
#define SCHEDULER_KEY_MAIN_LOOP
#define GARET
Jerald.
#define MIA
Mary.
#define ISAAC
Robin.
#define JENNA
Jasmine.
#define IVAN
Ivan.
void ShopCursor_Advance(struct ShopCursor *cursor)
Moves the cursor from its saved position toward its target, in a straight line over kind frames,...
Definition cursor.c:156
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
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
Definition dma.h:30
struct BattleUnit * UnitGetFar(u32 owner)
s32 Party_ListActiveOwnersFar(s16 *owners)
s32 Item_AdjustCounterFar(s32 item_id, s32 delta)
s32 Inventory_AddItemFar(s32 owner_id, s32 item_id)
s32 Item_GetEquipmentGroupFar(s32 item_id)
s32 Inventory_EquipFar(s32 owner, s32 slot)
void UiIcon_PrepareObjectFar(struct RenderOutput *object)
s32 BattleFx_GetResourceIdFar(u32 id)
void Battle_ResetEffectCounterFar(void)
struct FieldActor * Object_GetByIdFar(s32 objectId)
s32 AudioCommand_GetStateByteFar(void)
struct UiWindow * UiWindow_CreateFar(s32 x, s32 y, s32 width, s32 height, s32 attrs)
s32 Menu_RunConfirmSelectionAtFar(s32 x, s32 y, s32 selection)
s32 Menu_SelectShopCommandFar(s32 selection)
struct RenderOutput * RenderOutput_CreateFar(s32 slot, s32 flags, struct UiWindow *input, s32 offsetX, s32 offsetY)
void UiWork_FinalizeFar(struct UiWindow *work, s32 release)
struct UiWindow * UiWindow_CreateWithSideObjectFar(s32 arg0, s32 arg1, s32 x, s32 y)
s32 UiWork_IsCompleteFar(void)
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
struct GameState gGameState
void * gMenuWork
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
Definition heap.c:47
@ HEAP_SLOT_MENU
Definition heap_state.h:55
@ ITEM_ID_MASK
Definition item.h:16
@ INVENTORY_BROKEN
Definition item.h:18
@ ITEM_MURAMASA
Definition item_ids.h:12
@ ITEM_BONE
Definition item_ids.h:72
@ ITEM_VIRTUOUS_ARMLET
Definition item_ids.h:34
void Runtime_ReleaseHeapBlock(s32 slot)
s32 Shop_SelectUnit(void)
Runs the repair counter's member choice; always returns 0.
Definition repair.c:21
#define SHOP_DEBUG_STOCK_ROW
Definition run.c:171
UNUSED struct NodeChainNode * NodeChain_GetNodeAtIndex(struct NodeChainState *state)
Unused original list walker: follows the requested number of next links.
Definition run.c:303
void Shop_ReleaseCursorWork(void)
Stops the cursor task, frees the six cursor icons and the work block.
Definition run.c:79
void UiMessage_ShowAndRestoreState(s32 messageId)
Shows a shopkeeper's line as UiMessage_ShowAndWait does, hiding the hand cursor while it shows and pu...
Definition run.c:239
s32 Shop_ListAvailableArtifacts(void)
Lists the current shop's artifacts: every item of the shop's type whose shared stock counter is above...
Definition run.c:11
s32 UiMessage_ShowChoiceVariant(s32 choice)
Runs the Yes or No choice at the sanctum's place on the screen and returns it, keeping the hand curso...
Definition run.c:291
void Shop_StepCursor(void)
Advances the hand cursor one frame.
Definition run.c:39
s32 Battle_ApplyPresetItemsAndFlags(s32 unused)
Opens the debug shop with 200000 coins, the ticket counter at its cap, broken equipment for repairs a...
Definition run.c:179
s32 Shop_Run(s32 stockRow, s32 keeperId)
Runs a shop: the shopkeeper's welcome, then buy, sell, artifacts and repair until the player leaves.
Definition run.c:100
s32 UiMessage_ShowChoice(s32 choice)
Runs the Yes or No choice beside the shopkeeper's line and returns it, keeping the hand cursor's moti...
Definition run.c:278
void AudioCommand_WaitForStateByteClear(void)
Waits one frame at a time until the sound driver has finished the last command.
Definition run.c:198
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 UiMessage_ShowAndWait(s32 messageId)
Shows a shopkeeper's line and waits for its window to finish, one more frame included.
Definition run.c:214
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
Definition scheduler.c:102
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
s32 Shop_PickUnit(void)
Lets the player choose whose items to sell or repair, with the coins window and the member's item gri...
Definition sell.c:11
const u8 gShop_UpArrowTiles[]
const u8 gShop_GemTiles[]
const u8 gShop_SmallUpArrowTiles[]
const u8 gShop_SmallDownArrowTiles[]
const u8 gShop_DownArrowTiles[]
const u8 gShop_HandTiles[]
What every part of the shop object shares: its includes, the shop actions and sanctum services,...
#define SHOP_CONFIRM_MENU_X
@ SHOP_ACTION_SELL
@ SHOP_ACTION_REPAIR
@ SHOP_ACTION_ARTIFACTS
@ SHOP_ACTION_BUY
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
s8 poison
1 poisoned, 2 deadly poison
u8 haunt
set while an evil spirit grips the unit
s8 shopGifts
indexes the Game Ticket's credit cost
Definition game_state.h:28
struct NodeChainNode * next
Definition node_chain.h:13
struct NodeChainNode * node
Definition node_chain.h:18
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
s16 action
The parameter its action script reads (a follow distance or an angle), or the player's frames to its ...
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...
Byte view of the six colour writes in a quantity-bar segment.
Definition run.c:205
u8 filler0[4]
bytes before the first coloured pixel
Definition run.c:206
u8 values[21]
palette bytes at indices 0, 4, 8, 12, 16 and 20
Definition run.c:207
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
u16 previousPageIcon
Definition shop.h:36
s8 partyMemberCount
Definition shop.h:47
struct ShopCursor cursor
the hand cursor
Definition shop.h:31
s16 partyMemberIds[9]
the party in order (Party_ListActiveOwners)
Definition shop.h:30
u8 warriorShop
1 for stock rows 16 to 18, which greet as warriors'
Definition shop.h:52
u16 statDownIcon
Definition shop.h:40
u16 keeperResource
the shopkeeper's animation; picks the portrait
Definition shop.h:45
u16 nextPageIcon
Definition shop.h:37
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
s8 stockCount
Definition shop.h:46
s16 stockItemIds[129]
the items on sale, ended by 0
Definition shop.h:29
u8 shopType
the stock row's type: 0 items, 2 armor, else weapons
Definition shop.h:49
s8 partyAction
the counter chosen (enum ShopAction)
Definition shop.h:50
u8 mode
passed on as the hand cursor's kind; set to 12 at first
Definition shop.h:48
u16 gemIcon
Definition shop.h:38
u16 statUpIcon
Definition shop.h:39
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
signed int s32
Definition types.h:14
signed char s8
Definition types.h:10
signed short s16
Definition types.h:12
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
s32 Resource_ResetEntry(u32 no)
Frees cache entry no: its blocks go back and the entry is marked free (offset 0xffff).
Definition vram_cache.c:106
s32 Resource_FindFreeEntry(void)
Returns the number of the first free cache entry, or VRAM_CACHE_ENTRY_COUNT when all are taken.
Definition vram_cache.c:211
s32 VramCache_Load(u32 no, u32 size, const void *src)
Gives cache entry no size bytes of sprite VRAM and copies src there.
Definition vram_cache.c:143