Alchemy
Loading...
Searching...
No Matches

djinn_preview.c

Go to the documentation of this file.
1/// @file
2/// Previewing a Djinn change before it is made, the chosen member's status,
3/// and the checks that keep the members' Djinn counts even.
4/// Part of menu.c, the menu object, compiled only through it.
5
6#include "../menu_internal.h"
7
8/// Previews a give, trade, set or standby change without committing it.
9/// It saves and restores the unit records before polling for confirmation.
11 struct DjinnMenuWork *menu;
12 struct DjinnMenuBackdrop *backdrop;
13 struct UiRenderWork *render;
14 struct UiWindow *list;
15 s32 pageCounts[2];
16 s32 selectedPages[2];
17 s32 confirmationChoice;
18 u32 redraw;
19 s32 frame;
20 s32 page;
21 s32 previewMode;
22 s32 addPairSlot;
23 s32 step;
24 s32 row;
25 s32 result;
26 s32 zero;
27 s32 index;
28 s32 ownerIndex;
29
30 menu = gMenuWork;
31 confirmationChoice = 0;
32 result = 0;
33 redraw = 1;
34 frame = 0;
35 selectedPages[0] = 0;
36 page = 2;
37 menu->cursor->active = ICON_HIDDEN;
38 selectedPages[1] = 0;
39
40 for (ownerIndex = 3; ownerIndex >= 0; ownerIndex--) {
41 menu->ownerY[ownerIndex] = 0xc8;
42 }
43 menu->ownerX[menu->selectedColumn[1]] = 0x78;
44 menu->ownerY[menu->selectedColumn[1]] = 0x20;
45 menu->ownerX[menu->selectedColumn[0]] = 0x10;
46 menu->ownerY[menu->selectedColumn[0]] = 0x20;
47
49 WaitFrames(1);
51 UiWindow_UpdateOrCreate(&menu->helpWindow, 0, 0, 30, 5, 2);
52
53 pageCounts[0] = 1;
54 pageCounts[1] = 1;
55
56 // Measure the action-list pages using temporary unit mutations.
57 if (mode <= DJINN_COMPARE_GIVE) {
58 u16 *diffWork;
59 struct BattleUnit *originalUnit;
60 struct BattleUnit *unit;
61 s32 ownerId;
62 s32 firstElement;
63 s32 firstIndex;
64 s32 secondElement;
65 s32 secondIndex;
66 s32 firstWasSet;
67 s32 secondWasSet;
68 s32 lostCount;
69 s32 gainedCount;
70 s32 size;
71
73 size = sizeof(*originalUnit);
74 originalUnit = Runtime_BumpAllocateAlternatePool(size);
75 secondElement = 0;
76 secondIndex = 0;
77 ownerId = menu->shownOwner[0];
78 firstElement = menu->pairElement[0];
79 firstIndex = menu->pairIndex[0] & 31;
80 firstWasSet = (u16)(menu->pairEntries[0] & DJINN_ENTRY_IS_SET);
81
82 unit = UnitGetFar(ownerId);
83 Iwram_CopyWords(originalUnit, unit, size);
84 Djinn_DeactivateFar(ownerId, firstElement, firstIndex);
85 if (mode == DJINN_COMPARE_TRADE) {
86 secondElement = menu->pairElement[1];
87 secondIndex = menu->pairIndex[1] & 31;
88 secondWasSet = (u16)(menu->pairEntries[1] & DJINN_ENTRY_IS_SET);
89 Djinn_AddToOwnerFar(ownerId, secondElement, secondIndex);
90 if (secondWasSet != 0) {
91 Djinn_ActivateFar(ownerId, secondElement, secondIndex);
92 }
93 }
94 UnitCalcFar(ownerId);
95 pageCounts[0] =
97 diffWork, &gainedCount, &lostCount);
98 Iwram_CopyWords(unit, originalUnit, size);
99
100 ownerId = menu->shownOwner[1];
101 unit = UnitGetFar(ownerId);
102 Iwram_CopyWords(originalUnit, unit, size);
103 if (mode == DJINN_COMPARE_TRADE) {
104 Djinn_DeactivateFar(ownerId, secondElement, secondIndex);
105 }
106 Djinn_AddToOwnerFar(ownerId, firstElement, firstIndex);
107 if (firstWasSet != 0) {
108 Djinn_ActivateFar(ownerId, firstElement, firstIndex);
109 }
110 UnitCalcFar(ownerId);
111 pageCounts[1] =
112 OwnerAction_DiffSlots(originalUnit->actionSlots, unit->actionSlots,
113 diffWork, &gainedCount, &lostCount);
114 Iwram_CopyWords(unit, originalUnit, size);
115 MemFree(originalUnit);
116 MemFree(diffWork);
117 } else if (mode - 2 <= 1) {
118 u16 *diffWork;
119 struct BattleUnit *originalUnit;
120 struct BattleUnit *unit;
121 s32 firstOwnerId;
122 s32 firstElement;
123 s32 firstIndex;
124 s32 applySecond;
125 s32 lostCount;
126 s32 gainedCount;
127
129 originalUnit = Runtime_BumpAllocateAlternatePool(sizeof(*originalUnit));
130 firstOwnerId = menu->shownOwner[0];
131 firstElement = menu->pairElement[0];
132 firstIndex = menu->pairIndex[0] & 31;
133 applySecond = (mode == DJINN_COMPARE_SET);
134
135 unit = UnitGetFar(firstOwnerId);
136 Iwram_CopyWords(originalUnit, unit, sizeof(*originalUnit));
137 Djinn_DeactivateFar(firstOwnerId, firstElement, firstIndex);
138 if (applySecond != 0) {
139 Djinn_ActivateFar(firstOwnerId, firstElement, firstIndex);
140 }
141 UnitCalcFar(firstOwnerId);
142 pageCounts[0] =
143 OwnerAction_DiffSlots(originalUnit->actionSlots, unit->actionSlots,
144 diffWork, &gainedCount, &lostCount);
145 Iwram_CopyWords(unit, originalUnit, sizeof(*originalUnit));
146 pageCounts[1] = pageCounts[0];
147 page = 0;
148 MemFree(originalUnit);
149 MemFree(diffWork);
150 }
151
152 pageCounts[0] = ((pageCounts[0] - 1) / 5) + 1;
153 if (pageCounts[0] == 0) {
154 pageCounts[0] = 1;
155 }
156 pageCounts[1] = ((pageCounts[1] - 1) / 5) + 1;
157 if (pageCounts[1] == 0) {
158 pageCounts[1] = 1;
159 }
160
161 // Open the paired panes only after both unit records have been restored.
162 UiWindow_UpdateOrCreate(&menu->window, 0, 5, 15, 15, 2);
163 UiWindow_UpdateOrCreate(&menu->secondWindow, 15, 5, 15, 15, 2);
165
166 if (mode == DJINN_COMPARE_STANDBY) {
167 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareStandby, menu->helpWindow,
168 96, 0);
169 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareConfirm, menu->helpWindow,
170 96, 16);
171 } else if (mode == DJINN_COMPARE_SET) {
172 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareSet, menu->helpWindow, 96,
173 0);
174 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareConfirm, menu->helpWindow,
175 96, 16);
176 } else if (mode == DJINN_COMPARE_TRADE) {
177 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareTrade, menu->helpWindow, 128,
178 0);
179 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareConfirm, menu->helpWindow,
180 128, 8);
181 } else {
182 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareGive, menu->helpWindow, 128,
183 0);
184 UiText_DrawCharacterAtOffsetFar(MsgDjinnCompareConfirm, menu->helpWindow,
185 128, 8);
186 }
187
188 row = (mode == DJINN_COMPARE_GIVE);
189 if ((menu->pairEntries[0] & DJINN_ENTRY_IS_SET) == 0) {
191 }
192 UiText_DrawCharacterAtOffsetFar(((menu->pairEntries[0] & 0xe0) >> 5) * 20 +
193 (menu->pairEntries[0] & 31) +
194 MsgDjinnName,
195 menu->helpWindow, 48, row * 8);
197 ((menu->pairEntries[0] & 0xe0) >> 5) + 0x5001, 5,
198 row, zero = 0);
200
201 if (mode == DJINN_COMPARE_TRADE) {
202 if ((menu->pairEntries[1] & DJINN_ENTRY_IS_SET) == 0) {
204 }
205 UiText_DrawCharacterAtOffsetFar(((menu->pairEntries[1] & 0xe0) >> 5) * 20 +
206 (menu->pairEntries[1] & 31) +
207 MsgDjinnName,
208 menu->helpWindow, 48, 16);
210 ((menu->pairEntries[1] & 0xe0) >> 5) + 0x5001,
211 5, 2, mode);
213 } else if (mode - 2 <= 1) {
214 if ((menu->pairEntries[0] & DJINN_ENTRY_IS_SET) != 0) {
216 }
217 UiText_DrawCharacterAtOffsetFar(((menu->pairEntries[0] & 0xe0) >> 5) * 20 +
218 (menu->pairEntries[0] & 31) +
219 MsgDjinnName,
220 menu->helpWindow, 48, 16);
222 ((menu->pairEntries[0] & 0xe0) >> 5) + 0x5001,
223 5, 2, zero);
225 UiWindow_SetTilemapEntryFar(menu->helpWindow, 0xf296, 7, 1, zero);
226 }
227
228 for (;;) {
229 s32 pressedKeys;
230 s32 repeatedKeys;
231
232 render = (struct UiRenderWork *)gWindowWork[0];
233 backdrop = menu->backdrop;
234 pressedKeys = gKeysPressed;
235 repeatedKeys = gKeysRepeat;
236
237 if (backdrop->tutorialStep != 0) {
238 s16 *saved;
239 s32 size;
240
241 size = 0x200;
243 pressedKeys = 0;
244 repeatedKeys = 0;
245 backdrop->tutorialTimer += 1;
246
247 switch (backdrop->tutorialStep) {
248 case 5:
249 case 12:
250 case 23:
251 if (backdrop->tutorialTimer == 100) {
252 repeatedKeys = 1;
253 pressedKeys = 1;
254 backdrop->tutorialTimer = 0;
255 backdrop->tutorialStep += 1;
256 }
257 break;
258 case 10:
259 if (backdrop->tutorialTimer == 60) {
260 struct UiWindow *work;
261
262 Iwram_CopyWords(saved, render, size);
263 work =
264 UiText_OpenMessageWindowFar(MsgDjinnTutorialSetChanges, 8, 0, 1);
265 /* FAKEMATCH(one-pass): the cursor's store in a one-pass block, which
266 * keeps the window copy before it as the ROM does; as a plain
267 * statement, 11 of 1045 instructions differ in tbs-en. */
268 do {
269 menu->cursor->active = ICON_SHOWN;
270 } while (0);
271 UiMenu_SlideCursor(2, 96);
273 while (UiWork_IsCompleteFar() == 0) {
274 WaitFrames(1);
275 }
276 UiWork_FinalizeFar(work, 1);
277 Iwram_CopyWords(render, saved, size);
279 render->dirty = 1;
280 redraw = 1;
281 backdrop->tutorialTimer = 0;
282 backdrop->tutorialStep = 11;
283 /* FAKEMATCH(one-pass): the cursor's store in a one-pass block, which
284 * keeps the step's store before it as the ROM does; as a plain
285 * statement, 6 of 1045 instructions differ in tbs-en. */
286 do {
287 menu->cursor->active = ICON_HIDDEN;
288 } while (0);
289 }
290 break;
291 case 11:
292 if (backdrop->tutorialTimer == 60) {
293 struct UiWindow *work;
294
295 Iwram_CopyWords(saved, render, size);
296 work = UiText_OpenMessageWindowFar(MsgDjinnTutorialClassPsynergy, 8,
297 0, 1);
298 /* FAKEMATCH(one-pass): the cursor's store in a one-pass block, which
299 * keeps the window copy before it as the ROM does; as a plain
300 * statement, 13 of 1045 instructions differ in tbs-en. */
301 do {
302 menu->cursor->active = ICON_SHOWN;
303 } while (0);
304 UiMenu_SlideCursor(106, 56);
306 while (UiWork_IsCompleteFar() == 0) {
307 WaitFrames(1);
308 }
309 UiWork_FinalizeFar(work, 1);
310 Iwram_CopyWords(render, saved, size);
312 render->dirty = 1;
313 WaitFrames(1);
314 redraw = 1;
315 backdrop->tutorialTimer = 0;
316 backdrop->tutorialStep = 12;
317 /* FAKEMATCH(one-pass): the cursor's store in a one-pass block, which
318 * keeps the step's store before it as the ROM does; as a plain
319 * statement, 5 of 1045 instructions differ in tbs-en. */
320 do {
321 menu->cursor->active = ICON_HIDDEN;
322 } while (0);
323 }
324 break;
325 default:
326 break;
327 }
328 MemFree(saved);
329 }
330
331 if (redraw != 0) {
332 addPairSlot = 1;
333 if (mode <= DJINN_COMPARE_GIVE) {
334 UiWindow_ClearInteriorTilesFar(menu->helpWindow, 128, 16, 224, 24);
335 if (page == 1) {
336 UiText_DrawCharacterAtOffsetFar(MsgDjinnStatusHelp, menu->helpWindow,
337 128, 16);
338 } else {
339 UiWork_PushValueSlotFar(menu->shownOwner[page != 2], 1);
340 UiText_DrawCharacterAtOffsetFar(MsgDjinnPsyHelp, menu->helpWindow,
341 128, 16);
342 }
343 }
344 render->menuBusy = 1;
347 if ((redraw >> 1) != 0) {
348 WaitFrames(1);
349 }
350
351 if (mode == DJINN_COMPARE_SET) {
352 previewMode = 0;
353 addPairSlot = 0;
354 } else if (mode == DJINN_COMPARE_STANDBY) {
355 previewMode = 1;
356 addPairSlot = 0;
357 } else {
358 previewMode = 2;
359 }
360
361 switch (page) {
362 default:
364 break;
365 case 1:
366 if (mode == DJINN_COMPARE_GIVE) {
367 previewMode = 4;
368 }
369 DjinnMenu_DrawStatPreview(menu->window, 0, 0, menu->shownOwner[1], page,
370 0, previewMode, 0, 0);
372 page, 0, previewMode, selectedPages[1] + 1,
373 0);
374 break;
375 case 0:
376 if (mode == DJINN_COMPARE_GIVE) {
377 previewMode = 1;
378 addPairSlot = 0;
379 }
380 DjinnMenu_DrawStatPreview(menu->window, 0, 0, menu->pairOwner[0], page,
381 addPairSlot, previewMode, page, 1);
383 page, addPairSlot, previewMode,
384 selectedPages[0] + 1, 1);
385 break;
386 }
387 render->menuBusy = 0;
388 }
389
390 if (page <= 1) {
391 list = menu->secondWindow;
392 if (pageCounts[page] > 1) {
393 s32 top;
394
395 for (index = 0; index < pageCounts[page]; index++) {
396 s32 tile;
397
398 tile = 0xf031 + index;
399 if (index > 9) {
400 tile = 0xf030;
401 }
402 if (index == selectedPages[page]) {
403 tile -= 0x1000;
404 }
406 list, tile, list->width - pageCounts[page] + index - 2, -1, 0);
407 }
408 top = -1;
410 list->width - pageCounts[page] - 3, top, 0);
412 top, 0);
413 UiRender_MarkRow(render, list->y);
414 }
415 }
416
417 frame++;
418 step = (frame % 60) - 5;
419 if (step < 0) {
420 step = 0;
421 }
422 if (step > 29) {
423 step = 29;
424 }
425 FourObjectMotion_SetSlotPhase(0, 0xffff4000);
426 FourObjectMotion_SetSlotPhase(1, 0xffff4000);
427
428 if (mode <= DJINN_COMPARE_GIVE) {
429 s32 rise;
430 s32 slide;
431
432 rise = -Iwram_MulQ16(16, Trig_Sin((step % 30) * 0x444));
433 if (rise < -6) {
434 rise = -6;
435 }
436 if (rise > 12) {
437 rise = 12;
438 }
439 slide = (step % 35) * 2;
440 FourObjectMotion_SetSlotPosition(0, slide + 34, rise + 20, 0);
441 if (mode == DJINN_COMPARE_TRADE) {
442 FourObjectMotion_SetSlotPosition(1, 99 - slide, 36 - rise, 0);
443 }
444 } else {
446 }
447
448 if (redraw != 0) {
449 redraw = 0;
450 confirmationChoice = Menu_WrapIndex(confirmationChoice, 2);
451 }
452 UiMenu_PositionCursor(confirmationChoice * 56 + 80, 16);
453
454 if ((frame & 3) == 0) {
455 void *tile;
456 u32 fill;
457
458 tile = (void *)0x060052c0;
459 fill = 0x44444444;
460 if ((frame & 4) != 0) {
462 } else {
463 Iwram_FillWords(tile, 32, fill);
464 }
465 }
466
467 if ((pressedKeys & KEY_A) != 0) {
468 if (confirmationChoice == 0) {
469 result = 1;
470 break;
471 }
473 result = -1;
474 break;
475 }
476 if ((pressedKeys & KEY_START) != 0) {
478 result = -2;
479 break;
480 } else if ((pressedKeys & KEY_B) != 0) {
482 result = -1;
483 break;
484 } else if ((pressedKeys & KEY_R) != 0) {
485 if (mode <= DJINN_COMPARE_GIVE) {
486 page = ((page + 1) % 3);
487 redraw = 2;
489 }
490 } else if ((repeatedKeys & KEY_LEFT) != 0) {
491 if (page <= 1) {
492 selectedPages[page]--;
493 selectedPages[page] =
494 Menu_WrapIndex(selectedPages[page], pageCounts[page]);
497 redraw = 1;
498 }
499 } else if ((repeatedKeys & KEY_RIGHT) != 0) {
500 if (page <= 1) {
503 selectedPages[page]++;
504 redraw = 1;
505 selectedPages[page] =
506 Menu_WrapIndex(selectedPages[page], pageCounts[page]);
507 }
508 }
509 WaitFrames(1);
510 }
511
512 // Restore the ordinary list drawing tasks and close the preview panes.
516
517 ((struct UiRenderWork *)gWindowWork[0])->menuBusy = 1;
519 WaitFrames(1);
520 UiWindow_UpdateOrCreate(&menu->helpWindow, 13, 0, 17, 5, 2);
521 UiWindow_CloseIfOpen((struct UiWindow **)&menu->window, 1);
526 ((struct UiRenderWork *)gWindowWork[0])->menuBusy = 0;
527 WaitFrames(1);
528 return result;
529}
530
531/// Shows the chosen owner's current stats and paged Psynergy list.
533 s32 selectedPages[2];
534 s32 pageCounts[2];
535 s32 gained;
536 s32 lost;
537 s32 phase;
538 s32 redraw;
539 s32 frame;
540 struct UiWindow **leftWindowSlot;
541 struct UiWindow **rightWindowSlot;
542 struct UiRenderWork *render;
543 u32 pressedKeys;
544 u32 repeatedKeys;
545 struct DjinnMenuWork *menu;
546 struct BattleUnit *unit;
547 struct UiWindow *window;
548 u16 *listedActions;
549 void *saved;
550 s32 result;
551 s32 tile;
552 s32 pageIndex;
553 s32 side;
554 s32 *counts;
555 s32 blink;
556
557 menu = gMenuWork;
558 phase = 0;
559 redraw = 1;
560 result = 0;
561 frame = 0;
562 menu->cursor->active = ICON_HIDDEN;
563 selectedPages[1] = selectedPages[0] = result;
564 for (side = 3; side >= 0; side--)
565 menu->ownerY[side] = 200;
567 WaitFrames(1);
568 counts = pageCounts;
569 counts[1] = counts[0] = 1;
570 listedActions = Runtime_BumpAllocateAlternatePool(96);
572 unit = UnitGetFar(menu->shownOwner[0]);
573 counts[1] = counts[0] = OwnerAction_DiffSlots(
574 unit->actionSlots, unit->actionSlots, listedActions, &gained, &lost);
575 MemFree(saved);
576 MemFree(listedActions);
577 counts[0] = (counts[0] - 1) / 6 + 1;
578 if (counts[0] == 0)
579 counts[0] = 1;
580 counts[1] = (counts[1] - 1) / 6 + 1;
581 if (counts[1] == 0)
582 counts[1] = 1;
583 leftWindowSlot = (struct UiWindow **)&menu->window;
584 UiWindow_UpdateOrCreate(leftWindowSlot, 0, 5, 15, 15, 2);
585 rightWindowSlot = &menu->secondWindow;
586 UiWindow_UpdateOrCreate(rightWindowSlot, 15, 5, 15, 15, 2);
589 UiText_DrawCharacterAtOffsetFar(MsgCurrentStatus, menu->statusWindow, 0, 0);
590 UiText_DrawCharacterAtOffsetFar(MsgCurrentStatus + 2, menu->statusWindow, 0,
591 16);
592 side = 0;
593 while (1) {
594 render = (struct UiRenderWork *)gWindowWork[0];
595 pressedKeys = gKeysPressed;
596 repeatedKeys = gKeysRepeat;
597 if (redraw) {
598 render->menuBusy = 1;
601 DjinnMenu_DrawStatPreview(menu->window, 0, 0, menu->pairOwner[0], 0, 0, 3,
602 0, 1);
603 DjinnMenu_DrawStatPreview(menu->secondWindow, 0, 0, menu->pairOwner[0], 0,
604 0, 3, selectedPages[0] + 1, 1);
605 render->menuBusy = 0;
606 }
607 if (counts[side] > 1) {
608 window = menu->secondWindow;
609 for (pageIndex = 0; pageIndex < counts[side]; pageIndex++) {
610 tile = 0xf031 + pageIndex;
611 if (pageIndex > 9)
612 tile = 0xf030;
613 if (pageIndex == selectedPages[side])
614 tile -= 0x1000;
616 window, tile, window->width - counts[side] + pageIndex - 2, -1, 0);
617 }
619 window->width - counts[side] - 3, -1, 0);
621 window->width - 2, -1, 0);
622 UiRender_MarkRow(render, window->y);
623 }
624 frame++;
625 blink = frame % 60 - 5;
626 CLAMP(blink, 0, 29);
628 if (redraw) {
629 redraw = 0;
630 phase = Menu_WrapIndex(phase, 2);
631 }
632 if ((frame & 3) == 0) {
633 if (frame & 4)
634 Iwram_CopyWords((void *)0x060052c0, gMenu_BackdropFrameTile, 32);
635 else
636 Iwram_FillWords((void *)0x060052c0, 32, 0x44444444);
637 }
638 if (pressedKeys & KEY_START) {
640 result = -2;
641 break;
642 }
643 if (pressedKeys & (KEY_A | KEY_B | KEY_R | KEY_L)) {
645 result = -1;
646 break;
647 }
648 if (repeatedKeys & KEY_LEFT) {
649 selectedPages[side]--;
650 selectedPages[side] = Menu_WrapIndex(selectedPages[side], counts[side]);
653 redraw = 1;
654 } else if (repeatedKeys & KEY_RIGHT) {
655 selectedPages[side]++;
658 redraw = 1;
659 selectedPages[side] = Menu_WrapIndex(selectedPages[side], counts[side]);
660 }
661 WaitFrames(1);
662 }
664 ((struct UiRenderWork *)gWindowWork[0])->menuBusy = 1;
666 WaitFrames(1);
667 UiWindow_UpdateOrCreate(&menu->helpWindow, 13, 0, 17, 5, 2);
668 UiWindow_CloseIfOpen(leftWindowSlot, 1);
669 UiWindow_CloseIfOpen(rightWindowSlot, 1);
673 ((struct UiRenderWork *)gWindowWork[0])->menuBusy = 0;
674 WaitFrames(1);
675 return result;
676}
677
678/// Marks recipients that would leave unequal Djinn totals after a direct give.
679/// Returns how many recipients would need a trade instead.
680s32 Djinn_MarkBalancedEntries(s8 *requiresTrade, s32 sourceOwnerColumn) {
681 s32 tradeCount;
682 s32 ownerColumn;
683 s8 *entry;
684 struct DjinnMenuWork *menu;
685
686 menu = gMenuWork;
687 tradeCount = 0;
688 ownerColumn = 0;
689 if (tradeCount < menu->ownerCount) {
690 entry = requiresTrade;
691 do {
692 *entry = 0;
693 if (ownerColumn != sourceOwnerColumn) {
694 if (Djinn_CheckTurnBalance(sourceOwnerColumn, ownerColumn) == 0) {
695 *entry = 1;
696 tradeCount += 1;
697 }
698 }
699 ownerColumn += 1;
700 entry += 1;
701 } while (ownerColumn < menu->ownerCount);
702 }
703 return tradeCount;
704}
705
706/// Tests whether a hypothetical give leaves every pair of owners within one
707/// Djinn.
708s32 Djinn_CheckTurnBalance(s32 sourceOwnerColumn, s32 targetOwnerColumn) {
709 struct DjinnMenuWork *menu;
710 s8 ownedCounts[16];
711 u8 firstOwner;
712 u8 secondOwner;
713 s32 difference;
714 s32 balanced;
715
716 menu = gMenuWork;
717 Djinn_CountTurns((u8 *)ownedCounts);
718 ownedCounts[sourceOwnerColumn] -= 1;
719 ownedCounts[targetOwnerColumn] += 1;
720 balanced = 1;
721 for (firstOwner = 0; firstOwner < menu->ownerCount; firstOwner++) {
722 secondOwner = firstOwner;
723 if (firstOwner < menu->ownerCount) {
724 while (1) {
725 secondOwner++;
726 if (secondOwner >= menu->ownerCount)
727 break;
728 difference = ownedCounts[firstOwner] - ownedCounts[secondOwner];
729 if (difference < -1 || difference > 1) {
730 balanced = 0;
731 break;
732 }
733 }
734 }
735 }
736 return balanced;
737}
738
739/// Counts each owner's Djinn across its set and available bitmasks.
740void Djinn_CountTurns(u8 *ownedCounts) {
741 struct DjinnMenuWork *menu;
742 struct BattleUnit *unit;
743 s32 ownerIndex;
744 s32 element;
745 s32 djinnIndex;
746 s32 ownedCount;
747
748 menu = gMenuWork;
749 for (ownerIndex = 0; ownerIndex < menu->ownerCount; ownerIndex++) {
750 unit = UnitGetFar(menu->owners[ownerIndex]);
751 ownedCount = 0;
752 for (element = 0; element <= 3; element++) {
753 for (djinnIndex = 0; djinnIndex <= 19; djinnIndex++) {
754 if (unit->djinnActive[element] & (1 << djinnIndex))
755 ownedCount++;
756 else if (unit->djinnAvailable[element] & (1 << djinnIndex))
757 ownedCount++;
758 }
759 }
760 ownedCounts[ownerIndex] = ownedCount;
761 }
762}
void UiMenu_SlideCursor(s32 x, s32 y)
Slides the hand cursor from where it is to (x, y) inside the menu's top-left window over two frames,...
Definition common.c:625
void Menu_UpdateEntryObjectTransforms(void)
Scheduler callback: each frame, places every party member sprite created by PsynergyMenu_InitializeEn...
Definition common.c:580
void UiMenu_PositionCursor(s32 xOffset, s32 yOffset)
Places the hand cursor at (xOffset, yOffset) inside the menu's top-left window, bobbing.
Definition common.c:611
void UiWindow_CloseIfOpen(struct UiWindow **handle, s32 style)
Closes the window kept in *handle, if any, and clears the handle.
Definition common.c:98
s32 UiWindow_UpdateOrCreate(struct UiWindow **handle, s32 x, s32 y, s32 w, s32 h, s32 flags)
Opens the window kept in *handle, or redraws it if it is already open.
Definition common.c:78
s32 FourObjectMotion_SetSlotPosition(s32 index, s32 x, s32 y, s32 negative)
Updates one object's saved position and its signed y marker.
s32 FourObjectMotion_SetSlotPhase(s32 index, s32 phase)
#define DJINN_ENTRY_IS_SET
Definition djinn_menu.h:15
struct BattleUnit * UnitGetFar(u32 owner)
u32 Djinn_DeactivateFar(s32 owner, s32 index, s32 bit)
s32 Djinn_AddToOwnerFar(s32 owner, s32 index, s32 bit)
s32 Djinn_ActivateFar(s32 owner, s32 index, s32 bit)
void UnitCalcFar(s32 owner)
void AudioCommand_PlayFar(s32 id)
void RenderOutput_PrepareForRedrawFar(struct UiWindow *window)
void UiWindow_MarkVisibleTileAttributesFar(void)
void RenderOutput_ClearListFar(void *work)
void UiWork_SetParamNibbleFar(s32 param)
void UiWindow_ClearInteriorTilesFar(const struct UiWindow *window, u32 left, u32 top, u32 right, u32 bottom)
void UiText_DrawCharacterAtOffsetFar(s32 character, const struct UiWindow *position, u32 offsetX, u32 offsetY)
void UiWork_FinalizeFar(struct UiWindow *work, s32 release)
void UiWork_PushValueSlotFar(u32 value, u32 kind)
s32 UiWork_IsCompleteFar(void)
void UiWindow_SetTilemapEntryFar(struct UiWindow *window, s32 value, s32 x, s32 y, u32 mode)
void RenderOutput_RedrawSavedRectFar(struct UiWindow *window)
struct UiWindow * UiText_OpenMessageWindowFar(s32 message, s32 x, s32 y, u32 packed)
s32 Trig_Sin(s32 angle)
void Input_ResetKeyRepeat(void)
Restarts the key repeat delay, so held keys wait the full delay again.
Definition frame.c:289
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_BumpAllocateAlternatePool(s32 size)
As MemAlloc, but tries EWRAM first.
Definition heap.c:140
@ KEY_B
Definition io_reg.h:244
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_START
Definition io_reg.h:246
@ KEY_RIGHT
Definition io_reg.h:247
@ KEY_R
Definition io_reg.h:251
@ KEY_A
Definition io_reg.h:243
@ KEY_L
Definition io_reg.h:252
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
Definition iwram_call.h:85
static s32 Iwram_FillWords(void *destination, s32 size, u32 value)
Definition iwram_call.h:59
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
volatile u32 gKeysPressed
Keys that went down this frame.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
#define CLAMP(v, low, high)
Keeps v within low to high, the low bound tested first.
Definition macros.h:23
void MemFree(void *buffer)
s32 Menu_WrapIndex(s32 value, s32 modulus)
Wraps a cursor index that has stepped one past either end of modulus entries: -1 becomes modulus - 1 ...
Definition djinn.c:47
s32 DjinnMenu_DrawStatPreview(struct UiWindow *window, s32 x, s32 y, s32 ownerId, s32 removePairSlot, s32 addPairSlot, s32 previewMode, s32 page, s32 side)
Saves the unit, applies a hypothetical Djinn change, draws its differences and restores the original ...
Definition djinn.c:1564
s32 OwnerAction_DiffSlots(struct OwnerActionSlot *before, struct OwnerActionSlot *after, u16 *actionsOut, s32 *gainedCountOut, s32 *lostCountOut)
Lists the actions after a preview, marking gains, then appends the losses.
Definition djinn.c:495
s32 DjinnMenu_DrawPairPreview(s32 mode, s32 pageIndex)
Draws both sides of the give or trade preview for the selected page.
Definition djinn.c:1538
s32 DjinnMenu_ShowOwnerStatus(void)
Shows the chosen owner's current stats and paged Psynergy list.
s32 Djinn_MarkBalancedEntries(s8 *requiresTrade, s32 sourceOwnerColumn)
Marks recipients that would leave unequal Djinn totals after a direct give.
void Djinn_CountTurns(u8 *ownedCounts)
Counts each owner's Djinn across its set and available bitmasks.
s32 OwnerAction_RunCompareLoop(u32 mode)
Previews a give, trade, set or standby change without committing it.
s32 Djinn_CheckTurnBalance(s32 sourceOwnerColumn, s32 targetOwnerColumn)
Tests whether a hypothetical give leaves every pair of owners within one Djinn.
const u8 gMenu_BackdropFrameTile[]
What every part of the menu object shares: its includes, and the macros and types more than one part ...
#define ICON_HIDDEN
#define ICON_SHOWN
RenderOutput.active as the menu sets it: shown, or hidden but kept.
#define TEXT_COLOR_NORMAL
@ DJINN_COMPARE_GIVE
@ DJINN_COMPARE_STANDBY
@ DJINN_COMPARE_TRADE
@ DJINN_COMPARE_SET
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
#define SE_MENU_CANCEL
Definition songs.h:106
#define SE_MENU_CURSOR_MOVE
Definition songs.h:104
u8 gWindowWork[]
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u32 djinnActive[4]
The Djinn set, one bit per Djinni; only these add their stat bonuses.
struct BattleElementStats element[4]
Power and resistance in each element, 0 to 200, after equipment, element levels and Resistance stages...
struct OwnerActionSlot actionSlots[32]
The action list: Psynergy taught for good, then the class's and the equipment's (Unit_RefreshPsynergy...
u32 djinnAvailable[4]
The Djinn held, one bit per Djinni (by its index) in each element's word.
The Djinn menu's lists, the field tiles and palette it restores on closing, and the tutorial's state.
Definition djinn_menu.h:30
long tutorialStep
The Djinn tutorial's step: 0 outside it, else 1, 14, 27 or 28 to start, by flags 0x16f and 0x171.
Definition djinn_menu.h:37
s32 tutorialTimer
frames into the tutorial's current step
Definition djinn_menu.h:34
The Djinn menu's work, in the HEAP_SLOT_MENU work slot.
Definition djinn_menu.h:41
struct UiWindow * listWindow
Definition djinn_menu.h:53
u16 pairEntries[2]
255 at first
Definition djinn_menu.h:62
struct UiWindow * secondWindow
Definition djinn_menu.h:54
struct DjinnMenuBackdrop * backdrop
Definition djinn_menu.h:65
u8 pairOwner[2]
not named by TBS code
Definition djinn_menu.h:83
struct RenderOutput * cursor
Definition djinn_menu.h:46
struct UiWindow * window
Definition djinn_menu.h:50
struct UiWindow * helpWindow
Definition djinn_menu.h:56
struct UiWindow * statusWindow
Definition djinn_menu.h:45
u16 owners[DJINN_LIST_OWNERS]
the party in order
Definition djinn_menu.h:67
s16 ownerX[8]
screen pixels
Definition djinn_menu.h:58
s8 selectedColumn[2]
each pane's member, in owners
Definition djinn_menu.h:48
u8 pairIndex[2]
The Djinn chosen in each pane: index in their element, element, owner.
Definition djinn_menu.h:81
u8 pairElement[2]
Definition djinn_menu.h:82
s16 ownerY[8]
screen pixels
Definition djinn_menu.h:59
struct UiWindow * unknownWindow028
Definition djinn_menu.h:51
u8 shownOwner[2]
the member giving and the one receiving
Definition djinn_menu.h:70
u8 messageSpeed
0 to 2; 1 on a new game
Definition game_state.h:66
s8 active
its UI_SPRITE_ motion; 0 while free
The window system's work: the windows' tilemap, the windows, the three text channels,...
Definition window.h:19
u8 dirty
The tilemap's 4-row bands to upload: bit 0 for all, bit n + 1 for band n.
Definition window.h:32
u8 menuBusy
while set, the tilemap is not uploaded
Definition window.h:40
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
Definition uiwindow.h:11
u16 frame
The zoom's step: counts down from 7 to 0 while opening, and up from 0 to duration while closing.
Definition uiwindow.h:28
u16 y
tiles
Definition uiwindow.h:16
u16 width
tiles
Definition uiwindow.h:13
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed char s8
Definition types.h:10
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
#define UiRender_MarkRow(render, y)
Requests transfer of the four-row tilemap band containing window row y.
Definition uiwindow.h:73
#define UI_PAGE_ARROW_RIGHT
Definition window.h:67
#define UI_PAGE_ARROW_LEFT
Definition window.h:66