Alchemy
Loading...
Searching...
No Matches

staging.c

Go to the documentation of this file.
1/// @file
2/// An action played: its targets, and how an attack, a cast, an item, a
3/// summon or an escape is staged.
4/// Part of battle.c, the battle object, compiled only through it.
5
7
8/// Plays one action of the round, after delay frames facing the party: an
9/// enemy picks its ability now; the action is planned (its targets, hits
10/// and damage) and shown the way its staging asks, then the turn's end
11/// effects run and every unit returns to its spot. Returns 1 when the
12/// party got away, 0 otherwise, and -1 when the actor is already down.
13/// Called by Battle_RunEncounter for each action of the round, with a delay
14/// of 10 for the first. Resets the camera's view (gTransitionWork's frames,
15/// flag and yaw, gBattleWork->brightness, the transform and projection),
16/// builds gBattleWork->plan, and marks the action done (request->unitId to
17/// BATTLE_UNIT_LIST_END) unless the party fled.
19 s32 delay) {
20 struct BattlePresentationTransition *transition;
21 struct BattleWork *battle;
22 struct BattleCamera *camera;
23 struct BattleUnit *unit;
24 u16 actingUnit[2];
25 u16 unitIds[14];
26 s32 fled;
27 s32 result;
28 s32 unitCount;
29 s32 unitIndex;
30
31 fled = 0;
32 if (request->unitId == BATTLE_UNIT_LIST_END)
33 return 0;
34 unit = UnitGetFar(request->unitId);
35 if (unit->hp == 0)
36 return -1;
37 // An enemy settles its ability now, at its turn.
38 if (unit->classIndex == 0)
40
41 // The view: the camera eases over 60 frames, the background at full
42 // brightness (1.0 in 16.16).
44 transition->frames = 60;
46 transition->flag = 0;
47 battle->brightness = 0x10000;
50 Transform_SetLookAt(camera->eye, camera->pos);
51 Projection_Set(0x01fe0000, Iwram_RatioMulQ14(0x01fe0000, 0xc000), 0x7fff0000);
52 if (delay != 0) {
53 transition->targetYaw = YAW_PARTY_TURN;
54 WaitFrames(delay);
55 }
56 // Plan the action, with the actor highlighted, and stage it by its
57 // outcome. A plan that failed has shown its message; -1 waits for the
58 // player first.
59 actingUnit[0] = request->unitId;
60 actingUnit[1] = BATTLE_UNIT_LIST_END;
61 BattlePres_SetActorModes(actingUnit, 1);
62 result = BattleCommand_BuildPlan(request, &battle->plan);
63 if (result == 0) {
64 switch (battle->plan.outcome) {
67 break;
69 BattlePres_RunAttack(&battle->plan, 0);
70 break;
73 break;
76 break;
77 case PLAN_SHOW_CAST:
79 break;
82 break;
85 break;
86 case PLAN_SHOW_ITEM:
87 BattlePres_RunItem(&battle->plan, 0, request);
88 break;
89 case PLAN_SHOW_FLEE:
90 if (BattlePres_RunEscape(&battle->plan) != 0)
91 fled = 1;
92 if (fled != 0)
93 goto finish;
94 break;
95 }
96 } else {
97 if (result == -1) {
99 WaitFrames(3);
100 }
102 }
103
104 // The turn's end, then every unit back to its spot. A party that fled
105 // skips this and the action's mark.
108 BattleObjPut();
109 unitCount = BattleParty_ListActorIds(BATTLE_SIDE_BOTH, unitIds);
110 for (unitIndex = 0; unitIndex < unitCount; unitIndex++)
111 ObjMotRst(unitIds[unitIndex]);
112 request->unitId = BATTLE_UNIT_LIST_END;
113finish:
115 return fled;
116}
117
118/// Fills an effect command from a plan: its kind and strength,
119/// the actor and the targets still standing (or every target, for an effect
120/// that revives), at least the first.
121/// Called by each staging runner before its effect plays: RunUnitTransition,
122/// RunAttack, RunPlainAttack, RunItem and RunPsynergyCast. Writes effect's
123/// prelude (0), kind, variant, actor, actors, firstTarget, count and range
124/// (1); the caller sets its side.
125#ifdef UBFIX
126void BattlePres_BuildTargetList(struct BattlePlan *plan,
127 struct BattleEffectArgument *effect) {
128#else
130 struct BattleEffectArgument *effect) {
131#endif
132 s16 *outputTarget;
133 u32 flags;
134 s32 livingTargets;
135 s32 targetIndex;
136 u8 *inputTarget;
137
138 livingTargets = 0;
139 effect->prelude = 0;
140 flags = plan->presentationFlags;
141 effect->kind = flags & STAGING_KIND_MASK;
143 effect->actor = plan->actorId;
144 targetIndex = 0;
145 if (targetIndex < plan->targetCount) {
146 inputTarget = plan->targetIds;
147 outputTarget = effect->actors;
148 do {
149 if (UnitGetFar(*inputTarget)->hp != 0 ||
151 livingTargets++;
152 *outputTarget++ = *inputTarget;
153 }
154 targetIndex++;
155 inputTarget++;
156 } while (targetIndex < plan->targetCount);
157 }
158 if (livingTargets == 0) {
159 effect->actors[0] = plan->targetIds[0];
160 livingTargets = 1;
161 }
162 effect->firstTarget = plan->targetIds[0];
163 effect->count = livingTargets;
164 effect->range = 1;
165}
166
167/// Plays a unit's attempt to run. The party gets away unless the enemies
168/// struck first ("But there's no escape!"), each member able to move running
169/// off in turn; an enemy gets away 7 times in 10 and leaves the battle.
170/// Returns 1 when the party got away.
171/// Called by BattlePresentation_DispatchAction for PLAN_SHOW_FLEE. Turns the
172/// camera to the party's view and holds gTransitionWork->active while it
173/// runs; an enemy that gets away is taken out of the lists and its object
174/// released.
176 struct BattlePresentationTransition *presentation =
178 struct BattleWork *scene = WORK_SLOT(HEAP_SLOT_BATTLE);
179 /* FAKEMATCH(temporary): completed cleared a halfword at a time, which keeps
180 * partyMode a copy of its register (adds r2, r7, #0); as an s32 set to 0, 1
181 * of 105 instructions differ in tbs-en. */
182 union {
183 s32 value;
184 u16 halves[2];
185 } completed;
186 s32 partyMode;
187
188 completed.halves[0] = 0;
189 completed.halves[1] = 0;
190 presentation->targetYaw = YAW_PARTY_TURN;
191 presentation->active = 1;
193
194 // The party: each member that can move runs, the last listed first, eight
195 // frames apart.
196 if (plan->actorId <= 7) {
197 partyMode = completed.value;
198
200 partyMode = 1;
201 }
202
203 if (!partyMode) {
206 } else {
207 s16 unitIds[14];
208 s32 index =
210
211 while (index != -1) {
212 struct BattleUnit *unit = UnitGetFar(unitIds[index]);
213
214 if (unit->stun == 0 && unit->sleep == 0) {
215 BattleMotion_SetupEscapeObject(unitIds[index]);
216 WaitFrames(8);
217 }
218 index--;
219 }
220 WaitFrames(22);
221 completed.value = 1;
222 }
223 } else if (((Random16() * 10) >> 16) <= 6) {
224 // An enemy: a roll of 0 to 9, 7 in 10 away.
225 s16 event[2];
226
227 event[0] = plan->actorId;
228 event[1] = BATTLE_UNIT_LIST_END;
230 WaitFrames(8);
233 } else {
236 }
237
238 presentation->active = 0;
239 return completed.value;
240}
241
242/// Plays a summon or a full-screen Psynergy. The camera turns to the target
243/// side (or to the actor's, for a staged scene), the actor glows in its
244/// element and the other side fades out; then, unless the cast failed
245/// ("blocked" or too little PP), the target side's units are readied alone
246/// and the effect plays while the events run. Everyone fades back in.
247/// Called by BattlePresentation_DispatchAction for PLAN_SHOW_SUMMON (mode 1)
248/// and PLAN_SHOW_FULL_SCREEN (mode 0). Sets gTransitionWork's yaw (and its
249/// frames, for a scene), REG_BLDCNT and REG_BLDALPHA for the fades, and the
250/// units' record modes; schedules BattleEvent_Playback around the effect.
251/// mode : bit 0 hides the actor too (the summons)
253 u16 units[14];
254 struct BattlePresentationWork work;
255 u32 actor;
256 u32 target;
257 u32 count;
258 s32 i;
259 s32 n;
260 u32 kept;
261 struct MotionObject *object;
262 // UB: indexing past scalar gBattleWork reaches another work slot. Named
263 // slots keep the native EN size (0x3ba), but reorder address setup.
264#ifndef UBFIX
265 void **slots = (void **)&gBattleWork;
266#endif
267
268 // The camera: a staged scene turns to the actor's side over 60 frames (an
269 // enemy's to 0x5000); otherwise the acting side's usual view.
271 actor = plan->actorId;
272 target = plan->targetIds[0];
273 if (plan->presentationFlags & STAGING_SCENE) {
274 struct BattlePresentationTransition *transition;
275 s32 yaw;
276#ifdef UBFIX
278#else
279 transition = slots[HEAP_SLOT_BATTLE_BACKGROUND - HEAP_SLOT_BATTLE];
280#endif
281 yaw = YAW_PARTY_TURN;
282 if (actor > 7)
283 yaw = 0x5000;
284 transition->targetYaw = yaw;
285 transition->frames = 60;
286 } else {
287 struct BattlePresentationTransition *transition;
288 s32 yaw;
289#ifdef UBFIX
291#else
292 transition = slots[HEAP_SLOT_BATTLE_BACKGROUND - HEAP_SLOT_BATTLE];
293#endif
294 yaw = YAW_ENEMY_TURN;
295 if (actor <= 7)
296 yaw = YAW_PARTY_TURN;
297 if (transition->targetYaw != yaw)
298 transition->targetYaw = yaw;
299 }
300
301 // The actor raises its hand (animation 3) and glows; the units of the side
302 // not targeted fade out over 16 frames (and the actor too, for mode 1).
305 object = BattleObjGet(actor)->object;
308 for (i = 0; i != count; i++) {
309 if (units[i] == BATTLE_UNIT_REMOVED)
310 continue;
311 if (units[i] != actor) {
312 if ((target <= 7) != (units[i] <= 7))
314 } else {
316 }
317 }
318 // The sound of a cast, as the caster raises its hand.
321 if (mode & 1)
323 for (i = 0; i != 16; i++) {
324 REG_BLDALPHA = BLEND_ALPHA(16 - i, 16);
325 WaitFrames(1);
326 }
327 // A failed cast: "blocked" (sealed) or too little PP, shown at once.
328 if (plan->failure != 0) {
329 if (plan->failure == 1) {
331 BattleEvPush(BATTLE_EVENT_MESSAGE, MsgPsynergyBlocked);
332 } else {
333 BattleEvPush(BATTLE_EVENT_MESSAGE, MsgCastLacksPp);
334 }
337 } else {
338 // Only the target side's units stay on the field (with the actor, unless
339 // mode 1 hides it); the list is then reused for the plan's targets.
340 kept = 0;
341 for (i = 0; i < count; i++) {
342 u32 unit = units[i];
343 if (unit == actor) {
344 if (!(mode & 1))
345 units[kept++] = actor;
346 } else if ((target <= 7) == (unit <= 7)) {
347 units[kept++] = unit;
348 }
349 }
350 units[kept] = BATTLE_UNIT_LIST_END;
352 for (n = 0; n < plan->targetCount; n++)
353 units[n] = plan->targetIds[n];
354 units[n] = BATTLE_UNIT_LIST_END;
355 // Save each target's layer colour modes (all but its last layer) in
356 // work, beside the effect command. RunItem and RunPsynergyCast do the
357 // same.
358 // XXX: no code reads savedAnimationParameters by name; an effect that
359 // reads past its command into BattlePresentationWork would settle what
360 // they are kept for.
361 for (i = 0; i != work.effect.count; i++) {
362 struct AnimationObject *animation;
363 u32 child;
364
365 animation =
367 for (child = 0; child != animation->count - 1; child++)
368 work.savedAnimationParameters[i][child] =
369 animation->entries[child]->param;
370 }
371 // The side the effect plays on: 1 when the targets are the party's.
372 if (plan->presentationFlags & STAGING_SCENE) {
373 if (target > 7)
374 work.effect.side = 0;
375 else
376 work.effect.side = 1;
377 } else {
378 if (plan->targetIds[0] <= 7)
379 work.effect.side = 1;
380 else
381 work.effect.side = 0;
382 }
384 work.effect.side ^= 1;
385 // The effect runs to its end while playback, a scheduler callback, plays
386 // the targets' events from the frame the blow lands.
390 else if (plan->presentationFlags & STAGING_BY_ID_RANGE)
392 else
395 }
396
397 // Everyone back: the faded units fade in over 16 frames and every record
398 // mode is cleared.
399 BattleObjPut();
402 for (i = 0; i != count; i++) {
403 if (units[i] == BATTLE_UNIT_REMOVED || units[i] == actor)
404 continue;
405 if ((target <= 7) != (units[i] <= 7))
407 }
408 for (i = 0; i != 16; i++) {
409 REG_BLDALPHA = BLEND_ALPHA(i, 16);
410 WaitFrames(1);
411 }
412 for (i = 0; i != count; i++)
415 WaitFrames(1);
416 return 0;
417}
418
419/// Clears the highlights, then applies the action to each target in turn and
420/// plays its events; with no target, only waits for the player.
421/// Called by BattlePresentation_DispatchAction for PLAN_SHOW_MESSAGES, an
422/// action with no animation: each target's BattleTargetExec is played at
423/// once by BattleEv_DispatchQueued.
424/// plan : the action and its targets
425#ifdef UBFIX
426void BattlePres_RunActorEntries(struct BattlePlan *plan, s32 unused) {
427#else
429#endif
430 s32 targetIndex;
431
433 if (plan->targetCount == 0) {
435 } else {
436 for (targetIndex = 0; targetIndex < plan->targetCount; targetIndex++) {
437 BattleTargetExec(plan, targetIndex);
439 }
440 }
441 WaitFrames(1);
442}
443
444/// Plays an attack: the camera turns halfway to the attacker's view, the
445/// attacker runs up to its first target over its swing's frames, and the
446/// blow lands: a miss makes the target hop back; a hit plays its effect and
447/// the events, and a critical hit zooms in on the pair with only those two
448/// shown. Both then return. A miss "nimbly dodges the blow".
449/// Called by BattlePresentation_DispatchAction for PLAN_SHOW_ATTACK; mode is
450/// unused. Sets gTransitionWork's yaw (and its flag for a critical hit's
451/// zoom), the window registers (WIN0 and WIN1 to the battlefield, rows 16 to
452/// 136, both turned on), and schedules BattleEvent_Playback around the
453/// effect.
455 struct BattlePresentationWork work;
456 struct MotionObject *object;
457 struct AnimationObject *animation;
458 struct BattleUnit *unit;
459 s16 criticalPair[3];
460 s32 critical;
461 struct BattlePresentationTransition *transition;
462 s32 angle;
463 s32 adjusted;
464 s32 facingAngle;
465 s32 x;
466 s32 z;
467 s32 frames;
468 s32 missed;
469 s32 index;
470 s32 zoomOnCritical;
471
472 transition = gTransitionWork;
473 {
474 struct BattlePlan *savedPlan = plan;
475
476 /* FAKEMATCH(dead): plan cleared and restored under tests that emit
477 * nothing, ending a CSE block so the first read of plan reloads it;
478 * without them, 5 of 289 instructions differ in tbs-en. */
479 if (transition)
480 plan = NULL;
481 if (transition)
482 plan = savedPlan;
483 }
484
485 // The camera turns to halfway between the party's view (0x2000) and the
486 // attacker's bearing from the centre, an enemy's taken from the other
487 // side: 5 frames if it is there already, else 10.
488 object = BattleObjGet(plan->actorId)->object;
489 z = object->z;
490 x = object->x;
491 angle = (u16)ArcTan2(x, z);
492 adjusted = angle - 0x2000;
493 if (plan->actorId > 7)
494 adjusted = angle + 0x6000;
495 adjusted &= 0x7fff;
496 facingAngle = (adjusted - 0x2000) / 2 + 0x2000;
497
498 if (transition->targetYaw == facingAngle) {
499 transition->targetYaw = facingAngle;
500 WaitFrames(5);
501 } else {
502 transition->targetYaw = facingAngle;
503 WaitFrames(10);
504 }
505
508 if (work.effect.kind == 0x87)
510
511 unit = UnitGetFar(work.effect.actor);
512 UnitGetFar(work.effect.actors[0]);
513 critical = plan->targetCritical[0];
514 missed = plan->targetMultiplier[0] == 0;
515
516 // The run up: as long as the attacker's animation 2, with its class's hop
517 // height (16.16).
518 animation = GetMotionRecord(BattleObjGet(plan->actorId)->object, 0);
520 2, 1);
522 BattleClass_GetAttackHop(unit->classId) << 16);
524 (struct DispatchObject *)BattleObjGet(work.effect.actor)->object, 16);
525 BattleObjGet(work.effect.actors[0]);
526
527 if ((u16)work.effect.actors[0] <= 7)
528 work.effect.side = 1;
529 else
530 work.effect.side = 0;
531
532 REG_WIN0H = WIN_RANGE(0, 240);
533 REG_WIN0V = WIN_RANGE(16, 136);
534 REG_WIN1H = WIN_RANGE(0, 240);
535 REG_WIN1V = WIN_RANGE(16, 136);
539
540 // A miss: after 10 frames the target hops back; 16 frames later the dodge
541 // is shown at once.
542 if (missed != 0) {
543 WaitFrames(10);
545 WaitFrames(2);
546 WaitFrames(4);
547 WaitFrames(10);
549 BattleEvPush(BATTLE_EVENT_MESSAGE, MsgNimblyDodgesBlow);
551 ObjMotRst(work.effect.actors[0]);
552 } else {
553 // A hit. A critical hit plays the effect 200 kinds on, with only the pair
554 // on the field and the camera zooming in on them (scale 100 to 130) over
555 // the rest of the run up.
556 zoomOnCritical = 0;
557 work.effect.prelude = 0;
558 if (plan->presentationFlags != 0)
559 work.effect.prelude = 1;
560
561 if (critical != 0) {
562 work.effect.kind += 200;
563 zoomOnCritical = 1;
564 transition->flag = 1;
565 criticalPair[0] = work.effect.actor;
566 criticalPair[1] = work.effect.firstTarget;
567 criticalPair[2] = BATTLE_UNIT_LIST_END;
568 BattleActor_SpawnObjectsForList(criticalPair, 0);
569 }
570
571 // The effect starts 8 frames before the run up ends, at least one frame
572 // after it began.
573 frames -= 8;
574 if (frames <= 0)
575 frames = 1;
576 {
577 s32 first;
578 s32 second;
579
580 for (index = 0; index != frames; index++) {
581 if (zoomOnCritical != 0) {
582 first = work.effect.actor;
583 second = work.effect.firstTarget;
585 index * 30 / frames + 100);
586 }
587 WaitFrames(1);
588 }
589 }
590
592 if (work.effect.kind != 0) {
595 else
597 }
599 // After a critical hit every unit is shown again and the zoom ends.
600 if (critical != 0) {
601 transition->flag = 0;
604 }
605 ObjMotRst(work.effect.actors[0]);
606 }
607 ObjMotRst(work.effect.actor);
608 return 0;
609}
610
611/// Unused. Plays a plain attack run: the attacker runs up to its first target
612/// and the blow's effect and events play, or, with bit 1 of flags (a miss), the
613/// target hops back; both then return.
614/// Nothing calls it. BattlePres_RunAttack without the hop height, the windows,
615/// the critical zoom, the dodge message or playback; its events are played
616/// at once after the effect, and the camera's slower turn waits 20 frames.
618 struct BattlePresentationWork work;
619 struct BattlePlan *savedInput;
620 struct MotionObject *object;
621 struct AnimationObject *animation;
622 struct BattlePresentationTransition *transition;
623 s32 angle;
624 s32 adjusted;
625 s32 facingAngle;
626 s32 x;
627 s32 z;
628 s32 frames;
629 s32 missed;
630
631 transition = gTransitionWork;
632 savedInput = input;
633 object = BattleObjGet(savedInput->actorId)->object;
634 z = object->z;
635 x = object->x;
636 angle = (u16)ArcTan2(x, z);
637 adjusted = angle - 0x2000;
638 if (savedInput->actorId > 7)
639 adjusted = angle + 0x6000;
640 adjusted &= 0x7fff;
641 facingAngle = (adjusted - 0x2000) / 2 + 0x2000;
642
643 if (transition->targetYaw == facingAngle) {
644 transition->targetYaw = facingAngle;
645 WaitFrames(5);
646 } else {
647 transition->targetYaw = facingAngle;
648 WaitFrames(20);
649 }
650
652 BattlePres_BuildTargetList(savedInput, &work.effect);
653 UnitGetFar(work.effect.actor);
654 UnitGetFar(savedInput->targetIds[0]);
655
656 missed = flags & 2;
657 animation = GetMotionRecord(BattleObjGet(savedInput->actorId)->object, 0);
659 2, 1);
661 frames, 0);
663 (struct DispatchObject *)BattleObjGet(work.effect.actor)->object, 16);
664 BattleObjGet(savedInput->targetIds[0]);
665
666 if (savedInput->targetIds[0] <= 7)
667 work.effect.side = 1;
668 else
669 work.effect.side = 0;
670 if (missed != 0) {
671 WaitFrames(10);
673 WaitFrames(2);
674 WaitFrames(4);
675 WaitFrames(10);
676 ObjMotRst(savedInput->targetIds[0]);
677 } else {
680 ObjMotRst(savedInput->targetIds[0]);
681 }
682 ObjMotRst(work.effect.actor);
683 return 0;
684}
685
686/// Inventory_RemoveFar's result when the last one left its slot, and the
687/// slots after it moved up.
688#define ITEM_REMOVED_SLOT_GONE 2
689
690/// Plays an item's use: the camera turns to the user's side, the user raises
691/// the item and, for an item with an effect, the screen dims while it plays
692/// with the events. Then the item is spent as its use type says; when its
693/// slot empties, later item commands of the same member this round follow
694/// their items to their new slots (or lose theirs, -1).
695/// Called by BattlePresentation_DispatchAction for PLAN_SHOW_ITEM, with the
696/// action's record as selection. Sets gTransitionWork's yaw and, while an
697/// effect plays, dims gBattleWork->brightness and BG palettes 6 to 13; changes
698/// the user's inventory (Inventory_RemoveFar, Inventory_BreakFar, or the
699/// Empty Bottle) and the parameters of gBattleWork->actions.
701 struct BattleActionRecord *selection) {
702 struct BattlePresentationWork work;
703 struct MotionObject *object;
704 s32 targetOrFadeIndex;
705 s32 inventoryEntry;
706 struct BattleUnit *unit;
707 struct ItemDefinition *itemDefinition;
710
711 // The camera turns to the user's side; the user raises the item
712 // (animation 3).
713 // XXX: the test is > 4 where the other runners test > 7, so unit ids 5 to
714 // 7 take the enemies' view; which party members those ids are in a battle
715 // of this game would settle whether it is ever seen.
716 if (plan->actorId > 4)
718 else
720 if (transition->targetYaw != targetYaw)
721 transition->targetYaw = targetYaw;
724 object = BattleObjGet(work.effect.actor)->object;
727 if (plan->targetIds[0] <= 7)
728 work.effect.side = 1;
729 else
730 work.effect.side = 0;
731
732 for (targetOrFadeIndex = 0; targetOrFadeIndex != work.effect.count;
733 targetOrFadeIndex++) {
734 struct AnimationObject *animation = GetMotionRecord(
735 BattleObjGet(work.effect.actors[targetOrFadeIndex])->object, 0);
736 s32 entryIndex;
737
738 for (entryIndex = 0; entryIndex != animation->count - 1; entryIndex++)
739 work.savedAnimationParameters[targetOrFadeIndex][entryIndex] =
740 animation->entries[entryIndex]->param;
741 }
742
743 // An item with an effect dims the background over 20 frames, to about two
744 // thirds of its brightness (19 steps of 0x444 in 16.16), then plays it; one
745 // with none waits a second.
747 if (work.effect.kind != 0) {
748 s32 fade;
749
750 targetOrFadeIndex = 0;
751 fade = 0;
752 do {
753 struct BattleWork *battle = gBattleWork;
754
755 if (targetOrFadeIndex < 20) {
756 u16 *palette = battle->palette;
757 s32 value = 0x10000 - fade;
758
759 battle->brightness = value;
760 Graphics_ScaleRgb555Clamped(palette, (u16 *)(BG_PLTT + 6 * 16), value,
761 128);
762 }
763 WaitFrames(1);
764 targetOrFadeIndex++;
765 fade += 0x444;
766 } while (targetOrFadeIndex < 20);
769 else
771 } else {
772 WaitFrames(60);
773 }
776 for (targetOrFadeIndex = 0; targetOrFadeIndex != work.effect.count;
777 targetOrFadeIndex++)
778 ObjMotRst(work.effect.actors[targetOrFadeIndex]);
779
780 // Spend the item, by its use type.
781 unit = UnitGetFar(selection->unitId);
782 inventoryEntry = unit->inventory[selection->parameter];
783 itemDefinition = Item_GetDirectFar(inventoryEntry);
784 if (itemDefinition->useType == ITEM_USE_CONSUMED) {
785 s32 result = Inventory_RemoveFar(selection->unitId, selection->parameter);
786 s32 index = selection->parameter;
787 if (result == ITEM_REMOVED_SLOT_GONE) {
788 struct BattleWork *battle = gBattleWork;
789 u32 row;
790
791 for (row = 0; row < BATTLE_ACTION_CAPACITY; row++) {
792 if (battle->actions[row].command == CMD_ITEM &&
793 battle->actions[row].unitId == selection->unitId) {
794 if (battle->actions[row].parameter == index)
795 battle->actions[row].parameter = -1;
796 else if (battle->actions[row].parameter > index)
797 battle->actions[row].parameter--;
798 }
799 }
800 }
801 } else if (itemDefinition->useType == ITEM_USE_MAY_BREAK) {
802 // One time in eight it breaks, shown at once.
803 if ((BattleRandomFar() & 7) == 0) {
805 unit->inventory[selection->parameter]);
806 BattleEvPush(BATTLE_EVENT_MESSAGE, MsgUsedItemBroke);
807 Inventory_BreakFar(selection->unitId, selection->parameter);
809 }
810 } else if (itemDefinition->useType == ITEM_USE_EMPTIES) {
811 // Hermes' Water becomes one Empty Bottle, the slot's other bits dropped;
812 // any other such item stays as it was.
813 if ((inventoryEntry & ITEM_ID_MASK) == ITEM_HERMES_WATER)
814 inventoryEntry = ITEM_EMPTY_BOTTLE;
815 unit->inventory[selection->parameter] = inventoryEntry;
816 }
817 return 0;
818}
819
820/// Draws every sprite of an object in a colour mode (enum SpriteColorMode):
821/// colorMode on each sprite's first layer, SPRITE_COLOR_NORMAL on the others,
822/// and every layer's frame set to 255 (none) so that it is drawn again.
823/// Called by BattleMotion_FlashHit and BattleEvent_Playback (a hit's flashes
824/// and a unit's redraw), with the flash's colour or the unit's own
825/// (BattleMotion_GetSlotPalette).
826#ifdef UBFIX
828 s32 colorMode) {
829#else
831 s32 colorMode) {
832#endif
833 s32 recordIndex = 0;
834 s32 childIndex;
835 s32 entryCount;
836 struct AnimationObject *record;
837 struct AnimationEntry *child;
838 struct AnimationEntry **children;
839 /* FAKEMATCH(temporary): the mask in a variable and the frame read into
840 * another, so 255 stays in a register across the calls and is or-ed in;
841 * as child->frame |= 0xff, 10 of 46 instructions differ in tbs-en. */
842 u8 lastFrameMask = 0xff;
843 u8 previousFrame;
844
845 while ((record = GetMotionRecord(object, recordIndex)) != NULL) {
846 children = &record->entries[1];
847 child = record->entries[0];
848 previousFrame = child->frame;
849 child->frame = previousFrame | lastFrameMask;
850 entryCount = record->count;
851 child->param = colorMode;
852 for (childIndex = 1; childIndex < entryCount; childIndex++) {
853 child = *children++;
854 child->param = 0;
855 child->frame = 0xff;
856 }
857 recordIndex++;
858 }
859}
860
861/// Plays Psynergy, a Djinni or an enemy's cast. The camera turns toward
862/// the targets from the caster's side, the caster raises its hand and glows
863/// in its element (no glow for a Djinni); then the cast fails ("blocked" or
864/// too little PP) or its effect plays with the events, and the targets
865/// return to their spots.
866/// Called by BattlePresentation_DispatchAction for PLAN_SHOW_CAST (mode 0),
867/// PLAN_SHOW_DJINNI (1) and PLAN_SHOW_ENEMY_CAST (2). Sets gTransitionWork's
868/// yaw (and its frames for a fixed view), redraws the party's status without
869/// bit 0, and schedules BattleEvent_Playback around the effect.
870/// mode : 1 a Djinni, 2 an enemy's cast, 0 any other
872 struct BattlePresentationWork work;
874 struct MotionObject *object;
875 s32 isDjinni;
876 s32 targetIndex;
877
878 // The camera. STAGING_VIEW_ACROSS takes the other side's view (an enemy's
879 // cast 0x5000) over 60 frames. Otherwise it starts 0x1800 off the caster's
880 // bearing (less for the party, more for an enemy) and goes three quarters
881 // of the way to the caster's side's view; a cast on the caster's own side
882 // takes 0x2400 instead (-0x2400 for an enemy). STAGING_VIEW_REVERSED then
883 // overrides it with the opposite side's view.
885 transition->targetYaw = plan->actorId <= 7 ? YAW_ENEMY_TURN : 0x5000;
886 transition->frames = 60;
887 } else {
888 struct MotionObject *actor = BattleObjGet(plan->actorId)->object;
889 s32 angle = (u16)ArcTan2(actor->x, actor->z);
890 s32 targetYaw;
891
892 if (plan->actorId <= 7)
893 targetYaw = angle - 0x1800;
894 else
895 targetYaw = angle + 0x1800;
896 targetYaw = (s16)targetYaw;
897 targetYaw +=
898 ((plan->actorId <= 7 ? YAW_PARTY_TURN : YAW_ENEMY_TURN) - targetYaw) *
899 3 / 4;
900 if (!((plan->actorId <= 7) ^ (plan->targetIds[0] <= 7)))
901 targetYaw = plan->actorId <= 7 ? 0x2400 : -0x2400;
902 if (transition->targetYaw != targetYaw)
903 transition->targetYaw = targetYaw;
904 }
906 transition->targetYaw =
908 transition->frames = 60;
909 }
910
911 // The caster raises its hand (animation 3) and glows in its element (style
912 // 1 for an enemy's cast); a Djinni does not glow, and its effect plays its
913 // prelude instead.
915 isDjinni = mode & 1;
916 if (isDjinni)
917 work.effect.prelude = 1;
920 object = BattleObjGet(work.effect.actor)->object;
924 if (mode & 2)
926 else if (!isDjinni)
928 if (plan->targetIds[0] <= 7)
929 work.effect.side = 1;
930 else
931 work.effect.side = 0;
932
933 for (targetIndex = 0; targetIndex != work.effect.count; targetIndex++) {
934 struct AnimationObject *animation = GetMotionRecord(
935 BattleObjGet(work.effect.actors[targetIndex])->object, 0);
936 s32 entryIndex;
937
938 for (entryIndex = 0; entryIndex != animation->count - 1; entryIndex++)
939 work.savedAnimationParameters[targetIndex][entryIndex] =
940 animation->entries[entryIndex]->param;
941 }
942
943 // A failed cast is shown at once; otherwise the effect plays while the
944 // events do, and an ability with no effect only restores the palette.
945 if (plan->failure != 0) {
946 if (plan->failure == 1) {
948 BattleEvPush(BATTLE_EVENT_MESSAGE, MsgPsynergyBlocked);
949 } else {
950 BattleEvPush(BATTLE_EVENT_MESSAGE, MsgCastLacksPp);
951 }
954 } else {
956 if (work.effect.kind) {
959 else
961 } else {
963 }
966 for (targetIndex = 0; targetIndex != work.effect.count; targetIndex++)
967 ObjMotRst(work.effect.actors[targetIndex]);
968 }
969 return 0;
970}
971
972/// Flashes unit id as it is hit: puts it in its damage pose and switches its
973/// sprites between white and their own colours twice, two frames each, its
974/// status panel highlighted.
975/// Called for BATTLE_EVENT_HIT by BattleEv_DispatchQueued (BattleEvent_Playback
976/// flashes over frames itself). Waits 8 frames and redraws the party's status
977/// at the end.
978void BattleMotion_FlashHit(s32 unitId, s32 unused0, s32 unused1) {
979 u16 selection[2];
980 u16 *selected;
981 s32 listTerminator;
982 s32 flashesRemaining;
983
984 UnitGetFar(unitId);
986
987 selected = selection;
988 flashesRemaining = 1;
989 do {
990 listTerminator = BATTLE_UNIT_LIST_END;
991 selected[1] = listTerminator;
992 selected[0] = unitId;
996 WaitFrames(2);
997
998 selected[0] = unitId;
1002 WaitFrames(2);
1003 flashesRemaining--;
1004 } while (flashesRemaining >= 0);
1005
1007}
1008
1009/// Takes unit id out of the party's or the enemies' list and out of this
1010/// round's actions, and frees its name letter.
1011/// Called when a unit leaves the battle: by BattlePres_RunEscape (an enemy
1012/// that gets away), BattleMotion_ShowDowned and PLAY_FELLED in
1013/// BattleEvent_Playback (a fallen enemy), and
1014/// BattleActor_DestroyTemporaryObject. Sets the unit's side to
1015/// BATTLE_UNIT_ABSENT and its list entry to BATTLE_UNIT_REMOVED, releases its
1016/// name letter (BattleEnemy_ReleaseNameLetter), and ends its actions this
1017/// round (unitId BATTLE_UNIT_LIST_END). A unit in neither list only has its
1018/// side changed.
1020 struct BattleWork *battle;
1021 s32 partyIndex;
1022 u32 enemyOrActionIndex;
1023 s32 listedUnit;
1024
1025 // The party's list.
1026 battle = gBattleWork;
1028 for (partyIndex = 0;; partyIndex++) {
1029 if (battle->partyUnits[partyIndex] == unitId) {
1030 battle->partyUnits[partyIndex] = BATTLE_UNIT_REMOVED;
1031 goto removed;
1032 }
1033 if (battle->partyUnits[partyIndex] == BATTLE_UNIT_LIST_END)
1034 break;
1035 }
1036
1037 // The enemies' list.
1038 // The scan is a label loop, the form its branches match with.
1039 /* FAKEMATCH(one-pass): the block keeps the party loop's first test from
1040 * being peeled ahead of it; without the block, 12 of 53 instructions differ
1041 * in tbs-en. */
1042 do {
1043 enemyOrActionIndex = 0;
1044 again:
1045 listedUnit = battle->enemyIds[enemyOrActionIndex];
1046 if (listedUnit == unitId) {
1047 battle->enemyIds[enemyOrActionIndex] = BATTLE_UNIT_REMOVED;
1048 goto removed;
1049 }
1050 enemyOrActionIndex++;
1051 if (listedUnit == BATTLE_UNIT_LIST_END)
1052 return;
1053 goto again;
1054 } while (0);
1055
1056removed:
1057 // Free the letter that told the enemy apart from others of its class.
1059 for (enemyOrActionIndex = 0; enemyOrActionIndex < BATTLE_ACTION_CAPACITY;
1060 enemyOrActionIndex++) {
1061 if (battle->actions[enemyOrActionIndex].unitId == unitId)
1062 battle->actions[enemyOrActionIndex].unitId = BATTLE_UNIT_LIST_END;
1063 }
1064}
1065
1066/// Shows a downed unit: a party member lies down, an enemy keeps its damage
1067/// pose, turns grey, leaves the lists after four frames and dissolves a dot
1068/// at a time.
1069/// Called for BATTLE_EVENT_DEFEAT by BattleEv_DispatchQueued; PLAY_FELLED in
1070/// BattleEvent_Playback is its counterpart over frames. An enemy's object is
1071/// marked for release.
1073 void *records[4];
1074 struct BattleUnit *unit;
1075 struct AnimationObject *record;
1076 struct AnimationEntry *entry;
1077 s32 recordCount;
1078
1079 unit = UnitGetFar(unitId);
1080 recordCount = 0;
1081 while ((record = GetMotionRecord(BattleObjGet(unitId)->object,
1082 recordCount)) != 0) {
1083 if (unit->side != BATTLE_UNIT_ENEMY)
1085 else
1087 recordCount++;
1088 }
1089
1090 if (unit->side == BATTLE_UNIT_ENEMY) {
1091 recordCount = 0;
1092 while ((record = GetMotionRecord(BattleObjGet(unitId)->object,
1093 recordCount)) != 0) {
1094 entry = record->entries[0];
1095 records[recordCount] = record;
1096 entry->param = SPRITE_COLOR_GREY;
1097 entry->frame = 0xff;
1098 recordCount++;
1099 }
1100 WaitFrames(4);
1102 // The whole dissolve, over 32 frames.
1103 Map_RenderAllAnimatedTileFramesFar((u8 **)records, recordCount);
1105 }
1106}
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ SPRITE_COLOR_GREY
greyscale
Definition animspr.h:25
void BattlePres_SetActorRecordMode(s32 actorId, s32 mode)
Sets the OBJ mode (1 semi-transparent, 0 normal) of every sprite of a unit's battle object,...
Definition background.c:515
void BattlePres_SetupTransitionAtPairMidpoint(s32 firstUnitId, s32 secondUnitId, s32 zoom)
Points the battle camera, through BattlePres_SetupTransitionScene, at the ground between two units' b...
Definition background.c:406
void BattlePres_SetupTransitionScene(s32 x, s32 depth, s32 y, s32 zoom)
Points the battle camera at (x, depth, y) with a zoom in percent, and lines the perspective plane up ...
Definition background.c:359
void BattlePresentation_ConfigurePaletteFade(s32 mode, s32 unusedResource, s32 fade)
Switches the background's display mode, optionally sets its palette, and rebuilds both its maps.
Definition background.c:85
void BattlePres_SetActorModes(u16 *selectedUnits, s32 mode)
Highlights the units in selectedUnits, a list ended by BATTLE_UNIT_LIST_END, or with mode 0 stops the...
Definition background.c:609
u32 BattleClass_GetAttackHop(u32 index)
Returns how high a class hops as it runs up to attack, in pixels; 0 out of range.
Definition classes.c:73
s32 BattleParty_ListLivingUnits(s32 sideMask, u16 *unitIds)
Lists the units still standing (HP above 0) on the sides in sideMask (BATTLE_SIDE_PARTY,...
Definition encounter.c:437
s32 BattleParty_ListActorIds(s32 sideMask, u16 *unitIds)
Lists the units in the battle's unit lists on the sides in sideMask, party first, skipping those remo...
Definition encounter.c:510
u32 BattleEvPush(u32 opcode, u32 operand)
Queues one battle event (enum BattleEventOpcode) with its operand, and returns the opcode.
Definition events.c:321
u32 BattleEv_DispatchQueued(void)
Plays the queued battle events at once, in order (BattleEvent_Playback plays them over frames instead...
Definition events.c:241
s32 BattlePresentation_WaitForAdvance(void)
Shows the bobbing arrow at the message window and waits for the player to go on (B,...
Definition events.c:90
void BattleActor_SpawnObjectsForList(s16 *unitIds, s32 refreshPoses)
Readies the sprites of the units in list: releases those of every place list lacks,...
Definition objects.c:356
struct BattleObj * BattleObjGet(s32 unitId)
Returns unitId's battle object, through its place, or null for a unit with no place.
Definition objects.c:480
s32 BattleObj_MarkForRelease(s32 unitId)
Frees the enemy sprite slots unitId holds and marks its object for release at the end of the round (B...
Definition objects.c:543
void * BattleMotion_DestroyAllSlotObjects(void)
Releases the object of every unit marked by BattleObj_MarkForRelease, leaving its battle object with ...
Definition objects.c:557
void * GetMotionRecord(struct MotionObject *object, s32 recordIndex)
Returns sprite recordIndex of an object (0 only, for a single sprite), or null when it has no such sp...
Definition objects.c:628
void BattleObjPut(void)
Readies the sprite of every unit in the battle (releasing those of units that left) and sets each one...
Definition sprites.c:13
void BattleParty_ListAllUnitsAndSubmit(void)
Readies the sprite of every unit in the battle (releasing those of units that left),...
Definition sprites.c:22
s32 BattleMotion_GetSlotPalette(s32 id)
Returns the palette of unit id's battle object.
Definition sprites.c:32
@ POSE_PARTY_HELD
asleep, stunned or held; also a downed member
Definition battle.h:175
@ POSE_ENEMY_DOWN
a downed enemy stays in its damage pose
Definition battle.h:177
@ POSE_DAMAGE
taking damage
Definition battle.h:176
struct BattlePresentationTransition * gTransitionWork
@ BATTLE_EVENT_UNIT_NAME
a unit's name for the next message
@ BATTLE_EVENT_MESSAGE
a message, waiting for the player
@ BATTLE_EVENT_ITEM_NAME
an item's name for the next message
What every part of the battle object shares: its includes, in their original order,...
#define STAGING_ON_DOWNED
shown on downed targets too (revivals)
#define ITEM_USE_CONSUMED
one is used up
#define STAGING_VARIANT_SHIFT
#define STAGING_BY_ID_RANGE
BattleFx_DispatchByIdRangeFar.
#define STAGING_KIND_MASK
#define STAGING_VARIANT_MASK
#define ITEM_USE_EMPTIES
Hermes' Water leaves an Empty Bottle.
#define STAGING_VIEW_REVERSED
#define BLEND_SPRITES_OVER_ALL
REG_BLDCNT: blend the semi-transparent sprites (OBJ mode 1) over every layer, to fade them.
#define STAGING_VIEW_ACROSS
More of BattlePlan.presentationFlags: the camera takes the other side's view (an enemy's cast a view ...
#define BATTLE_WININ
The battle's windows: window 0 shows BG0 to BG2, sprites and blending, window 1 BG0,...
@ PLAN_SHOW_ATTACK
the actor runs up and strikes
@ PLAN_SHOW_CAST
Psynergy, and Venus, Mercury, Mars, Jupiter.
@ PLAN_SHOW_ENEMY_CAST
an enemy's Psynergy
@ PLAN_SHOW_FLEE
a unit runs
@ PLAN_SHOW_ITEM
an item
@ PLAN_SHOW_DJINNI
a Djinni with no attack (Granite, Quartz...)
@ PLAN_SHOW_FULL_SCREEN
Gaia, Rockfall, Procne and their kin.
@ PLAN_SHOW_MESSAGES
no animation: each target's events only
@ PLAN_SHOW_SUMMON
the larger summons, the actor hidden
#define ITEM_USE_MAY_BREAK
breaks one time in eight
#define STAGING_SCENE
BattleFx_RunSceneEffectFar, actor's view.
#define YAW_PARTY_TURN
The camera's yaw while a party member acts, and while an enemy does.
#define YAW_ENEMY_TURN
#define BATTLE_WINOUT
#define STAGING_OTHER_SIDE
played from the other side
@ BATTLE_ENCOUNTER_ENEMIES_FIRST
@ BATTLE_UNIT_LIST_END
ends the list
@ BATTLE_UNIT_REMOVED
a place whose unit has left the battle
@ BATTLE_UNIT_ABSENT
@ BATTLE_UNIT_ENEMY
@ BATTLE_SIDE_PARTY
@ BATTLE_SIDE_BOTH
@ CMD_ITEM
struct BattleWork * gBattleWork
@ BATTLE_ACTION_CAPACITY
Definition battle_work.h:66
s32 BattleCommand_SelectAutomatic(struct BattleActionRecord *request, s32 retry)
Chooses an enemy's action (a party member's is chosen in the menu): one of the eight in its definitio...
Definition enemy_ai.c:33
void BattleFx_RunTableEffectFar(struct BattleEffectArgument *effect)
void BattleFx_RunSceneEffectFar(struct BattleEffectArgument *effect)
void BattleFx_DispatchByIdRangeFar(struct BattleEffectArgument *effect)
void Map_RenderAllAnimatedTileFramesFar(u8 **table, s32 cnt)
s32 AnimationObjects_SelectAnimationFar(struct AnimationObject *state, s32 flags)
s32 ResourceMetadata_SumCommandLengthsFar(s32 id, u32 no, s32 cnt)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void ObjectDispatch_SetAnimationSpeedFar(struct DispatchObject *obj, s32 val)
struct BattleUnit * UnitGetFar(u32 owner)
struct ItemDefinition * Item_GetDirectFar(s32 item)
s32 Inventory_RemoveFar(s32 owner, s32 slot)
s32 Inventory_BreakFar(s32 owner, s32 slot)
s32 BattleRandomFar(void)
void AudioCommand_PlayFar(s32 id)
s32 BattleLayout_HighlightPartyPanelsFar(u16 *ids)
void PartyStatusDrawFar(s32 flags)
void UiText_ShowMessageAndWaitCoreFar(s32 argument)
s32 BattleEnemy_ReleaseNameLetter(s32 actorId)
Frees a departing enemy's name letter for the next of its class, reading the letter back from the end...
Definition formation.c:320
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
@ HEAP_SLOT_BATTLE_BACKGROUND
Definition heap_state.h:45
@ HEAP_SLOT_CAMERA
Definition heap_state.h:38
@ HEAP_SLOT_BATTLE
Definition heap_state.h:37
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
Definition heap_state.h:14
#define REG_WIN1H
Definition io_reg.h:75
#define REG_WININ
Definition io_reg.h:81
#define REG_WIN0H
Definition io_reg.h:74
@ DISPCNT_WIN0_ON
Definition io_reg.h:45
@ DISPCNT_WIN1_ON
Definition io_reg.h:46
#define REG_DISPCNT
Definition io_reg.h:9
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
Definition io_reg.h:145
#define REG_BLDALPHA
Definition io_reg.h:142
#define REG_WINOUT
Definition io_reg.h:82
#define WIN_RANGE(start, end)
A REG_WINxH or REG_WINxV value: the window covers start up to, but not including, end.
Definition io_reg.h:80
#define BG_PLTT
Definition io_reg.h:157
#define REG_BLDCNT
Definition io_reg.h:119
#define REG_WIN1V
Definition io_reg.h:77
#define REG_WIN0V
Definition io_reg.h:76
@ ITEM_ID_MASK
Definition item.h:16
@ ITEM_HERMES_WATER
Definition item_ids.h:44
@ ITEM_EMPTY_BOTTLE
Definition item_ids.h:45
static s32 Iwram_RatioMulQ14(s32 divisor, s32 value)
All calls go through this layer.
Definition iwram_call.h:51
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
s32 ArcTan2(s32 x, s32 y)
Returns the angle of the vector (x, y), in 1/65536 turns, measured from the y axis: 0 along +y,...
Definition math.c:36
void BattleMotion_ApproachTarget(s32 actorId, s32 targetId, s32 travelDivisor, s32 initialVelocityY)
Sends unit actorId three quarters of the way to unit targetId, arriving in travelDivisor steps,...
Definition motion.c:191
void BattleMotion_ResetObjectAtScaledAnchor(s32 unitId)
Sends unitId hopping out to one and a half times its spot's distance from the centre.
Definition motion.c:111
void ObjMotRst(s32 unitId)
Sends unitId back to its spot, landing there, and turns it to face the centre.
Definition motion.c:17
void BattleMotion_SetupEscapeObject(s32 unitId)
Sends unitId running off its side of the battlefield, three times as far out as its spot,...
Definition motion.c:46
s32 BattleCommand_BuildPlan(struct BattleActionRecord *request, struct BattlePlan *plan)
Announces the action and plans its targets and effects.
Definition plan.c:108
s32 BattleEventRuntime_WaitForReady(void)
Waits, a frame at a time, until BattleEvent_Playback has played every target, then removes the callba...
Definition playback.c:458
void BattleEvent_Playback(void)
Plays the plan's targets one at a time: resolves the next target with BattleTargetExec,...
Definition playback.c:87
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
Definition scheduler.c:102
#define SE_CAST
Definition songs.h:149
#define NULL
Definition bilibin.h:6
#define ITEM_REMOVED_SLOT_GONE
Inventory_RemoveFar's result when the last one left its slot, and the slots after it moved up.
Definition staging.c:688
s32 BattlePresentation_DispatchAction(struct BattleActionRecord *request, s32 delay)
Plays one action of the round, after delay frames facing the party: an enemy picks its ability now; t...
Definition staging.c:18
s32 BattlePres_RunActorEntries(struct BattlePlan *plan, s32 unused)
Clears the highlights, then applies the action to each target in turn and plays its events; with no t...
Definition staging.c:428
s32 BattlePres_RunItem(struct BattlePlan *plan, s32 unused, struct BattleActionRecord *selection)
Plays an item's use: the camera turns to the user's side, the user raises the item and,...
Definition staging.c:700
UNUSED s32 BattlePres_RunPlainAttack(struct BattlePlan *input, s32 flags)
Unused.
Definition staging.c:617
s32 BattlePres_RunEscape(struct BattlePlan *plan)
Plays a unit's attempt to run.
Definition staging.c:175
void BattleMotion_FlashHit(s32 unitId, s32 unused0, s32 unused1)
Flashes unit id as it is hit: puts it in its damage pose and switches its sprites between white and t...
Definition staging.c:978
s32 BattlePres_RunPsynergyCast(struct BattlePlan *plan, s32 mode)
Plays Psynergy, a Djinni or an enemy's cast.
Definition staging.c:871
s32 BattlePres_BuildTargetList(struct BattlePlan *plan, struct BattleEffectArgument *effect)
Fills an effect command from a plan: its kind and strength, the actor and the targets still standing ...
Definition staging.c:129
s32 BattleMotion_SetRecordChildValues(struct MotionObject *object, s32 colorMode)
Draws every sprite of an object in a colour mode (enum SpriteColorMode): colorMode on each sprite's f...
Definition staging.c:830
s32 BattlePres_RunAttack(struct BattlePlan *plan, s32 mode)
Plays an attack: the camera turns halfway to the attacker's view, the attacker runs up to its first t...
Definition staging.c:454
void BattleActor_RemoveFromLists(s32 unitId)
Takes unit id out of the party's or the enemies' list and out of this round's actions,...
Definition staging.c:1019
s32 BattlePresentation_RunUnitTransition(struct BattlePlan *plan, s32 mode)
Plays a summon or a full-screen Psynergy.
Definition staging.c:252
void BattleMotion_ShowDowned(s32 unitId)
Shows a downed unit: a party member lies down, an enemy keeps its damage pose, turns grey,...
Definition staging.c:1072
void BattlePres_RestorePalette(void)
Copies the background's saved palette back undarkened, as the star field of BattleFx_PlayUnitElementE...
Definition star_field.c:469
void BattleFx_PlayUnitElementEffect(s32 unitId, s32 element, s32 mode, s32 variant)
Plays a glow of the element about a unit, and returns when it is over.
Definition star_field.c:363
s32 Graphics_ScaleRgb555Clamped(u16 *source, u16 *destination, s32 scale, s32 count)
Copies count colours from source to destination, each channel scaled by scale (16....
Definition star_field.c:315
One animation layer of a sprite: its animation id, frames, running script and timer.
Definition animspr.h:37
u8 param
SpriteColorMode its pixels are drawn with; 0 when taken.
Definition animspr.h:45
s16 animId
the sprite id whose metadata and frames it uses
Definition animspr.h:38
u8 mode
frame codec: 1 type-01, 3 LZ, anything else raw
Definition animspr.h:47
u8 frame
frame shown, frameBase plus the facing offset; 255 none
Definition animspr.h:53
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationEntry * entries[4]
its layers; empty ones null
Definition animspr.h:130
u8 count
layers in use, up to the last one present
Definition animspr.h:129
A unit's chosen action for the turn: its command, the command's parameter, its target and range,...
s16 parameter
an ability id, or CMD_ITEM's inventory index (-1 gone)
s16 command
enum BattleCommand
The battle camera: its eye, the focus it turns about, and its pitch, yaw and distance.
s32 pos[3]
the focus, 16.16 fixed-point pixels
s32 eye[3]
The eye, 16.16 fixed-point pixels: written each frame distance behind the focus along the turned view...
The command shared by an effect's caller, dispatcher and handlers.
s32 range
forwarded action range, otherwise initialized to 1
s32 actor
the user's unit id
s32 side
1 when the targets are the party, 0 for enemies
s32 kind
handler table index; 200 more for a critical hit
s16 actors[8]
the targets' unit ids, count of them
s32 variant
the ability's size, from 0 (Quake, then Earthquake)
s32 count
targets in actors, at least 1
s32 prelude
1 plays a prelude: in some effects a Djinni appears
s32 firstTarget
the action's first target, standing or not
struct MotionObject * object
NULL once released.
One action, as BattleCommand_BuildPlan lays it out for BattleTargetExec to apply target by target.
Definition battle_type.h:26
s32 outcome
enum BattlePlanStaging: how the action is shown
Definition battle_type.h:40
u32 presentationFlags
How the effect is staged (STAGING_ in battle_internal.h).
Definition battle_type.h:44
s8 targetCount
targets in targetIds
Definition battle_type.h:28
u8 actorId
the acting unit
Definition battle_type.h:27
u8 targetIds[BATTLE_TARGET_CAPACITY]
in battlefield order
Definition battle_type.h:29
s8 targetCritical[BATTLE_TARGET_CAPACITY]
enum BattleCritical
Definition battle_type.h:34
s32 failure
0 cast; 1 the Psynergy is sealed, 2 too little PP
Definition battle_type.h:45
s32 element
enum Element
Definition battle_type.h:39
s8 targetMultiplier[BATTLE_TARGET_CAPACITY]
The damage multiplier: 0 a miss, 1 a blow, 2 or 3 a double or triple.
Definition battle_type.h:33
The battle background's work slot as the camera reads it: the yaw the camera eases toward and the fra...
s32 frames
frames left to ease the yaw, a sixteenth a frame
s32 flag
0 lets the camera update set the background's range each frame; 1 for a critical hit's zoom and once ...
s32 active
BattleBackgroundView's busy, at the same offset.
The effect updates its command while the presentation keeps animation state.
struct BattleEffectArgument effect
u8 savedAnimationParameters[8][4]
Each target's animation entries' param, saved before the effect.
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 side
BATTLE_UNIT_ABSENT (0), BATTLE_UNIT_ENEMY (1) or BATTLE_UNIT_PARTY (2).
s16 hp
current HP, 0 when downed
u8 classId
Who the unit is: a character's id (ISAAC to JENNA, below 8) or an enemy's id (BattleUnitSet).
u8 classIndex
The character's class, worked out from its Djinn (Unit_UpdateClass); 0 marks an enemy,...
u16 inventory[15]
Items held, one entry each: bits 15..11 quantity | 10 broken | 9 equipped | 8..0 item id (INVENTORY_*...
The battle's own work: its enemies, units and their objects, the turn's actions, the spoils,...
Definition battle_work.h:71
u8 partyStatus
PARTY_STATUS_SUMMONS or PARTY_STATUS_NO_SUMMONS.
Definition battle_work.h:86
struct BattlePlan plan
u16 background
the battle background's id
u8 encounterMode
BATTLE_ENCOUNTER_: who strikes first.
Definition battle_work.h:91
s16 partyUnits[7]
ends with BATTLE_UNIT_LIST_END
s32 brightness
the backdrop's brightness, 16.16, 0x10000 full
struct BattleActionRecord actions[BATTLE_ACTION_CAPACITY]
The actions chosen for the turn.
u16 palette[128]
the backdrop's colours, before scaling
s16 enemyIds[BATTLE_ENEMY_CAPACITY+1]
ends with BATTLE_UNIT_LIST_END
A field object as the object dispatcher's far calls take it.
An item's definition: its price, type, who can equip it, its bonuses and unleash, its effects and the...
Definition item.h:104
u8 useType
what using it costs (ITEM_USE_), or 0 for nothing
Definition item.h:113
An effect object that moves and draws one sprite: its position, scale, velocity and target,...
Definition motobj.h:20
s32 z
16.16 fixed-point pixels
Definition motobj.h:25
u16 angle
1/65536 turns
Definition motobj.h:22
s32 x
16.16 fixed-point pixels
Definition motobj.h:23
s32 BattleTargetExec(struct BattlePlan *plan, s32 slot)
Applies the planned ability to one of its targets: first its damage or healing, then its added effect...
void Projection_Set(u32 focal, u32 nearDepth, u32 farDepth)
Sets gProjection's focal length and depth range directly.
Definition transform.c:350
void Render_ResetTransformState(void)
Allocates the one-level save area (heap slot HEAP_SLOT_TRANSFORM_STACK), clears gTransformStackDepth ...
Definition transform.c:19
void Transform_SetLookAt(s32 *eye, s32 *target)
Makes the camera at eye looking at target the whole of gTransform.
Definition transform.c:318
s32 BattleUnit_ProcessTurnEnd(struct BattlePlan *plan)
Ends one unit's turn: its Djinn on standby are taken off its set, the Djinn a summon used begin to re...
Definition turn_end.c:528
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11