Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
switch_in_menu.c
Go to the documentation of this file.
1/* FIGHTSTG's switch-in menu: which Digimon of the incoming partner comes in,
2 and whether it does the pair technique. */
3
5
6/* Draws the switch-in menu's frames, the second one with the pair technique */
8 SpriteDrawer drawer;
9 void *sheet;
10
12 initSpriteDrawer(&drawer);
14 drawer.setTexture(0x200, 0);
15 drawer.draw(sheet, 0x2B, 0xA7, 0x8F);
16 if (task->tech != 0) {
17 drawer.draw(sheet, 2, 0xA7, 0xB8);
18 drawer.draw(sheet, 0x29, 0xA3, 0x21);
19 }
20}
21
22/* Makes the switch-in menu's windows: the four names, the choices and the MP */
24 s32 i;
25
26 for (i = 0; i < 4; i++) {
27 w->names[i] = createTextWindow(BATTLE_LAYER_MENUS, 1, 0xBB, 0x92 + i * 0x13);
28 }
29 w->choices[4] = createTextWindow(BATTLE_LAYER_MENUS, 1, 0xAB, 0x92);
30 w->choices[0] = createTextWindow(BATTLE_LAYER_MENUS, 1, 0xBB, 0xA5);
31 w->choices[1] = createTextWindow(BATTLE_LAYER_MENUS, 1, 0xBB, 0xB8);
32 w->choices[2] = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x10E, 0xBA);
33 w->choices[3] = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x133, 0xBA);
34 for (i = 0; i < 4; i++) {
36 }
37}
38
39/* Shows the names of the incoming partner's Digimon, or hides them */
41 DigimonData *data;
42 s32 i;
43
44 if (visible) {
45 for (i = 0; i < task->count; i++) {
46 data = GET_DIGIMON(task->ids[i]);
47 if (data != NULL) {
49 }
50 }
51 } else {
52 for (i = 0; i < 4; i++) {
53 if (w->names[i] != NULL) {
54 w->names[i]->setVisible(w->names[i], visible);
55 }
56 }
57 }
58}
59
60/* Shows the picked Digimon's name and the choices, switching in palette 7
61 when flag 0x10 bars it and the pair technique in palette 7 when it can't be
62 done, with its MP cost and the active fighter's MP; or hides them */
64 char *text;
65 BattleFighter *active;
66 BattleFighter *other;
67 DigimonData *data;
68 s32 i;
69
71 if (visible) {
73 other = &FIGHTSTG_battle.state.fighters[0][task->fighter];
74 data = GET_DIGIMON(task->ids[task->digimon]);
76 w->choices[0]->setString(w->choices[0], text, 0x1B);
77 if ((active->flags & FIGHTER_NO_SWITCH) || (other->flags & FIGHTER_NO_SWITCH)) {
79 } else {
81 }
82 if (task->tech != 0) {
83 w->choices[1]->setString(w->choices[1], text, 0x1C);
84 w->choices[2]->setString(w->choices[2], text, 0xD);
85 w->choices[3]->setNumber(w->choices[3], 0, TECHS[task->tech - 1].mp);
86 w->choices[3]->setRightAlign(w->choices[3], 1);
87 if (active->mp < TECHS[task->tech - 1].mp || other->mp < TECHS[task->tech - 1].mp) {
89 } else if ((active->flags & FIGHTER_NO_DIGIVOLVE) || (other->flags & FIGHTER_NO_DIGIVOLVE) || (active->flags & FIGHTER_ASLEEP)) {
91 } else if (active->hp <= 0 || other->hp <= 0) {
93 } else {
95 }
96 w->mp[0]->setString(w->mp[0], text, 0xD);
97 w->mp[1]->setNumber(w->mp[1], 0, active->mp);
98 w->mp[1]->setRightAlign(w->mp[1], 1);
99 w->mp[2]->setString(w->mp[2], text, 0x10);
100 w->mp[3]->setNumber(w->mp[3], 0, active->maxMp);
101 w->mp[3]->setRightAlign(w->mp[3], 1);
102 }
103 } else {
104 for (i = 0; i < 5; i++) {
105 if (w->choices[i] != NULL) {
106 w->choices[i]->setVisible(w->choices[i], visible);
107 }
108 }
109 for (i = 0; i < 4; i++) {
110 if (w->mp[i] != NULL) {
111 w->mp[i]->setVisible(w->mp[i], visible);
112 }
113 }
114 }
115}
116
117/* the cursors of FIGHTSTG_updateSwitchInMenu's two steps */
119 { 4, 168, 147, 19, 36, 167, 146, 19 },
120 { 2, 168, 166, 19, 34, 167, 165, 19 },
121};
122/* the x of FIGHTSTG_createSwitchInWindows's MP windows */
124 0xAC, 0xD8, 0xD9, 0xFB,
125};
126
127/* Lists the partner and the Digimon in its slots, and makes the menu's
128 windows. */
130 s32 member;
131 s32 count;
132 s32 i;
133
134 member = task->partner;
135 GAME.funcs.getPartnerSlots(member, task->slots);
136 count = 1;
137 task->ids[0] = DIGIMON_DATA[member].id;
138 for (i = 0; i < 3; i++) {
139 if (task->slots[i] >= 3) {
140 task->ids[count] = task->slots[i];
141 count++;
142 }
143 }
144 task->count = count;
145 FIGHTSTG_pairCursors[0].count = count;
147 task->shownPage = -1;
148}
149
150/* Sets the pair technique of the active fighter's Digimon with the chosen
151 one, 0 for none (a temporary active fighter keeps the one it has). */
152static inline void findPairTech(SwitchInMenu *task) {
153 DigimonData *data;
154 DigimonData *partner;
155
158 partner = GET_DIGIMON(task->ids[task->digimon]);
159 if (data->pairPartner != 0 && data->pairPartner == partner->nameId) {
160 task->tech = data->pairTech;
161 } else {
162 task->tech = 0;
163 }
164 }
165}
166
167/* Confirms the switch (unless either fighter has FIGHTER_NO_SWITCH) or the
168 pair technique, if both fighters can use it, paying its MP from both. */
169static inline void confirmSwitchIn(SwitchInMenu *task, SwitchInMenuWindows *w) {
170 BattleFighter *active;
171 BattleFighter *other;
172
174 other = &FIGHTSTG_battle.state.fighters[0][task->fighter];
176 if (w->techCursor->sel == 0) {
177 if (!(active->flags & FIGHTER_NO_SWITCH) && !(other->flags & FIGHTER_NO_SWITCH)) {
178 *task->result = 0;
179 *task->result |= task->ids[task->digimon] << 4;
180 task->setSubstate(task, 0);
182 w->techCursor->locked = 1;
183 }
184 } else if (active->mp >= TECHS[task->tech - 1].mp && other->mp >= TECHS[task->tech - 1].mp &&
185 !(active->flags & FIGHTER_NO_DIGIVOLVE) && !(other->flags & FIGHTER_NO_DIGIVOLVE) && !(active->flags & FIGHTER_ASLEEP) && active->hp > 0 &&
186 other->hp > 0) {
187 active->mp -= TECHS[task->tech - 1].mp;
188 other->mp -= TECHS[task->tech - 1].mp;
189 *task->result = w->techCursor->sel;
190 *task->result |= task->ids[task->digimon] << 4;
191 *task->techResult = task->tech;
192 task->setSubstate(task, 0);
194 w->techCursor->locked = 1;
195 }
196}
197
198/* Shows the PartnerInfo page again when the page or the chosen Digimon
199 changed, closing the shown one. */
201 s32 changed;
202
203 if (task->shownPage != task->page) {
204 changed = 1;
205 } else if (w->cursor == NULL) {
206 changed = 0;
207 } else if (task->digimon != w->cursor->sel) {
208 task->digimon = w->cursor->sel;
209 changed = 1;
210 } else {
211 changed = 0;
212 }
213 if (changed) {
214 task->shownPage = task->page;
215 if (w->info[0] != NULL) {
216 w->info[0]->setState(w->info[0], 2);
217 w->info[1] = FIGHTSTG_createPartnerInfo(task->partner, task->page, task->digimon);
218 } else {
219 if (w->info[1] != NULL) {
220 w->info[1]->setState(w->info[1], 2);
221 }
222 w->info[0] = FIGHTSTG_createPartnerInfo(task->partner, task->page, task->digimon);
223 }
224 }
225}
226
227/* The switch-in menu's task: L1 and R1 turn the PartnerInfo's page, cross
228 picks the Digimon, then switching (not with flag 0x10 on either fighter)
229 or the pair technique (with the MP, HP and none of flag 0x20 or sleep),
230 which spends both fighters' MP; triangle goes back a step */
232 s32 pressed;
233
234 switch (task->state) {
235 case TASK_INIT:
236 default:
237 listSwitchInDigimon(task, w);
238 task->nextState(task);
239 /* fallthrough */
240 case TASK_RUN:
241 switch (task->substate) {
242 case 0:
243 default:
244 switch (task->step) {
245 case 0:
246 default:
248 w->cursor->sel = task->digimon;
249 if (w->techCursor != NULL) {
250 w->techCursor->setState(w->techCursor, 3);
251 }
252 task->nextStep(task);
253 break;
254 case 1:
255 /* the match depends on the do-while and its breaks, the stages' early
256 exit, here and in the technique menu below */
257 do {
258 pressed = PAD.getPressed(0);
259 if (pressed & (1 << PAD_TRIANGLE)) {
261 *task->result = -2;
262 task->setState(task, 3);
263 break;
264 }
265 if (pressed & (1 << PAD_CROSS)) {
267 task->nextSubstate(task);
268 FIGHTSTG_showSwitchInNames(task, w, 0);
269 w->cursor->locked = 1;
270 break;
271 }
272 if (pressed & (1 << PAD_R1)) {
273 if (++task->page == 3) {
274 task->page = 0;
275 }
277 break;
278 }
279 if (pressed & (1 << PAD_L1)) {
280 if (--task->page < 0) {
281 task->page = 2;
282 }
284 break;
285 }
286 FIGHTSTG_showSwitchInNames(task, w, 1);
288 } while (0);
289 break;
290 }
291 break;
292 case 1:
293 switch (task->step) {
294 case 0:
295 default:
296 findPairTech(task);
297 /* the match depends on the ?: (an if/else gives 23 diffs) */
298 FIGHTSTG_pairCursors[1].count = task->tech != 0 ? 2 : 1;
300 if (w->cursor != NULL) {
301 w->cursor->setState(w->cursor, 3);
302 }
303 task->nextStep(task);
304 break;
305 case 1:
306 do {
307 pressed = PAD.getPressed(0);
308 if (pressed & (1 << PAD_CROSS)) {
309 confirmSwitchIn(task, w);
310 break;
311 }
312 if (pressed & (1 << PAD_TRIANGLE)) {
314 task->setSubstate(task, 0);
316 break;
317 }
318 if (pressed & (1 << PAD_R1)) {
319 if (++task->page == 3) {
320 task->page = 0;
321 }
323 break;
324 }
325 if (pressed & (1 << PAD_L1)) {
326 if (--task->page < 0) {
327 task->page = 2;
328 }
330 break;
331 }
332 FIGHTSTG_showSwitchInNames(task, w, 0);
334 } while (0);
335 break;
336 }
338 break;
339 }
340 updatePartnerInfoPage(task, w);
341 break;
342 case 2:
343 case 3:
344 break;
345 }
346}
347
348/* Opens the switch-in menu for fighter *result, without the pair technique */
351
352 task->result = result;
353 task->fighter = *result;
354 task->partner = GAME.funcs.getPartyMember(*result);
355 *result = -1;
356 return task;
357}
358
359/* Opens the switch-in menu for fighter *result, with the pair technique,
360 which goes into *techResult */
363
364 task->techResult = techResult;
365 return task;
366}
Battle FIGHTSTG_battle
the battle: its fighters, speed and drawing functions
Definition battle.c:16
#define FIGHTER_NO_SWITCH
can't switch out or run away (TECH_EFFECT_NO_SWITCH)
Definition battle.h:186
#define FIGHTER_NO_DIGIVOLVE
can't digivolve or use a switch-in technique (TECH_EFFECT_NO_DIGIVOLVE)
Definition battle.h:187
#define FIGHTER_ASLEEP
can't act or run away; a hit may wake it up
Definition battle.h:185
MenuCursor * FIGHTSTG_createCursor(CursorLayout *layout)
Creates a menu cursor laid out by layout.
Definition cursor.c:136
#define BATTLE_LAYER_MENUS
the HUD, the menus and the messages
Definition types.h:31
FIGHTSTG.PRO: the battle.
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
DigimonData DIGIMON_DATA[55]
55 entries: the 52 Digimon, then three placeholders (0x1D4-0x1D6)
Definition digimon.c:7
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_FILE(file)
Definition file.h:190
#define TEXT_DIGIMON_NAMES
DIGNAM.
Definition file.h:211
#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
FileCache FILE_CACHE
The file cache.
Definition file_cache.c:7
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
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
PartnerInfo * FIGHTSTG_createPartnerInfo(s32 partner, s32 page, s32 slot)
Shows page page about the partner in slot (0 for itself)
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 flags
FIGHTER_*.
Definition battle.h:204
u8 temporary
id is a temporary Digimon
Definition battle.h:202
s16 id
the Digimon (DIGIMON_DATA)
Definition battle.h:192
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
A menu cursor's layout, which FIGHTSTG_createCursor copies into its task: a highlight bar over count ...
Definition menu.h:288
s32 count
Definition menu.h:289
Digimon definition (DIGIMON_DATA, 52 of them; the first 8 are the partners)
Definition game_state.h:86
u8 nameId
string in file 0x4F
Definition game_state.h:105
u8 pairPartner
the Digimon (from 1) it does pairTech with, 0 for none
Definition game_state.h:96
u16 pairTech
its pair technique, with pairPartner
Definition game_state.h:91
void *(* load)(u32 file)
Definition file.h:92
void *(* getEntry)(u32 fileAndIndex)
Definition file.h:96
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 sel
Definition menu.h:304
void(* setState)(struct MenuCursor *task, s32 state)
Definition menu.h:303
s32 locked
Definition menu.h:305
s32(* getPressed)(s32 pad)
Definition pad.h:125
void(* setState)(struct PartnerInfo *task, s32 state)
Definition menu.h:201
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_updateSwitchInMenu's children.
Definition menu.h:126
TextWindow * mp[4]
"MP", the active fighter's, "/", its max
Definition menu.h:132
TextWindow * names[4]
Definition menu.h:130
TextWindow * choices[5]
switching (text 0x1B), the pair technique (0x1C), "MP", its MP and the Digimon's name
Definition menu.h:131
struct MenuCursor * cursor
Definition menu.h:127
struct PartnerInfo * info[2]
shown and hiding, in turns
Definition menu.h:129
struct MenuCursor * techCursor
Definition menu.h:128
The menu after the switch menu (FIGHTSTG_createSwitchInMenu): which of the incoming partner's Digimon...
Definition menu.h:110
s32 partner
its party member
Definition menu.h:116
s32 * result
-1 until it is done, then the Digimon << 4 | 0 to switch or 1 for the pair technique,...
Definition menu.h:112
s16 ids[4]
the partner, then its digivolutions (slots of 3 or more)
Definition menu.h:118
s32 fighter
the incoming one, *result when it was made
Definition menu.h:115
s32 state
Definition menu.h:111
void(* setState)(struct SwitchInMenu *task, s32 state)
Definition menu.h:111
void(* setSubstate)(struct SwitchInMenu *task, s32 substate)
Definition menu.h:111
s32 digimon
the line of ids picked
Definition menu.h:117
s32 count
Definition menu.h:119
void(* nextStep)(struct SwitchInMenu *task)
Definition menu.h:111
s32 * techResult
gets the technique picked
Definition menu.h:122
s32 step
Definition menu.h:111
s32 shownPage
Definition menu.h:114
s16 slots[4]
GAME.funcs.getPartnerSlots's.
Definition menu.h:120
s32 tech
the pair technique, from 1, 0 for none
Definition menu.h:121
void(* nextSubstate)(struct SwitchInMenu *task)
Definition menu.h:111
s32 substate
Definition menu.h:111
void(* nextState)(struct SwitchInMenu *task)
Definition menu.h:111
s32 page
the PartnerInfo page, 0-2
Definition menu.h:113
u16 mp
its cost
Definition game_state.h:111
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
static void updatePartnerInfoPage(SwitchInMenu *task, SwitchInMenuWindows *w)
Shows the PartnerInfo page again when the page or the chosen Digimon changed, closing the shown one.
void FIGHTSTG_showSwitchInChoices(SwitchInMenu *task, SwitchInMenuWindows *w, s32 visible)
Shows the picked Digimon's name and the choices, switching in palette 7 when flag 0x10 bars it and th...
static void findPairTech(SwitchInMenu *task)
Sets the pair technique of the active fighter's Digimon with the chosen one, 0 for none (a temporary ...
void FIGHTSTG_drawSwitchInMenu(SwitchInMenu *task)
Draws the switch-in menu's frames, the second one with the pair technique.
static void confirmSwitchIn(SwitchInMenu *task, SwitchInMenuWindows *w)
Confirms the switch (unless either fighter has FIGHTER_NO_SWITCH) or the pair technique,...
SwitchInMenu * FIGHTSTG_createSwitchInMenu(s32 *result)
Opens the switch-in menu for fighter *result, without the pair technique.
SwitchInMenu * FIGHTSTG_createPairSwitchMenu(s32 *result, s32 *techResult)
Opens the switch-in menu for fighter *result, with the pair technique, which goes into *techResult.
void FIGHTSTG_updateSwitchInMenu(SwitchInMenu *task, SwitchInMenuWindows *w)
The switch-in menu's task: L1 and R1 turn the PartnerInfo's page, cross picks the Digimon,...
s32 FIGHTSTG_mpWindowX[4]
the x of FIGHTSTG_createSwitchInWindows's MP windows
void FIGHTSTG_createSwitchInWindows(SwitchInMenu *task, SwitchInMenuWindows *w)
Makes the switch-in menu's windows: the four names, the choices and the MP.
void FIGHTSTG_showSwitchInNames(SwitchInMenu *task, SwitchInMenuWindows *w, s32 visible)
Shows the names of the incoming partner's Digimon, or hides them.
CursorLayout FIGHTSTG_pairCursors[2]
the cursors of FIGHTSTG_updateSwitchInMenu's two steps
static void listSwitchInDigimon(SwitchInMenu *task, SwitchInMenuWindows *w)
Lists the partner and the Digimon in its slots, and makes the menu's windows.
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
#define PALETTE_WHITE
The text windows' palettes (TextWindow.palette, setPalette): rows of the font's CLUTs,...
Definition text.h:112
#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)