Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
tech_menu.c
Go to the documentation of this file.
1/* FIGHTSTG's technique menu. */
2
4
5/* Draws the page's technique icons, the page arrows (blinking) and the frame */
7 SpriteDrawer drawer;
8 void *sheet;
9 s32 index;
10 s32 tech;
11 s32 i;
12
13 initSpriteDrawer(&drawer);
15 drawer.setTexture(0x140, 0);
17 for (i = 0; i < TECH_MENU_LINES; i++) {
18 index = task->page * TECH_MENU_LINES + i;
19 if (index < task->count) {
20 tech = task->techs[index] & SKILL_ID;
21 if (tech == 0) {
22 break;
23 }
24 drawer.draw(sheet, TECHS[tech - 1].icon + 0x37, 0x1D, 0x45 + i * 0xE);
25 }
26 }
27 drawer.setTexture(0x200, 0);
29 if (GFX.funcs.getTime() & 0x10) {
30 if (task->page > 0) {
31 drawer.draw(sheet, 0x1F, 0x10, 0x9F);
32 }
33 if (task->page < task->pageCount - 1) {
34 drawer.draw(sheet, 0x20, 0x90, 0x9F);
35 }
36 }
37 drawer.draw(sheet, 0x2A, 8, 0x3E);
38 drawer.draw(sheet, 0x29, 0xA3, 0x21);
39 drawer.draw(sheet, 0x31, 0xB, 0xBC);
40}
41
42/* Makes the technique menu's windows: the page buttons, the active fighter's
43 MP over its max (or a text by its MP for a temporary Digimon), the six
44 names, the description and the technique's MP cost */
48 s32 i;
49
50 children[1].window = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x1A, 0x9F);
51 children[1].window->setString(children[1].window, text, 0x11);
52 children[1].window->setPalette(children[1].window, PALETTE_DARK_BLUE);
53 children[2].window = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x80, 0x9F);
54 children[2].window->setString(children[2].window, text, 0x12);
55 children[2].window->setPalette(children[2].window, PALETTE_DARK_BLUE);
56 children[3].window = createTextWindow(BATTLE_LAYER_MENUS, 3, 0xAC, 0x3A);
57 children[3].window->setString(children[3].window, text, 0xD);
58 children[6].window = createTextWindow(BATTLE_LAYER_MENUS, 3, 0xD8, 0x3A);
59 if (fighter->temporary) {
60 if (fighter->mp < 100) {
61 children[6].window->setString(children[6].window, text, 0x1A);
62 } else if (fighter->mp < 1000) {
63 children[6].window->setString(children[6].window, text, 0xF);
64 } else {
65 children[6].window->setString(children[6].window, text, 0x24);
66 }
67 } else {
68 children[6].window->setNumber(children[6].window, 0, fighter->mp);
69 }
70 children[6].window->setRightAlign(children[6].window, 1);
71 children[5].window = createTextWindow(BATTLE_LAYER_MENUS, 3, 0xD9, 0x3A);
72 children[5].window->setString(children[5].window, text, 0x10);
73 children[4].window = createTextWindow(BATTLE_LAYER_MENUS, 3, 0xFB, 0x3A);
74 children[4].window->setNumber(children[4].window, 0, fighter->maxMp);
75 children[4].window->setRightAlign(children[4].window, 1);
76 for (i = 0; i < TECH_MENU_LINES; i++) {
77 children[7 + i].window = createTextWindow(BATTLE_LAYER_MENUS, 1, 0x2A, 0x45 + i * 0xE);
78 }
79 children[13].window = createTextWindow(BATTLE_LAYER_MENUS, 1, 0x14, 0xC2);
80 children[14].window = createTextWindow(BATTLE_LAYER_MENUS, 1, 0x100, 0xD0);
81 children[15].window = createTextWindow(BATTLE_LAYER_MENUS, 1, 0x12B, 0xD0);
82}
83
84/* Shows the page's techniques (palette 7 for those the fighter lacks the MP
85 for, 3 its signature one, 4 those passed on) and the description and MP
86 cost of the one under the cursor, or text 0x13 when there are none */
89 s32 index;
90 s32 tech;
91 s32 mp;
92 s32 i;
93
94 if (task->count != 0) {
95 for (i = 0; i < TECH_MENU_LINES; i++) {
96 index = task->page * TECH_MENU_LINES + i;
97 if (index > task->count - 1) {
98 children[7 + i].window->setVisible(children[7 + i].window, 0);
99 } else {
100 tech = task->techs[index];
101 children[7 + i].window->setString(children[7 + i].window, FILE_CACHE.load(TEXT_FILE(TEXT_SKILL_NAMES)), tech & SKILL_ID);
102 mp = FIGHTSTG_battleFuncs.getTechCost(0, tech);
103 if (fighter->temporary) {
104 if (tech & 0x8000) {
105 children[7 + i].window->setPalette(children[7 + i].window, PALETTE_YELLOW);
106 } else if (tech & SKILL_MARKED) {
107 children[7 + i].window->setPalette(children[7 + i].window, PALETTE_GREEN);
108 } else {
109 children[7 + i].window->setPalette(children[7 + i].window, PALETTE_WHITE);
110 }
111 } else if (fighter->mp < mp) {
112 children[7 + i].window->setPalette(children[7 + i].window, PALETTE_GREY);
113 } else if (tech & 0x8000) {
114 children[7 + i].window->setPalette(children[7 + i].window, PALETTE_YELLOW);
115 } else if (tech & SKILL_MARKED) {
116 children[7 + i].window->setPalette(children[7 + i].window, PALETTE_GREEN);
117 } else {
118 children[7 + i].window->setPalette(children[7 + i].window, PALETTE_WHITE);
119 }
120 }
121 }
122 mp = FIGHTSTG_battleFuncs.getTechCost(0, task->techs[task->page * TECH_MENU_LINES + children[0].cursor->sel]);
123 tech = task->techs[task->page * TECH_MENU_LINES + children[0].cursor->sel];
124 if (fighter->temporary == 0 && fighter->mp < mp) {
125 children[13].window->setString(children[13].window, FILE_CACHE.load(TEXT_FILE(TEXT_BATTLE_MENU)), 0x54);
126 children[14].window->setString(children[14].window, FILE_CACHE.load(TEXT_FILE(TEXT_BATTLE_MENU)), 0xD);
127 children[14].window->setPalette(children[14].window, PALETTE_GREY);
128 children[15].window->setNumber(children[15].window, 0, mp);
129 children[15].window->setRightAlign(children[15].window, 1);
130 children[15].window->setPalette(children[15].window, PALETTE_GREY);
131 } else {
132 children[13].window->setString(children[13].window, FILE_CACHE.load(TEXT_FILE(TEXT_SKILL_INFO)), tech & SKILL_ID);
133 children[14].window->setString(children[14].window, FILE_CACHE.load(TEXT_FILE(TEXT_BATTLE_MENU)), 0xD);
134 children[15].window->setNumber(children[15].window, 0, mp);
135 children[15].window->setRightAlign(children[15].window, 1);
136 if (tech & SKILL_MARKED) {
137 children[14].window->setPalette(children[14].window, PALETTE_GREEN);
138 children[15].window->setPalette(children[15].window, PALETTE_GREEN);
139 } else {
140 children[14].window->setPalette(children[14].window, PALETTE_WHITE);
141 children[15].window->setPalette(children[15].window, PALETTE_WHITE);
142 }
143 }
144 } else {
145 children[13].window->setString(children[13].window, FILE_CACHE.load(TEXT_FILE(TEXT_BATTLE_MENU)), 0x13);
146 }
147}
148
149/* The techniques of a Digimon of the partner's slots: its entry's, its
150 signature one when it is temporary, then the ones the other entries can
151 pass on. */
152static inline void listSlotTechs(TechMenu *task, BattleFighter *fighter, s32 member, s32 id) {
153 s32 extra[10];
154 DigimonData *data;
155 s32 slots;
156 s32 found;
157 s32 count;
158 s32 tech;
159 s32 i;
160 s32 j;
161
162 slots = GAME.funcs.getPartnerSlots(member, task->slots);
163 task->count = 0;
164 for (i = 0; i < slots; i++) {
165 GAME.funcs.getPartnerEntry(member, task->slots[i], &task->entries[i]);
166 if (id == task->entries[i].id) {
167 for (j = 0; j < 6; j++) {
168 if (task->entries[i].skills[j] != 0) {
169 task->techs[task->count++] = (s16)(task->entries[i].skills[j] & ~SKILL_MARKED);
170 }
171 }
172 }
173 }
174 if (fighter->temporary != 0) {
175 data = GET_DIGIMON(fighter->id);
176 found = 0;
177 for (j = 0; j < task->count; j++) {
178 if ((task->techs[j] & SKILL_ID) == data->skills[6]) {
179 task->techs[j] = (task->techs[j] & SKILL_ID) | 0x8000;
180 found = -1;
181 break;
182 }
183 }
184 if (found != -1) {
185 task->techs[task->count++] = data->skills[6] | 0x8000;
186 }
187 }
188 /* the techniques the other entries can pass on */
189 for (j = 0; j < 10; j++) {
190 extra[j] = 0;
191 }
192 count = 0;
193 for (i = 0; i < slots; i++) {
194 if (id != task->entries[i].id) {
195 for (j = 0; j < 6; j++) {
196 if (task->entries[i].skills[j] & SKILL_MARKED) {
197 extra[count++] = task->entries[i].skills[j];
198 }
199 }
200 }
201 }
202 for (j = 0; j < count; j++) {
203 tech = extra[j] & SKILL_ID;
204 for (i = 0; i < task->count; i++) {
205 if (tech == (task->techs[i] & SKILL_ID)) {
206 tech = 0;
207 break;
208 }
209 }
210 if (tech != 0) {
211 task->techs[task->count++] = extra[j];
212 }
213 }
214}
215
216/* Counts the menu's pages and sets the cursor's lines for the first one. */
217static inline void setTechPages(TechMenu *task) {
218 if (task->count != 0) {
219 if (task->count % TECH_MENU_LINES != 0) {
220 task->pageCount = task->count / TECH_MENU_LINES + 1;
221 } else {
222 task->pageCount = task->count / TECH_MENU_LINES;
223 }
224 }
225 if (task->count != 0) {
226 if (task->count > TECH_MENU_LINES) {
228 } else {
230 }
231 }
232#if VERSION_EU || VERSION_JP
233 else {
235 }
236#endif
237}
238
239/* Shows the page turned to, with the cursor on its first line. */
240static inline void showNewTechPage(TechMenu *task, TechMenuChild *children) {
241 s32 lines;
242
243 children[0].cursor->sel = 0;
244 lines = task->count - task->page * TECH_MENU_LINES;
245 if (lines > TECH_MENU_LINES) {
246 lines = TECH_MENU_LINES;
247 }
248 children[0].cursor->params.count = lines;
249 FIGHTSTG_showTechPage(task, children);
251}
252
253/* The battle's technique menu: the active fighter's techniques (a Digimon of
254 a partner's slots has its entry's, its signature one and the ones the other
255 entries can pass on), six a page. L1 and R1 turn the pages, cross picks
256 the technique under the cursor into *result, spending its MP (a temporary
257 Digimon spends none), and triangle gives -2 */
259 BattleFighter *fighter;
260 BattleFighter *active;
261 s32 member;
262 s32 id;
263 s32 pressed;
264 s32 page;
265 s32 mp;
266
267 switch (task->state) {
268 case TASK_INIT:
269 default:
272 id = fighter->id;
273 if (id == DIGIMON_DATA[member].id) {
274 task->techs[0] = DIGIMON_DATA[member].skills[6] | 0x8000;
275 task->count = 1;
276 } else {
277 listSlotTechs(task, fighter, member, id);
278 }
279 setTechPages(task);
281 FIGHTSTG_createTechWindows(task, children);
282 FIGHTSTG_showTechPage(task, children);
283 task->nextState(task);
284 break;
285 case TASK_RUN:
287 /* the match depends on the do-while and its breaks, which skip the
288 update of sel, the stages' early exit */
289 do {
290 pressed = PAD.getPressed(0);
291 page = task->page;
292 if (task->pageCount != 0) {
293 if (pressed & (1 << PAD_L1)) {
294 if (--task->page < 0) {
295 task->page = 0;
296 }
297 } else if (pressed & (1 << PAD_R1)) {
298 if (++task->page > task->pageCount - 1) {
299 task->page = task->pageCount - 1;
300 }
301 }
302 }
303 if (page != task->page) {
304 showNewTechPage(task, children);
305 } else if (task->sel != children[0].cursor->sel) {
306 FIGHTSTG_showTechPage(task, children);
307 } else if (pressed & (1 << PAD_CROSS)) {
309 if (task->count != 0) {
311 /* the match depends on the choice written in both branches */
312 if (active->temporary != 0) {
313 *task->result = task->techs[task->page * TECH_MENU_LINES + children[0].cursor->sel] & SKILL_ID;
314 task->setState(task, 3);
315 children[0].cursor->locked = 1;
316 break;
317 }
318 mp = FIGHTSTG_battleFuncs.getTechCost(0, task->techs[task->page * TECH_MENU_LINES + children[0].cursor->sel]);
319 if (active->mp >= mp) {
320 active->mp -= mp;
321 *task->result = task->techs[task->page * TECH_MENU_LINES + children[0].cursor->sel] & SKILL_ID;
322 task->setState(task, 3);
323 children[0].cursor->locked = 1;
324 break;
325 }
326 }
327 } else if (pressed & (1 << PAD_TRIANGLE)) {
329 *task->result = -2;
330 task->setState(task, 3);
331 break;
332 }
333 task->sel = children[0].cursor->sel;
334 } while (0);
335 break;
336 case 2:
337 case 3:
338 break;
339 }
340}
341
342/* Opens the battle's technique menu; *result gets the technique picked, or
343 -2 to go back */
345 TechMenu *task = createTask(FIGHTSTG_updateTechMenu, sizeof(TechMenu), 16 * sizeof(TechMenuChild));
346
347 task->result = result;
348 *result = -1;
349 return task;
350}
Battle FIGHTSTG_battle
the battle: its fighters, speed and drawing functions
Definition battle.c:16
BattleFuncs FIGHTSTG_battleFuncs
the battle's stats and the functions that compute with them
Definition battle.c:25
MenuCursor * FIGHTSTG_createCursor(CursorLayout *layout)
Creates a menu cursor laid out by layout.
Definition cursor.c:136
#define TECH_MENU_LINES
The lines of a page of the technique menu.
Definition menu.h:65
#define BATTLE_LAYER_MENUS
the HUD, the menus and the messages
Definition types.h:31
FIGHTSTG.PRO: the battle.
signed int s32
Definition common.h:11
signed short s16
Definition common.h:9
DigimonData DIGIMON_DATA[55]
55 entries: the 52 Digimon, then three placeholders (0x1D4-0x1D6)
Definition digimon.c:7
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_RUN
Definition task.h:35
#define TASK_INIT
Tasks: every game object is a task, a heap block that starts with this header and is updated once per...
Definition task.h:34
#define TEXT_BATTLE_MENU
MFIGHT: WFIGHTMN's.
Definition file.h:218
#define TEXT_SKILL_NAMES
SKLNAM.
Definition file.h:223
#define TEXT_FILE(file)
Definition file.h:190
#define FILE_BATTLE_MENU
The battle menu's files (WFIGHTMN, WFIGHTTS): FILE_BATTLE_IMAGES is an archive whose entries go throu...
Definition file.h:294
#define TEXT_SKILL_INFO
SKLINF.
Definition file.h:222
#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
#define SKILL_MARKED
marked in the lab (STGDGLAB_updateSkillPanel)
Definition game_state.h:257
#define SKILL_ID
PartnerEntry.skills.
Definition game_state.h:255
DigimonData *(* GET_DIGIMON)(s32 id)
getDigimon for the overlays, in the small data (.sdata) between game/items.c's and file/file_table....
Definition get_digimon.c:10
CursorLayout FIGHTSTG_techCursor
FIGHTSTG_updateTechMenu's cursor.
Definition item_menu.c:95
TechData TECHS[443]
The techniques, from 1: technique n is TECHS[n - 1].
Definition items.c:906
PadState PAD
Controller input: cleared by initPad, then the methods.
Definition pad.c:168
#define PAD_CROSS
Definition pad.h:31
#define PAD_TRIANGLE
Definition pad.h:32
#define PAD_L1
Definition pad.h:28
#define PAD_R1
Definition pad.h:29
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_CONFIRM
SYSTEM07.
Definition sound.h:44
#define SOUND_MENU_CANCEL
SYSTEM01.
Definition sound.h:39
#define SOUND_MENU_MOVE
SYSTEM06.
Definition sound.h:43
void initSpriteDrawer(SpriteDrawer *obj)
Clears a sprite drawer to neutral (no scale, gray tint, follows the scroll), gives it its methods and...
One of the battle's fighters, three on each side (WFIGHTMN's BattleUnit): a partner's HP and MP go ba...
Definition battle.h:191
u8 temporary
id is a temporary Digimon
Definition battle.h:202
s16 id
the Digimon (DIGIMON_DATA)
Definition battle.h:192
s32(* getTechCost)(u8 side, s32 id)
Definition battle.h:361
s32 active[2]
each side's fighter
Definition battle.h:226
BattleFighter fighters[2][3]
Definition battle.h:227
BattleState state
Definition battle.h:240
s32 count
Definition menu.h:289
Digimon definition (DIGIMON_DATA, 52 of them; the first 8 are the partners)
Definition game_state.h:86
u16 skills[7]
[1]-[6] are learnt at skillLevels
Definition game_state.h:90
void *(* load)(u32 file)
Definition file.h:92
void *(* getEntry)(u32 fileAndIndex)
Definition file.h:96
s32(* getPartnerEntry)()
-1 if it hasn't the Digimon
Definition game_state.h:36
s32(* getPartyMember)(u32 index)
Definition game_state.h:24
s32(* getPartnerSlots)()
(partner, s16 *out): the count
Definition game_state.h:32
GameFuncs funcs
Definition game_state.h:582
s32(* getTime)(void)
Definition gfx.h:31
GfxFuncs funcs
Definition gfx.h:77
s32 sel
Definition menu.h:304
s32 locked
Definition menu.h:305
CursorLayout params
Definition menu.h:306
s32(* getPressed)(s32 pad)
Definition pad.h:125
s16 skills[6]
SKILL_ID and the flags below, 0 for none.
Definition game_state.h:251
s16 id
FIRST_ENTRY_ID and up.
Definition game_state.h:248
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(* draw)()
(sheet, frame, x, y)
Definition gfx.h:246
void(* setTexture)()
(x, y)
Definition gfx.h:242
FIGHTSTG_createTechMenu's task: a menu of techniques, six a page.
Definition menu.h:68
s32 pageCount
Definition menu.h:77
s32 state
Definition menu.h:69
s32 * result
-1 until it is done
Definition menu.h:70
void(* nextState)(struct TechMenu *task)
Definition menu.h:69
PartnerEntry entries[3]
skills with SKILL_MARKED can be passed on
Definition menu.h:73
s32 techs[12]
ids in the low 13 bits, from 1
Definition menu.h:74
s32 sel
the cursor's line last frame
Definition menu.h:71
s32 count
Definition menu.h:75
s16 slots[4]
GAME.funcs.getPartnerSlots's.
Definition menu.h:72
s32 page
Definition menu.h:76
void(* setState)(struct TechMenu *task, s32 state)
Definition menu.h:69
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
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
void FIGHTSTG_createTechWindows(TechMenu *task, TechMenuChild *children)
Makes the technique menu's windows: the page buttons, the active fighter's MP over its max (or a text...
Definition tech_menu.c:45
static void showNewTechPage(TechMenu *task, TechMenuChild *children)
Shows the page turned to, with the cursor on its first line.
Definition tech_menu.c:240
static void setTechPages(TechMenu *task)
Counts the menu's pages and sets the cursor's lines for the first one.
Definition tech_menu.c:217
void FIGHTSTG_showTechPage(TechMenu *task, TechMenuChild *children)
Shows the page's techniques (palette 7 for those the fighter lacks the MP for, 3 its signature one,...
Definition tech_menu.c:87
void FIGHTSTG_updateTechMenu(TechMenu *task, TechMenuChild *children)
The battle's technique menu: the active fighter's techniques (a Digimon of a partner's slots has its ...
Definition tech_menu.c:258
static void listSlotTechs(TechMenu *task, BattleFighter *fighter, s32 member, s32 id)
The techniques of a Digimon of the partner's slots: its entry's, its signature one when it is tempora...
Definition tech_menu.c:152
void FIGHTSTG_drawTechMenu(TechMenu *task)
Draws the page's technique icons, the page arrows (blinking) and the frame.
Definition tech_menu.c:6
TechMenu * FIGHTSTG_createTechMenu(s32 *result)
Opens the battle's technique menu; *result gets the technique picked, or -2 to go back.
Definition tech_menu.c:344
#define PALETTE_DARK_BLUE
Definition text.h:114
#define PALETTE_GREEN
Definition text.h:116
#define PALETTE_WHITE
The text windows' palettes (TextWindow.palette, setPalette): rows of the font's CLUTs,...
Definition text.h:112
#define PALETTE_YELLOW
Definition text.h:115
#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)
One of FIGHTSTG_updateTechMenu's children: the cursor first, then the text windows.
Definition menu.h:314
MenuCursor * cursor
Definition menu.h:315
TextWindow * window
Definition menu.h:316