Alchemy
Loading...
Searching...
No Matches

projectiles.c

Go to the documentation of this file.
1/// @file
2/// Projectile volleys (Slash, Shuriken, Wing Flutter, Blizzard ...).
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7/// Djinni entrance: sparks swirl around a point that travels from the user
8/// to the goal and gather into the Djinni, which sways for 16 frames and
9/// bursts into motes. Leaves the canvas cleared for the effect that
10/// follows.
11///
12/// The prelude of the stat boosts, the projectile volleys, the healing motes,
13/// the Djinn beams, the burst scenes, Bind, Hail, Ground, Torch and Vine,
14/// called with the work block they then use. Opens the canvas layer but does
15/// not close it: it removes the transfer and palette fade callbacks, frees
16/// both blitters, clears the canvas and its VRAM, and sets REG_BLDALPHA back
17/// to 16/16. Copies the Djinni's palette over the first 128 bytes of BG
18/// palette RAM, starts a 24-frame backdrop fade (work->fadeFrames), and uses
19/// PARTICLES 0 to 63 for the sparks and work->particles for the motes.
20///
21/// effect: the user and the targets.
22/// mode: the Djinni: 0 Venus, 1 Mercury, 2 Mars, 3 Jupiter; 4 to 7 the same
23/// over 84 frames instead of 64.
24/// side: 1 mirrors the pictures.
25/// anchor: where the Djinni appears: 0 over the first target, 1 at the
26/// first target's x at depth 0, 2 over the user, 3 at the user's x
27/// at depth 0, 4 in the centre of the field.
28/// outX, outY: receive the Djinni's last screen position.
30 s32 side, s32 anchor, s32 *outX, s32 *outY) {
31 s32 center[3];
32 s32 goal[3];
33 s32 step[3];
34 s32 point[3];
35 struct EffectPosition position;
36 void **slots;
37 void **cursor;
38 struct BattleEffectWork *work;
39 void *canvas;
40 BlitterPair draw;
41 u8 *sheet;
42 s32 frameCount;
43 struct MotionObject *target;
44 struct MotionObject *user;
45 u8 *palette;
46 s32 sheetId;
47 s32 frame;
48 s32 i;
49
50 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
51 sheet = EFFECT_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
52 work->effect = effect;
54 work->fadeFrames = 24;
55 work->fadeStep = 0;
56 if (mode > 3) {
57 mode -= 4;
58 frameCount = 84;
59 } else {
60 frameCount = 64;
61 }
62 switch (mode) {
63 case 0:
65 break;
66 case 1:
68 break;
69 case 2:
71 break;
72 default:
74 break;
75 }
76 // The small Djinni's resource is its palette, then its picture.
77 palette = Resource_GetTableEntry(sheetId);
78 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
79 Resource_DecodeType01(palette + 128, work->sheet);
81 if (side == 1) {
87 } else {
92 }
96 target = GetBattleObjectSlotFar(work->effect->actors[0])->object;
97 // Sparks spread out flat from the centre, 20 to 51 pixels up.
98 for (i = 0; i != 64; i++) {
99 struct EffectStep *spark = &PARTICLES[i];
100 s32 angle = Random16() & 0xffff;
101 s32 speed = (Random16() & 255) + 128;
102
103 SET_POSITION(spark, 0, ((Random16() & 31) + 20) << 16, 0);
104 SET_VELOCITY(spark, (Trig_Sin(angle) * speed) >> 5, 0,
105 (Trig_Cos(angle) * speed) >> 5);
106 spark->variant = 0;
107 }
109 // The centre moves from the user to the goal, 60 pixels up, over frames
110 // 6 to 45.
111 SET_VECTOR(center, user->x, 0, user->z);
112 // Every caller passes a literal anchor: 0, 1, 2 or 4 (Vine), never table
113 // data. The goal is therefore set before the interpolation starts.
114 switch (anchor) {
115 case 0:
116 SET_VECTOR(goal, target->x, 0x3c0000, target->z);
117 break;
118 case 1:
119 SET_VECTOR(goal, target->x, 0x3c0000, 0);
120 break;
121 case 2:
122 SET_VECTOR(goal, user->x, 0x3c0000, user->z);
123 break;
124 case 3:
125 SET_VECTOR(goal, user->x, 0x3c0000, 0);
126 break;
127 case 4:
128 SET_VECTOR(goal, 0, 0x3c0000, 0);
129 break;
130 }
131 SET_VECTOR(step, (goal[0] - center[0]) / 40, (goal[1] - center[1]) / 40,
132 (goal[2] - center[2]) / 40);
133 for (frame = 0; frame != frameCount; frame++) {
134 struct BattleCamera *camera = gCameraWork;
135
136 // The long version fades the canvas out over its last 8 frames; the sound
137 // plays on frame 8.
138 if (frame > 75)
139 REG_BLDALPHA = BLEND_ALPHA(168 - frame * 2, 16);
140 if (frame == 8)
143 if (frame >= 6 && frame <= 45) {
144 center[0] += step[0];
145 center[1] += step[1];
146 center[2] += step[2];
147 }
149 // The user glows white from frame 0 to frame 24.
150 if (frame == 0)
152 0);
153 if (frame == 24)
154 ObjectGroup_UpdateMembers(work->effect->actor, 0, -1, -1, 0);
155 // Only the first 32 sparks are drawn. Spark i appears on frame i / 8 and
156 // spins about the centre on one of four axes, drawn larger the nearer it
157 // is; from 24 frames after appearing it is pulled in, and goes out once
158 // it nears the centre.
159 for (i = 0; i != 32; i++) {
160 struct EffectStep *spark = &PARTICLES[i];
161
162 if (frame >= i / 8 && spark->variant == 0) {
163 s32 size;
164
166 switch (i & 3) {
167 case 0:
168 SceneTransform_ApplyYaw(frame * (i * 32 + 256));
169 break;
170 case 1:
171 SceneTransform_ApplyPitch(-frame * (i * 32 + 256));
172 break;
173 case 2:
174 SceneTransform_ApplyRoll(-frame * (i * 32 + 256));
175 break;
176 case 3:
177 SceneTransform_ApplyPitch(-frame * (i * 32 + 256));
178 SceneTransform_ApplyRoll(-frame * (i * 32 + 256));
179 break;
180 }
181 EffectPosition_ProjectPoint(&spark->x, &position);
182 position.x >>= 1;
184 CLAMP(position.depth, 250, 634);
185 size = 8 - (position.depth - 250) / 64;
186 EFFECT_DRAW_MOTE(draw[1], canvas, sheet, position.x, position.y, size);
188 if (frame >= i / 8 + 24) {
189 s32 pullX = -spark->x >> 7;
190 s32 pullY = -spark->y >> 7;
191 s32 pullZ = -spark->z >> 7;
192
193 spark->velocityX += pullX;
194 spark->velocityY += pullY;
195 spark->velocityZ += pullZ;
196 SET_VELOCITY(spark, spark->velocityX * 62 / 64,
197 spark->velocityY * 62 / 64, spark->velocityZ * 62 / 64);
198 if ((pullX > -2048 && pullX < 2048) &&
199 (pullZ > -2048 && pullZ < 2048))
200 spark->variant = -1;
201 }
202 }
203 }
204 // The Djinni sways 4 pixels either side of the centre on frames 54 to
205 // 69; the short version ends on frame 63, before its burst.
206 if (frame >= 54 && frame <= 69) {
207 SET_VECTOR(point, (Trig_Sin(frame << 10) * 4), 0, 0);
208 EffectPosition_ProjectPoint(point, &position);
209 *outX = position.x;
210 *outY = position.y;
211 position.x >>= 1;
212 draw[0](canvas, work->sheet, position.x - 10, position.y - 20, 20, 40);
213 }
214 // On frame 64 (long version only), 64 motes burst from the Djinni, each
215 // lasting 9 to 24 frames; its x is a screen position, and the canvas is
216 // half as wide.
217 if (frame == 64) {
218 for (i = 0; i != 64; i++) {
219 struct EffectStep *mote = &work->particles[i];
220 s32 angle = Random16() & 0xffff;
221 s32 speed = (Random16() & 255) + 128;
222
223 mote->x = *outX << 15;
224 mote->y = *outY << 16;
225 mote->velocityX = (Trig_Sin(angle) * speed) >> 6;
226 mote->velocityY = (Trig_Cos(angle) * speed) >> 5;
227 mote->variant = (Random16() & 15) + 8;
228 }
229 }
230 // Live motes shrink as their frames run out.
231 if (frame > 63) {
232 for (i = 0; i != 64; i++) {
233 struct EffectStep *mote = &work->particles[i];
234
235 if (mote->variant >= 0) {
236 s32 size = (mote->variant >> 3) + 2;
237
238 EFFECT_DRAW_MOTE(draw[0], canvas, sheet, Q_16_16_TO_INT(mote->x),
239 Q_16_16_TO_INT(mote->y), size);
241 mote->variant--;
242 }
243 }
244 }
246 }
247 // Leave the canvas cleared and fully shown for the effect that follows,
248 // without closing the layer.
254 REG_BLDALPHA = BLEND_ALPHA(16, 16);
255}
256
257// Projectile volleys and rushing strikes.
258// The folder README describes them under "Effect families".
259
260#define PROJECTILE_VOLLEY_ANIMATION_STEP_FAST 0x30 ///< the user's, while firing
261/// The user's animation step after the volley: the usual speed.
262#define PROJECTILE_VOLLEY_ANIMATION_STEP_NORMAL 0x10
263
264/// Six comets fly at each target, three frames apart, and burst into a flash
265/// and sparks; the effect's variant picks one of three comets.
266///
267/// Abilities: Slash, Wind Slash, Sonic Slash (kind 19).
270}
271/// Four spinning shurikens fly at each target, five frames apart, and vanish
272/// once past it.
273///
274/// Abilities: Shuriken (kind 54).
277}
278/// Ten pellets fly slowly at each target and bounce off it, up or down at
279/// random.
280///
281/// Abilities: Crazy Voice (kind 303).
284}
285/// Five yellow sparks fly level at each target, five frames apart.
286///
287/// Abilities: Wing Flutter (kind 307).
290}
291/// Ten large yellow sparks stream level at each target, one a frame, spread up
292/// and down.
293///
294/// Abilities: Wing Stroke (kind 381).
297}
298/// Ten small yellow sparks stream level at each target, one a frame.
299///
300/// Abilities: Wing Beat (kind 306).
303}
304/// Puts the user into its action pose (2) and fires the volley in this mode
305/// while its animation runs fast.
306///
307/// Called by Cutting Edge, Heat Wave and Blizzard. Leaves the user in its
308/// action pose, its animation back at the usual speed.
309static inline void
311 struct DispatchObject *user;
312
313 user = (struct DispatchObject *)GetBattleObjectSlotFar(effect->actor)->object;
317 BattleFx_RunProjectileVolley(effect, mode);
320}
321
322/// From the user's action pose, one large comet in ice colours flies at each
323/// target and bursts into 80 sparks.
324///
325/// Abilities: Cutting Edge (kind 57).
328}
329/// From the user's action pose, seven fireballs trailing embers fly at each
330/// target, two frames apart, each bursting into 40 sparks.
331///
332/// Abilities: Heat Wave (kind 59).
335}
336/// Thirty ice chips fall from high above the user onto each target, without
337/// shaking the screen or knocking the target back; the battle shows the damage
338/// on frame 48.
339///
340/// Abilities: Sleet (kind 205).
343}
344/// Sixty ice chips stream at each target, one a frame, without knocking it
345/// back.
346///
347/// Abilities: Ice Blessing (kind 402).
350}
351/// From the user's action pose, sixty ice chips stream at each target, one a
352/// frame, scattered up and down, without knocking it back.
353///
354/// Abilities: Blizzard (kind 63).
357}
358
359/// PARTICLES holds the hit flashes from 0, the sparks from 100 and the
360/// fireball trails from 512.
361#define PROJECTILE_VOLLEY_PARTICLE_COUNT 1024
362
363/// The bytes of a gProjectiles_Modes row.
365 PROJECTILE_VOLLEY_SHOTS, ///< shots at each target
366 PROJECTILE_VOLLEY_STEPS, ///< frames a shot takes to reach its target
367 PROJECTILE_VOLLEY_STAGGER, ///< frames between shots
368 PROJECTILE_VOLLEY_DELAY, ///< frames between targets
369 PROJECTILE_VOLLEY_SPARKS ///< sparks thrown on each hit
370};
371
372// Where the volley's pictures sit in the sheet.
373#define PROJECTILE_VOLLEY_COMET_CELLS 0x1000 ///< comets: the top half of each
374#define PROJECTILE_VOLLEY_STREAK_CELLS 0x2000 ///< wind streaks
375/// The hit flashes turned on their side, after the upright ones.
376#define PROJECTILE_VOLLEY_FLASH_TURNED 0x128a
377/// The yellow spark sheet: the small spark (12x8) first, then the medium one
378/// (18x13), then the large one.
379#define PROJECTILE_VOLLEY_MEDIUM_SPARK_CELLS (12 * 8)
380#define PROJECTILE_VOLLEY_LARGE_SPARK_CELLS (12 * 8 + 18 * 13)
381#define PROJECTILE_VOLLEY_DJINNI_CELLS 0x65c0 ///< the small Mercury djinni
382#define PROJECTILE_VOLLEY_FIRST_SPARK 100 ///< the first spark in PARTICLES
383#define PROJECTILE_VOLLEY_FIRST_TRAIL 512 ///< the first trail in PARTICLES
384
385/// Projectile volley: shots fly from the user to each target and burst
386/// into a flash and sparks when they pass it. The hit sound plays at most
387/// once every 8 frames.
388///
389/// Called by the eleven wrappers above, and by casting impacts 15 (mode 9)
390/// and 26 (mode 8, which no wrapper uses) once their prelude ends. With more
391/// than 63 shots in all it fires at the first target only, writing
392/// work->effect->count. Writes REG_BLDCNT in mode 1 and the first 128 bytes
393/// of BG palette RAM in modes 2 and 5; sets work->shakeFrames on each hit
394/// but in mode 7. Ends with the transfer callback removed, the blitter freed
395/// and the canvas layer closed; the second blitter is built and freed for
396/// each picture that needs it.
397///
398/// effect: the user and the targets. variant picks the comet in mode 0
399/// (mode 5 always uses comet 2, mode 8 comet 0); with prelude 1 a
400/// Mercury Djinni enters first.
401/// mode: the shot and its flight (0 to 11): 0, 5 and 8 comets (5 in the
402/// ice palette), 1 shurikens, 2 bouncing pellets, 3, 4 and 11
403/// yellow sparks, 6 fireballs with trails, 7, 9 and 10 ice chips.
405 s32 mode) {
406 struct EffectPosition position;
407 s32 screenX;
408 s32 screenY;
409 void **slots;
410 void **cursor;
411 struct BattleEffectWork *work;
412 void *canvas;
413 s32 i;
414 s32 j;
415 s32 frame;
416 BlitterPair draw;
417 struct BattleCamera *camera;
418 u8 *sheet;
419 s32 soundCooldown;
420 s32 total;
421 s32 kind;
422 s32 shots;
423 s32 steps;
424 struct MotionObject *user;
425 s32 k;
426 // The trail particles placed, and later the sparks' speed shift: one
427 // local for both, as separate locals change the register allocation.
428 s32 trailsOrShift;
429 s32 hit;
430 s32 x;
431
432 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
433 camera = EFFECT_SLOT(slots, HEAP_SLOT_CAMERA);
434 sheet = EFFECT_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
435 soundCooldown = 0;
436 work->effect = effect;
437 kind = effect->variant;
438 // The canvas's BG priority: 0 for Ice Blessing, 1 for the others. A
439 // Djinni prelude then opens the layer again at priority 0.
440 if (mode == 10)
442 else
444 if (work->effect->prelude == 1)
445 BattleFx_RunDjinniEntrance(effect, 1, work->effect->side, 2, &screenX,
446 &screenY);
447
448 // The main blitter, mirrored on side 1: brightest-wins for Cutting Edge,
449 // additive for the others.
450 if (mode == 5) {
451 if (work->effect->side == 1)
454 else
456 } else {
457 if (work->effect->side == 1)
461 else
464 }
466
467 // The shot pictures, and how long each mode's trails last: comets keep
468 // three quarters of each level a frame, shurikens none, the rest half.
470 if (mode == 0 || mode == 5 || mode == 8) {
471 if (mode == 5)
472 kind = 2;
473 if (mode == 8)
474 kind = 0;
475 if (kind == 0)
477 work->sheet + PROJECTILE_VOLLEY_COMET_CELLS, 1,
478 1);
479 else if (kind == 1)
481 work->sheet + PROJECTILE_VOLLEY_COMET_CELLS, 1,
482 1);
483 else
485 work->sheet + PROJECTILE_VOLLEY_COMET_CELLS, 1,
486 1);
487 // The ice palette is copied twice, before and after the streaks load.
488 if (mode == 5) {
490 Iwram_CopyWords((void *)BG_PLTT, pal, 128);
491 }
493 work->sheet + PROJECTILE_VOLLEY_STREAK_CELLS, 1,
494 0);
495 if (mode == 5) {
497 Iwram_CopyWords((void *)BG_PLTT, pal, 128);
498 }
500 } else if (mode == 1) {
502 1);
503 REG_BLDCNT = 0;
505 } else if (mode == 2) {
506 Iwram_CopyWords((void *)BG_PLTT,
509 work->sheet, 0, 0);
511 } else if (mode == 3 || mode == 4 || mode == 11) {
513 1, 1);
515 } else if (mode == 6) {
517 1);
519 } else {
520 // The ice chips, and the small Mercury Djinni the prelude draws.
522 1);
524 work->sheet + PROJECTILE_VOLLEY_DJINNI_CELLS, 1,
525 0);
527 }
530
531 // Where the shots start and how fast they fly.
535 {
539
540 // Keep the shots within work->particles' 64.
541 if (work->effect->count * shots > 63)
542 work->effect->count = 1;
543
544 // Each shot starts at the user, at a height its mode picks, and is aimed
545 // to reach its target in `steps` frames: straight across for sparks and
546 // Cutting Edge, at a random height near the target for the others.
547
549 struct MotionObject *target =
551 s32 targetHeight = BattleUnit_GetEffectHeightFar(work->effect->actors[i]);
552
553 for (j = 0; j != shots; j++) {
554 struct EffectStep *shot = &work->particles[i * shots + j];
555
556 shot->x = user->x;
557 if (mode == 7)
558 shot->y = user->y + ((Random16() & 15) << 16) + 0x3a0000;
559 else if (mode == 10)
560 shot->y = user->y + height / 2;
561 else if (mode == 6)
562 shot->y = user->y + height / 2;
563 else if (mode == 9)
564 shot->y = user->y + height / 2 + ((16 - (Random16() & 31)) << 16);
565 else if ((u32)(mode - 3) <= 1)
566 shot->y = user->y + height / 2 + ((16 - (Random16() & 31)) << 16);
567 else if (mode == 11)
568 shot->y = user->y + height / 2 + ((32 - (Random16() & 63)) << 16);
569 else if (mode == 5)
570 shot->y = user->y + height / 2;
571 else
572 shot->y = user->y + height;
573 shot->z = user->z;
574 shot->velocityX = (target->x - shot->x) / steps;
575 if (mode == 7)
576 shot->velocityY =
577 (s32)(target->y + ((Random16() & 63) << 16) - shot->y - 0xc0000) /
578 steps;
579 else if (mode == 8)
580 shot->velocityY =
581 (s32)(target->y + ((Random16() & 7) << 16) - shot->y + 0x160000) /
582 steps;
583 else if (mode == 9)
584 shot->velocityY =
585 (s32)(target->y + ((64 - (Random16() & 63)) << 16) - shot->y) /
586 steps;
587 else if (mode == 10)
588 shot->velocityY =
589 (s32)(target->y + ((Random16() & 31) << 16) - shot->y + 0x40000) /
590 steps;
591 else if ((u32)(mode - 3) <= 1 || mode == 11 || mode == 5)
592 shot->velocityY = 0;
593 else if (mode == 6)
594 shot->velocityY = (s32)(target->y + targetHeight / 2 +
595 ((Random16() & 15) << 16) - shot->y) /
596 steps;
597 else
598 shot->velocityY = (s32)(target->y + targetHeight -
599 ((Random16() & 15) << 16) - shot->y) /
600 steps;
601 shot->velocityZ = (target->z - shot->z) / steps;
602 shot->variant = 0;
603 }
604 }
605 // Free every flash, spark and trail.
606 for (i = 0; i != PROJECTILE_VOLLEY_PARTICLE_COUNT; i++)
607 PARTICLES[i].variant = 0;
608 // Every shot's flight, then 16 frames (32 for fireballs) for the last
609 // hits to fade.
610 if (mode == 6)
611 total = work->effect->count * delay + shots * stagger + 32;
612 else
613 total = work->effect->count * delay + shots * stagger + 16;
614
615 // Each frame: the prelude's Djinni, the shots and their hits, the hit
616 // flashes, the sparks and the trails, in that order.
617 for (frame = 0; frame != total; frame++) {
618 s32 index;
619
620 // The battle shows the damage on frame 16, 32 for Heat Wave and 48 for
621 // Sleet; Cutting Edge shows it on its first hit instead.
622 if (soundCooldown > 0)
623 soundCooldown--;
624 if (mode == 6) {
625 if (frame == 4)
627 if (frame == 32)
629 } else if (mode == 7) {
630 if (frame == 48)
632 } else if (mode != 5) {
633 if (frame == 16)
635 }
636
637 // Prelude: the small Djinni circles, and from frame 70 rises away; it
638 // is drawn twice on the first four frames. Its blitter is built and
639 // freed each frame.
640 if (work->effect->prelude == 1) {
641 s32 x = ((-Trig_Sin(frame << 11) * 4) >> 16) + screenX / 2 - 10;
642 s32 y = ((Trig_Cos(frame << 11) * 2) >> 16) + screenY - 24;
643
644 if (frame > 69)
645 y = y - frame * 2 + 138;
646 if (work->effect->side == 1)
650 else
654 if (frame <= 3)
655 draw[1](canvas, work->sheet + PROJECTILE_VOLLEY_DJINNI_CELLS, x, y,
656 20, 40);
657 draw[1](canvas, work->sheet + PROJECTILE_VOLLEY_DJINNI_CELLS, x, y, 20,
658 40);
660 }
661
662 // The shots: shot j at target i launches after frame
663 // j * stagger + i * delay. index counts every shot, so each has its own
664 // hit flash in PARTICLES.
666 index = 0;
668 struct MotionObject *target =
670
671 for (j = 0; j != shots; j++, index++) {
672 if (j * stagger + i * delay < frame) {
673 struct EffectStep *shot = &work->particles[i * shots + j];
674 struct EffectPosition *screenPosition = &position;
675
676 // The screen position (half across, on the canvas).
677 EffectPosition_ProjectPoint(shot, screenPosition);
678 screenPosition->x >>= 1;
679 shot->x += shot->velocityX;
680 shot->y += shot->velocityY;
681 shot->z += shot->velocityZ;
682 if (mode == 6) {
683 // Leave two trail particles behind the fireball.
684 trailsOrShift = 0;
687 struct EffectStep *particle = &PARTICLES[k];
688
689 if (particle->variant == 0) {
690 particle->x = position.x << 16;
691 particle->y = position.y << 16;
692 particle->velocityX = ((Random16() & 255) - 128) << 11;
693 particle->velocityY = ((Random16() & 255) - 128) << 11;
694 particle->variant = (Random16() & 7) + 32;
695 trailsOrShift++;
696 if (trailsOrShift == 2)
697 break;
698 }
699 }
700 }
701 if (shot->variant == 0) {
702 // A shot hits once it is on the target's side of the field and
703 // past the target's x.
704 x = shot->x;
705 if (target->x < 0) {
706 hit = x < 0;
707 /* FAKEMATCH: cancelling updates under if (target) end CSE
708 * before the hit test and emit nothing; without them, 77
709 * instructions differ in tbs-en. */
710 if (target) {
711 hit ^= x;
712 hit ^= x;
713 }
714 if (!hit)
715 goto drawShot;
716 } else {
717 hit = x >= 0;
718 /* FAKEMATCH: the same CSE block end keeps the opposite sign
719 * result before its side check; without this second pair, 14
720 * instructions differ in tbs-en. */
721 if (target) {
722 hit ^= x;
723 hit ^= x;
724 }
725 if (!hit)
726 goto drawShot;
727 }
728 if (ABS(x) >= ABS(target->x)) {
729 s32 spawned = 0;
730 struct EffectStep *flash = &PARTICLES[index];
731
732 shot->variant = 1;
733 if (mode == 5) {
735 } else if (mode != 6 && soundCooldown == 0) {
736 soundCooldown = 8;
738 }
739 // The hit: the shot's flash starts where it was drawn, the
740 // screen shakes (but for Sleet), the target flashes and,
741 // but for the ice chips, recoils.
742 if (mode == 2) {
743 // Pellets bounce back, up or down at random.
744 s32 kick = ((Random16() & 31) + 32) << 12;
745
746 if (Random16() & 1)
747 shot->velocityY += kick;
748 else
749 shot->velocityY -= kick;
750 shot->velocityX = -shot->velocityX;
751 }
752 flash->variant = 1;
753 SET_POSITION(flash, screenPosition->x, screenPosition->y, 0);
754 if (mode != 7)
755 work->shakeFrames = 2;
758 8);
759 if (mode != 7 && mode != 9 && mode != 10) {
760 if (mode == 5)
762 4);
763 else
765 5);
766 }
767 // Sparks: the mode's count, in the first free slots from 100,
768 // living 16 to 23 frames; Cutting Edge's fly twice as fast.
769 trailsOrShift = mode == 5 ? 12 : 11;
772 struct EffectStep *particle = &PARTICLES[k];
773
774 if (particle->variant == 0) {
775 particle->x = position.x << 16;
776 particle->y = position.y << 16;
777 particle->velocityX = ((Random16() & 255) - 128)
778 << trailsOrShift;
779 particle->velocityY = ((Random16() & 255) - 128)
780 << trailsOrShift;
781 particle->variant = (Random16() & 7) + 16;
782 spawned++;
783 if (spawned ==
785 break;
786 }
787 }
788 }
789 }
790 drawShot:
791 // Draw the shot, hit or not.
792 if (mode == 0 || mode == 5 || mode == 8) {
793 // The picture holds the top half; the bottom half is drawn
794 // flipped.
795 if (work->effect->side == 1)
799 else
803 canvas, work->sheet + PROJECTILE_VOLLEY_COMET_CELLS,
804 screenPosition->x - 16,
805 screenPosition->y - gProjectiles_CometHeights[kind], 32,
808 if (work->effect->side == 1)
812 else
817 canvas, work->sheet + PROJECTILE_VOLLEY_COMET_CELLS,
818 screenPosition->x - 16, screenPosition->y, 32,
821 } else if (mode == 1) {
822 // Shurikens vanish once past their target.
823 if (ABS(shot->x) <= ABS(target->x))
824 draw[0](canvas, work->sheet + frame % 6 * (32 * 24),
825 screenPosition->x - 16, screenPosition->y - 12, 32, 24);
826 } else if (mode == 7 || mode == 9 || mode == 10) {
827 s32 cell = j & 3;
828 draw[0](canvas, work->sheet + gProjectiles_PelletOffsets[cell],
829 screenPosition->x - 4, screenPosition->y - 4, 8, 8);
830 } else if (mode == 2) {
831 draw[0](canvas, work->sheet + j % 6 * (8 * 16),
832 screenPosition->x - 4, screenPosition->y - 8, 8, 16);
833 } else if (mode == 3) {
834 draw[0](canvas,
836 screenPosition->x - 9, screenPosition->y - 7, 18, 13);
837 } else if (mode == 4) {
838 draw[0](canvas, work->sheet, screenPosition->x - 6,
839 screenPosition->y - 4, 12, 8);
840 } else if (mode == 11) {
841 draw[0](canvas, work->sheet + PROJECTILE_VOLLEY_LARGE_SPARK_CELLS,
842 screenPosition->x - 15, screenPosition->y - 12, 29, 23);
843 } else {
844 draw[0](canvas, work->sheet, screenPosition->x - 20,
845 screenPosition->y - 32, 40, 64);
846 }
847 }
848 }
849 }
850
851 // Hit flashes, 12 frames: half a picture, drawn again flipped for the
852 // other half (odd flashes use the pictures turned on their side). A
853 // flash's z counts its frames, stepping the picture every 2.
854 if (mode == 0 || mode == 5 || mode == 8) {
855 for (i = 0; i != work->effect->count * shots; i++) {
856 struct EffectStep *flash = &PARTICLES[i];
857
858 if (flash->variant == 1) {
859 s32 step = flash->z / 2;
860
861 if (!(i & 1)) {
865 canvas, work->sheet + gProjectiles_FlashOffsets[step],
866 flash->x - gProjectiles_FlashWidths[step],
867 flash->y - gProjectiles_FlashRises[step],
875 canvas, work->sheet + gProjectiles_FlashOffsets[step],
876 flash->x,
877 flash->y + gProjectiles_FlashSteps[step] -
882 } else {
886 canvas,
887 work->sheet + gProjectiles_FlashOffsets[step] +
889 flash->x - gProjectiles_FlashRises[step],
890 flash->y - gProjectiles_FlashWidths[step],
898 canvas,
899 work->sheet + gProjectiles_FlashOffsets[step] +
901 flash->x + gProjectiles_FlashSteps[step] -
903 flash->y, gProjectiles_FlashHeights[step],
906 }
907 flash->z++;
908 if (flash->z == 12)
909 flash->variant = 0;
910 }
911 }
912 }
913
914 // Sparks fall and bounce off the bottom (y 112) at half speed,
915 // shrinking as their frames run out.
918 struct EffectStep *particle = &PARTICLES[i];
919
920 if (particle->variant > 0) {
921 s32 size = (particle->variant >> 3) + 1;
922
923 EFFECT_DRAW_MOTE(draw[0], canvas, sheet, Q_16_16_TO_INT(particle->x),
924 Q_16_16_TO_INT(particle->y), size);
925 EffectStep_AdvanceWithGravity2D(particle, 60, 0x1000);
926 if (particle->y > 0x700000)
927 particle->velocityY = -particle->velocityY / 2;
928 particle->variant--;
929 }
930 }
931
932 // Fireball trails rise and shrink as they fade.
935 struct EffectStep *particle = &PARTICLES[i];
936
937 if (particle->variant > 0) {
938 s32 size = (particle->variant >> 4) + 1;
939
940 EFFECT_DRAW_MOTE(draw[0], canvas, sheet, Q_16_16_TO_INT(particle->x),
941 Q_16_16_TO_INT(particle->y), size);
942 EffectStep_AdvanceWithGravity2D(particle, 60, -0x4000);
943 particle->variant--;
944 }
945 }
946 Camera_ApplyShake(4, 4);
947 EFFECT_END_FRAME(work);
948 }
949 }
950
952}
953
954/// Sends a battler back to its place (its anchor) with a hop.
955///
956/// Nothing calls it; ObjMotRst (battle/motion.c) sets the same motion without
957/// the hop. Sets the battler's motion object to move at up to 8 pixels a frame,
958/// jumping at 4 pixels a frame under the usual gravity, and selects its
959/// animation 1.
961 struct BattleObj *slot = GetBattleObjectSlotFar(id);
962 struct MotionObject *object = slot->object;
963
964 object->acceleration = 0x20000;
965 object->speedLimit = 0x80000;
966 object->velocityY = 0x40000;
967 object->verticalMotionStrength = 0xab85;
968 object->verticalMotionPhase = 0;
969 object->autoFaceMotion = 0;
970 object->snapToTarget = 1;
972 Object_SetMoveTargetFar((struct ObjectRuntime *)object, slot->anchorX, 0,
973 slot->anchorZ);
975}
976
977/// Moves a battler 80% of the way to another one over a number of frames,
978/// in its action pose. The speed is that distance over the frames; the
979/// distance is taken in 1/256 pixels so its square fits in 32 bits.
980///
981/// Called by BattleFx_RunRushingStrike. Sets the battler's acceleration,
982/// speed limit and gravity, turns it to face its motion, starts it moving on
983/// the ground towards that point and selects its animation 2.
984void BattleFx_SetApproachMotion(s32 id, s32 targetId, s32 frames) {
985 struct BattleObj *slot = GetBattleObjectSlotFar(id);
986 struct BattleObj *targetSlot = GetBattleObjectSlotFar(targetId);
987 struct MotionObject *object = slot->object;
988 struct MotionObject *target = targetSlot->object;
989 s32 rate = 80;
990 s32 diffX = target->x - object->x;
991 s32 startX = object->x;
992 s32 dx = rate * diffX / 100;
993 s32 diffZ = target->z - object->z;
994 s32 startZ = object->z;
995 s32 dz = rate * diffZ / 100;
996 s32 x = startX + dx;
997 s32 z = startZ + dz;
998 s32 stepX = dx >> 8;
999 s32 stepZ = dz >> 8;
1000 s32 speed;
1001
1002 speed = Iwram_Sqrt(stepX * stepX + stepZ * stepZ);
1003 speed = (speed << 8) / frames;
1004 object->acceleration = speed;
1005 object->speedLimit = speed;
1006 object->snapToTarget = 1;
1007 object->verticalMotionStrength = 0xab85;
1008 object->velocityY = 0;
1009 object->verticalMotionPhase = 0;
1010 object->autoFaceMotion = 1;
1012 Object_SetMoveTargetFar((struct ObjectRuntime *)object, x, 0, z);
1014}
1015
1016#undef PROJECTILE_VOLLEY_ANIMATION_STEP_FAST
1017#undef PROJECTILE_VOLLEY_ANIMATION_STEP_NORMAL
1018#undef PROJECTILE_VOLLEY_PARTICLE_COUNT
1019#undef PROJECTILE_VOLLEY_COMET_CELLS
1020#undef PROJECTILE_VOLLEY_STREAK_CELLS
1021#undef PROJECTILE_VOLLEY_FLASH_TURNED
1022#undef PROJECTILE_VOLLEY_MEDIUM_SPARK_CELLS
1023#undef PROJECTILE_VOLLEY_LARGE_SPARK_CELLS
1024#undef PROJECTILE_VOLLEY_DJINNI_CELLS
1025#undef PROJECTILE_VOLLEY_FIRST_SPARK
1026#undef PROJECTILE_VOLLEY_FIRST_TRAIL
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
struct BattleCamera * gCameraWork
@ COMPOSITE_FLIP_X
@ COMPOSITE_FLIP
@ COMPOSITE_FLIP_Y
@ COMPOSITE_ADDITIVE
@ COMPOSITE_MAX
BattleEffectDrawRectangle DrawRectangle
#define EFFECT_FOR_EACH_TARGET(i, effect)
Loops i over the effect's targets, effect->actors[0] to effect->actors[effect->count - 1]: the loops ...
void Palette_StepFadeTransfer(void)
Darkens the battle backdrop while the canvas is open: for fadeFrames frames, writes the backdrop's co...
Definition canvas.c:243
void BattleFx_ProcessPendingGraphicsTransfer(void)
Copies the canvas to VRAM once the effect has finished drawing a frame (transferPending): the 128x128...
Definition canvas.c:103
void BattleFx_BeginCanvasLayer(s32 bgControl)
Opens the canvas layer: starts the background palette fade, makes BG2 the canvas, alpha-blended over ...
Definition canvas.c:314
void Resource_LoadAndDecompress(s32 id, void *dst, s32 skipPalette, s32 copyPalette)
Decompresses a resource whose first 128 bytes may be a palette.
void ObjectGroup_UpdateMembers(s32 actorId, s32 palette, s32 animation, s32 timerSlot, s32 timerFrames)
Updates every animation group of one battler's object.
Definition dispatch.c:254
What every part of the battle effect object shares: its includes, macros and frame-loop helpers.
#define EFFECT_RELEASE_BLITTERS()
Frees the two blitters, the alternate first.
#define EFFECT_DRAW_MOTE(draw, canvas, sheet, x, y, size)
Particle sheets hold ten mote cells, 1x2 to 10x20 pixels.
#define EFFECT_PRESENT_FRAME(work)
Ends a frame of a canvas effect: marks the canvas ready for the transfer callback,...
#define EFFECT_SET_TRANSFER(work, mode, value)
Sets how the canvas transfer treats what is left in the canvas after each copy: mode with value (see ...
@ CANVAS_COPY_AND_CLEAR
copy, then fill the canvas with transferValue
@ CANVAS_COPY_AND_FADE
copy, keeping 50% or 75% (transferValue) of each pixel in the canvas for the next frame
#define CANVAS_BYTES
The canvas: 128x128 pixels, one byte each, in its heap slot and in VRAM at BG_CHAR_BLOCK(1).
#define EFFECT_CALLBACK_ORDER
The scheduler order of every per-frame effect callback (Scheduler_AddOrUpdateCallback sorts the frame...
#define EFFECT_SLOT(slots, slot)
A work slot read through a pointer to the effect's own slot, gWorkSlot[HEAP_SLOT_BATTLE_EFFECT].
#define EFFECT_FINISH_CANVAS_ONE_BLITTER()
The same for an effect that drew through one blitter.
#define EFFECT_SHOW_DAMAGE(hitSound)
Lets the battle show the damage: resumes its paused playback, which plays hitSound (an SE_ id; 0 keep...
#define EFFECT_START_TRANSFER(work, mode, value)
Sets the transfer, then starts copying the canvas to VRAM once a frame.
#define EFFECT_LOAD_BLITTER(slot, flags, mode)
Builds a blitter for the 128x128 canvas (1 << 7 pixels each way) in work slot slot: BattleFx_BuildBli...
#define EFFECT_GET_SLOTS(slots, cursor, work, canvas)
Starts at the effect's entry in the whole work-slot array.
#define EFFECT_END_FRAME(work)
The usual end of an effect frame: counts down the targets' flash timers (ObjectGroup_TickMemberTimers...
#define EFFECT_VIEW_FROM_CAMERA(camera)
Starts a frame's 3D projection from the battle camera: resets the transform, then looks from camera->...
u8 gProjectiles_FlashSteps[]
u8 gProjectiles_FlashHeights[]
u8 gProjectiles_FlashRises[]
u8 gProjectiles_CometHeights[]
Comet picture heights, by comet kind.
u8 gProjectiles_Modes[][5]
Each projectile volley mode, by the PROJECTILE_VOLLEY_ columns (projectiles.c).
u16 gProjectiles_PelletOffsets[]
Ice chip pictures, by shot index & 3.
u16 gProjectiles_FlashOffsets[]
u8 gProjectiles_FlashWidths[]
struct BattleObj * GetBattleObjectSlotFar(s32 objectId)
Far call to BattleObjGet.
s32 BattleUnit_GetEffectHeightFar(s32 id)
void BattleMotion_ApplyVariantMotionFar(s32 id, s32 variant)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void ObjectDispatch_SetAnimationSpeedFar(struct DispatchObject *obj, s32 val)
void Object_SetMoveTargetFar(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
void ObjectDispatch_StartIdleFar(struct DispatchObject *obj)
void AudioCommand_PlayFar(s32 id)
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
void Camera_ApplyShake(s32 rangeX, u32 rangeY)
Shakes the battle view while gBattleFxWork's shakeFrames lasts, moving BG1 and the projection centre ...
Definition hail.c:364
@ HEAP_SLOT_BLITTER_ALTERNATE
Definition heap_state.h:47
@ HEAP_SLOT_BATTLE_SHEET
Definition heap_state.h:44
@ HEAP_SLOT_CAMERA
Definition heap_state.h:38
@ HEAP_SLOT_BLITTER
Definition heap_state.h:46
#define BG_CHAR_BLOCK(n)
Definition io_reg.h:166
#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 BG_PLTT
Definition io_reg.h:157
#define REG_BLDCNT
Definition io_reg.h:119
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
Definition iwram_call.h:85
static s32 Iwram_Sqrt(s32 value)
Definition iwram_call.h:63
static s32 Iwram_ClearWords(void *destination, s32 size)
Definition iwram_call.h:55
#define SET_VELOCITY(p, vx, vy, vz)
Definition macros.h:18
#define ABS(v)
The magnitude of v. v is read twice.
Definition macros.h:32
#define SET_POSITION(p, px, py, pz)
Sets the position or the velocity of a particle, a piece of debris or an object in one statement.
Definition macros.h:16
#define SET_VECTOR(v, x, y, z)
Sets the x, y and z of a three-part vector: a position about to be projected, a per-frame step,...
Definition macros.h:12
#define CLAMP(v, low, high)
Keeps v within low to high, the low bound tested first.
Definition macros.h:23
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
void Runtime_ReleaseHeapBlock(s32 slot)
void EffectStep_AdvanceWithGravity2D(struct EffectStep *step, s32 damping, s32 gravity)
Moves a particle one frame on the screen: adds its velocity, then gravity to its vertical speed,...
Definition positions.c:46
void EffectStep_AdvanceWithGravity3D(struct EffectStep *step, s32 damping, s32 gravity)
Moves a particle one frame in three dimensions: adds its velocity, then gravity to its vertical speed...
Definition positions.c:29
s32 EffectPosition_ProjectPoint(const void *point, struct EffectPosition *position)
Projects a point in the current transform onto the screen, 16 pixels higher, and returns the projecti...
Definition positions.c:64
void BattleFx_RunWingBeat(struct BattleEffectArgument *effect)
Ten small yellow sparks stream level at each target, one a frame.
UNUSED void BattleFx_InitializeRisingObject(s32 id)
Sends a battler back to its place (its anchor) with a hop.
void BattleFx_RunWingFlutter(struct BattleEffectArgument *effect)
Five yellow sparks fly level at each target, five frames apart.
void BattleFx_RunCuttingEdge(struct BattleEffectArgument *effect)
From the user's action pose, one large comet in ice colours flies at each target and bursts into 80 s...
#define PROJECTILE_VOLLEY_ANIMATION_STEP_FAST
the user's, while firing
void BattleFx_RunDjinniEntrance(struct BattleEffectArgument *effect, s32 mode, s32 side, s32 anchor, s32 *outX, s32 *outY)
Djinni entrance: sparks swirl around a point that travels from the user to the goal and gather into t...
Definition projectiles.c:29
#define PROJECTILE_VOLLEY_LARGE_SPARK_CELLS
void BattleFx_RunProjectileVolley(struct BattleEffectArgument *effect, s32 mode)
Projectile volley: shots fly from the user to each target and burst into a flash and sparks when they...
void BattleFx_RunIceBlessing(struct BattleEffectArgument *effect)
Sixty ice chips stream at each target, one a frame, without knocking it back.
void BattleFx_RunSleet(struct BattleEffectArgument *effect)
Thirty ice chips fall from high above the user onto each target, without shaking the screen or knocki...
#define PROJECTILE_VOLLEY_STREAK_CELLS
wind streaks
void BattleFx_RunHeatWave(struct BattleEffectArgument *effect)
From the user's action pose, seven fireballs trailing embers fly at each target, two frames apart,...
void BattleFx_RunSlash(struct BattleEffectArgument *effect)
Six comets fly at each target, three frames apart, and burst into a flash and sparks; the effect's va...
VolleyField
The bytes of a gProjectiles_Modes row.
@ PROJECTILE_VOLLEY_DELAY
frames between targets
@ PROJECTILE_VOLLEY_SHOTS
shots at each target
@ PROJECTILE_VOLLEY_STEPS
frames a shot takes to reach its target
@ PROJECTILE_VOLLEY_STAGGER
frames between shots
@ PROJECTILE_VOLLEY_SPARKS
sparks thrown on each hit
void BattleFx_RunBlizzard(struct BattleEffectArgument *effect)
From the user's action pose, sixty ice chips stream at each target, one a frame, scattered up and dow...
#define PROJECTILE_VOLLEY_ANIMATION_STEP_NORMAL
The user's animation step after the volley: the usual speed.
void BattleFx_RunCrazyVoice(struct BattleEffectArgument *effect)
Ten pellets fly slowly at each target and bounce off it, up or down at random.
#define PROJECTILE_VOLLEY_PARTICLE_COUNT
PARTICLES holds the hit flashes from 0, the sparks from 100 and the fireball trails from 512.
#define PROJECTILE_VOLLEY_FIRST_TRAIL
the first trail in PARTICLES
void BattleFx_RunShuriken(struct BattleEffectArgument *effect)
Four spinning shurikens fly at each target, five frames apart, and vanish once past it.
#define PROJECTILE_VOLLEY_COMET_CELLS
comets: the top half of each
void BattleFx_RunWingStroke(struct BattleEffectArgument *effect)
Ten large yellow sparks stream level at each target, one a frame, spread up and down.
#define PROJECTILE_VOLLEY_MEDIUM_SPARK_CELLS
The yellow spark sheet: the small spark (12x8) first, then the medium one (18x13),...
void BattleFx_SetApproachMotion(s32 id, s32 targetId, s32 frames)
Moves a battler 80% of the way to another one over a number of frames, in its action pose.
#define PROJECTILE_VOLLEY_DJINNI_CELLS
the small Mercury djinni
static void BattleFx_RunVolleyWithAction(struct BattleEffectArgument *effect, s32 mode)
Puts the user into its action pose (2) and fires the volley in this mode while its animation runs fas...
#define PROJECTILE_VOLLEY_FIRST_SPARK
the first spark in PARTICLES
#define PROJECTILE_VOLLEY_FLASH_TURNED
The hit flashes turned on their side, after the upright ones.
char ResourceId_CometSheetC
char ResourceId_VenusDjinnSmallSheet
char ResourceId_MarsDjinnSmallSheet
char ResourceId_ShurikenSheet
char ResourceId_MercuryDjinnSmallSheet
char ResourceId_IceChipSheet
char ResourceId_CometSheetA
char ResourceId_ParticleSpritesA
char ResourceId_FireballSheet
char ResourceId_ProjectileVolleyImage
char ResourceId_CometSheetB
char ResourceId_IceBlockSheet
char ResourceId_JupiterDjinnSmallSheet
char ResourceId_WindStreakSheet
char ResourceId_YellowSparkSheet
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
Definition decompress.c:31
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
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
#define SE_133
Definition songs.h:126
#define SE_136
Definition songs.h:129
#define SE_132
Definition songs.h:125
#define SE_212
Definition songs.h:207
#define SE_HEAVY_IMPACT
Definition songs.h:127
void * gWorkSlot[]
The battle camera: its eye, the focus it turns about, and its pitch, yaw and distance.
The command shared by an effect's caller, dispatcher and handlers.
s32 actor
the user's unit id
s32 side
1 when the targets are the party, 0 for enemies
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
The running battle effect's work: its canvas image, 64 particles, the display registers it stages and...
s32 fadeFrames
backdrop fade frames left (Palette_StepFadeTransfer)
s32 frame
frame counter some effects keep, from 0
s32 fadeStep
CANVAS_FADE_STEPs the backdrop has darkened so far.
s32 shakeFrames
shake frames left; Camera_ApplyShake counts down
struct BattleEffectArgument * effect
the command being run
struct EffectStep particles[64]
free while variant is -1
A unit's place on the battlefield: its sprite object, resources and animations, its anchor spot and s...
struct MotionObject * object
NULL once released.
s32 anchorZ
16.16 fixed-point pixels
s32 anchorX
16.16 fixed-point pixels
A field object as the object dispatcher's far calls take it.
A point projected onto the screen, with its depth.
Definition effect_step.h:46
s32 y
screen pixels
Definition effect_step.h:59
s32 depth
projected depth, larger further away
Definition effect_step.h:60
s32 x
screen pixels
Definition effect_step.h:58
A moving point of an effect: its position, its velocity and a value each effect uses its own way (a s...
Definition effect_step.h:13
s32 velocityX
16.16 fixed-point pixels per frame
Definition effect_step.h:28
s32 z
16.16 fixed-point pixels
Definition effect_step.h:26
s32 variant
each effect's own: a size, a countdown, -1 for idle
Definition effect_step.h:31
s32 x
16.16 fixed-point pixels
Definition effect_step.h:24
s32 y
16.16 fixed-point pixels
Definition effect_step.h:25
s32 velocityY
16.16 fixed-point pixels per frame
Definition effect_step.h:29
s32 velocityZ
16.16 fixed-point pixels per frame
Definition effect_step.h:30
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
s32 y
16.16 fixed-point pixels
Definition motobj.h:24
u16 height
half the sprite's box height; FieldActor's radius
Definition motobj.h:29
s32 acceleration
Horizontal speed gained each frame towards the target, or lost braking without one,...
Definition motobj.h:37
s32 x
16.16 fixed-point pixels
Definition motobj.h:23
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
void SceneTransform_ApplyYaw(s32 angle)
Rotates gTransform about the Y axis by angle.
Definition transform.c:113
void SceneTransform_ApplyPitch(s32 angle)
Rotates gTransform about the X axis by angle.
Definition transform.c:97
void Transform_Pop(void)
Restores gTransform from the save area, if Transform_Push saved it.
Definition transform.c:49
void SceneTransform_ApplyPosition(const s32 *position)
Translates gTransform by position (x, y, z in 16.16).
Definition transform.c:145
void Transform_Push(void)
Saves gTransform into the save area (one level deep; a second save is ignored).
Definition transform.c:30
void SceneTransform_ApplyRoll(s32 angle)
Rotates gTransform about the Z axis by angle.
Definition transform.c:129
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
#define EFFECT_CLIP_BOUNDS
Clips overflow on all four sides.
Definition effect.h:224
#define Q_16_16_TO_INT(v)
Definition effect.h:231
#define PARTICLES
The map cell buffer (gMapCellBuffer), which the effects borrow, has two views here: Ram_MapCellBuffer...
Definition effect.h:221
DrawRectangle BlitterPair[2]
A blitter pair: [0] built in HEAP_SLOT_BLITTER and [1] in HEAP_SLOT_BLITTER_ALTERNATE (BattleFx_Fetch...
Definition effect.h:244