Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
field_menu.c
Go to the documentation of this file.
1#include "engine/game.h"
2#include <libgs.h>
3#include <libetc.h>
4#include <libsnd.h>
5
6/* Starts opening (open != 0) or closing a panel */
7void startPanel(PanelAnim *panel, s32 open) {
8 panel->active = 1;
9 if (open) {
11 panel->level = 0;
12 panel->step = ONE / panel->duration;
13 } else {
15 panel->level = ONE;
16 panel->step = -((ONE / panel->duration) * 2);
17 }
18}
19
20/* Advances a panel animation; 1 once it has finished */
22 if (!panel->active) {
23 return 1;
24 }
25 panel->level += panel->step;
26 if (panel->step > 0) {
27 if (panel->level > ONE) {
28 panel->level = ONE;
29 panel->active = 0;
30 return 1;
31 }
32 } else if (panel->level < 0) {
33 panel->level = 0;
34 panel->active = 0;
35 return 1;
36 }
37 return 0;
38}
39
40/* The party pages' windows: [0] the name, [1]-[5] the labels and [6]-[10] the values */
42 {12, 55, 0, 19},
43 {1, 16, 0, 28},
44 {2, 16, 0, 37},
45 {4, 61, 0, 37},
46 {3, 16, 0, 46},
47 {4, 61, 0, 46},
48 {13, 44, 0, 28},
49 {14, 59, 0, 37},
50 {14, 94, 0, 37},
51 {14, 59, 0, 46},
52 {14, 94, 0, 46},
53};
54
55/* The stats the pages' values show, as indices into the stats halfwords */
57
58/* Creates the field menu's windows: the title, the options, the cursor, the money and the pages */
60 s32 i;
61 s32 j;
62 WindowPos *pos;
63
64 win->title = createTextWindow(task->layerId, 1, 0x98, 0x13);
65 for (i = 0; i < task->count; i++) {
66 win->options[i] = createTextWindow(task->layerId, 1, 0xBD, 0x31 + i * 14);
67 }
68 win->cursor = createCursor(task->layerId, 0, 0xB0, task->cursor * 14 + 0x31);
69 win->cursor->setVisible(win->cursor, 0);
70 win->moneyLabel = createTextWindow(task->layerId, 3, 0x46, 0xA6);
71 win->money = createTextWindow(task->layerId, 3, 0x42, 0xA6);
72 for (j = 0; j < 3; j++) {
73 pos = &FIELD_MENU_LAYOUT[0];
74 win->pages[j].name = createTextWindow(task->layerId, 1, pos->x, pos->y + j * 46);
75 for (i = 0; i < 5; i++) {
76 pos = &FIELD_MENU_LAYOUT[1 + i];
77 win->pages[j].labels[i] = createTextWindow(task->layerId, 3, pos->x, pos->y + j * 46);
78 }
79 for (i = 0; i < 5; i++) {
80 pos = &FIELD_MENU_LAYOUT[6 + i];
81 win->pages[j].values[i] = createTextWindow(task->layerId, 3, pos->x, pos->y + j * 46);
82 }
83 }
84}
85
86/* Fills a party member's page of the field menu (name and five stats), or hides it */
87void showPartnerPage(void *menu, FieldMenuWindows *win, s32 page, s32 show) {
88 PartnerTotals stats;
89 PartnerStats *info;
90 s32 id;
91 s32 i;
92
93 if (show) {
94 id = GAME.funcs.getPartyMember(page);
95 if (id >= 0) {
96 info = GAME.funcs.getPartnerStats(id);
97 GAME.funcs.computeStats(id, &stats);
98 win->pages[page].name->setString(win->pages[page].name, info, -1);
99 for (i = 0; i < 5; i++) {
100 /* the match depends on these two forms: (&FIELD_MENU_LAYOUT[1])[i] steps a pointer
101 from the labels, FIELD_MENU_LAYOUT[6 + i] below an offset from the array */
102 win->pages[page].labels[i]->setString(win->pages[page].labels[i], FILE_CACHE.load(TEXT_FILE(TEXT_STATUS)), (&FIELD_MENU_LAYOUT[1])[i].string);
103 win->pages[page].values[i]->setNumber(win->pages[page].values[i], 0, stats.stats[PAGE_STATS[i]]);
104 win->pages[page].values[i]->setRightAlign(win->pages[page].values[i], 1);
105 }
106 } else {
107 win->pages[page].name->setString(win->pages[page].name, FILE_CACHE.load(TEXT_FILE(TEXT_STATUS)), 0xC);
108 for (i = 0; i < 5; i++) {
109 win->pages[page].values[i]->setString(win->pages[page].values[i], FILE_CACHE.load(TEXT_FILE(TEXT_STATUS)), FIELD_MENU_LAYOUT[6 + i].string);
110 win->pages[page].values[i]->setRightAlign(win->pages[page].values[i], 1);
111 }
112 }
113 } else {
114 win->pages[page].name->setVisible(win->pages[page].name, 0);
115 for (i = 0; i < 5; i++) {
116 win->pages[page].labels[i]->setVisible(win->pages[page].labels[i], 0);
117 win->pages[page].values[i]->setVisible(win->pages[page].values[i], 0);
118 }
119 }
120}
121
122/* The field's stages by mode: -1 from MODE_NEW_GAME (where the field menu
123 greys out option 2), 1 from 0x270, else 0 */
125 s32 value = GAME.funcs.getMode();
126
127 if (value == MODE_STATUS) {
128 value = GAME.fieldMode;
129 }
130 if (value >= MODE_NEW_GAME) {
131 return -1;
132 }
133 return value >= 0x270;
134}
135
136/* The options' strings, without and with the extra option */
138 { 6, 7, 8, 9, 10, 0 },
139 { 6, 7, 8, 9, 10, 11 },
140};
141
142s32 FIELD_MENU_SPRITES[6] = { 29, 30, 31, 32, 33, 34 };
143
144/* Starts the field menu: opens the panels and the windows, with the extra option
145 when the player has item 0x192 and option 2 only in a field zone */
146static inline void openFieldMenu(FieldMenu *task, FieldMenuWindows *win) {
147 task->nextState(task);
148 task->panels[0].duration = task->panels[1].duration = task->panels[2].duration = 10;
149 startPanel(&task->panels[0], 1);
150 startPanel(&task->panels[1], 1);
151 startPanel(&task->panels[2], 1);
152 if (GAME.items[0x192] != 0) {
154 task->extraOption = 1;
155 } else {
157 }
158 task->count = task->extraOption + 5;
159 if (getFieldZone() >= 0) {
160 task->option2Enabled = 1;
161 } else {
162 task->option2Enabled = 0;
163 }
164 createFieldMenuWindows(task, win);
165}
166
167/* Once the second panel is open: the options (option 2 greyed when disabled) */
168static inline void showFieldMenuOptions(FieldMenu *task, FieldMenuWindows *win) {
169 showPartnerPage(task, win, 1, 1);
170 for (task->counter = 0; task->counter < task->count; task->counter++) {
173 }
175 if (task->option2Enabled == 0) {
176 win->options[2]->setPalette(win->options[2], PALETTE_GREY);
177 }
178}
179
180/* Once the third panel is open: the money and the cursor */
181static inline void showFieldMenuMoney(FieldMenu *task, FieldMenuWindows *win) {
182 showPartnerPage(task, win, 2, 1);
184 win->money->setNumber(win->money, 0, GAME.money);
185 win->money->setRightAlign(win->money, 1);
186 win->cursor->setVisible(win->cursor, 1);
187}
188
189/*
190 * Moves the cursor, or on a choice (option 2 only when enabled) or a cancel
191 * closes the panels, with the step that picks the next mode
192 */
193static inline void chooseFieldMenuOption(FieldMenu *task, FieldMenuWindows *win) {
194 s32 prev;
195 s32 done;
196
197 prev = task->cursor;
199 if (--task->cursor < 0) {
200 task->cursor = 0;
201 }
202 } else if (PAD_PRESSED(PAD_DOWN) || PAD_REPEATED(PAD_DOWN)) {
203 task->cursor++;
204 if (task->cursor > task->count - 1) {
205 task->cursor = task->count - 1;
206 }
207 }
208 if (prev != task->cursor) {
210 win->cursor->setPos(win->cursor, 0xB0, task->cursor * 14 + 0x31);
211 return;
212 }
213 done = 0;
214 if (PAD_PRESSED(PAD_CROSS)) {
216 if (task->option2Enabled == 0 && task->cursor == 2) {
217 return;
218 }
219 done = 1;
220 if (GAME.funcs.getMode() == MODE_STATUS) {
221 task->step = 1;
222 } else {
223 task->step = 0;
224 }
226 } else if (PAD_PRESSED(PAD_TRIANGLE)) {
228 done = 1;
229 if (GAME.funcs.getMode() == MODE_STATUS) {
230 task->step = 0;
231 } else {
232 task->step = 1;
233 }
234 }
235 if (done) {
236 startPanel(&task->panels[0], 0);
237 startPanel(&task->panels[1], 0);
238 startPanel(&task->panels[2], 0);
239 showPartnerPage(task, win, 2, 0);
240 win->moneyLabel->setVisible(win->moneyLabel, 0);
241 win->money->setVisible(win->money, 0);
242 win->cursor->setVisible(win->cursor, 0);
243 task->substate++;
244 }
245}
246
247/*
248 * Steps the fade to the next mode, a CLUT row each 2 frames: its first three
249 * sprites through rows 0-7, the next three through rows 8-15; then it asks for the
250 * mode (the field's, from the status screen; else the status screen, with the option)
251 */
252static inline void stepFieldMenuFade(FieldMenu *task) {
253 switch (task->substate) {
254 default:
255 task->setState(task, TASK_DONE);
256 /* fallthrough */
257 case 0:
258 case 1:
259 case 2:
260 if (GFX.funcs.getTime() - task->time >= 2) {
261 task->time = GFX.funcs.getTime();
262 if (++task->fadeRow >= 8) {
263 if (++task->substate != 3) {
264 task->fadeRow = 0;
265 } else {
266 task->fadeRow = 8;
267 }
268 }
269 }
270 break;
271 case 3:
272 case 4:
273 case 5:
274 if (GFX.funcs.getTime() - task->time >= 2) {
275 task->time = GFX.funcs.getTime();
276 if (++task->fadeRow >= 0x10) {
277 if (++task->substate == 6) {
278 task->fadeRow = 0xF;
279 } else {
280 task->fadeRow = 8;
281 }
282 }
283 }
284 break;
285 case 6:
286 if (GAME.funcs.getMode() == MODE_STATUS) {
288 } else {
291 }
292 task->substate++;
293 break;
294 case 7:
295 break;
296 }
297}
298
299/* Draws the fade to the next mode: the rows already dark, and the current one at its CLUT row */
300static inline void drawFieldMenuFade(FieldMenu *task) {
301 SpriteDrawer obj2;
302 s32 j;
303
304 initSpriteDrawer(&obj2);
305 obj2.setTexture(0x140, 0);
306 obj2.setLayerId(task->layerId, task->depth);
307 obj2.setFollowScroll(0);
308 for (j = 0; j <= task->substate; j++) {
309 if (j == 6) {
310 break;
311 }
312 if (j == task->substate) {
313 obj2.setClutRow(task->fadeRow);
314 } else if (j < 3) {
315 obj2.setClutRow(7);
316 } else {
317 obj2.setClutRow(0xF);
318 }
320 }
321}
322
323/* Runs the field menu: opens its panels, moves the cursor and switches mode on a choice */
325 SpriteDrawer obj;
326 s32 i;
327 s32 y;
328 s32 y2;
329
330 switch (task->state) {
331 case 0:
332 default:
333 openFieldMenu(task, win);
334 break;
335 case 1:
336 switch (task->substate) {
337 default:
338 case 0:
339 if (updatePanel(&task->panels[0])) {
340 showPartnerPage(task, win, 0, 1);
343 task->substate++;
344 }
345 break;
346 case 1:
347 if (updatePanel(&task->panels[1])) {
348 showFieldMenuOptions(task, win);
349 task->substate++;
350 }
351 break;
352 case 2:
353 if (updatePanel(&task->panels[2])) {
354 showFieldMenuMoney(task, win);
355 task->substate++;
356 }
357 break;
358 case 3:
359 chooseFieldMenuOption(task, win);
360 break;
361 case 4:
362 if (updatePanel(&task->panels[2])) {
363 showPartnerPage(task, win, 1, 0);
364 for (task->counter = 0; task->counter < task->count; task->counter++) {
365 win->options[task->counter]->setVisible(win->options[task->counter], 0);
366 }
368 task->substate++;
369 }
370 break;
371 case 5:
372 if (updatePanel(&task->panels[1])) {
373 showPartnerPage(task, win, 0, 0);
374 win->title->setVisible(win->title, 0);
376 task->substate++;
377 }
378 break;
379 case 6:
380 if (updatePanel(&task->panels[0])) {
381 if (task->step == 0) {
382 task->setState(task, TASK_DONE);
383 task->time = GFX.funcs.getTime();
384 } else {
385 task->setState(task, TASK_KILL);
386 }
387 }
388 break;
389 }
390 initSpriteDrawer(&obj);
391 obj.setTexture(0x140, 0);
392 obj.setLayerId(task->layerId, task->depth);
393 obj.setFollowScroll(0);
394 for (i = 0, y = 0x11, y2 = 0x25; i < 3; i++) {
395 if (task->panels[i].level != 0) {
396 STRETCH_SPRITE(obj, task->panels[i].level, 0, y2);
397 obj.draw(FILE_CACHE.getEntry(FILE_MENU_SPRITES << 16), 0x15, 0, y);
398 obj.draw(FILE_CACHE.getEntry(FILE_MENU_SPRITES << 16), 0x17, 0, y);
399 }
400 y += 0x2E;
401 y2 += 0x2E;
402 }
403 if (task->panels[0].level != 0) {
404 STRETCH_SPRITE(obj, task->panels[0].level, 0x140, 0x19);
405 obj.draw(FILE_CACHE.getEntry(FILE_MENU_SPRITES << 16), 0x18, 0x22, 0xD);
406 }
407 if (task->panels[1].level != 0) {
408 STRETCH_SPRITE(obj, task->panels[1].level, 0x140, 0x52);
409 obj.draw(FILE_CACHE.getEntry(FILE_MENU_SPRITES << 16), 0x1C - task->extraOption, 0xA8, 0x28);
410 }
411 if (task->panels[2].level != 0) {
412 STRETCH_SPRITE(obj, task->panels[2].level, 0, 0xA8);
413 obj.draw(FILE_CACHE.getEntry(FILE_MENU_SPRITES << 16), 0x1A, 0, 0x9E);
414 }
415 break;
416 case 2:
417 stepFieldMenuFade(task);
418 drawFieldMenuFade(task);
419 break;
420 case 3:
421 break;
422 }
423}
424
425/* Opens the field menu on a layer with the cursor on an option */
426FieldMenu *createFieldMenu(s32 layerId, s32 cursor) {
428
429 task->layerId = layerId;
430 task->depth = 1;
431 task->cursor = cursor;
432 return task;
433}
signed int s32
Definition common.h:11
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
GameState GAME
The save data, the game mode and the methods.
Definition state.c:64
#define TASK_KILL
Definition task.h:37
#define TASK_DONE
Definition task.h:36
Cursor * createCursor(s16 layerId, s32 depth, s16 x, s16 y)
A menu cursor on a layer at (x, y)
Definition cursor.c:92
static void drawFieldMenuFade(FieldMenu *task)
Draws the fade to the next mode: the rows already dark, and the current one at its CLUT row.
Definition field_menu.c:300
s32 updatePanel(PanelAnim *panel)
Advances a panel animation; 1 once it has finished.
Definition field_menu.c:21
s32 FIELD_MENU_SPRITES[6]
Definition field_menu.c:142
void showPartnerPage(void *menu, FieldMenuWindows *win, s32 page, s32 show)
Fills a party member's page of the field menu (name and five stats), or hides it.
Definition field_menu.c:87
static void showFieldMenuMoney(FieldMenu *task, FieldMenuWindows *win)
Once the third panel is open: the money and the cursor.
Definition field_menu.c:181
s32 PAGE_STATS[5]
The stats the pages' values show, as indices into the stats halfwords.
Definition field_menu.c:56
s32 FIELD_MENU_OPTIONS[2][6]
The options' strings, without and with the extra option.
Definition field_menu.c:137
s32 getFieldZone(void)
The field's stages by mode: -1 from MODE_NEW_GAME (where the field menu greys out option 2),...
Definition field_menu.c:124
static void showFieldMenuOptions(FieldMenu *task, FieldMenuWindows *win)
Once the second panel is open: the options (option 2 greyed when disabled)
Definition field_menu.c:168
void createFieldMenuWindows(FieldMenu *task, FieldMenuWindows *win)
Creates the field menu's windows: the title, the options, the cursor, the money and the pages.
Definition field_menu.c:59
FieldMenu * createFieldMenu(s32 layerId, s32 cursor)
Opens the field menu on a layer with the cursor on an option.
Definition field_menu.c:426
static void openFieldMenu(FieldMenu *task, FieldMenuWindows *win)
Starts the field menu: opens the panels and the windows, with the extra option when the player has it...
Definition field_menu.c:146
void startPanel(PanelAnim *panel, s32 open)
Starts opening (open != 0) or closing a panel.
Definition field_menu.c:7
WindowPos FIELD_MENU_LAYOUT[11]
The party pages' windows: [0] the name, [1]-[5] the labels and [6]-[10] the values.
Definition field_menu.c:41
static void chooseFieldMenuOption(FieldMenu *task, FieldMenuWindows *win)
Moves the cursor, or on a choice (option 2 only when enabled) or a cancel closes the panels,...
Definition field_menu.c:193
static void stepFieldMenuFade(FieldMenu *task)
Steps the fade to the next mode, a CLUT row each 2 frames: its first three sprites through rows 0-7,...
Definition field_menu.c:252
void updateFieldMenu(FieldMenu *task, FieldMenuWindows *win)
Runs the field menu: opens its panels, moves the cursor and switches mode on a choice.
Definition field_menu.c:324
#define TEXT_FILE(file)
Definition file.h:190
#define TEXT_STATUS
STATUS: the field menu's and STSTATUS's.
Definition file.h:225
#define FILE_MENU_SPRITES
Files the engine loads by number.
Definition file.h:188
FileCache FILE_CACHE
The file cache.
Definition file_cache.c:7
long open(char *name, unsigned long mode)
The kernel's file functions (libapi.h); the sim: device is the PC's.
struct FieldMenuChoice FIELD_MENU_CHOICE
menu/field_menu.c's
Definition game_bss.c:21
#define MODE_NEW_GAME
Game modes (GameState: mode >> 8 is the overlay) that more than their own overlay asks for.
Definition game_state.h:429
#define STAT_MP
Definition game_state.h:283
#define STAT_MAX_HP
Definition game_state.h:282
#define STAT_HP
Definition game_state.h:281
#define MODE_STATUS
STSTATUS: the field menu's screens (FIELD_MENU_CHOICE)
Definition game_state.h:450
#define STAT_LEVEL
Indices of a partner's stats (PartnerStats.stats, computeStats, setStat)
Definition game_state.h:279
#define STAT_MAX_MP
Definition game_state.h:284
#define STRETCH_SPRITE(sprite, level, x, y)
Definition gfx.h:273
#define PAD_CROSS
Definition pad.h:31
#define PAD_DOWN
Definition pad.h:24
#define PAD_TRIANGLE
Definition pad.h:32
#define PAD_PRESSED(button)
One button of pad 1: newly pressed, auto-repeated while held, or held.
Definition pad.h:140
#define PAD_UP
Definition pad.h:22
#define PAD_REPEATED(button)
Definition pad.h:141
SoundState SOUND
rsin and rcos (libgte) read rsin_tbl[a - 0x800] and the like: their addresses before the table fall i...
Definition sound.c:180
#define SOUND_MENU_CLOSE
SYSTEM04.
Definition sound.h:42
#define SOUND_SELECT
Sounds the overlays share, with SOUNDTST's names.
Definition sound.h:38
#define SOUND_MENU_OPEN
SYSTEM03.
Definition sound.h:41
#define SOUND_MENU_CANCEL
SYSTEM01.
Definition sound.h:39
#define SOUND_CURSOR
SYSTEM02: a cursor moves.
Definition sound.h:40
void initSpriteDrawer(SpriteDrawer *obj)
Clears a sprite drawer to neutral (no scale, gray tint, follows the scroll), gives it its methods and...
void(* setPos)()
(cursor, x, y)
Definition text.h:34
void(* setVisible)()
(cursor, visible)
Definition text.h:33
s32 extra
the list had the extra option: STSTATUS_screens' row
Definition menu.h:132
The children of the field menu.
Definition menu.h:92
PartnerPage pages[3]
Definition menu.h:98
TextWindow * options[6]
Definition menu.h:96
TextWindow * title
Definition menu.h:93
TextWindow * moneyLabel
Definition menu.h:94
struct Cursor * cursor
Definition menu.h:97
TextWindow * money
Definition menu.h:95
The menu opened on the field: the three party members' pages, a list of options (FIELD_MENU_OPTIONS,...
Definition menu.h:116
s32 option2Enabled
Definition menu.h:123
PanelAnim panels[3]
Definition menu.h:126
s32 counter
Definition menu.h:117
s32 extraOption
Definition menu.h:122
s32 fadeRow
Definition menu.h:124
s32 substate
Definition menu.h:117
s32 layerId
Definition menu.h:118
s32 depth
Definition menu.h:119
s32 time
Definition menu.h:125
void(* nextState)(struct FieldMenu *task)
Definition menu.h:117
s32 count
Definition menu.h:121
s32 cursor
Definition menu.h:120
s32 step
Definition menu.h:117
s32 state
Definition menu.h:117
void(* setState)(struct FieldMenu *task, s32 state)
Definition menu.h:117
void *(* load)(u32 file)
Definition file.h:92
void *(* getEntry)(u32 fileAndIndex)
Definition file.h:96
s32(* getMode)(void)
Definition game_state.h:19
struct PartnerStats *(* getPartnerStats)(s32 partner)
Definition game_state.h:38
void(* computeStats)(s32 partner, union PartnerTotals *out)
Definition game_state.h:31
void(* requestMode)(s32 mode, s32 arg)
Definition game_state.h:21
s32(* getPartyMember)(u32 index)
Definition game_state.h:24
s8 items[0x193]
counts, up to 99
Definition game_state.h:512
s32 fieldMode
where the menu returns to
Definition game_state.h:503
GameFuncs funcs
Definition game_state.h:582
s32(* getTime)(void)
Definition gfx.h:31
GfxFuncs funcs
Definition gfx.h:77
Opens or closes a menu panel: level goes 0 -> ONE in duration frames (or back at twice the speed),...
Definition menu.h:18
s32 step
Definition menu.h:20
s32 level
Definition menu.h:21
s32 active
Definition menu.h:22
s32 duration
Definition menu.h:19
TextWindow * values[5]
Definition menu.h:88
TextWindow * labels[5]
Definition menu.h:87
TextWindow * name
Definition menu.h:86
A partner Digimon from its name on (Partner.info), as getPartnerStats gives it.
Definition game_state.h:303
short(* playSound)(s32 id)
returns the voice of a key-on
Definition sound.h:187
Draws sprites from a sprite sheet (such as file 0x277, the menu graphics): a sheet has a table of fra...
Definition gfx.h:223
void(* setLayerId)()
(id, depth)
Definition gfx.h:244
void(* setFollowScroll)()
(on)
Definition gfx.h:251
void(* setClutRow)()
(row)
Definition gfx.h:247
void(* draw)()
(sheet, frame, x, y)
Definition gfx.h:246
void(* setTexture)()
(x, y)
Definition gfx.h:242
void(* setPalette)(struct TextWindow *obj, u8 arg)
Definition text.h:174
void(* setRightAlign)()
no prototype: callers would truncate u8 args
Definition text.h:178
void(* setNumber)()
Definition text.h:166
void(* setString)()
Definition text.h:165
void(* setVisible)(struct TextWindow *obj, u8 arg)
Definition text.h:177
Where a window goes, and the string it shows.
Definition menu.h:102
s16 y
Definition menu.h:106
s16 x
Definition menu.h:104
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
#define PALETTE_GREY
what is unavailable
Definition text.h:119
TextWindow * createTextWindow(s16 layerId, s16 style, s16 x, s16 y)
A text window on a layer, in a font style, at (x, y)
computeStats' result: the stats with the equipment added, by STAT_* or by name.
Definition game_state.h:409
s16 stats[24]
Definition game_state.h:410