Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
battle.c
Go to the documentation of this file.
1/* CARDGAME's card battle (CARDGAME_createBattle): the opponent, the deck
2 choice, the rounds, the plays and their results. */
3
5
6/* Loads the opponent's data (FILE_CARDGAME_OPPONENTS, entry arg - 1): its deck and its card order */
8 CardOpponent *opponent;
9 s32 i;
10
12 opponent = &battle->opponents[battle->arg - 1];
13 battle->opponentLevel = opponent->level;
14 battle->prize = CARDGAME_prizeItems[opponent->prize];
15 for (i = 0; i < 40; i++) {
16 battle->opponentDraws[i].order = i;
17 battle->opponentDraws[i].group = opponent->cards[i].group;
18 battle->opponentPlans[i].kind = opponent->cards[i].kind;
19 battle->opponentPlans[i].flagged = (opponent->cards[i].card & 0x8000) != 0;
20 switch (battle->opponentPlans[i].kind) {
21 case 1:
22 battle->opponentPlans[i].priority = i + 400;
23 break;
24 case 2:
25 battle->opponentPlans[i].priority = i + 300;
26 break;
27 case 3:
28 battle->opponentPlans[i].priority = i + 500;
29 break;
30 case 4:
31 battle->opponentPlans[i].priority = i + 200;
32 break;
33 case 5:
34 battle->opponentPlans[i].priority = i + 600;
35 break;
36 case 6:
37 battle->opponentPlans[i].priority = i + 100;
38 break;
39 case 7:
40 battle->opponentPlans[i].priority = i + 700;
41 break;
42 }
43 }
44 for (i = 0; i < 27; i++) {
45 if (opponent->counterCards[i] == 0) {
46 battle->counterCards[i] = 7;
47 battle->counterCards[i + 1] = 8;
48 battle->counterCards[i + 2] = 24;
49 battle->counterCards[i + 3] = 31;
50 battle->counterCards[i + 4] = 32;
51 battle->counterCards[i + 5] = 0;
52 battle->counterCards[i + 6] = 6;
53 battle->counterCards[i + 7] = 12;
54 battle->counterCards[i + 8] = 18;
55 battle->counterCards[i + 9] = 27;
56 battle->counterCards[i + 10] = 30;
57 battle->counterCards[i + 11] = 33;
58 battle->counterCards[i + 12] = 37;
59 battle->counterCards[i + 13] = 38;
60 battle->counterCards[i + 14] = 0xFF;
61 break;
62 }
63 battle->counterCards[i] = opponent->counterCards[i] - 1;
64 }
65 for (i = 0; i < 40; i++) {
66 battle->opponentDeck[i] = (opponent->cards[i].card & 0xFFF) - 1;
67 }
68}
69
70/* Sorts the opponent's hand by its cards' opponentPlans kind, then value */
72 s32 i;
73 s32 j;
74 s32 swap;
75 s32 card;
76 s32 ka;
77 s32 kb;
78 s32 va;
79 s32 vb;
80
81 for (i = 0; i < battle->sides[1].pile.handCount - 1; i++) {
82 swap = 0;
83 for (j = i + 1; j < battle->sides[1].pile.handCount; j++, swap = 0) {
84 ka = battle->opponentPlans[battle->sides[1].pile.hand[i] - 40].kind;
85 kb = battle->opponentPlans[battle->sides[1].pile.hand[j] - 40].kind;
86 va = battle->opponentPlans[battle->sides[1].pile.hand[i] - 40].priority;
87 vb = battle->opponentPlans[battle->sides[1].pile.hand[j] - 40].priority;
88 if (kb < ka || (ka == kb && vb < va)) {
89 swap = 1;
90 }
91 if (swap) {
92 card = battle->sides[1].pile.hand[i];
93 battle->sides[1].pile.hand[i] = battle->sides[1].pile.hand[j];
94 battle->sides[1].pile.hand[j] = card;
95 }
96 }
97 }
98}
99
100/* drawEnd: the first card of the opponent's deck above the round's level
101 (round); reserveStart: the end of its deck before the cards of kind 7 */
103 s32 i;
104
105 for (i = battle->sides[1].pile.deckTop; i < 40; i++) {
106 if (battle->round * 2 + 2 < battle->opponentDraws[i].group) {
107 break;
108 }
109 }
110 battle->drawEnd = i;
111 for (i = 40; i > 0; i--) {
112 if (battle->opponentDraws[i - 1].group != 7) {
113 break;
114 }
115 }
116 battle->reserveStart = i;
117}
118
119/* Puts side 1's hand back on its pile and renumbers the pile's cards */
121 CardPile *pile = &battle->sides[1].pile;
122 s32 start = pile->deckTop;
123 s32 i;
124 s32 j;
125 s16 card;
126
127 while (pile->handCount > 0) {
128 pile->deck[--pile->deckTop] = pile->hand[--pile->handCount];
129 pile->deckCount++;
130 }
131 if (start != pile->deckTop) {
132 for (i = pile->deckTop; i < start; i++) {
133 battle->opponentDraws[i].group = battle->round * 2 + 1;
134 }
135 }
136 for (i = 0; i < 40; i++) {
137 j = pile->deckTop;
138 if (battle->opponentDraws[j].group > battle->round * 2 + 2) {
139 break;
140 }
141 card = pile->deck[j];
142 while (j < battle->reserveStart - 1) {
143 pile->deck[j] = pile->deck[j + 1];
144 battle->opponentDraws[j].group = battle->opponentDraws[j + 1].group;
145 j++;
146 }
147 pile->deck[battle->reserveStart - 1] = card;
148 battle->opponentDraws[battle->reserveStart - 1].group = 7;
149 }
150 for (i = 0; i < 40; i++) {
151 battle->opponentDraws[i].order = i;
152 }
153}
154
155/* Lays out the cards of one of a side's piles (which: 0 the hand; 1 the discards; 2 the deck from deckTop) as sprites in a row */
156void CARDGAME_layOutPile(CardBattle *battle, CardBattleItems *items, s32 side, s32 which) {
157 CardScreen *screen = items->screen;
158 CardAnim *anim = &battle->anim;
159 s32 i;
160
161 switch (which) {
162 case 0:
163 anim->count = battle->sides[side].pile.handCount;
164 break;
165 case 1:
166 anim->count = battle->sides[side].pile.discardCount;
167 break;
168 case 2:
169 anim->count = battle->sides[side].pile.deckCount;
170 break;
171 }
172 anim->time = 0;
173 anim->shown = 0;
174 anim->stagger = 0;
175 anim->duration = anim->count * 4 + 10;
176 if (anim->count != 0) {
177 for (i = 0; i < 40; i++) {
178 if (i < anim->count) {
179 screen->addSprite(screen, i, screen->getHandOffset(anim->count, i) + 0x1800, 0x6100);
180 switch (which) {
181 case 0:
182 screen->setSpriteCard(screen, i, battle->sides[side].pile.hand[i]);
183 break;
184 case 1:
185 screen->setSpriteCard(screen, i, battle->sides[side].pile.discards[i]);
186 break;
187 case 2:
188 screen->setSpriteCard(screen, i, battle->sides[side].pile.deck[battle->sides[side].pile.deckTop + i]);
189 break;
190 }
191 if (anim->faceDown != 0) {
192 screen->sprites[i].visible = 2;
193 }
194 screen->sprites[i].scaleX = 0;
195 items->screen->sprites[i].dimmed = battle->anim.dimmed[i];
196 } else {
197 screen->removeSprite(screen, i);
198 }
199 }
200 anim->faceDown = 0;
201 } else {
202 anim->faceDown = 0;
203 screen->addSprite(screen, 0, screen->getHandOffset(anim->count, 0) + 0x1800, 0x6100);
204 screen->sprites[0].visible = 3;
205 screen->sprites[0].scaleX = 0;
206 for (i = 1; i < 40; i++) {
207 screen->removeSprite(screen, i);
208 }
209 }
210}
211
212/* Closes the panels once; 1 once they are closed */
214 s32 done = 0;
215
216 if (battle->subState == 0) {
218 items->screen->closePanels(items->screen);
219 battle->subState++;
220 }
221 if (items->screen->panels[0].state == 0 && battle->anim.current == CARD_ANIM_NONE) {
222 done = 1;
223 }
224 return done;
225}
226
227/* Starts the count of side's hand, discards or deck (which 0-2) */
228void CARDGAME_startPileCount(CardBattle *battle, CardBattleItems *items, s32 side, s32 which) {
229 CardAnim *anim = &battle->anim;
230
231 switch (which) {
232 case 0:
233 anim->count = battle->sides[side].pile.handCount;
234 break;
235 case 1:
236 anim->count = battle->sides[side].pile.discardCount;
237 break;
238 case 2:
239 anim->count = battle->sides[side].pile.deckCount;
240 break;
241 }
242 anim->time = 0;
243 anim->shown = 0;
244 anim->stagger = 0;
245 anim->duration = anim->count * 4 + 10;
246}
247
248/* Marks in each slot sprite's marks[play] whether play of record.plays
249 applies to it, by the play's targetKind */
250static inline void markPlayTargets(CardBattle *battle, CardScreen *screen, s32 play) {
251 CardSlot *slot;
252 CardSprite *sprite;
253 s32 j;
254 s32 first;
255 s32 index;
256 s32 card;
257
258 switch (battle->record.plays[play].targetKind) {
259 case 0:
260 for (j = 0; j < 12; j++) {
261 if (j < 6) {
262 if (j >= battle->players[0].slotCount) {
263 continue;
264 }
265 slot = &battle->players[0].slots[j];
266 } else {
267 index = j - 6;
268 if (index >= battle->players[1].slotCount) {
269 continue;
270 }
271 slot = &battle->players[1].slots[index];
272 }
273 if (slot->order == battle->record.plays[play].target) {
274 screen->sprites[j].marks[play] = 1;
275 }
276 }
277 break;
278 case 1:
279 first = 0;
280 if (battle->record.plays[play].side != 0) {
281 first = 6;
282 }
283 sprite = &screen->sprites[first];
284 for (j = 0; j < 6; j++) {
285 sprite[j].marks[play] = 1;
286 }
287 break;
288 case 2:
289 first = 0;
290 if (battle->record.plays[play].side == 0) {
291 first = 6;
292 }
293 sprite = &screen->sprites[first];
294 for (j = 0; j < 6; j++) {
295 sprite[j].marks[play] = 1;
296 }
297 break;
298 case 3:
299 for (j = 0; j < 12; j++) {
300 screen->sprites[j].marks[play] = 1;
301 }
302 break;
303 case 4:
304 case 5:
305 case 6:
306 case 7:
307 case 8:
308 for (j = 0; j < 12; j++) {
309 if (j < 6) {
310 card = battle->players[0].slots[j].card;
311 } else {
312 card = battle->players[1].slots[j - 6].card;
313 }
314 switch (battle->record.plays[play].targetKind) {
315 case 4:
316 if (screen->getCardColor(screen, card) != 1) {
317 screen->sprites[j].marks[play] = 1;
318 }
319 break;
320 case 5:
321 if (screen->getCardColor(screen, card) != 2) {
322 screen->sprites[j].marks[play] = 1;
323 }
324 break;
325 case 6:
326 if (screen->getCardColor(screen, card) == 3) {
327 screen->sprites[j].marks[play] = 1;
328 }
329 break;
330 case 7:
331 if (screen->getCardColor(screen, card) != 4) {
332 screen->sprites[j].marks[play] = 1;
333 }
334 break;
335 case 8:
336 if (screen->getCardColor(screen, card) == 6) {
337 screen->sprites[j].marks[play] = 1;
338 }
339 break;
340 }
341 }
342 break;
343 case 9:
344 break;
345 }
346}
347
348/* Lays out the slots as sprites (0-5 player 0's, 6-11 player 1's) and each
349 play of record.plays (12 on), marking in marks[play] the slot sprites it
350 applies to (markPlayTargets) */
352 CardScreen *screen = items->screen;
353 s32 i;
354
355 for (i = 0; i < 6; i++) {
356 if (i >= battle->players[0].slotCount) {
357 break;
358 }
359#if PAL_VIDEO
361#else
362 screen->addSprite(screen, i, 0x1800 + i * 0x2900, 0x9000);
363#endif
364 screen->setSpriteCard(screen, i, battle->players[0].slots[i].card);
365 screen->sprites[i].ap = battle->players[0].slots[i].ap;
366 screen->sprites[i].hp = battle->players[0].slots[i].hp;
367 screen->sprites[i].scaleX = 0;
368 }
369 for (i = 0; i < 6; i++) {
370 if (i >= battle->players[1].slotCount) {
371 break;
372 }
373#if PAL_VIDEO
375#else
376 screen->addSprite(screen, i + 6, 0x1800 + i * 0x2900, 0x3200);
377#endif
378 screen->setSpriteCard(screen, i + 6, battle->players[1].slots[i].card);
379 screen->sprites[i + 6].ap = battle->players[1].slots[i].ap;
380 screen->sprites[i + 6].hp = battle->players[1].slots[i].hp;
381 screen->sprites[i + 6].scaleX = 0;
382 if (battle->anim.faceDown != 0) {
383 screen->sprites[i + 6].visible = 2;
384 }
385 }
386 battle->anim.faceDown = 0;
387 for (i = 0; i < battle->record.playCount; i++) {
388 screen->addSprite(screen, i + 12, 0x5100 + i * 0x3200, 0x6100);
389 screen->setSpriteCard(screen, i + 12, battle->record.plays[i].card);
390 screen->sprites[i + 12].scaleX = 0;
391 screen->sprites[i + 12].order = i + 1;
392 screen->sprites[i + 12].marks[0] = 0;
393 screen->sprites[i + 12].marks[1] = 0;
394 screen->sprites[i + 12].marks[2] = 0;
395 screen->sprites[i + 12].moving = 0;
396 if (battle->record.plays[i].mark != 0) {
397 screen->sprites[i + 12].marks[battle->record.plays[i].mark] = 1;
398 }
399 markPlayTargets(battle, screen, i);
400 }
401}
402
403/* Starts the fade that fade asks for (CARDGAME_fadeColors) */
405 s32 frames;
406 CardFader *fader;
407 s32 i;
408
409 if (battle->fade != 0) {
410 i = battle->fade - 1;
411 frames = 10;
413 items->fader = fader;
415 if (CARDGAME_fadeColors[i].blend == 2) {
416 frames = 15;
417 }
418 items->fader->start(items->fader, 0, 0, 0, frames, 1);
419 battle->fade = 0;
420 }
421}
422
423/* Sets the 15 sprites' anim.dimmed to whether anim.dimAll is 2, once it is
424 set */
426 CardAnim *anim = &battle->anim;
427 u8 state = anim->dimAll;
428 s32 i;
429
430 if (state != 0) {
431 for (i = 0; i < 15; i++) {
432 battle->anim.dimmed[i] = state == 2;
433 }
434 anim->dimAll = 0;
435 }
436}
437
438/* Scales the slots in, a pair every 4 frames, then shows the plays */
439static inline void showSlots(CardBattle *battle, CardBattleItems *items, CardAnim *anim) {
440 if (anim->stagger >= 4) {
441 if (anim->shown < battle->players[0].slotCount) {
442 items->screen->scaleSprite(items->screen, anim->shown, 10, 0x1000, 0x1000);
443 }
444 if (anim->shown < battle->players[1].slotCount) {
445 items->screen->scaleSprite(items->screen, anim->shown + 6, 10, 0x1000, 0x1000);
446 }
447 anim->shown++;
448 anim->stagger -= 4;
449 }
450 anim->time += GFX.funcs.getFrameTime();
451 anim->stagger += GFX.funcs.getFrameTime();
452 if (anim->duration < anim->time) {
454 }
455}
456
457/* Scales the plays in, one every 4 frames, opening each one's gauge after it */
458static inline void showPlays(CardBattle *battle, CardBattleItems *items, CardAnim *anim) {
459 if (anim->stagger >= 4) {
460 if (anim->shown < battle->record.playCount) {
461 items->screen->scaleSprite(items->screen, anim->shown + 12, 10, 0x1000, 0x1000);
462 }
463 if (anim->shown - 1 < battle->record.playCount && anim->shown - 1 >= 0) {
464 items->screen->openGauge(items->screen, anim->shown - 1, battle->record.plays[anim->shown - 1].side);
465 }
466 anim->shown++;
467 anim->stagger -= 4;
468 }
469 anim->time += GFX.funcs.getFrameTime();
470 anim->stagger += GFX.funcs.getFrameTime();
471 if (anim->duration < anim->time) {
472 anim->current = CARD_ANIM_NONE;
473 }
474}
475
476/* Scales the slots out, a pair every 4 frames, then hides the plays */
477static inline void hideSlots(CardBattle *battle, CardBattleItems *items, CardAnim *anim) {
478 if (anim->stagger >= 4) {
479 if (anim->shown < battle->players[0].slotCount) {
480 items->screen->scaleSprite(items->screen, anim->shown, 5, 0, 0x1000);
481 }
482 if (anim->shown < battle->players[1].slotCount) {
483 items->screen->scaleSprite(items->screen, anim->shown + 6, 5, 0, 0x1000);
484 }
485 anim->shown++;
486 anim->stagger -= 4;
487 }
488 anim->time += GFX.funcs.getFrameTime();
489 anim->stagger += GFX.funcs.getFrameTime();
490 if (anim->duration < anim->time) {
492 }
493}
494
495/* Scales the plays out with their gauges, one every 4 frames */
496static inline void hidePlays(CardBattle *battle, CardBattleItems *items, CardAnim *anim) {
497 if (anim->stagger >= 4) {
498 if (anim->shown < battle->record.playCount) {
499 items->screen->scaleSprite(items->screen, anim->shown + 12, 5, 0, 0x1000);
500 items->screen->closeGauge(items->screen, anim->shown);
501 }
502 anim->shown++;
503 anim->stagger -= 4;
504 }
505 anim->time += GFX.funcs.getFrameTime();
506 anim->stagger += GFX.funcs.getFrameTime();
507 if (anim->duration < anim->time) {
508 anim->current = CARD_ANIM_NONE;
509 }
510}
511
512/* Scales a pile's cards in, one every 4 frames (at least one) */
513static inline void showPile(CardAnim *anim, CardScreen *screen) {
514 s32 count;
515
516 count = anim->count;
517 if (count == 0) {
518 count = 1;
519 }
520 if (anim->shown < count && anim->stagger >= 4) {
521 screen->scaleSprite(screen, anim->shown, 10, 0x1000, 0x1000);
522 anim->shown++;
523 anim->stagger -= 4;
524 }
525 if (anim->time > anim->duration) {
526 anim->current = CARD_ANIM_NONE;
527 }
528 anim->time += GFX.funcs.getFrameTime();
529 anim->stagger += GFX.funcs.getFrameTime();
530}
531
532/* Scales a pile's cards out, one every 4 frames (at least one) */
533static inline void hidePile(CardAnim *anim, CardScreen *screen) {
534 s32 count;
535
536 count = anim->count;
537 if (count == 0) {
538 count = 1;
539 }
540 if (anim->shown < count && anim->stagger >= 4) {
541 screen->scaleSprite(screen, anim->shown, 5, 0, 0x1000);
542 anim->shown++;
543 anim->stagger -= 4;
544 }
545 if (anim->time > anim->duration) {
546 anim->current = CARD_ANIM_NONE;
547 }
548 anim->time += GFX.funcs.getFrameTime();
549 anim->stagger += GFX.funcs.getFrameTime();
550}
551
552/* Starts (anim.next) and runs (anim.current) the screen's card animations: the hands', the record's and a pile's sprites scaling in or out */
554 CardAnim *anim = &battle->anim;
555 CardScreen *screen = items->screen;
556 s32 index = 0;
557 s32 i;
558
559 if (anim->next != CARD_ANIM_NONE) {
560 switch (anim->next) {
562 CARDGAME_layOutSlots(battle, items);
563 anim->time = 3;
564 anim->shown = 0;
565 anim->stagger = 4;
566 anim->duration = (battle->players[0].slotCount > battle->players[1].slotCount ? battle->players[0].slotCount : battle->players[1].slotCount) * 8;
567 for (i = 0; i < 40; i++) {
568 items->screen->sprites[i].dimmed = battle->anim.dimmed[i];
569 }
570 break;
572 anim->time = 3;
573 anim->shown = 0;
574 anim->stagger = 4;
575 anim->duration = battle->record.playCount * 10;
576 break;
578 anim->time = 3;
579 anim->shown = 0;
580 anim->stagger = 4;
581 anim->duration = (battle->players[0].slotCount > battle->players[1].slotCount ? battle->players[0].slotCount : battle->players[1].slotCount) * 5;
582 break;
584 anim->time = 3;
585 anim->shown = 0;
586 anim->stagger = 4;
587 anim->duration = battle->record.playCount * 5 + 22;
588 break;
591 index++;
592 /* fallthrough */
594 index++;
595 /* fallthrough */
597 index++;
598 /* fallthrough */
601 index++;
602 /* fallthrough */
604 index++;
605 /* fallthrough */
607 index++;
608 CARDGAME_layOutPile(battle, items, CARDGAME_animPiles[index][0], CARDGAME_animPiles[index][1]);
609 break;
611 CARDGAME_startPileCount(battle, items, 0, 0);
612 break;
614 CARDGAME_startPileCount(battle, items, 0, 1);
615 break;
617 CARDGAME_startPileCount(battle, items, 0, 2);
618 break;
620 CARDGAME_startPileCount(battle, items, 1, 1);
621 break;
623 CARDGAME_startPileCount(battle, items, 1, 2);
624 break;
626 CARDGAME_startPileCount(battle, items, 1, 0);
627 break;
628 }
629 anim->hide = anim->next + 1;
630 anim->current = anim->next;
631 anim->next = CARD_ANIM_NONE;
632 }
633 switch (anim->current) {
635 showSlots(battle, items, anim);
636 break;
638 showPlays(battle, items, anim);
639 break;
641 hideSlots(battle, items, anim);
642 break;
644 hidePlays(battle, items, anim);
645 break;
652 showPile(anim, screen);
653 break;
660 hidePile(anim, screen);
661 break;
663 anim->current = CARD_ANIM_NONE;
665 break;
667 anim->current = CARD_ANIM_NONE;
669 break;
670 }
671}
672
673/* Shows both sides' values on their panels: the points of each colour, the
674 deck, hand and discards, AP and HP */
676 s32 side;
677 s32 i;
678
679 for (side = 0; side < 2; side++) {
680 for (i = 0; i < 5; i++) {
681 items->screen->setPanelValue(items->screen, side, i, battle->sides[side].pile.points[i]);
682 }
683 items->screen->setPanelValue(items->screen, side, CARD_PANEL_DECK, battle->sides[side].pile.deckCount);
684 items->screen->setPanelValue(items->screen, side, CARD_PANEL_HAND, battle->sides[side].pile.handCount);
685 items->screen->setPanelValue(items->screen, side, CARD_PANEL_DISCARDS, battle->sides[side].pile.discardCount);
686 items->screen->setPanelValue(items->screen, side, CARD_PANEL_AP, battle->sides[side].pile.apTotal);
687 items->screen->setPanelValue(items->screen, side, CARD_PANEL_HP, battle->sides[side].pile.hpTotal);
688 }
689}
690
691/* Sorts the cards list[from..to) (range: to << 16 | from) by their values,
692 moving opponentDraws (flags bit 0) and effectStep.eligible (bit 1) with them */
693void CARDGAME_sortCards(CardBattle *battle, s16 *list, s32 range, s32 flags) {
694 CardDraw draw;
695 s16 id;
696 s8 eligible;
697 s32 from;
698 s32 to;
699 s16 *ids;
700 s32 i;
701 s32 j;
702
703 from = range & 0xFFFF;
704 to = range >> 16;
705 /* the match depends on this copy of list after from and to: list stays
706 in $a1 until here, so from gets $s0 and leaves $a1 to flags & 1 */
707 ids = list;
708 for (i = from; i < to - 1; i++) {
709 for (j = i + 1; j < to; j++) {
710 if (battle->cards[ids[i]] > battle->cards[ids[j]]) {
711 id = ids[i];
712 ids[i] = ids[j];
713 ids[j] = id;
714 if (flags & 1) {
715 draw = battle->opponentDraws[i];
716 battle->opponentDraws[i] = battle->opponentDraws[j];
717 battle->opponentDraws[j] = draw;
718 }
719 if (flags & 2) {
720 eligible = battle->effectStep.eligible[i - from];
721 battle->effectStep.eligible[i - from] = battle->effectStep.eligible[j - from];
722 battle->effectStep.eligible[j - from] = eligible;
723 }
724 }
725 }
726 }
727}
728
729/* Shuffles the player's pile's deck[base..base + n) with 40 random swaps */
730void CARDGAME_shufflePile(CardBattle *battle, s32 base, s32 n) {
731 CardPile *pile = &battle->sides[0].pile;
732 s32 i;
733 s32 a;
734 s32 b;
735 s32 card;
736
737 if (n >= 2) {
738 for (i = 0; i < 40; i++) {
739 a = RANDOM.next() % n + base;
740 b = RANDOM.next() % n + base;
741 card = pile->deck[a];
742 pile->deck[a] = pile->deck[b];
743 pile->deck[b] = card;
744 }
745 }
746}
747
748/* Goes to the next phaseStep after frames frames */
749static inline void waitPhaseStep(CardBattle *battle, s32 frames) {
750 battle->phaseTime += GFX.funcs.getFrameTime();
751 if (battle->phaseTime >= frames) {
752 battle->phaseTime = 0;
753 battle->phaseStep++;
754 }
755}
756
757/* Opens deck window index with its sound */
758static inline void openDeckWindow(CardBattle *battle, CardBattleItems *items, s32 index) {
761 battle->phaseTime = 0;
762 battle->phaseStep++;
763}
764
765/* Closes deck window index with its sound */
766static inline void closeDeckWindow(CardBattle *battle, CardBattleItems *items, s32 index) {
768 items->deckWindows[index]->close(items->deckWindows[index]);
769 battle->phaseTime = 0;
770 battle->phaseStep++;
771}
772
773/* Up and Down move the marker between the three decks; Cross picks the
774 marked one, which blinks */
775static inline void moveDeckMarker(CardBattle *battle, CardBattleItems *items) {
776 if ((PAD.getPressed(0) & (1 << PAD.getButtonBit(0, PAD_UP))) |
777 (PAD.getRepeated(0) & (1 << PAD.getButtonBit(0, PAD_UP)))) {
778 if (battle->deckChoice > 0) {
779 battle->deckChoice--;
781 }
782 } else if ((PAD.getPressed(0) & (1 << PAD.getButtonBit(0, PAD_DOWN))) |
783 (PAD.getRepeated(0) & (1 << PAD.getButtonBit(0, PAD_DOWN)))) {
784 if (battle->deckChoice < 2) {
785 battle->deckChoice++;
787 }
788 } else if (PAD_PRESSED(PAD_CROSS)) {
790 battle->phaseTime = 0;
791 battle->phaseStep++;
792 items->deckWindows[battle->deckChoice]->setBlink(items->deckWindows[battle->deckChoice]);
793 items->marker->setFast(items->marker);
794 }
796}
797
798/* Loads the chosen deck (or the default one when it is empty) and the
799 opponent's, fills both piles and shuffles the player's */
800static inline void loadChosenDeck(CardBattle *battle, CardBattleItems *items) {
801 CardPile *pile;
802 s32 i;
803
804 if (GAME.decks[battle->deckChoice].cards[0] != 0) {
805 for (i = 0; i < 40; i++) {
806 battle->playerDeck[i] = GAME.decks[battle->deckChoice].cards[i] - 1;
807 }
808 } else {
809 for (i = 0; i < 40; i++) {
810 battle->playerDeck[i] = CARDGAME_defaultDeck[i];
811 }
812 }
813 battle->cardCount = items->screen->loadCardImages(battle->cards, battle->playerDeck, battle->opponentDeck);
814 for (i = 0; i < 40; i++) {
815 battle->sides[0].pile.deck[i] = i;
816 battle->sides[1].pile.deck[i] = i + 40;
817 }
818 battle->round = 0;
819 CARDGAME_findOpponentDeckLimits(battle, items);
820 battle->sides[1].pile.deckCount = 40;
821 battle->sides[0].pile.deckCount = 40;
822 battle->sides[1].pile.deckTop = 0;
823 battle->sides[0].pile.deckTop = 0;
824 CARDGAME_showPanelValues(battle, items);
825 pile = &battle->sides[0].pile;
826 battle->shufflePile(battle, pile->deckTop, pile->deckCount);
827}
828
829/* Chooses the player's deck: opens the three deck windows and a marker, Up/Down/Cross pick one, then loads both decks' cards; 1 once done */
831 CardPreloader *preloader;
832 s32 done = 0;
833
834 switch (battle->phaseStep) {
835 case 0:
836 default:
837 preloader = items->preloader;
838 if (preloader == NULL) {
839 battle->phaseStep++;
840 } else if (preloader->state == 1 && preloader->ready != 0) {
841 battle->phaseStep++;
842 }
843 break;
844 case 1:
845 items->screen->openWindow(items->screen, 5, 5, 0x41, 0, 0x26);
848 battle->phaseTime = 0;
849 battle->phaseStep++;
850 break;
851 case 2:
852 waitPhaseStep(battle, 11);
853 break;
854 case 3:
855 openDeckWindow(battle, items, 1);
856 break;
857 case 4:
858 waitPhaseStep(battle, 11);
859 break;
860 case 5:
861 openDeckWindow(battle, items, 2);
862 break;
863 case 6:
864 waitPhaseStep(battle, 11);
865 break;
866 case 7:
868 battle->phaseTime = 0;
869 battle->phaseStep++;
870 break;
871 case 8:
872 battle->phaseTime += GFX.funcs.getFrameTime();
873 if (battle->phaseTime >= 11) {
874 battle->phaseTime = 0;
875 battle->deckChoice = 0;
876 battle->phaseStep++;
877 }
878 break;
879 case 9:
880 moveDeckMarker(battle, items);
881 break;
882 case 10:
883 waitPhaseStep(battle, 15);
884 break;
885 case 11:
886 items->marker->close(items->marker);
887 battle->phaseTime = 0;
888 battle->phaseStep++;
889 break;
890 case 13:
891 closeDeckWindow(battle, items, 0);
892 break;
893 case 14:
894 waitPhaseStep(battle, 4);
895 break;
896 case 15:
897 closeDeckWindow(battle, items, 1);
898 break;
899 case 16:
900 waitPhaseStep(battle, 4);
901 break;
902 case 17:
903 closeDeckWindow(battle, items, 2);
904 break;
905 case 18:
906 waitPhaseStep(battle, 4);
907 break;
908 case 19:
909 items->screen->closeWindow(items->screen, 5);
910 battle->phaseTime = 0;
911 battle->phaseStep++;
912 break;
913 case 12:
914 case 20:
915 waitPhaseStep(battle, 6);
916 break;
917 case 21:
918 loadChosenDeck(battle, items);
919 done = 1;
920 break;
921 }
922 return done;
923}
924
925/* Runs step 0xA7 (CARDGAME_startFirstPick) and then keeps who goes first
926 (firstStarter); 1 once done */
928 s32 done = 0;
929
930 if (battle->phaseStep == 0) {
931 battle->effectStep.next = 0xA7;
932 battle->run = CARD_RUN_STEP;
933 battle->phaseStep = 1;
934 } else {
935 if (battle->effectStep.choice == 0) {
936 battle->firstStarter = 0;
937 } else {
938 battle->firstStarter = 1;
939 }
940 done = 1;
941 }
942 return done;
943}
944
945/* Runs step 20 (CARDGAME_stepStart) and then returns its choice + 1: 1 dealt,
946 2 the player's deck was short, 3 the opponent's */
948 s32 result = 0;
949
950 if (battle->phaseStep == 0) {
951 battle->effectStep.next = 0x14;
952 battle->run = CARD_RUN_STEP;
953 battle->phaseStep++;
954 } else {
955 switch (battle->effectStep.choice) {
956 case 0:
957 result = 1;
958 break;
959 case 1:
960 result = 2;
961 break;
962 case 2:
963 result = 3;
964 break;
965 }
966 }
967 return result;
968}
969
970/* Takes the first flagged card out of the hand of side record.turnSide into the play record.plays[playCount]; returns its condition id */
972 s32 i;
973 s32 j;
974 s32 side;
975 s32 card;
976 s16 index;
977
978 for (i = 0; i < 10; i++) {
979 if (battle->effectStep.marked[i] != 0) {
980 break;
981 }
982 }
983 side = battle->record.turnSide;
984 card = battle->cards[battle->sides[side].pile.hand[i]];
985 battle->record.plays[battle->record.playCount].side = side;
986 index = battle->sides[side].pile.hand[i];
987 battle->record.plays[battle->record.playCount].card = index;
988 battle->record.plays[battle->record.playCount].targetKind = CARDGAME_getEffectField(battle->cards[index], 3, 0);
989 for (j = i; j < battle->sides[side].pile.handCount - 1; j++) {
990 battle->sides[side].pile.hand[j] = battle->sides[side].pile.hand[j + 1];
991 }
992 battle->sides[side].pile.handCount--;
993 return CARDGAME_getEffectField(card, 0, 0);
994}
995
996/* Flags (effectStep.marked) the slots that the current play's target kind (record.plays[playCount].targetKind) picks */
998 CardSlot *slot;
999 s32 card;
1000 s32 i;
1001
1002 for (i = 0; i < 12; i++) {
1003 battle->effectStep.marked[i] = 0;
1004 switch (battle->record.plays[battle->record.playCount].targetKind) {
1005 case 0:
1006 if (i < 6) {
1007 if (i >= battle->players[0].slotCount) {
1008 break;
1009 }
1010 slot = &battle->players[0].slots[i];
1011 } else {
1012 if (i - 6 >= battle->players[1].slotCount) {
1013 break;
1014 }
1015 slot = &battle->players[1].slots[i - 6];
1016 }
1017 if (slot->order == battle->record.plays[battle->record.playCount].target) {
1018 battle->effectStep.marked[i] = 1;
1019 }
1020 break;
1021 case 2:
1022 if (i < 6 && i < battle->players[0].slotCount) {
1023 battle->effectStep.marked[i] = 1;
1024 }
1025 break;
1026 case 1:
1027 if (i >= 6 && i - 6 < battle->players[1].slotCount) {
1028 battle->effectStep.marked[i] = 1;
1029 }
1030 break;
1031 case 3:
1032 battle->effectStep.marked[i] = 1;
1033 break;
1034 case 4:
1035 if (i < 6) {
1036 card = battle->players[0].slots[i].card;
1037 } else {
1038 card = battle->players[1].slots[i - 6].card;
1039 }
1040 if (screen->getCardColor(screen, card) != 1) {
1041 battle->effectStep.marked[i] = 1;
1042 }
1043 break;
1044 case 5:
1045 if (i < 6) {
1046 card = battle->players[0].slots[i].card;
1047 } else {
1048 card = battle->players[1].slots[i - 6].card;
1049 }
1050 if (screen->getCardColor(screen, card) != 2) {
1051 battle->effectStep.marked[i] = 1;
1052 }
1053 break;
1054 case 6:
1055 if (i < 6) {
1056 card = battle->players[0].slots[i].card;
1057 } else {
1058 card = battle->players[1].slots[i - 6].card;
1059 }
1060 if (screen->getCardColor(screen, card) == 3) {
1061 battle->effectStep.marked[i] = 1;
1062 }
1063 break;
1064 case 7:
1065 if (i < 6) {
1066 card = battle->players[0].slots[i].card;
1067 } else {
1068 card = battle->players[1].slots[i - 6].card;
1069 }
1070 if (screen->getCardColor(screen, card) != 4) {
1071 battle->effectStep.marked[i] = 1;
1072 }
1073 break;
1074 case 8:
1075 if (i < 6) {
1076 card = battle->players[0].slots[i].card;
1077 } else {
1078 card = battle->players[1].slots[i - 6].card;
1079 }
1080 if (screen->getCardColor(screen, card) == 6) {
1081 battle->effectStep.marked[i] = 1;
1082 }
1083 break;
1084 case 9:
1085 break;
1086 }
1087 }
1088}
1089
1090/* Starts the rounds: clears the record, shows the slots and opens the panels */
1091static inline void startRounds(CardBattle *battle, CardBattleItems *items) {
1092 battle->record.turnState = 16;
1093 battle->record.playCount = 0;
1094 battle->record.passes = 0;
1095 battle->record.plays[0].mark = 0;
1096 battle->record.plays[1].mark = 0;
1097 battle->record.plays[2].mark = 0;
1099 battle->anim.next = CARD_ANIM_SHOW_SLOTS;
1100 battle->record.starter = battle->record.turnSide = battle->firstStarter;
1101 items->screen->openPanels(items->screen);
1102}
1103
1104/* Picks the side that plays next, by the starter and the plays so far, or
1105 once three cards are played resolves them */
1106static inline void startPlay(CardBattle *battle, CardBattleItems *items) {
1107 switch (battle->record.playCount) {
1108 case 0:
1109 case 2:
1110 if (battle->record.starter != 0) {
1111 battle->record.turnState = 3;
1112 } else {
1113 battle->record.turnState = 2;
1114 }
1115 break;
1116 case 1:
1117 if (battle->record.starter != 0) {
1118 battle->record.turnState = 2;
1119 } else {
1120 battle->record.turnState = 3;
1121 }
1122 break;
1123 default:
1124 battle->record.turnState = 12;
1125 break;
1126 }
1127 if (battle->record.playCount != 0) {
1128 battle->record.passes = 0;
1129 }
1130 battle->record.answer = -1;
1131 items->screen->setPanelValue(items->screen, 0, CARD_PANEL_HAND, battle->sides[0].pile.handCount);
1132 items->screen->setPanelValue(items->screen, 1, CARD_PANEL_HAND, battle->sides[1].pile.handCount);
1133}
1134
1135/* The computer plays a card (CARDGAME_pickComputerCard); without one it
1136 passes when it would play first, else the plays resolve */
1137static inline void playComputerTurn(CardBattle *battle, CardBattleItems *items) {
1138 s32 condition;
1139 s32 i;
1140
1142 if (CARDGAME_pickComputerCard(battle, items->screen)) {
1143 condition = CARDGAME_takeFlaggedCard(battle, items);
1144 if (condition == 0x83 || condition == 0x84) {
1145 for (i = 0; i < 15; i++) {
1146 battle->effectStep.marked[i] = 0;
1147 }
1148 battle->effectStep.marked[battle->record.playCount + 11] = 1;
1149 battle->record.plays[battle->record.playCount - 1].mark = 1;
1150 }
1151 if (battle->record.passes != 0) {
1153 items->screen->closePanelIcon(items->screen, 0);
1154 }
1155 battle->record.turnState = 9;
1156 CARDGAME_flagTargetSlots(battle, items->screen);
1157 } else if (battle->record.playCount == 0) {
1158 battle->record.turnState = 11;
1159 battle->record.waitTime = 20;
1160 battle->record.passes++;
1162 items->screen->openPanelIcon(items->screen, 1);
1163 } else {
1164 battle->record.turnState = 12;
1165 }
1166}
1167
1168/* The player picks a card to play (effect step 0x98); without one they pass
1169 when they would play first, else the plays resolve */
1170static inline void playPlayerTurn(CardBattle *battle, CardBattleItems *items) {
1171 if (battle->record.answer == -1) {
1172 battle->run = CARD_RUN_STEP;
1173 battle->effectStep.next = 0x98;
1174 battle->sortCards(battle, battle->sides[0].pile.hand, battle->sides[0].pile.handCount << 16, 0);
1175 } else if (battle->record.answer != 0) {
1176 battle->record.turnState = CARDGAME_turnStates[battle->record.turnSide + 2];
1177 battle->record.answer = -1;
1178 if (battle->record.passes != 0) {
1179 items->screen->panels[1].scale.state = 0;
1180 }
1181 } else if (battle->record.playCount == 0) {
1182 battle->record.turnState = 11;
1183 battle->record.waitTime = 20;
1184 battle->record.passes++;
1186 items->screen->openPanelIcon(items->screen, 0);
1187 } else {
1188 battle->record.turnState = 12;
1189 }
1190}
1191
1192/* Takes the picked card into the play and runs its condition's step: when it
1193 holds the card is played, else it goes back to the hand */
1194static inline void takePickedCard(CardBattle *battle, CardBattleItems *items) {
1195 s32 side;
1196
1197 if (battle->record.answer == -1) {
1198 battle->effectStep.next = CARDGAME_takeFlaggedCard(battle, items);
1199 battle->run = CARD_RUN_STEP;
1200 } else if (battle->record.answer != 0) {
1201 battle->record.turnState = CARDGAME_turnStates[battle->record.turnSide + 6];
1202 } else {
1203 side = battle->record.turnSide;
1204 battle->sides[side].pile.hand[battle->sides[side].pile.handCount] = battle->record.plays[battle->record.playCount].card;
1205 battle->sides[side].pile.handCount++;
1206 battle->sortCards(battle, battle->sides[0].pile.hand, battle->sides[0].pile.handCount << 16, 0);
1207 battle->record.turnState = CARDGAME_turnStates[battle->record.turnSide + 2];
1208 battle->record.answer = -1;
1209 }
1210}
1211
1212/* Starts the next turn, the other side starting; after two passes the rounds
1213 end (state 15) */
1214static inline void startNextTurn(CardBattle *battle) {
1215 battle->record.turnState = 1;
1216 battle->record.playCount = 0;
1217 battle->record.plays[0].mark = 0;
1218 battle->record.plays[1].mark = 0;
1219 battle->record.plays[2].mark = 0;
1220 battle->record.starter ^= 1;
1221 battle->record.turnSide = battle->record.starter;
1222 battle->record.turns++;
1223 if (battle->record.passes >= 2) {
1224 battle->record.turnState = 15;
1225 battle->subState = 0;
1226 }
1227}
1228
1229/* Runs the rounds of plays (state record.turnState): each side in turn plays a card, the computer through CARDGAME_pickComputerCard; 1 once over */
1231 s32 done = 0;
1232
1233 switch (battle->record.turnState) {
1234 case 0:
1235 default:
1236 startRounds(battle, items);
1237 break;
1238 case 16:
1239 if (items->screen->panels[0].state == 2 && battle->anim.current == CARD_ANIM_NONE) {
1240 battle->record.turnState = 17;
1241 items->screen->openWindow(items->screen, 5, 5, battle->phase == CARD_PHASE_PLAYS_BEFORE ? 0x3C : 0x3D, 0, 0x6E);
1242 }
1243 break;
1244 case 17:
1245 if (items->screen->windows[5].state == 2) {
1247 battle->record.turnState = 18;
1248 items->screen->closeWindow(items->screen, 5);
1249 }
1250 }
1251 break;
1252 case 18:
1253 if (items->screen->windows[5].state == 0) {
1254 battle->record.turnState = 1;
1255 }
1256 break;
1257 case 1:
1258 startPlay(battle, items);
1259 break;
1260 case 3:
1261 playComputerTurn(battle, items);
1262 break;
1263 case 2:
1264 playPlayerTurn(battle, items);
1265 break;
1266 case 4:
1267 case 5:
1268 if (battle->record.answer == -1) {
1269 battle->run = CARD_RUN_STEP;
1270 battle->effectStep.next = 0x99;
1271 } else if (battle->record.answer != 0) {
1272 battle->record.turnState = CARDGAME_turnStates[battle->record.turnSide + 4];
1273 battle->record.answer = -1;
1274 } else {
1276 battle->record.answer = -1;
1277 if (battle->record.passes != 0) {
1278 items->screen->panels[1].scale.state = 2;
1279 }
1280 }
1281 break;
1282 case 6:
1283 case 7:
1284 takePickedCard(battle, items);
1285 break;
1286 case 9:
1287 battle->effectStep.next = 0x13;
1288 battle->run = CARD_RUN_STEP;
1289 battle->record.turnState = 10;
1290 break;
1291 case 8:
1292 battle->effectStep.next = 0x12;
1293 battle->run = CARD_RUN_STEP;
1294 battle->record.turnState = 10;
1295 break;
1296 case 10:
1297 battle->record.turnState = 1;
1298 battle->record.turnSide ^= 1;
1299 battle->record.playCount++;
1300 break;
1301 case 11:
1302 if (--battle->record.waitTime <= 0) {
1303 battle->record.turnState = 14;
1304 }
1305 break;
1306 case 12:
1307 if (battle->record.playCount > 0) {
1308 battle->run = CARD_RUN_RESOLVE;
1309 battle->record.turnState = 13;
1310 battle->resolveState = 0;
1311 battle->subTime = 0;
1312 battle->subState = 0;
1313 battle->playsToResolve = battle->record.playCount;
1314 } else {
1315 battle->record.turnState = 14;
1316 }
1317 break;
1318 case 13:
1319 battle->record.turnState = 12;
1320 break;
1321 case 14:
1322 startNextTurn(battle);
1323 break;
1324 case 15:
1325 items->screen->closePanelIcon(items->screen, 0);
1326 items->screen->closePanelIcon(items->screen, 1);
1327 if (CARDGAME_stepHidePanels(battle, items)) {
1328 done = 1;
1329 }
1330 break;
1331 }
1332 return done;
1333}
1334
1335/* Clears record.turnState, shows the panel values and sorts the player's hand */
1337 battle->record.turnState = 0;
1338 CARDGAME_showPanelValues(battle, items);
1339 battle->sortCards(battle, battle->sides[0].pile.hand, battle->sides[0].pile.handCount << 16, 0);
1340}
1341
1342/* Takes the marked cards (effectStep.marked) out of pile's hand */
1344 s32 i;
1345 s32 j;
1346
1347 for (i = pile->handCount - 1; i >= 0; i--) {
1348 if (battle->effectStep.marked[i] != 0) {
1349 for (j = i; j < pile->handCount - 1; j++) {
1350 pile->hand[j] = pile->hand[j + 1];
1351 }
1352 pile->handCount--;
1353 }
1354 }
1355}
1356
1357/* Puts the battle's card card in side's slot index, with its AP and HP and
1358 the order it came out in */
1359void CARDGAME_setSlot(CardBattle *battle, s32 side, s32 card, s32 index) {
1360 CardDrawer drawer;
1361 CardPlayer *player = &battle->players[side];
1362
1363 initCardDrawer(&drawer);
1364 drawer.setCard(battle->cards[card] + 1);
1365 player->slots[index].ap = drawer.card->ap;
1366 player->slots[index].hp = drawer.card->hp;
1367 player->slots[index].apBonus = 0;
1368 player->slots[index].hpBonus = 0;
1369 player->slots[index].card = card;
1370 player->slots[index].owner = side;
1371 player->slots[index].side = side;
1372 player->slots[index].order = battle->slotCount++;
1373}
1374
1375/* CardBattle.addCard: puts card in side's next slot */
1376void CARDGAME_addCard(CardBattle *battle, s32 side, s32 card) {
1377 CardPlayer *player = &battle->players[side];
1378
1379 CARDGAME_setSlot(battle, side, card, player->slotCount++);
1380}
1381
1382/* Puts side's flagged cards of its pile into its slots, up to effectStep.count of them */
1384 CardPlayer *player = &battle->players[side];
1385 CardPile *pile = &battle->sides[side].pile;
1386 s32 i;
1387
1388 player->slotCount = 0;
1389 for (i = 0; i < pile->handCount; i++) {
1390 if (player->slotCount < battle->effectStep.count && battle->effectStep.marked[i] != 0) {
1391 CARDGAME_addCard(battle, side, pile->hand[i]);
1392 }
1393 }
1394 CARDGAME_removeMarkedHandCards(battle, pile);
1395}
1396
1397/* Sets the values of a slot that holds the pass-th card of CARDGAME_countingCards from the battle's counts (0 to 99) */
1399 CardSide *cardSide = &battle->sides[side];
1400 CardPlayer *player = &battle->players[side];
1401 s32 values[2];
1402 s32 i;
1403 s32 base;
1404
1405 if (battle->cards[slot->card] == CARDGAME_countingCards[pass]) {
1406 for (i = 0; i < 2; i++) {
1407 if (i == 0) {
1408 base = slot->apBonus;
1409 } else {
1410 base = slot->hpBonus;
1411 }
1412 switch (pass) {
1413 case 0:
1414 values[i] = player->slotCount * 20 + base;
1415 break;
1416 case 1:
1417 values[i] = cardSide->pile.handCount * 10 + 10 + base;
1418 break;
1419 case 2:
1420 values[i] = cardSide->pile.discardCount * 20 + 10 + base;
1421 break;
1422 case 3:
1423 values[i] = (battle->players[0].slotCount + battle->players[1].slotCount) * 10 + base;
1424 break;
1425 case 4:
1426 values[i] = (battle->sides[0].pile.discardCount + battle->sides[1].pile.discardCount) * 10 + 10 + base;
1427 break;
1428 }
1429 if (values[i] >= 99) {
1430 values[i] = 99;
1431 }
1432 if (values[i] <= 0) {
1433 values[i] = 0;
1434 }
1435 }
1436 slot->ap = values[0];
1437 slot->hp = values[1];
1438 }
1439}
1440
1441/* Sets the values of the counting cards out, pass by pass
1442 (CARDGAME_setCountingCardValues); whether any card is out */
1444 s32 found = 0;
1445 s32 pass;
1446 s32 side;
1447 s32 i;
1448 CardPlayer *player;
1449
1450 for (pass = 0; pass < 5; pass++) {
1451 for (side = 0; side < 2; side++) {
1452 player = &battle->players[side];
1453 for (i = 0; i < player->slotCount; i++) {
1454 found = 1;
1455 CARDGAME_setCountingCardValues(battle, &player->slots[i], side, pass);
1456 }
1457 }
1458 }
1459 return found;
1460}
1461
1462/* Side's apTotal and hpTotal become the sums of its slot cards' ap and hp */
1464 s32 i;
1465
1466 battle->sides[side].pile.apTotal = 0;
1467 battle->sides[side].pile.hpTotal = 0;
1468 for (i = 0; i < battle->players[side].slotCount; i++) {
1469 battle->sides[side].pile.apTotal += battle->players[side].slots[i].ap;
1470 battle->sides[side].pile.hpTotal += battle->players[side].slots[i].hp;
1471 }
1472}
1473
1474/* A battle step: each side puts out its flagged cards (putOutCards) between messages 0x9A, 0x9D and 0x9E; 1 once done */
1476 s32 done = 0;
1477
1478 switch (battle->phaseStep) {
1479 case 0:
1480 battle->effectStep.next = 0x9A;
1481 battle->run = CARD_RUN_STEP;
1482 battle->phaseStep = 1;
1483 break;
1484 case 1:
1485 battle->putOutCards(battle, 0);
1486 battle->phaseStep = 2;
1487 items->screen->setPanelValue(items->screen, 0, CARD_PANEL_HAND, battle->sides[0].pile.handCount);
1488 break;
1489 case 2:
1491 battle->effectStep.next = 0x9D;
1492 battle->run = CARD_RUN_STEP;
1493 battle->phaseStep = 3;
1494 break;
1495 case 3:
1496 battle->putOutCards(battle, 1);
1497 battle->phaseStep = 4;
1499 CARDGAME_sumSlotValues(battle, 1);
1500 CARDGAME_sumSlotValues(battle, 0);
1501 items->screen->setPanelValue(items->screen, 1, CARD_PANEL_HAND, battle->sides[1].pile.handCount);
1502 break;
1503 case 4:
1504 battle->effectStep.next = 0x9E;
1505 battle->run = CARD_RUN_STEP;
1506 battle->phaseStep = 5;
1507 break;
1508 case 5:
1509 done = 1;
1510 break;
1511 }
1512 return done;
1513}
1514
1515/* Finds three or more of one card (with a CardImage.comboCard) among a side's slots, by id from start: flags them in effectStep.eligible; the index after them or -1 */
1517 CardSortEntry entries[6];
1518 CardSortEntry entry;
1519 CardDrawer drawer;
1520 s32 count;
1521 s32 value;
1522 s32 result;
1523 s32 i;
1524 s32 j;
1525 s32 k;
1526
1527 result = -1;
1528 value = 0x51;
1529 count = battle->players[side].slotCount;
1530 initCardDrawer(&drawer);
1531 for (i = 0; i < count; i++) {
1532 entries[i].card = battle->cards[battle->players[side].slots[i].card];
1533 entries[i].slot = i;
1534 }
1535 for (i = 0; i < count - 1; i++) {
1536 for (j = i + 1; j < count; j++) {
1537 if (entries[i].card > entries[j].card) {
1538 entry = entries[i];
1539 entries[i] = entries[j];
1540 entries[j] = entry;
1541 }
1542 }
1543 }
1544 j = 0;
1545 for (i = start; i < count - 1; i++) {
1546 drawer.setCard(entries[i].card + 1);
1547 if (drawer.card->comboCard != 0 && entries[i].card == entries[i + 1].card) {
1548 value = drawer.card->comboCard;
1549 j++;
1550 } else if (j < 2) {
1551 j = 0;
1552 } else {
1553 break;
1554 }
1555 }
1556 if (j >= 2) {
1557 for (k = 0; k < count; k++) {
1558 battle->effectStep.eligible[k] = 0;
1559 }
1560 for (; j >= 0; j--) {
1561 battle->effectStep.eligible[entries[i - j].slot] = 1;
1562 }
1563 battle->effectStep.vars[4] = value;
1564 result = i + 1;
1565 }
1566 return result;
1567}
1568
1569/* Opens the panels for a phase */
1571 items->screen->openPanels(items->screen);
1573 battle->anim.next = CARD_ANIM_SHOW_SLOTS;
1574 battle->phaseStep = 0;
1575}
1576
1577/* Runs effect step 0x19 for each set of three or more of one card among the
1578 player's slots (CARDGAME_findCardSet), then goes on to the opponent's */
1579static inline void runPlayerCardSets(CardBattle *battle) {
1580 battle->phaseTime = CARDGAME_findCardSet(battle, 0, battle->phaseTime);
1581 if (battle->phaseTime == -1) {
1582 battle->phaseStep = 2;
1583 battle->phaseTime = 0;
1584 } else {
1585 battle->effectStep.next = 0x19;
1586 battle->run = CARD_RUN_STEP;
1587 }
1588}
1589
1590/* Runs effect step 0x1A for each set of three or more of one card among the
1591 opponent's slots (CARDGAME_findCardSet) */
1592static inline void runOpponentCardSets(CardBattle *battle) {
1593 battle->phaseTime = CARDGAME_findCardSet(battle, 1, battle->phaseTime);
1594 if (battle->phaseTime == -1) {
1595 battle->phaseStep = 8;
1596 } else {
1597 battle->effectStep.next = 0x1A;
1598 battle->run = CARD_RUN_STEP;
1599 }
1600}
1601
1602/* Runs effect step 0x1B for the kept card (keptCard) until keptCount runs
1603 out */
1604static inline void runKeptCardSteps(CardBattle *battle) {
1605 if (battle->keptCard != 0) {
1606 battle->effectStep.next = 0x1B;
1607 battle->run = CARD_RUN_STEP;
1608 battle->keptCount--;
1609 }
1610 if (battle->keptCount == 0) {
1611 battle->phaseStep = 9;
1612 } else {
1613 battle->phaseStep = 8;
1614 }
1615}
1616
1617/* When a side has no slots left, the round ends at once, the higher total
1618 winning; else the round's result window opens */
1619static inline void checkEmptyRows(CardBattle *battle, CardScreen *screen) {
1620 if (battle->players[0].slotCount == 0 || battle->players[1].slotCount == 0) {
1621 if (battle->sides[0].pile.hpTotal > battle->sides[1].pile.hpTotal) {
1622 battle->roundWinner = 0;
1623 } else {
1624 battle->roundWinner = 1;
1625 }
1626 battle->phaseStep = 11;
1627 if (battle->players[battle->roundWinner].slotCount == 0 && battle->players[battle->roundWinner ^ 1].slotCount != 0) {
1628 battle->phaseStep = 10;
1629 battle->phaseTime = 0;
1630 }
1631 } else {
1632 battle->phaseStep = 3;
1633 screen->openWindow(screen, 5, 5, 13, 0, 110);
1634 }
1635}
1636
1637/* Gives the round to the side with the higher total (pile.hpTotal) and runs
1638 its win's effect step (0x18 the player's, 0x17 the opponent's) */
1639static inline void pickRoundWinner(CardBattle *battle) {
1640 if (battle->sides[0].pile.hpTotal > battle->sides[1].pile.hpTotal) {
1641 battle->effectStep.next = 0x18;
1642 battle->roundWinner = 0;
1643 } else {
1644 battle->effectStep.next = 0x17;
1645 battle->roundWinner = 1;
1646 }
1647 battle->run = CARD_RUN_STEP;
1648 battle->phaseStep = 11;
1649 battle->phaseTime = 0;
1650}
1651
1652/* Blinks the round winner's wins on its panel with a flash, then counts the
1653 win and shows the round's result */
1654static inline void countRoundWin(CardBattle *battle, CardBattleItems *items, CardScreen *screen) {
1655 CardFader *fader;
1656 s32 side;
1657
1658 side = battle->roundWinner;
1659 if (battle->phaseTime & 1) {
1660 items->screen->panels[side].wins = battle->sides[side].pile.wins + 1;
1661 } else {
1662 items->screen->panels[side].wins = battle->sides[side].pile.wins;
1663 }
1664 if (battle->phaseTime == 0) {
1665 SOUND.playSound(0x9C0002);
1666 fader = CARDGAME_createFader(1);
1667 items->fader = fader;
1668 fader->setColor(fader, 0x80, 0x80, 0x80);
1669 items->fader->start(items->fader, 0, 0, 0, 10, 1);
1670 }
1671 battle->phaseTime += GFX.funcs.getFrameTime();
1672 if (battle->phaseTime >= 51) {
1673 items->screen->panels[side].wins = battle->sides[side].pile.wins + 1;
1674 battle->sides[side].pile.wins++;
1675 battle->phaseStep = 12;
1676 if (battle->roundWinner == 0) {
1677 screen->openWindow(screen, 5, 5, 16, 0, 110);
1678 } else if (battle->sides[0].pile.hpTotal != battle->sides[1].pile.hpTotal) {
1679 screen->openWindow(screen, 5, 5, 17, 0, 110);
1680 } else {
1681 screen->openMessage(screen, 18, 0, 0, 1);
1682 }
1683 }
1684}
1685
1686/* Waits for the round's result: its window, or the draw message when the
1687 totals are equal */
1688static inline void waitRoundResultShown(CardBattle *battle, CardScreen *screen) {
1689 s32 done;
1690
1691 if (battle->sides[0].pile.hpTotal != battle->sides[1].pile.hpTotal) {
1692 done = screen->windows[5].state == 2;
1693 } else {
1694 done = screen->message.state == 2;
1695 }
1696 if (done) {
1697 battle->phaseStep = 13;
1698 }
1699}
1700
1701/* Cross or Triangle closes the round's result window or message */
1702static inline void closeRoundResult(CardBattle *battle, CardScreen *screen) {
1704 if (battle->sides[0].pile.hpTotal != battle->sides[1].pile.hpTotal) {
1705 screen->closeWindow(screen, 5);
1706 } else {
1707 screen->closeMessage(screen);
1708 }
1709 battle->phaseStep = 14;
1710 }
1711}
1712
1713/* Once the round's result is closed, opens message 19 */
1714static inline void waitRoundResultClosed(CardBattle *battle, CardScreen *screen) {
1715 s32 done;
1716
1717 if (battle->sides[0].pile.hpTotal != battle->sides[1].pile.hpTotal) {
1718 done = screen->windows[5].state == 0;
1719 } else {
1720 done = screen->message.state == 0;
1721 }
1722 if (done) {
1723 battle->phaseStep = 15;
1724 screen->openMessage(screen, 19, 0, 0, 1);
1725 }
1726}
1727
1728/* Once a side has two wins, shows who won the battle; else goes on to the
1729 next round */
1730static inline void checkBattleWinner(CardBattle *battle, CardScreen *screen) {
1731 if (screen->message.state == 0) {
1732 if (battle->sides[0].pile.wins >= 2) {
1734 screen->openWindow(screen, 5, 5, 21, 0, 110);
1735 battle->phaseStep = 19;
1736 battle->playerLost = 0;
1737 } else if (battle->sides[1].pile.wins >= 2) {
1738 screen->openWindow(screen, 5, 5, 22, 0, 110);
1739 battle->phaseStep = 19;
1740 battle->playerLost = 1;
1741 } else {
1742 battle->phaseStep = 18;
1743 }
1744 }
1745}
1746
1747/* Runs the round's closing effect step: 0x1C after the player's win, 0x1D
1748 after the opponent's */
1749static inline void runRoundEndStep(CardBattle *battle) {
1750 if (battle->roundWinner == 0) {
1751 battle->effectStep.next = 0x1C;
1752 } else {
1753 battle->effectStep.next = 0x1D;
1754 }
1755 battle->run = CARD_RUN_STEP;
1756 battle->phaseStep = 26;
1757}
1758
1759/* Cross or Triangle closes the battle's result: the player's win goes on to
1760 the prize, a loss ends it */
1761static inline void closeBattleResult(CardBattle *battle, CardScreen *screen) {
1763 if (battle->roundWinner == 0) {
1764 screen->closeWindow(screen, 5);
1765 battle->phaseStep = 21;
1766 battle->subState = 0;
1767 } else {
1768 battle->phaseStep = 25;
1769 }
1770 }
1771}
1772
1773/* The end of a round: shows both sides' cards, gives the round to the higher total (pile.hpTotal) and the battle to the first side with two rounds; 1 for the next round, 2 once the battle is over */
1775 CardScreen *screen = items->screen;
1776 s32 result = 0;
1777
1778 switch (battle->phaseStep) {
1779 case 0:
1780 if (items->screen->panels[0].state == 2 && battle->anim.current == CARD_ANIM_NONE) {
1781 battle->phaseStep = 1;
1782 battle->phaseTime = 0;
1783 }
1784 break;
1785 case 1:
1786 runPlayerCardSets(battle);
1787 break;
1788 case 2:
1789 runOpponentCardSets(battle);
1790 break;
1791 case 8:
1792 runKeptCardSteps(battle);
1793 break;
1794 case 9:
1795 checkEmptyRows(battle, screen);
1796 break;
1797 case 3:
1798 if (screen->windows[5].state == 2) {
1799 battle->phaseStep = 4;
1800 }
1801 break;
1802 case 4:
1804 battle->phaseStep = 5;
1805 screen->closeWindow(screen, 5);
1806 }
1807 break;
1808 case 5:
1809 if (screen->windows[5].state == 0) {
1810 battle->phaseStep = 6;
1811 }
1812 break;
1813 case 6:
1814 battle->effectStep.next = 0x15;
1815 battle->run = CARD_RUN_STEP;
1816 battle->phaseStep = 7;
1817 break;
1818 case 7:
1819 battle->effectStep.next = 0x16;
1820 battle->run = CARD_RUN_STEP;
1821 battle->phaseStep = 10;
1822 battle->phaseTime = 0;
1823 break;
1824 case 10:
1825 pickRoundWinner(battle);
1826 break;
1827 case 11:
1828 countRoundWin(battle, items, screen);
1829 break;
1830 case 12:
1831 waitRoundResultShown(battle, screen);
1832 break;
1833 case 13:
1834 closeRoundResult(battle, screen);
1835 break;
1836 case 14:
1837 waitRoundResultClosed(battle, screen);
1838 break;
1839 case 15:
1840 if (screen->message.state == 2) {
1841 battle->phaseStep = 16;
1842 }
1843 break;
1844 case 16:
1846 screen->closeMessage(screen);
1847 battle->phaseStep = 17;
1848 }
1849 break;
1850 case 17:
1851 checkBattleWinner(battle, screen);
1852 break;
1853 case 18:
1854 runRoundEndStep(battle);
1855 break;
1856 case 19:
1857 if (screen->windows[5].state == 2) {
1858 battle->phaseStep = 20;
1859 }
1860 break;
1861 case 20:
1862 closeBattleResult(battle, screen);
1863 break;
1864 case 21:
1865 if (screen->windows[5].state == 0 && CARDGAME_stepHidePanels(battle, items)) {
1866 battle->phaseStep = 22;
1867 screen->openMessage(screen, battle->prize, 0, 0, 3);
1868 }
1869 break;
1870 case 22:
1871 if (screen->message.state == 2) {
1872 battle->phaseStep = 23;
1873 }
1874 break;
1875 case 23:
1877 battle->phaseStep = 25;
1878 }
1879 break;
1880 case 25:
1881 result = 2;
1882 break;
1883 case 26:
1884 result = 1;
1885 break;
1886 }
1887 return result;
1888}
1889
1890/* Puts pile's hand back on top of its deck */
1892 while (pile->handCount > 0) {
1893 pile->deck[--pile->deckTop] = pile->hand[--pile->handCount];
1894 pile->deckCount++;
1895 }
1896}
1897
1898/* Puts both hands back in the decks, shuffles the player's, clears the
1899 round's values and moves on to the next round (round) */
1901 CardPile *pile = &battle->sides[0].pile;
1902
1904 CARDGAME_returnOpponentHand(battle, items);
1905#if VERSION_US
1906 CARDGAME_findOpponentDeckLimits(battle, items);
1907#endif
1908 battle->shufflePile(battle, pile->deckTop, pile->deckCount);
1909 battle->keptCard = 0;
1910 battle->keptCount = 0;
1911 battle->sides[0].pile.apTotal = 0;
1912 battle->sides[0].pile.hpTotal = 0;
1913 battle->sides[1].pile.apTotal = 0;
1914 battle->sides[1].pile.hpTotal = 0;
1915 CARDGAME_showPanelValues(battle, items);
1916 battle->round++;
1917#if VERSION_EU || VERSION_JP
1918 CARDGAME_findOpponentDeckLimits(battle, items);
1919#endif
1920}
1921
1922/* Starts the step of battle message prevPhase (CARDGAME_battleMessages) */
1924 s32 i = battle->prevPhase;
1925
1926 battle->run = CARD_RUN_STEP;
1929}
1930
1931/* Sets up a card battle: the sides' panels, no result, CARD_PHASE_FADE_IN */
1933 battle->sides[0].pile.side = 0;
1934 battle->sides[1].pile.side = 1;
1935 battle->result = 0;
1936 battle->playerLost = 1;
1937 battle->phase = CARD_PHASE_FADE_IN;
1938}
1939
1940/* Runs the battle's current phase (phase), after switching to the one asked for in nextPhase; 1 once the battle is over */
1942 s32 done = 0;
1943
1944 if (battle->nextPhase != CARD_PHASE_NONE) {
1945 switch (battle->nextPhase) {
1946 case CARD_PHASE_FADE_IN:
1948 battle->phaseStep = 0;
1949 battle->phaseTime = 0;
1950 break;
1952 case CARD_PHASE_DEAL:
1953 case CARD_PHASE_PUT_OUT:
1954 battle->phaseStep = 0;
1955 break;
1958 CARDGAME_prepareTurn(battle, items);
1959 break;
1961 CARDGAME_openPanelsPhase(battle, items);
1962 break;
1964 CARDGAME_startNextRound(battle, items);
1965 break;
1966 }
1967 battle->prevPhase = battle->phase;
1968 battle->phase = battle->nextPhase;
1969 battle->nextPhase = CARD_PHASE_NONE;
1970 }
1971 switch (battle->phase) {
1972 case CARD_PHASE_FADE_IN:
1973 switch (battle->phaseStep) {
1974 case 0:
1975 default:
1976 items->screen->fadeState = 1;
1977 battle->phaseStep = 1;
1978 break;
1979 case 1:
1980 if (items->screen->fadeState == 2) {
1981 battle->nextPhase = CARD_PHASE_MESSAGE;
1982 }
1983 break;
1984 }
1985 break;
1987 if (CARDGAME_chooseDeck(battle, items)) {
1988 battle->nextPhase = CARD_PHASE_MESSAGE;
1989 }
1990 break;
1992 if (CARDGAME_runFirstPick(battle, items)) {
1993 battle->nextPhase = CARD_PHASE_MESSAGE;
1994 }
1995 break;
1996 case CARD_PHASE_DEAL:
1997 switch (CARDGAME_runStartStep(battle, items)) {
1998 case 1:
1999 battle->nextPhase = CARD_PHASE_MESSAGE;
2000 break;
2001 case 2:
2002 battle->playerLost = 1;
2003 done = 1;
2004 break;
2005 case 3:
2006 battle->playerLost = 0;
2007 done = 1;
2008 break;
2009 }
2010 break;
2013 if (CARDGAME_playRounds(battle, items)) {
2014 battle->nextPhase = CARD_PHASE_MESSAGE;
2015 }
2016 break;
2017 case CARD_PHASE_PUT_OUT:
2018 if (CARDGAME_runPutOut(battle, items)) {
2019 battle->nextPhase = CARD_PHASE_MESSAGE;
2020 }
2021 break;
2023 switch (CARDGAME_endRound(battle, items)) {
2024 case 1:
2026 break;
2027 case 2:
2028 done = 1;
2029 break;
2030 }
2031 break;
2033 battle->nextPhase = CARD_PHASE_MESSAGE;
2034 break;
2035 case CARD_PHASE_MESSAGE:
2036 CARDGAME_startBattleMessage(battle, items);
2037 break;
2038 }
2039 return done;
2040}
2041
2042/* Opens the panels once; 1 once they are open */
2044 s32 done = 0;
2045
2046 if (battle->subState == 0) {
2048 battle->anim.next = CARD_ANIM_SHOW_SLOTS;
2049 items->screen->openPanels(items->screen);
2050 battle->subState++;
2051 }
2052 if (items->screen->panels[0].state == 2 && battle->anim.current == CARD_ANIM_NONE) {
2053 done = 1;
2054 }
2055 return done;
2056}
2057
2058/* Shows the last card played (record.plays) in window 2 for 35 frames (Cross cuts it short), then scales its sprite away; 1 once done */
2060 s32 done = 0;
2061 s32 place;
2062 s32 i;
2063
2064 switch (battle->subState) {
2065 case 0:
2066 battle->subState = 1;
2067 battle->subTime = 0;
2068 place = battle->record.plays[battle->record.playCount - 1].side;
2069#if PAL_VIDEO
2070 items->screen->openWindow(items->screen, 2, 1, battle->cards[battle->record.plays[battle->record.playCount - 1].card] + 1,
2072#else
2073 items->screen->openWindow(items->screen, 2, 1, battle->cards[battle->record.plays[battle->record.playCount - 1].card] + 1,
2074 CARDGAME_playedCardPos[0][place].x, CARDGAME_playedCardPos[0][place].y);
2075#endif
2076 for (i = 0; i < 15; i++) {
2077 items->screen->sprites[i].moving = 0;
2078 }
2079 break;
2080 case 1:
2081 if (battle->subTime >= 20 && PAD_HELD(PAD_CROSS)) {
2082 battle->subTime = 35;
2083 }
2084 battle->subTime += GFX.funcs.getFrameTime();
2085 if (battle->subTime >= 35) {
2086 items->screen->closeWindow(items->screen, 2);
2087 items->screen->scaleSprite(items->screen, battle->record.playCount + 11, 8, 0x1400, 0x1400);
2088 items->screen->closeGauge(items->screen, battle->record.playCount - 1);
2089 battle->subState = 2;
2090 battle->subTime = 0;
2091 SOUND.playSound(0x8004603C);
2092 }
2093 break;
2094 case 2:
2095 battle->subTime += GFX.funcs.getFrameTime();
2096 if (battle->subTime >= 8) {
2097 items->screen->startBlink(items->screen, battle->record.playCount + 11);
2098 battle->subState = 3;
2099 battle->subTime = 0;
2100 }
2101 break;
2102 case 3:
2103 battle->subTime += GFX.funcs.getFrameTime();
2104 if (battle->subTime >= 15) {
2105 items->screen->scaleSprite(items->screen, battle->record.playCount + 11, 4, 0, 0);
2106 battle->subState = 5;
2107 battle->subTime = 0;
2108 SOUND.playSound(0x8004603C);
2109 }
2110 break;
2111 case 5:
2112 battle->subTime += GFX.funcs.getFrameTime();
2113 if (battle->subTime >= 15) {
2114 done = 1;
2115 }
2116 break;
2117 }
2118 return done;
2119}
2120
2121/* When the played card's play condition holds, shows its message instead of
2122 its effects; else starts its effects */
2123static inline void checkPlayedCard(CardBattle *battle, CardBattleItems *items) {
2124 s16 card;
2125
2126 card = battle->cards[battle->record.plays[battle->record.playCount - 1].card];
2127 if (CARDGAME_checkPlayCondition(battle, items->screen, CARDGAME_getEffectField(card, 1, 0))) {
2128 items->screen->openMessage(items->screen, CARDGAME_getEffectField(card, 2, 0), 0, 1, 1);
2129 battle->resolveState = 8;
2130 } else {
2131 battle->effectPos = 0;
2132 battle->resolveState = 7;
2133 }
2134}
2135
2136/* Runs the played card's effect steps one after another, then clears its
2137 marks */
2138static inline void runCardEffects(CardBattle *battle, CardBattleItems *items) {
2139 s32 i;
2140 s32 text;
2141
2142 text = CARDGAME_getEffectField(battle->cards[battle->record.plays[battle->record.playCount - 1].card], 4, battle->effectPos);
2143 if (text != 0) {
2144 battle->effectStep.next = text;
2145 battle->run = CARD_RUN_STEP;
2146 battle->effectPos++;
2147 } else {
2148 if (battle->record.playCount >= 2) {
2149 battle->record.plays[battle->record.playCount - 2].mark = 0;
2150 }
2151 for (i = 0; i < 12; i++) {
2152 items->screen->sprites[i].marks[battle->record.playCount - 1] = 0;
2153 }
2154 battle->resolveState = 10;
2155 }
2156}
2157
2158/* Puts the played card in its side's discards (unless it is card 13) and
2159 takes it (and the one before when that was discarded) off the record */
2160static inline void discardPlayedCard(CardBattle *battle) {
2161 s32 index;
2162 s32 side;
2163 s8 count;
2164
2165 index = battle->record.plays[battle->record.playCount - 1].card;
2166 side = battle->record.plays[battle->record.playCount - 1].side;
2167 if (battle->cards[index] != 13) {
2168 battle->sides[side].pile.discards[battle->sides[side].pile.discardCount] = index;
2169 battle->sides[side].pile.discardCount++;
2170 }
2171 count = battle->record.playCount;
2172 battle->record.playCount = count - 1;
2173 if (battle->prevDiscarded != 0) {
2174 battle->record.playCount = count - 2;
2175 }
2176 battle->resolveState = 13;
2177 battle->subTime = 0;
2178 battle->subState = 0;
2179}
2180
2181/* Plays out the last card played (record.plays): its effect and its messages, then puts it in its side's discards (pile.discards); 1 once done */
2183 u8 done = 0;
2184
2185 switch (battle->resolveState) {
2186 case 0:
2187 default:
2188 if (CARDGAME_setAllCountingValues(battle)) {
2189 battle->effectStep.next = 0x5D;
2190 battle->run = CARD_RUN_STEP;
2191 battle->resolveState = 1;
2192 break;
2193 }
2194 battle->resolveState = 3;
2195 /* fallthrough */
2196 case 3:
2197 if (items->screen->panels[0].state == 0) {
2198 battle->resolveState = 4;
2199 } else {
2200 battle->resolveState = 5;
2201 battle->subTime = 0;
2202 battle->subState = 0;
2203 battle->prevDiscarded = 0;
2204 }
2205 break;
2206 case 1:
2207 battle->effectStep.next = 0x4C;
2208 battle->run = CARD_RUN_STEP;
2209 battle->resolveState = 2;
2210 break;
2211 case 2:
2212 battle->effectStep.next = 0x5A;
2213 battle->run = CARD_RUN_STEP;
2214 battle->resolveState = 3;
2215 break;
2216 case 4:
2217 if (CARDGAME_stepShowPanels(battle, items)) {
2218 battle->resolveState = 5;
2219 battle->subTime = 0;
2220 battle->subState = 0;
2221 battle->prevDiscarded = 0;
2222 }
2223 break;
2224 case 5:
2225 if (CARDGAME_showPlayedCard(battle, items)) {
2226 battle->resolveState = 6;
2227 battle->subTime = 0;
2228 battle->subState = 0;
2229 }
2230 break;
2231 case 6:
2232 checkPlayedCard(battle, items);
2233 break;
2234 case 7:
2235 runCardEffects(battle, items);
2236 break;
2237 case 8:
2239 items->screen->closeMessage(items->screen);
2240 battle->resolveState = 9;
2241 }
2242 break;
2243 case 9:
2244 if (items->screen->message.state == 0) {
2245 battle->resolveState = 12;
2246 }
2247 break;
2248 case 10:
2249 battle->effectStep.next = 0x5A;
2250 battle->run = CARD_RUN_STEP;
2251 battle->resolveState = 11;
2252 break;
2253 case 11:
2254 battle->resolveState = 12;
2255 break;
2256 case 12:
2257 discardPlayedCard(battle);
2258 break;
2259 case 13:
2260 CARDGAME_showPanelValues(battle, items);
2261 battle->resolveState = 14;
2262 break;
2263 case 14:
2264 if (CARDGAME_setAllCountingValues(battle)) {
2265 battle->effectStep.next = 0x5D;
2266 battle->run = CARD_RUN_STEP;
2267 battle->resolveState = 15;
2268 } else {
2269 done = 1;
2270 }
2271 break;
2272 case 15:
2273 battle->effectStep.next = 0x4C;
2274 battle->run = CARD_RUN_STEP;
2275 battle->resolveState = 16;
2276 break;
2277 case 16:
2278 battle->effectStep.next = 0x5A;
2279 battle->run = CARD_RUN_STEP;
2280 battle->resolveState = 17;
2281 break;
2282 case 17:
2283 done = 1;
2284 break;
2285 }
2286 return done;
2287}
2288
2289/* Up and Down move the menu's cursor (wrapping round its five rows), Cross
2290 picks the row, Triangle closes the menu */
2291static inline void moveMenuCursor(CardBattle *battle, CardBattleItems *items) {
2292 s32 cursor;
2293
2294 if ((PAD.getPressed(0) & (1 << PAD.getButtonBit(0, PAD_UP))) |
2295 (PAD.getRepeated(0) & (1 << PAD.getButtonBit(0, PAD_UP)))) {
2296 cursor = battle->record.menuCursor - 1;
2297 if (cursor < 0) {
2298 cursor = 4;
2299 }
2300 battle->record.menuCursor = cursor;
2302 } else if ((PAD.getPressed(0) & (1 << PAD.getButtonBit(0, PAD_DOWN))) |
2303 (PAD.getRepeated(0) & (1 << PAD.getButtonBit(0, PAD_DOWN)))) {
2304 battle->record.menuCursor = (u8)(battle->record.menuCursor + 1) % 5;
2306 }
2307 if (PAD_PRESSED(PAD_CROSS)) {
2308 items->screen->confirmMenu(items->screen);
2309 battle->record.menuState = 4;
2310 } else if (PAD_PRESSED(PAD_TRIANGLE)) {
2312 items->screen->closeMenu(items->screen);
2313 battle->record.menuState = 4;
2314 battle->record.menuCursor = 3;
2315 }
2316 items->screen->setMenuRow(items->screen, battle->record.menuCursor);
2317}
2318
2319/* Once the menu is closed, goes to the picked row's help, back, or the quit
2320 question */
2321static inline void openMenuChoice(CardBattle *battle, CardBattleItems *items) {
2322 if (items->screen->menuState == 0) {
2323 switch (battle->record.menuCursor) {
2324 case 0:
2325 battle->record.menuState = 5;
2326 break;
2327 case 1:
2328 battle->record.menuState = 6;
2329 break;
2330 case 2:
2331 battle->record.menuState = 7;
2332 break;
2333 case 3:
2334 battle->record.menuState = 15;
2335 break;
2336 case 4:
2337 items->screen->openMessage(items->screen, 0x2C, 1, 0, 1);
2338 battle->record.menuState = 8;
2339 break;
2340 }
2341 }
2342}
2343
2344/* The quit question: Up and Down choose yes or no, Cross answers, Triangle
2345 answers no */
2346static inline void answerQuitQuestion(CardBattle *battle, CardBattleItems *items) {
2347 if (PAD_PRESSED(PAD_CROSS)) {
2348 items->screen->confirmMessage(items->screen);
2349 battle->record.menuState = 10;
2350 } else if ((PAD.getPressed(0) & (1 << PAD.getButtonBit(0, PAD_UP))) |
2351 (PAD.getRepeated(0) & (1 << PAD.getButtonBit(0, PAD_UP)))) {
2352 if (items->screen->message.choice != 0) {
2354 }
2355 items->screen->message.choice = 0;
2356 } else if ((PAD.getPressed(0) & (1 << PAD.getButtonBit(0, PAD_DOWN))) |
2357 (PAD.getRepeated(0) & (1 << PAD.getButtonBit(0, PAD_DOWN)))) {
2358 if (items->screen->message.choice != 1) {
2360 }
2361 items->screen->message.choice = 1;
2362 } else if (PAD_PRESSED(PAD_TRIANGLE)) {
2364 items->screen->message.choice = 1;
2365 items->screen->confirmMessage(items->screen);
2366 items->screen->message.choice = 1;
2367 battle->record.menuState = 10;
2368 }
2369}
2370
2371/* The battle menu (record.menuState its state): three help messages, back, and quitting after a yes/no question; 1 when closed, 2 to quit */
2373 s32 result = 0;
2374
2375 switch (battle->record.menuState) {
2376 case 1:
2377 default:
2378 /* save the battle state and the screen's, restored in case 15 */
2379 battle->savedStep = battle->effectStep;
2380 battle->record.menuCursor = 0;
2382 items->screen->openMenu(items->screen, 0);
2383 battle->record.menuState = 2;
2384 break;
2385 case 2:
2386 if (items->screen->menuState == 2) {
2387 battle->record.menuState = 3;
2388 }
2389 break;
2390 case 3:
2391 moveMenuCursor(battle, items);
2392 break;
2393 case 4:
2394 openMenuChoice(battle, items);
2395 break;
2396 case 5:
2397 battle->effectStep.next = 0x9B;
2398 battle->run = CARD_RUN_STEP;
2399 battle->record.menuState = 11;
2400 break;
2401 case 6:
2402 battle->effectStep.next = 0xA8;
2403 battle->run = CARD_RUN_STEP;
2404 battle->record.menuState = 12;
2405 break;
2406 case 7:
2407 battle->effectStep.next = 0x9C;
2408 battle->run = CARD_RUN_STEP;
2409 battle->record.menuState = 13;
2410 break;
2411 case 8:
2412 if (items->screen->message.state == 2) {
2413 battle->record.menuState = 9;
2414 }
2415 break;
2416 case 9:
2417 answerQuitQuestion(battle, items);
2418 break;
2419 case 10:
2420 if (items->screen->message.state == 0) {
2421 if (items->screen->message.choice == 0) {
2422 result = 2;
2423 } else {
2424 battle->record.menuState = 14;
2425 }
2426 }
2427 break;
2428 case 11:
2429 case 12:
2430 case 13:
2431 case 14:
2432 items->screen->openMenu(items->screen, battle->record.menuCursor);
2433 battle->record.menuState = 2;
2434 break;
2435 case 15:
2436 battle->effectStep = battle->savedStep;
2437 result = 1;
2439 battle->record.menuState = 0;
2440 break;
2441 }
2442 return result;
2443}
2444
2445/* A frame of the card battle: the sprites' flags, the card animations, the
2446 fades, then the phase, the effect step, the card's resolution or the battle
2447 menu; 1 once it is over */
2449 s32 done = 0;
2450
2452 CARDGAME_updateCardAnims(battle, items);
2453 CARDGAME_startStepFade(battle, items);
2454 switch (battle->run) {
2455 case CARD_RUN_PHASE:
2456 default:
2457 if (CARDGAME_runPhase(battle, items)) {
2458 done = 1;
2459 }
2460 break;
2461 case CARD_RUN_STEP:
2462 CARDGAME_runEffectStep(battle, items->screen);
2463 break;
2464 case CARD_RUN_RESOLVE:
2465 if (CARDGAME_resolveCard(battle, items)) {
2466 battle->run = CARD_RUN_PHASE;
2467 }
2468 break;
2469 case CARD_RUN_MENU:
2470 switch (CARDGAME_runBattleMenu(battle, items)) {
2471 case 1:
2472 battle->run = CARD_RUN_STEP;
2473 break;
2474 case 2:
2475 done = 1;
2476 break;
2477 }
2478 break;
2479 }
2480 return done;
2481}
2482
2483/* The card battle task: sets up the battle and fades in, runs it (CARDGAME_runBattle), then fades out and gives the player the prize item for a win; result 2 once over */
2485 TimLoader tim;
2486 CardFader *fader;
2487
2488 switch (battle->state) {
2489 case 0:
2490 default:
2491 if (SOUND.isLoading() == 0) {
2493 CARDGAME_initBattle(battle, items);
2494 CARDGAME_loadOpponent(battle, items);
2495 items->screen = CARDGAME_createScreen(battle->cards);
2497 items->screen->resetPanels(items->screen);
2498 items->screen->opponentLevel = battle->opponentLevel;
2499 items->screen->opponent = battle->arg;
2500 initTimLoader(&tim);
2501 tim.setImagePos(0x280, 0);
2503 fader = CARDGAME_createFader(2);
2504 items->fader = fader;
2505 fader->setColor(fader, 0xFF, 0xFF, 0xFF);
2506 items->fader->start(items->fader, 0, 0, 0, 100, 0);
2507 battle->setState(battle, 2);
2509 }
2510 break;
2511 case 1:
2512 if (CARDGAME_runBattle(battle, items)) {
2513 fader = CARDGAME_createFader(2);
2514 items->fader = fader;
2515 fader->setColor(fader, 0, 0, 0);
2516 items->fader->start(items->fader, 0xFF, 0xFF, 0xFF, 100, 0);
2517 battle->setState(battle, 2);
2518 battle->result = 1;
2519 }
2520 break;
2521 case 2:
2522 if (battle->substate == 0 && items->fader->isDone(items->fader)) {
2523 items->fader->kill(items->fader);
2524 if (battle->result != 0) {
2525 if (battle->result != 2) {
2526 if (battle->playerLost == 0) {
2527 if (GAME.items[battle->prize] < 99) {
2528 GAME.items[battle->prize]++;
2529 }
2531 } else {
2533 }
2534 }
2535 battle->result = 2;
2536 } else {
2537 battle->setState(battle, 1);
2538 }
2539 battle->substate = 1;
2540 }
2541 break;
2542 case 3:
2543 if (battle->playerLost == 0) {
2545 } else {
2547 }
2548 break;
2549 }
2550}
2551
2552/* Creates the card battle against opponent arg (CARDGAME_loadOpponent), with
2553 its functions, and loads its sound bank */
2555 CardBattle *battle = createTask(CARDGAME_updateBattle, sizeof(CardBattle), 7 * 4);
2556
2558 battle->sortCards = CARDGAME_sortCards;
2560 battle->addCard = CARDGAME_addCard;
2561 battle->scoreHand = CARDGAME_scoreHand;
2562 battle->arg = arg;
2563 SOUND.loadBank(0x27);
2564 return battle;
2565}
s32 CARDGAME_checkPlayCondition(CardBattle *battle, CardScreen *screen, s32 kind)
Whether the condition kind (1-11) of the card being played holds for its side: 1 if it does.
CARDGAME.PRO: the card battle (mode 0x700).
void initCardDrawer(CardDrawer *obj)
Clears a card drawer, gives it its methods and binds it.
s32 CARDGAME_runPutOut(CardBattle *battle, CardBattleItems *items)
A battle step: each side puts out its flagged cards (putOutCards) between messages 0x9A,...
Definition battle.c:1475
void CARDGAME_layOutPile(CardBattle *battle, CardBattleItems *items, s32 side, s32 which)
Lays out the cards of one of a side's piles (which: 0 the hand; 1 the discards; 2 the deck from deckT...
Definition battle.c:156
void CARDGAME_layOutSlots(CardBattle *battle, CardBattleItems *items)
Lays out the slots as sprites (0-5 player 0's, 6-11 player 1's) and each play of record....
Definition battle.c:351
void CARDGAME_sumSlotValues(CardBattle *battle, s32 side)
Side's apTotal and hpTotal become the sums of its slot cards' ap and hp.
Definition battle.c:1463
void CARDGAME_returnOpponentHand(CardBattle *battle, CardBattleItems *items)
Puts side 1's hand back on its pile and renumbers the pile's cards.
Definition battle.c:120
void CARDGAME_setCountingCardValues(CardBattle *battle, CardSlot *slot, s32 side, s32 pass)
Sets the values of a slot that holds the pass-th card of CARDGAME_countingCards from the battle's cou...
Definition battle.c:1398
static void closeDeckWindow(CardBattle *battle, CardBattleItems *items, s32 index)
Closes deck window index with its sound.
Definition battle.c:766
static void pickRoundWinner(CardBattle *battle)
Gives the round to the side with the higher total (pile.hpTotal) and runs its win's effect step (0x18...
Definition battle.c:1639
static void closeBattleResult(CardBattle *battle, CardScreen *screen)
Cross or Triangle closes the battle's result: the player's win goes on to the prize,...
Definition battle.c:1761
static void markPlayTargets(CardBattle *battle, CardScreen *screen, s32 play)
Marks in each slot sprite's marks[play] whether play of record.plays applies to it,...
Definition battle.c:250
void CARDGAME_initBattle(CardBattle *battle, CardBattleItems *items)
Sets up a card battle: the sides' panels, no result, CARD_PHASE_FADE_IN.
Definition battle.c:1932
void CARDGAME_prepareTurn(CardBattle *battle, CardBattleItems *items)
Clears record.turnState, shows the panel values and sorts the player's hand.
Definition battle.c:1336
static void checkPlayedCard(CardBattle *battle, CardBattleItems *items)
When the played card's play condition holds, shows its message instead of its effects; else starts it...
Definition battle.c:2123
s32 CARDGAME_runStartStep(CardBattle *battle, CardBattleItems *items)
Runs step 20 (CARDGAME_stepStart) and then returns its choice + 1: 1 dealt, 2 the player's deck was s...
Definition battle.c:947
static void showSlots(CardBattle *battle, CardBattleItems *items, CardAnim *anim)
Scales the slots in, a pair every 4 frames, then shows the plays.
Definition battle.c:439
void CARDGAME_resetSpriteFlags(CardBattle *battle)
Sets the 15 sprites' anim.dimmed to whether anim.dimAll is 2, once it is set.
Definition battle.c:425
void CARDGAME_updateCardAnims(CardBattle *battle, CardBattleItems *items)
Starts (anim.next) and runs (anim.current) the screen's card animations: the hands',...
Definition battle.c:553
void CARDGAME_startStepFade(CardBattle *battle, CardBattleItems *items)
Starts the fade that fade asks for (CARDGAME_fadeColors)
Definition battle.c:404
s32 CARDGAME_runBattle(CardBattle *battle, CardBattleItems *items)
A frame of the card battle: the sprites' flags, the card animations, the fades, then the phase,...
Definition battle.c:2448
u8 CARDGAME_resolveCard(CardBattle *battle, CardBattleItems *items)
Plays out the last card played (record.plays): its effect and its messages, then puts it in its side'...
Definition battle.c:2182
void CARDGAME_sortCards(CardBattle *battle, s16 *list, s32 range, s32 flags)
Sorts the cards list[from..to) (range: to << 16 | from) by their values, moving opponentDraws (flags ...
Definition battle.c:693
s32 CARDGAME_findCardSet(CardBattle *battle, s32 side, s32 start)
Finds three or more of one card (with a CardImage.comboCard) among a side's slots,...
Definition battle.c:1516
static void countRoundWin(CardBattle *battle, CardBattleItems *items, CardScreen *screen)
Blinks the round winner's wins on its panel with a flash, then counts the win and shows the round's r...
Definition battle.c:1654
s32 CARDGAME_stepHidePanels(CardBattle *battle, CardBattleItems *items)
Closes the panels once; 1 once they are closed.
Definition battle.c:213
static void runKeptCardSteps(CardBattle *battle)
Runs effect step 0x1B for the kept card (keptCard) until keptCount runs out.
Definition battle.c:1604
static void showPile(CardAnim *anim, CardScreen *screen)
Scales a pile's cards in, one every 4 frames (at least one)
Definition battle.c:513
void CARDGAME_putOutCards(CardBattle *battle, s32 side)
Puts side's flagged cards of its pile into its slots, up to effectStep.count of them.
Definition battle.c:1383
s32 CARDGAME_stepShowPanels(CardBattle *battle, CardBattleItems *items)
Opens the panels once; 1 once they are open.
Definition battle.c:2043
static void runCardEffects(CardBattle *battle, CardBattleItems *items)
Runs the played card's effect steps one after another, then clears its marks.
Definition battle.c:2138
static void showPlays(CardBattle *battle, CardBattleItems *items, CardAnim *anim)
Scales the plays in, one every 4 frames, opening each one's gauge after it.
Definition battle.c:458
s32 CARDGAME_takeFlaggedCard(CardBattle *battle, CardBattleItems *items)
Takes the first flagged card out of the hand of side record.turnSide into the play record....
Definition battle.c:971
static void moveDeckMarker(CardBattle *battle, CardBattleItems *items)
Up and Down move the marker between the three decks; Cross picks the marked one, which blinks.
Definition battle.c:775
static void waitPhaseStep(CardBattle *battle, s32 frames)
Goes to the next phaseStep after frames frames.
Definition battle.c:749
s32 CARDGAME_setAllCountingValues(CardBattle *battle)
Sets the values of the counting cards out, pass by pass (CARDGAME_setCountingCardValues); whether any...
Definition battle.c:1443
void CARDGAME_removeMarkedHandCards(CardBattle *battle, CardPile *pile)
Takes the marked cards (effectStep.marked) out of pile's hand.
Definition battle.c:1343
static void waitRoundResultShown(CardBattle *battle, CardScreen *screen)
Waits for the round's result: its window, or the draw message when the totals are equal.
Definition battle.c:1688
static void startRounds(CardBattle *battle, CardBattleItems *items)
Starts the rounds: clears the record, shows the slots and opens the panels.
Definition battle.c:1091
static void hidePile(CardAnim *anim, CardScreen *screen)
Scales a pile's cards out, one every 4 frames (at least one)
Definition battle.c:533
static void playComputerTurn(CardBattle *battle, CardBattleItems *items)
The computer plays a card (CARDGAME_pickComputerCard); without one it passes when it would play first...
Definition battle.c:1137
s32 CARDGAME_runPhase(CardBattle *battle, CardBattleItems *items)
Runs the battle's current phase (phase), after switching to the one asked for in nextPhase; 1 once th...
Definition battle.c:1941
static void checkBattleWinner(CardBattle *battle, CardScreen *screen)
Once a side has two wins, shows who won the battle; else goes on to the next round.
Definition battle.c:1730
static void waitRoundResultClosed(CardBattle *battle, CardScreen *screen)
Once the round's result is closed, opens message 19.
Definition battle.c:1714
static void closeRoundResult(CardBattle *battle, CardScreen *screen)
Cross or Triangle closes the round's result window or message.
Definition battle.c:1702
static void discardPlayedCard(CardBattle *battle)
Puts the played card in its side's discards (unless it is card 13) and takes it (and the one before w...
Definition battle.c:2160
void CARDGAME_sortOpponentHand(CardBattle *battle)
Sorts the opponent's hand by its cards' opponentPlans kind, then value.
Definition battle.c:71
static void openDeckWindow(CardBattle *battle, CardBattleItems *items, s32 index)
Opens deck window index with its sound.
Definition battle.c:758
static void runRoundEndStep(CardBattle *battle)
Runs the round's closing effect step: 0x1C after the player's win, 0x1D after the opponent's.
Definition battle.c:1749
void CARDGAME_showPanelValues(CardBattle *battle, CardBattleItems *items)
Shows both sides' values on their panels: the points of each colour, the deck, hand and discards,...
Definition battle.c:675
static void answerQuitQuestion(CardBattle *battle, CardBattleItems *items)
The quit question: Up and Down choose yes or no, Cross answers, Triangle answers no.
Definition battle.c:2346
static void startPlay(CardBattle *battle, CardBattleItems *items)
Picks the side that plays next, by the starter and the plays so far, or once three cards are played r...
Definition battle.c:1106
static void hideSlots(CardBattle *battle, CardBattleItems *items, CardAnim *anim)
Scales the slots out, a pair every 4 frames, then hides the plays.
Definition battle.c:477
static void hidePlays(CardBattle *battle, CardBattleItems *items, CardAnim *anim)
Scales the plays out with their gauges, one every 4 frames.
Definition battle.c:496
void CARDGAME_returnHandToDeck(CardPile *pile)
Puts pile's hand back on top of its deck.
Definition battle.c:1891
static void openMenuChoice(CardBattle *battle, CardBattleItems *items)
Once the menu is closed, goes to the picked row's help, back, or the quit question.
Definition battle.c:2321
void CARDGAME_setSlot(CardBattle *battle, s32 side, s32 card, s32 index)
Puts the battle's card card in side's slot index, with its AP and HP and the order it came out in.
Definition battle.c:1359
void CARDGAME_shufflePile(CardBattle *battle, s32 base, s32 n)
Shuffles the player's pile's deck[base..base + n) with 40 random swaps.
Definition battle.c:730
s32 CARDGAME_runFirstPick(CardBattle *battle, CardBattleItems *items)
Runs step 0xA7 (CARDGAME_startFirstPick) and then keeps who goes first (firstStarter); 1 once done.
Definition battle.c:927
void CARDGAME_findOpponentDeckLimits(CardBattle *battle, CardBattleItems *items)
drawEnd: the first card of the opponent's deck above the round's level (round); reserveStart: the end...
Definition battle.c:102
static void checkEmptyRows(CardBattle *battle, CardScreen *screen)
When a side has no slots left, the round ends at once, the higher total winning; else the round's res...
Definition battle.c:1619
void CARDGAME_startBattleMessage(CardBattle *battle, CardBattleItems *items)
Starts the step of battle message prevPhase (CARDGAME_battleMessages)
Definition battle.c:1923
static void loadChosenDeck(CardBattle *battle, CardBattleItems *items)
Loads the chosen deck (or the default one when it is empty) and the opponent's, fills both piles and ...
Definition battle.c:800
void CARDGAME_openPanelsPhase(CardBattle *battle, CardBattleItems *items)
Opens the panels for a phase.
Definition battle.c:1570
void CARDGAME_updateBattle(CardBattle *battle, CardBattleItems *items)
The card battle task: sets up the battle and fades in, runs it (CARDGAME_runBattle),...
Definition battle.c:2484
s32 CARDGAME_playRounds(CardBattle *battle, CardBattleItems *items)
Runs the rounds of plays (state record.turnState): each side in turn plays a card,...
Definition battle.c:1230
s32 CARDGAME_chooseDeck(CardBattle *battle, CardBattleItems *items)
Chooses the player's deck: opens the three deck windows and a marker, Up/Down/Cross pick one,...
Definition battle.c:830
void CARDGAME_flagTargetSlots(CardBattle *battle, CardScreen *screen)
Flags (effectStep.marked) the slots that the current play's target kind (record.plays[playCount]....
Definition battle.c:997
static void runOpponentCardSets(CardBattle *battle)
Runs effect step 0x1A for each set of three or more of one card among the opponent's slots (CARDGAME_...
Definition battle.c:1592
static void runPlayerCardSets(CardBattle *battle)
Runs effect step 0x19 for each set of three or more of one card among the player's slots (CARDGAME_fi...
Definition battle.c:1579
static void playPlayerTurn(CardBattle *battle, CardBattleItems *items)
The player picks a card to play (effect step 0x98); without one they pass when they would play first,...
Definition battle.c:1170
void CARDGAME_startPileCount(CardBattle *battle, CardBattleItems *items, s32 side, s32 which)
Starts the count of side's hand, discards or deck (which 0-2)
Definition battle.c:228
void CARDGAME_loadOpponent(CardBattle *battle, CardBattleItems *items)
Loads the opponent's data (FILE_CARDGAME_OPPONENTS, entry arg - 1): its deck and its card order.
Definition battle.c:7
CardBattle * CARDGAME_createBattle(s32 arg)
Creates the card battle against opponent arg (CARDGAME_loadOpponent), with its functions,...
Definition battle.c:2554
s32 CARDGAME_runBattleMenu(CardBattle *battle, CardBattleItems *items)
The battle menu (record.menuState its state): three help messages, back, and quitting after a yes/no ...
Definition battle.c:2372
static void moveMenuCursor(CardBattle *battle, CardBattleItems *items)
Up and Down move the menu's cursor (wrapping round its five rows), Cross picks the row,...
Definition battle.c:2291
static void takePickedCard(CardBattle *battle, CardBattleItems *items)
Takes the picked card into the play and runs its condition's step: when it holds the card is played,...
Definition battle.c:1194
void CARDGAME_addCard(CardBattle *battle, s32 side, s32 card)
CardBattle.addCard: puts card in side's next slot.
Definition battle.c:1376
s32 CARDGAME_endRound(CardBattle *battle, CardBattleItems *items)
The end of a round: shows both sides' cards, gives the round to the higher total (pile....
Definition battle.c:1774
s32 CARDGAME_showPlayedCard(CardBattle *battle, CardBattleItems *items)
Shows the last card played (record.plays) in window 2 for 35 frames (Cross cuts it short),...
Definition battle.c:2059
void CARDGAME_startNextRound(CardBattle *battle, CardBattleItems *items)
Puts both hands back in the decks, shuffles the player's, clears the round's values and moves on to t...
Definition battle.c:1900
static void startNextTurn(CardBattle *battle)
Starts the next turn, the other side starting; after two passes the rounds end (state 15)
Definition battle.c:1214
#define FILE_CARDGAME_OPPONENTS
The opponents of the card battles (CardOpponent)
Definition battle.h:15
@ CARD_PHASE_FIRST_PICK
who starts
Definition battle.h:82
@ CARD_PHASE_PUT_OUT
Definition battle.h:85
@ CARD_PHASE_DEAL
six cards to each side
Definition battle.h:83
@ CARD_PHASE_NEXT_ROUND
Definition battle.h:88
@ CARD_PHASE_PLAYS_AFTER
plays after: any kind but 0
Definition battle.h:86
@ CARD_PHASE_PLAYS_BEFORE
plays before the cards are put out: kind 2 cards only
Definition battle.h:84
@ CARD_PHASE_END_ROUND
Definition battle.h:87
@ CARD_PHASE_FADE_IN
Definition battle.h:80
@ CARD_PHASE_NONE
for nextPhase: no switch
Definition battle.h:79
@ CARD_PHASE_CHOOSE_DECK
Definition battle.h:81
@ CARD_PHASE_MESSAGE
Definition battle.h:89
@ CARD_RUN_MENU
Definition battle.h:74
@ CARD_RUN_RESOLVE
the card just played (CARDGAME_resolveCard)
Definition battle.h:73
@ CARD_RUN_STEP
an effect step (CARDGAME_runEffectStep)
Definition battle.h:72
@ CARD_RUN_PHASE
the battle's phase (CARDGAME_runPhase)
Definition battle.h:71
#define CARD_ANIM_UNDIM_ALL
CardAnim.dimAll.
Definition battle.h:189
@ CARD_ANIM_HIDE_DECK
Definition battle.h:175
@ CARD_ANIM_HIDE_HAND
Definition battle.h:173
@ CARD_ANIM_LAY_OUT_HAND
the hand laid out at once
Definition battle.h:184
@ CARD_ANIM_HIDE_SLOTS
Definition battle.h:169
@ CARD_ANIM_SHOW_OPPONENT_DISCARDS
Definition battle.h:182
@ CARD_ANIM_SHOW_HAND
the player's piles...
Definition battle.h:172
@ CARD_ANIM_SHOW_DISCARDS
Definition battle.h:176
@ CARD_ANIM_SHOW_OPPONENT_DECK
Definition battle.h:180
@ CARD_ANIM_SHOW_PLAYS
Definition battle.h:170
@ CARD_ANIM_HIDE_OPPONENT_DISCARDS
Definition battle.h:183
@ CARD_ANIM_HIDE_OPPONENT_DECK
Definition battle.h:181
@ CARD_ANIM_SHOW_SLOTS
Definition battle.h:168
@ CARD_ANIM_SHOW_DECK
Definition battle.h:174
@ CARD_ANIM_LAY_OUT_OPPONENT_HAND
Definition battle.h:185
@ CARD_ANIM_HIDE_PLAYS
Definition battle.h:171
@ CARD_ANIM_HIDE_OPPONENT_HAND
Definition battle.h:179
@ CARD_ANIM_SHOW_OPPONENT_HAND
...and the opponent's
Definition battle.h:178
@ CARD_ANIM_NONE
Definition battle.h:167
@ CARD_ANIM_HIDE_DISCARDS
Definition battle.h:177
CardFader * CARDGAME_createFader(u8 blend)
Creates a fader, with the semi-transparency rate BLEND.
Definition fader.c:112
CardScreen * CARDGAME_createScreen(s16 *cards)
Creates the card screen over cards, with its functions.
Definition screen.c:684
s16 CARDGAME_animPiles[7][2]
the side and pile CARDGAME_updateCardAnims passes to CARDGAME_layOutPile
Definition cardgame_3.c:160
CardFadeColor CARDGAME_fadeColors[]
CARDGAME_startStepFade's fade colours and blends, by fade - 1.
Definition cardgame_3.c:156
s32 CARDGAME_slotRowPositions[2][4]
sprite positions, by SHIFT_PAL_SCREEN
Definition cardgame_3.c:14
u8 CARDGAME_turnStates[]
the next record.turnState state, by step and side
Definition cardgame_3.c:162
u16 CARDGAME_defaultDeck[]
the deck used when the chosen one is empty: its first 40 cards, as card ids - 1 (CardBattle....
Definition cardgame_3.c:144
CardOffset CARDGAME_deckWindowPos[3]
the three deck windows
Definition cardgame_3.c:161
CardBattleMessage CARDGAME_battleMessages[]
the step and nextPhase of CARDGAME_startBattleMessage, by prevPhase
Definition cardgame_3.c:165
CardMessageWindow CARDGAME_savedScreenState
Definition cardgame_3.c:193
CardOffset CARDGAME_playedCardPos[2][2]
then the same moved for SHIFT_PAL_SCREEN
Definition cardgame_3.c:177
s16 CARDGAME_prizeItems[]
the item an opponent gives for a win (CardBattle.prize), by its CardOpponent.prize
Definition cardgame_3.c:137
s16 CARDGAME_countingCards[]
five card ids, minus one
Definition cardgame_3.c:134
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
signed char s8
Definition common.h:7
signed short s16
Definition common.h:9
unsigned char u8
Definition common.h:8
s32 CARDGAME_scoreHand(CardBattle *battle, s32 side, s32 mask)
Scores the cards in a side's slots, counting runs of the same card.
Definition computer.c:143
s32 CARDGAME_pickComputerCard(CardBattle *battle, CardScreen *screen)
Picks the computer's next card, flagging it in effectStep.marked; returns 1 if one was found.
Definition computer.c:615
CardMarker * CARDGAME_createMarker(s16 x, s16 y)
Creates the deck marker at x, y, which shows the selected deck window.
Definition deck_choice.c:98
CardDeckWindow * CARDGAME_createDeckWindow(s32 deck, s32 x, s32 y)
Creates the window of deck deck at x, y, with how many cards of each colour it has.
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
void CARDGAME_runEffectStep(CardBattle *battle, CardScreen *screen)
Starts the effect step battle->effectStep.next asks for (startEffectStep), then runs the current one ...
s32 CARDGAME_getEffectField(s32 index, u32 field, s32 offset)
One field of card effect index (CardEffect): 0 its condition, 1 its play condition,...
GameFlags FLAGS_00
The flag bitset FLAGS_00 and the event functions.
Definition events.c:701
GameState GAME
The save data, the game mode and the methods.
Definition state.c:64
s32 SHIFT_PAL_SCREEN
moves both display areas 0x18 lines down
Definition eu_settings.c:15
FileCache FILE_CACHE
The file cache.
Definition file_cache.c:7
PadState PAD
Controller input: cleared by initPad, then the methods.
Definition pad.c:168
#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_HELD(button)
Definition pad.h:142
CardPreloader * CARDGAME_startPreloader(void)
Starts the preloader of the card game's files (CARDGAME_tickPreloader)
Definition preloader.c:46
Random RANDOM
Definition random.c:533
@ CARD_PANEL_HAND
Definition screen.h:200
@ CARD_PANEL_DISCARDS
Definition screen.h:201
@ CARD_PANEL_HP
Definition screen.h:203
@ CARD_PANEL_AP
Definition screen.h:202
@ CARD_PANEL_DECK
Definition screen.h:199
#define FILE_CARDGAME_TIMS
CARDGAME's own pictures, a TIM archive.
Definition screen.h:15
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_WIN_JINGLE
W_JINGLE: a battle won.
Definition sound.h:48
#define MUSIC_CARD_BATTLE
CBTLMAIN: the card battles.
Definition sound.h:113
#define SOUND_MENU_CLOSE
SYSTEM04.
Definition sound.h:42
#define SOUND_MENU_CONFIRM
SYSTEM07.
Definition sound.h:44
#define SOUND_MENU_OPEN
SYSTEM03.
Definition sound.h:41
#define SOUND_MENU_CANCEL
SYSTEM01.
Definition sound.h:39
#define SOUND_MENU_MOVE
SYSTEM06.
Definition sound.h:43
#define SOUND_CURSOR
SYSTEM02: a cursor moves.
Definition sound.h:40
Task * start(void)
The mode's entry point (MODE_ENTRY_POINTS): starts its root task (update_scene.inc....
Definition start.inc.c:3
The running animation of the cards on the table (CARDGAME_updateCardAnims)
Definition battle.h:193
s32 duration
Definition battle.h:205
s32 count
the pile's cards
Definition battle.h:204
u8 faceDown
the next pile or slots are laid out face down
Definition battle.h:198
u8 next
the one to start
Definition battle.h:195
s32 time
Definition battle.h:201
s32 shown
the sprites scaled so far
Definition battle.h:202
u8 current
a CardAnimId
Definition battle.h:194
u8 dimAll
sets dimmed of the first 15 sprites once
Definition battle.h:199
u8 hide
the one that hides what the last one showed
Definition battle.h:197
s32 stagger
one more sprite scales every 4 frames
Definition battle.h:203
u8 dimmed[40]
by sprite
Definition battle.h:200
The card battle's task items.
Definition battle.h:284
CardPreloader * preloader
the card game's files' (CARDGAME_startPreloader)
Definition battle.h:285
CardFader * fader
Definition battle.h:286
CardDeckWindow * deckWindows[3]
Definition battle.h:288
CardScreen * screen
Definition battle.h:289
CardMarker * marker
the deck choice's
Definition battle.h:287
u16 phase
for CardBattle.nextPhase
Definition battle.h:96
u16 step
for CardStep.next
Definition battle.h:95
The card battle (CARDGAME_createBattle).
Definition battle.h:226
u8 fade
the fade to start (CARDGAME_fadeColors), plus one
Definition battle.h:251
s32 prize
the item the player wins (GAME.items)
Definition battle.h:236
u8 run
what runs this frame (CARD_RUN_*)
Definition battle.h:238
u8 phaseStep
the phase's own state
Definition battle.h:243
u8 drawEnd
the first card of the opponent's deck above the round's group
Definition battle.h:260
void(* putOutCards)(struct CardBattle *battle, s32 side)
Definition battle.h:278
u8 playsToResolve
record.playCount, as CARDGAME_resolveCard starts; nothing reads it
Definition battle.h:266
CardPlayer players[2]
Definition battle.h:275
void(* setState)(struct CardBattle *task, s32 state)
Definition battle.h:227
s16 deckChoice
the player's deck (GAME.decks)
Definition battle.h:235
u8 arg
the mode argument: the opponent, from 1
Definition battle.h:233
CardRecord record
Definition battle.h:273
u8 firstStarter
the side that starts the first round
Definition battle.h:239
u8 resolveState
CARDGAME_resolveCard's.
Definition battle.h:264
u8 opponentLevel
CardOpponent.level.
Definition battle.h:234
s16 playerDeck[40]
the player's deck
Definition battle.h:232
s16 cards[250]
card ids, minus one (CARDGAME_loadCardImages)
Definition battle.h:228
u8 result
2 once the battle is over
Definition battle.h:248
s32 substate
Definition battle.h:227
u8 playerLost
0 once the player has won the battle
Definition battle.h:247
u8 prevDiscarded
the card before the last one played went off too
Definition battle.h:265
u8 keptCount
and how many times
Definition battle.h:250
s32(* scoreHand)(struct CardBattle *battle, s32 side, s32 mask)
Definition battle.h:280
CardPlan opponentPlans[40]
one per card of side 1 (40-79)
Definition battle.h:257
s32 phaseTime
a frame count, or the phase's own counter
Definition battle.h:244
s16 effectPos
the step of the card's effect script to run next
Definition battle.h:267
u8 roundWinner
the side that won the round
Definition battle.h:246
u8 phase
a CARD_PHASE_*
Definition battle.h:242
void(* shufflePile)(struct CardBattle *battle, s32 base, s32 n)
Definition battle.h:276
u8 reserveStart
the first card of the opponent's deck held back (group 7)
Definition battle.h:261
CardOpponent * opponents
file FILE_CARDGAME_OPPONENTS
Definition battle.h:237
s32 subState
the state of a phase's helpers (CARDGAME_showPlayedCard...)
Definition battle.h:270
s32 state
Definition battle.h:227
CardAnim anim
Definition battle.h:263
void(* sortCards)(struct CardBattle *battle, s16 *list, s32 range, s32 flags)
Definition battle.h:277
CardStep effectStep
Definition battle.h:262
u8 nextPhase
the phase to switch to, if not 0
Definition battle.h:241
CardStep savedStep
the step, while the battle menu is open
Definition battle.h:272
void(* addCard)(struct CardBattle *battle, s32 side, s32 card)
Definition battle.h:279
u8 cardCount
in cards
Definition battle.h:229
u8 round
from 0
Definition battle.h:245
s16 opponentDeck[40]
the opponent's deck
Definition battle.h:231
u8 prevPhase
Definition battle.h:240
s32 subTime
and their frame count
Definition battle.h:271
u8 counterCards[0x1B]
the cards the computer answers with a kind 4 card, up to an 0xFF
Definition battle.h:259
u8 keptCard
the card CARDGAME_keepLastCard kept, plus one
Definition battle.h:249
u8 slotCount
the slots added so far
Definition battle.h:253
CardSide sides[2]
Definition battle.h:274
CardDraw opponentDraws[40]
by the opponent's deck card
Definition battle.h:255
s16 card
the id plus one in the low 12 bits; bit 15 a flag
Definition battle.h:210
u8 group
when the computer draws it (CardDraw.group)
Definition battle.h:211
u8 kind
how it plays it (CardPlan.kind)
Definition battle.h:212
void(* close)(struct CardDeckWindow *window)
Definition choice.h:53
void(* setBlink)(struct CardDeckWindow *window)
Definition choice.h:52
Where a card of the opponent's deck is drawn (CardBattle.opponentDraws): the computer draws the cards...
Definition battle.h:102
u8 order
its place in the deck
Definition battle.h:103
u8 group
Definition battle.h:104
Draws the cards' images (CardImage), from files 0x7E7-0x7EB.
Definition gfx.h:193
void(* setCard)()
(id)
Definition gfx.h:205
CardImage * card
Definition gfx.h:194
Fades the screen to a colour: a POLY_F4 over it, blended (blend is the semi-transparency rate)
Definition screen.h:34
void(* kill)(struct CardFader *fader)
Definition screen.h:47
void(* setColor)(struct CardFader *fader, u8 r, u8 g, u8 b)
Definition screen.h:44
s32(* isDone)(struct CardFader *fader)
Definition screen.h:46
void(* start)(struct CardFader *fader, u8 r, u8 g, u8 b, s32 frames, s32 killWhenDone)
Definition screen.h:45
s16 comboCard
the card (from 1) that three or more of it make (CARDGAME_findCardSet), 0 for none
Definition gfx.h:183
u8 hp
Definition gfx.h:175
u8 ap
Definition gfx.h:174
void(* close)(struct CardMarker *marker)
Definition choice.h:33
void(* setFast)(struct CardMarker *marker)
Definition choice.h:34
void(* setPos)(struct CardMarker *marker, s16 x, s16 y)
Definition choice.h:32
s16 choice
the cursor's row
Definition screen.h:254
u8 state
1 opening, 2 open, 4 confirmed, 5 closing
Definition screen.h:256
s16 x
Definition screen.h:60
s16 y
Definition screen.h:61
An opponent of the card battle: an entry of file FILE_CARDGAME_OPPONENTS, picked by CardBattle....
Definition battle.h:217
u8 level
shown after "LV" (card text 0x3E), 4-92
Definition battle.h:220
CardDeckCard cards[40]
Definition battle.h:218
s32 prize
its index in CARDGAME_prizeItems
Definition battle.h:221
s16 counterCards[20]
from 1, up to a 0: CardBattle.counterCards before the usual ones
Definition battle.h:219
s32 wins
the rounds won shown
Definition screen.h:158
CardPanelScale scale
Definition screen.h:159
s16 state
Definition screen.h:137
A player's cards in a card battle (CardSide.pile)
Definition battle.h:108
s16 hpTotal
the sum of its slot cards' hp: the higher one wins the round
Definition battle.h:110
s16 deckCount
the cards left in the deck
Definition battle.h:113
s16 discardCount
Definition battle.h:112
s16 deck[40]
deckTop on are left
Definition battle.h:118
s16 handCount
Definition battle.h:114
u8 side
its panel
Definition battle.h:116
s16 deckTop
the index of the deck's top card
Definition battle.h:111
u8 points[5]
one per card colour
Definition battle.h:115
s16 apTotal
the sum of its slot cards' ap, which comes off the other side's hpTotal
Definition battle.h:109
u8 wins
rounds won: two win the battle
Definition battle.h:117
s16 discards[10]
the cards played and lost from the slots, discardCount in use
Definition battle.h:120
s16 hand[10]
handCount in use
Definition battle.h:119
u8 kind
1-7 (CardDeckCard.kind)
Definition battle.h:64
u8 flagged
bit 15 of the card in the opponent's deck
Definition battle.h:65
s16 priority
by kind, then by place in the deck
Definition battle.h:66
s16 card
the index in the battle's card list
Definition battle.h:44
u8 targetKind
its effect's (CardEffect.target)
Definition battle.h:47
u8 side
who played it
Definition battle.h:46
u8 target
the slot's order, or the card, it was played on
Definition battle.h:48
s16 mark
Definition battle.h:45
One of the two players of a card battle.
Definition battle.h:37
CardSlot slots[8]
Definition battle.h:39
u8 slotCount
Definition battle.h:38
Reads CARDGAME's files into the file cache, one at a time.
Definition screen.h:25
s32 ready
the files before the first -2 are in
Definition screen.h:27
u8 menuState
CARDGAME_runBattleMenu's state.
Definition battle.h:126
s32 waitTime
Definition battle.h:136
u8 turns
the turns of plays this round
Definition battle.h:131
u8 turnState
CARDGAME_playRounds' state.
Definition battle.h:129
u8 menuCursor
CARDGAME_runBattleMenu's cursor, 0-4.
Definition battle.h:127
s8 answer
a step's result: -1 while waiting, then 0 or 1
Definition battle.h:135
s8 playCount
the plays in use
Definition battle.h:130
u8 turnSide
the side whose turn it is
Definition battle.h:134
u8 passes
the turns with no card played: two end the plays
Definition battle.h:132
u8 starter
the side that starts the round
Definition battle.h:133
CardPlay plays[3]
the cards played this turn, up to three
Definition battle.h:137
The battle screen (created by CARDGAME_createScreen): the two panels, the cards on the table and the ...
Definition screen.h:263
CardMessageWindow message
Definition screen.h:274
void(* setSpriteCard)(struct CardScreen *screen, s32 sprite, s32 index)
Definition screen.h:324
void(* openWindow)(struct CardScreen *screen, s32 index, s16 layout, s32 value, s32 x, s32 y)
Definition screen.h:288
void(* openMenu)(struct CardScreen *screen, s16 row)
Definition screen.h:306
void(* setPanelValue)(struct CardScreen *screen, s32 side, u32 which, s32 value)
Definition screen.h:285
void(* scaleSprite)(struct CardScreen *screen, s32 index, s32 duration, s32 scaleX, s32 scaleY)
Definition screen.h:318
s32(* getCardColor)(struct CardScreen *screen, s32 index)
Definition screen.h:325
void(* resetPanels)(struct CardScreen *screen)
Definition screen.h:296
void(* openPanels)(struct CardScreen *screen)
Definition screen.h:295
CardSprite sprites[40]
Definition screen.h:271
void(* openMessage)(struct CardScreen *screen, s32 message, s32 prompt, s16 choice, s32 place)
Definition screen.h:302
s32(* getHandOffset)(s32 count, s32 index)
Definition screen.h:299
void(* closeMenu)(struct CardScreen *screen)
Definition screen.h:307
void(* confirmMessage)(struct CardScreen *screen)
Definition screen.h:304
s32(* removeSprite)(struct CardScreen *screen, s32 index)
Definition screen.h:315
void(* closePanels)(struct CardScreen *screen)
Definition screen.h:294
void(* openPanelIcon)(struct CardScreen *screen, s32 side)
Definition screen.h:297
CardWindow windows[6]
Definition screen.h:281
void(* closeMessage)(struct CardScreen *screen)
Definition screen.h:303
s16 menuState
Definition screen.h:280
void(* closeWindow)(struct CardScreen *screen, s32 index)
Definition screen.h:289
s32(* loadCardImages)(s16 *dst, s16 *player, s16 *opponent)
Definition screen.h:326
u8 fadeState
0 dark, 1 fading in, 2 shown
Definition screen.h:284
s32(* startBlink)(struct CardScreen *screen, s32 index)
Definition screen.h:316
void(* confirmMenu)(struct CardScreen *screen)
Definition screen.h:308
s16 opponent
CardBattle.arg.
Definition screen.h:268
void(* closeGauge)(struct CardScreen *screen, s32 index)
Definition screen.h:287
void(* setMenuRow)(struct CardScreen *screen, s16 row)
Definition screen.h:309
void(* closePanelIcon)(struct CardScreen *screen, s32 side)
Definition screen.h:298
void(* openGauge)(struct CardScreen *screen, s32 index, s16 value)
Definition screen.h:286
s32(* addSprite)(struct CardScreen *screen, s32 index, s32 x, s32 y)
Definition screen.h:314
CardPanel panels[2]
Definition screen.h:270
s16 opponentLevel
CardBattle.opponentLevel.
Definition screen.h:269
Each player's side of a card battle (CardBattle.sides)
Definition battle.h:159
CardPile pile
Definition battle.h:160
A card a player has out (CARDGAME_setSlot)
Definition battle.h:19
u8 owner
Definition battle.h:26
s16 hp
its hit points, 0 to 99: at 0 it is lost
Definition battle.h:24
s16 hpBonus
and to its hp
Definition battle.h:22
u8 side
Definition battle.h:25
s16 apBonus
what the effects added to its ap
Definition battle.h:21
s16 ap
its attack points, 0 to 99
Definition battle.h:23
s16 card
the index in the battle's card list
Definition battle.h:20
u8 order
CardBattle.slotCount when it was added.
Definition battle.h:27
A slot's card, sorted by id (CARDGAME_findCardSet)
Definition battle.h:31
s16 card
its id, minus one
Definition battle.h:33
A card on the battle screen (CardScreen.sprites)
Definition screen.h:163
s16 moving
Definition screen.h:177
u8 ap
the values shown, which count towards the slot's
Definition screen.h:188
u8 dimmed
Definition screen.h:194
u8 order
a played card's place in the record, from 1
Definition screen.h:191
u8 visible
Definition screen.h:190
s16 scaleX
Definition screen.h:170
u8 marks[3]
the plays that apply to the card, drawn as marks
Definition screen.h:185
s8 eligible[0x29]
the cards or slots that can be picked
Definition battle.h:154
u8 count
the cards picked, or to draw
Definition battle.h:152
s32 vars[5]
values each step uses its own way
Definition battle.h:149
s8 marked[40]
the cards or slots picked
Definition battle.h:155
s32 choice
the card, slot or answer chosen; -1 for none
Definition battle.h:151
u8 next
the step to start: CARDGAME_runEffectStep sets it up first
Definition battle.h:145
s16 cards[40]
Definition game_state.h:275
void *(* load)(u32 file)
Definition file.h:92
void *(* getEntry)(u32 fileAndIndex)
Definition file.h:96
s32 cardBattleWon
1 when the player won the card battle; updateModeFlags copies it to FLAG_CARD_BATTLE_WON
Definition game_state.h:50
s8 items[0x193]
counts, up to 99
Definition game_state.h:512
Deck decks[3]
Definition game_state.h:516
s32(* getFrameTime)(void)
Definition gfx.h:32
GfxFuncs funcs
Definition gfx.h:77
s32(* getRepeated)(s32 pad)
Definition pad.h:127
s32(* getButtonBit)(s32 pad, s32 button)
Definition pad.h:130
s32(* getPressed)(s32 pad)
Definition pad.h:125
s32(* next)(void)
0 to RANDOM_COUNT - 1
Definition random.h:15
s32(* isLoading)(void)
Definition sound.h:193
void(* stopSound)(s32 id)
Definition sound.h:195
void(* loadBank)(s32 id)
Definition sound.h:190
short(* playSound)(s32 id)
returns the voice of a key-on
Definition sound.h:187
Uploads TIM images to VRAM (initTimLoader); acts on TIM_LOADER.
Definition gfx.h:325
void(* setImagePos)()
(x, y)
Definition gfx.h:336
void(* loadArchive)()
(archive): each image 64 halfwords to the right
Definition gfx.h:338
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
void initTimLoader(TimLoader *obj)
Clears a TIM loader, gives it its methods and binds it.
Definition tim_loader.c:119