Alchemy
Loading...
Searching...
No Matches

burst_shower.c

Go to the documentation of this file.
1/// @file
2/// The blessings' burst showers.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7// The burst shower's second picture in the sheet, after the tornado.
8#define BURST_SHOWER_CELLS 0xC56
9#define BURST_SHOWER_BURSTS 48 ///< one fired a frame from frame 0
10#define BURST_SHOWER_BURST_LIFE 24 ///< frames each burst lives
11
12/// The burst shower's styles, its mode argument.
14 BURST_SHOWER_MODE_FLASH, ///< flash bursts
15 BURST_SHOWER_MODE_ICE, ///< in the ice block palette
16 BURST_SHOWER_MODE_SPRAY, ///< in the water spray palette
17 BURST_SHOWER_MODE_PINK, ///< pink, fired from 16 pixels lower
18 BURST_SHOWER_MODE_DJINNI, ///< Mars djinni palette, 28 pixels in front
19 BURST_SHOWER_MODE_LIGHTNING, ///< no bursts: a violet lightning bolt
20 BURST_SHOWER_MODE_GREY, ///< grey; the targets stay solid black
21 BURST_SHOWER_MODE_FACES, ///< demon faces from 16 pixels in front
22};
23
24/// Arms DMA 0 to copy one word of gBattleFxWork's bg2xLines table into BG2X at
25/// each horizontal blank, bending BG2 line by line.
26///
27/// Runs each frame as a scheduler callback added by the target motes, the
28/// casting impacts, Condemn, the gathering lights, Torch and Planet Diver,
29/// each of which removes it before it returns. Stops DMA 0 and restarts it
30/// from the top of the table.
33 volatile u16 *channel = REG_DMA0;
34 Dma_Stop(channel);
35 Dma_Set(work->bg2xLines, (void *)&REG_BG2X, DMA_HBLANK_WORD_PER_LINE,
36 (volatile u32 *)channel);
37}
38
39/// The user fires a stream of flash bursts at the targets, one a frame, each
40/// towards a random point near a target.
41///
42/// Abilities: Fire Blessing (kind 400).
45}
46/// The user fires a stream of bursts at the targets in the water-spray palette.
47///
48/// Abilities: Water Blessing (kind 401).
51}
52/// The user fires a stream of grey bursts at the targets, which turn solid
53/// black and stay so.
54///
55/// Abilities: Dark Blessing (kind 403).
58}
59/// Fires pink bursts from 16 pixels below the normal origin.
60///
61/// Abilities: Dark Blessing, Acid Blessing (kind 404).
64}
65/// Shows violet lightning between the user and targets instead of bursts: a
66/// bolt flickers through three pictures in front of the user, and the targets
67/// flash in turn without being knocked back.
68///
69/// Abilities: Storm Blessing (kind 405).
72}
73/// The user fires a stream of demon faces at the targets, from 16 pixels in
74/// front of it.
75///
76/// Abilities: Evil Blessing (kind 406).
79}
80/// The user fires a stream of Mars-coloured bursts at the targets, from 28
81/// pixels in front of it.
82///
83/// Abilities: Deadly Gas (kind 407).
86}
87#define BURST_SHOWER_FRAMES 64
88
89/// Burst shower: for 48 frames the user fires one burst a frame at a random
90/// point near one of the targets, taking them in turn, and each target is
91/// hit every 8 frames. Each burst lives 24 frames. A sound plays on frame 4
92/// and the battle shows the damage on frame 24 (frame 60 in the grey mode).
93///
94/// Called by the seven blessing wrappers above. Each burst is one of
95/// work->particles, its variant counting the frames it has lived (-1 when
96/// free). Writes REG_BLDALPHA, the first 64 BG colours (all but modes 5 and
97/// 7), REG_BLDCNT in the grey mode and REG_BG2PA in the lightning mode; sets
98/// work->shakeFrames on each hit. Ends with the transfer callback removed,
99/// the blitters freed and the canvas layer closed.
100///
101/// effect: the user and the targets.
102/// mode: the burst and its palette: 0 flash bursts, 1 in the ice block
103/// palette, 2 in the water spray palette, 3 pink and fired from 16
104/// pixels lower, 4 in the Mars djinni palette from 28 pixels in
105/// front, 6 grey (the targets turn solid black and stay so), 7 demon
106/// faces from 16 pixels in front. Mode 5 fires no bursts: a violet
107/// lightning bolt stands between the user and the targets, on a
108/// canvas shown at three times its width. No kind in the effect
109/// table uses mode 1.
111 u32 *slots;
112 struct BattleEffectWork *work;
113 void *canvas;
114 u8 *sprites;
115 BlitterPair draw;
116 struct EffectPosition origin;
117 struct EffectPosition targetSpots[8];
118 s32 aim[3];
119 u16 *color;
120 s32 frame;
121 s32 i;
122 s32 target;
123 s32 level;
124 s32 paletteId;
125 s32 width;
126 s32 height;
127
128 // The slots are read from the canvas's, not the work block's.
130 canvas = (void *)slots[0];
132 sprites = (u8 *)CANVAS_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
133 work->effect = effect;
135 REG_BLDALPHA = BLEND_ALPHA(16, 16);
136
137 // The faces are drawn facing each way by side; the others take the usual
138 // pair for the side.
139 if (mode == BURST_SHOWER_MODE_FACES) {
145 } else {
147 }
148
149 // The pictures and the palette. The tornado is loaded first in every mode
150 // but never drawn here; its size fixes where the burst pictures start.
152 if (mode == BURST_SHOWER_MODE_LIGHTNING) {
154 (work->sheet + BURST_SHOWER_CELLS), 1, 1);
155 } else if (mode == BURST_SHOWER_MODE_FACES) {
157 (work->sheet + BURST_SHOWER_CELLS), 1, 1);
158 } else {
160 (work->sheet + BURST_SHOWER_CELLS), 1, 1);
162 0);
163 // The grey mode: a ramp of 16 greys, four entries each, with blending
164 // off.
165 if (mode == BURST_SHOWER_MODE_GREY) {
166 for (i = 0, color = (u16 *)BG_PLTT; i != 64; i++) {
167 level = i / 4;
168 *color = ((level << 10) | (level << 5)) | level;
169 color++;
170 }
171 REG_BLDCNT = 0;
172 } else {
173 switch (mode) {
175 paletteId = (s32)&ResourceId_FlashBurstSheet;
176 break;
178 paletteId = (s32)&ResourceId_IceBlockSheet;
179 break;
181 paletteId = (s32)&ResourceId_WaterSpraySheet;
182 break;
184 paletteId = (s32)&ResourceId_PinkPalette;
185 break;
187 default:
188 paletteId = (s32)&ResourceId_MarsDjinnSheet;
189 break;
190 }
191 Iwram_CopyWords((void *)BG_PLTT, Resource_GetTableEntry(paletteId), 128);
192 }
193 }
194
195 // The faces leave shorter trails than the bursts.
196 if (mode == BURST_SHOWER_MODE_FACES) {
198 } else {
200 }
203
204 for (i = 0; i != 64; i++) {
205 work->particles[i].variant = -1;
206 }
207
208 // Where the bursts start: the user, moved for some modes. The lightning's
209 // canvas is shown at three times its width, so its x is a third.
211 if (mode == BURST_SHOWER_MODE_PINK) {
212 origin.y -= 16;
213 }
214 if (mode == BURST_SHOWER_MODE_DJINNI) {
215 if (work->effect->side == 1) {
216 origin.x += 28;
217 } else {
218 origin.x -= 28;
219 }
220 }
221 if (mode == BURST_SHOWER_MODE_FACES) {
222 if (work->effect->side == 1) {
223 origin.x += 16;
224 } else {
225 origin.x -= 16;
226 }
227 }
228 if (mode == BURST_SHOWER_MODE_LIGHTNING) {
229 origin.x = origin.x / 3;
230 REG_BG2PA = Q_8_8(1.0 / 3);
231 }
232
233 // Where each target stands.
234 i = 0;
235 while (i != work->effect->count) {
237 &targetSpots[i]);
238 i += 1;
239 }
240
241 frame = 0;
242 do {
243 // The bursts aim at the targets in turn, one a frame.
244 target = frame % work->effect->count;
245 if (frame == 4) {
247 }
248 if (mode != BURST_SHOWER_MODE_GREY) {
249 if (frame == 24) {
251 }
252 } else {
253 if (frame == 60) {
255 }
256 }
257
258 // Mode 5 draws the lightning from the user, stepping through its three
259 // 72x62 pictures every 3 frames (0x1200 bytes apart); the others fire one
260 // burst a frame for 48 frames at a random point near a target.
261 if (mode == BURST_SHOWER_MODE_LIGHTNING) {
262 if (work->effect->side == 1) {
263 draw[0](canvas,
264 (work->sheet + BURST_SHOWER_CELLS) + ((frame / 3 % 3 * 9) << 9),
265 origin.x - 2, origin.y - 32, 72, 62);
266 } else {
267 draw[0](canvas,
268 (work->sheet + BURST_SHOWER_CELLS) + ((frame / 3 % 3 * 9) << 9),
269 origin.x - 70, origin.y - 32, 72, 62);
270 }
271 } else {
272 // The point is picked every frame, fired or not, as it draws two
273 // random numbers.
274 aim[0] = (targetSpots[target].x + (Random16() & 31)) - 16;
275 aim[1] = (targetSpots[target].y + (Random16() & 63)) - 16;
276 if (frame <= BURST_SHOWER_BURSTS - 1) {
277 // The canvas is half the screen's width, so x is halved. The burst
278 // reaches its point in 32 frames.
279 work->particles[frame].x = origin.x << 15;
280 work->particles[frame].y = origin.y << 16;
281 work->particles[frame].velocityX = (aim[0] - origin.x) << 11;
282 work->particles[frame].velocityY = (aim[1] - origin.y) << 11;
283 work->particles[frame].variant = 0;
284 }
285 }
286
287 // Move and draw the bursts; each lasts 24 frames and steps through the
288 // 32x64 pictures (0x800 bytes apart) every 4. The faces have one picture,
289 // mirrored on side 1.
290 i = 0;
291 width = 32;
292 height = 64;
293 do {
294 struct EffectStep *spark = &work->particles[i];
295 // A burst shows from its third frame, or its seventh for the faces
296 // and the djinni.
297 if (spark->variant >= 0) {
298 if (mode == BURST_SHOWER_MODE_FACES) {
299 if (spark->variant > 5) {
300 draw[work->effect->side](canvas, (work->sheet + BURST_SHOWER_CELLS),
301 Q_16_16_TO_INT(spark->x) - 16,
302 Q_16_16_TO_INT(spark->y) - 32, width,
303 height);
304 }
305 } else if (mode == BURST_SHOWER_MODE_DJINNI) {
306 if (spark->variant > 5) {
307 draw[0](canvas,
308 (work->sheet + BURST_SHOWER_CELLS) +
309 ((spark->variant / 4) << 11),
310 Q_16_16_TO_INT(spark->x) - 16,
311 Q_16_16_TO_INT(spark->y) - 32, width, height);
312 }
313 } else if (mode != BURST_SHOWER_MODE_LIGHTNING) {
314 if (spark->variant > 1) {
315 draw[0](canvas,
316 (work->sheet + BURST_SHOWER_CELLS) +
317 ((spark->variant / 4) << 11),
318 Q_16_16_TO_INT(spark->x) - 16,
319 Q_16_16_TO_INT(spark->y) - 32, width, height);
320 }
321 }
322 spark->x += spark->velocityX;
323 spark->y += spark->velocityY;
324 spark->variant += 1;
325 if (spark->variant == BURST_SHOWER_BURST_LIFE) {
326 spark->variant = -1;
327 }
328 }
329 i += 1;
330 } while (i != 64);
331
332 // Hit each target every 8 frames, once its turn has come: target i on
333 // frames whose low three bits are i.
334 if (mode == BURST_SHOWER_MODE_LIGHTNING) {
335 i = 0;
336 while (i != work->effect->count) {
337 // The bolt strikes target i from frame i * 4 + 2 and does not knock
338 // it back.
339 if ((frame >= (i * 4) + 2) && ((frame & 7) == i)) {
340 work->shakeFrames = 8;
342 POSE_DAMAGE, i, 4);
343 }
344 i += 1;
345 }
346 } else {
347 i = 0;
348 while (i != work->effect->count) {
349 // The bursts reach target i from frame i * 4 + 16.
350 if ((frame >= (i * 4) + 16) && ((frame & 7) == i)) {
351 work->shakeFrames = 8;
352 if (mode == BURST_SHOWER_MODE_GREY) {
355 } else {
358 }
360 }
361 i += 1;
362 }
363 }
364
365 Camera_ApplyShake(4, 4);
366 // In the grey mode the flash timers never run down, so the targets stay
367 // black.
368 if (mode != BURST_SHOWER_MODE_GREY) {
370 }
372 frame += 1;
373 } while (frame != BURST_SHOWER_FRAMES);
374
376}
377
378#undef BURST_SHOWER_CELLS
379#undef BURST_SHOWER_BURSTS
380#undef BURST_SHOWER_BURST_LIFE
381#undef BURST_SHOWER_FRAMES
@ SPRITE_COLOR_BLACK
solid colour 1, black
Definition animspr.h:31
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
@ COMPOSITE_FLIP_X
@ COMPOSITE_MAX
BattleEffectDrawRectangle DrawRectangle
void BattleFx_RunDeadlyGas(struct BattleEffectArgument *effect)
The user fires a stream of Mars-coloured bursts at the targets, from 28 pixels in front of it.
void BattleFx_ArmBg2AffineHBlankDma(void)
Arms DMA 0 to copy one word of gBattleFxWork's bg2xLines table into BG2X at each horizontal blank,...
void BattleFx_RunBurstShower(struct BattleEffectArgument *effect, s32 mode)
Burst shower: for 48 frames the user fires one burst a frame at a random point near one of the target...
#define BURST_SHOWER_BURSTS
one fired a frame from frame 0
Definition burst_shower.c:9
#define BURST_SHOWER_BURST_LIFE
frames each burst lives
void BattleFx_RunStormBlessing(struct BattleEffectArgument *effect)
Shows violet lightning between the user and targets instead of bursts: a bolt flickers through three ...
void BattleFx_RunFireBlessing(struct BattleEffectArgument *effect)
The user fires a stream of flash bursts at the targets, one a frame, each towards a random point near...
#define BURST_SHOWER_FRAMES
void BattleFx_RunEvilBlessing(struct BattleEffectArgument *effect)
The user fires a stream of demon faces at the targets, from 16 pixels in front of it.
#define BURST_SHOWER_CELLS
Definition burst_shower.c:8
void BattleFx_RunAcidBlessing(struct BattleEffectArgument *effect)
Fires pink bursts from 16 pixels below the normal origin.
void BattleFx_RunDarkBlessing(struct BattleEffectArgument *effect)
The user fires a stream of grey bursts at the targets, which turn solid black and stay so.
void BattleFx_RunWaterBlessing(struct BattleEffectArgument *effect)
The user fires a stream of bursts at the targets in the water-spray palette.
BurstShowerMode
The burst shower's styles, its mode argument.
@ BURST_SHOWER_MODE_DJINNI
Mars djinni palette, 28 pixels in front.
@ BURST_SHOWER_MODE_FACES
demon faces from 16 pixels in front
@ BURST_SHOWER_MODE_PINK
pink, fired from 16 pixels lower
@ BURST_SHOWER_MODE_SPRAY
in the water spray palette
@ BURST_SHOWER_MODE_LIGHTNING
no bursts: a violet lightning bolt
@ BURST_SHOWER_MODE_FLASH
flash bursts
@ BURST_SHOWER_MODE_ICE
in the ice block palette
@ BURST_SHOWER_MODE_GREY
grey; the targets stay solid black
void ObjectGroup_TickMemberTimers(void)
Counts down each target's flash timer, which ObjectGroup_UpdateMembers starts; when one runs out,...
Definition canvas.c:275
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.
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
Definition dma.h:62
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_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_FADE
copy, keeping 50% or 75% (transferValue) of each pixel in the canvas for the next frame
#define EFFECT_CALLBACK_ORDER
The scheduler order of every per-frame effect callback (Scheduler_AddOrUpdateCallback sorts the frame...
static void Dma_Stop(volatile u16 *channel)
Stops a DMA channel: clears its repeat and start timing bits, then its enable bit,...
#define EFFECT_FINISH_CANVAS()
The usual end of a canvas effect: stops the transfer callback before freeing what it reads,...
#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_LOAD_BLITTER(slot, flags, mode)
Builds a blitter for the 128x128 canvas (1 << 7 pixels each way) in work slot slot: BattleFx_BuildBli...
#define CANVAS_SLOT(slots, slot)
A work slot read through a pointer to the canvas slot, gWorkSlot[HEAP_SLOT_BATTLE_CANVAS],...
void BattleMotion_ApplyVariantMotionFar(s32 id, s32 variant)
void AudioCommand_PlayFar(s32 id)
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_BATTLE_EFFECT
Definition heap_state.h:42
@ HEAP_SLOT_BLITTER_ALTERNATE
Definition heap_state.h:47
@ HEAP_SLOT_BATTLE_SHEET
Definition heap_state.h:44
@ HEAP_SLOT_BLITTER
Definition heap_state.h:46
@ HEAP_SLOT_BATTLE_CANVAS
Definition heap_state.h:43
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
Definition heap_state.h:14
#define DMA_HBLANK_WORD_PER_LINE
Definition io_reg.h:230
#define Q_8_8(n)
The BG2/BG3 affine matrix entries are signed 8.8 fixed point: texels stepped per screen pixel.
Definition io_reg.h:59
#define REG_DMA0
Definition io_reg.h:151
#define REG_BG2X
Definition io_reg.h:65
#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_BG2PA
Definition io_reg.h:61
#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
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
void BattleFx_FetchRectangleBlitters(s32 flip, BlitterPair out)
Builds the two usual routines that draw onto the 128x128 canvas, both clipped on both axes.
void EffectPosition_ProjectScaledBattler(s32 id, struct EffectPosition *position)
The screen position of a battler, scaled for the battle view, 16 pixels higher.
Definition positions.c:88
void EffectPosition_ProjectSprite(s32 id, struct EffectPosition *position)
The screen position of a battler's sprite, at its scaled height, 16 pixels higher.
Definition positions.c:77
char ResourceId_PinkPalette
char ResourceId_TornadoSheet
char ResourceId_MarsDjinnSheet
char ResourceId_VioletLightningSheetA
char ResourceId_DemonFaceSheet
char ResourceId_WaterSpraySheet
char ResourceId_ParticleSpritesA
char ResourceId_IceBlockSheet
char ResourceId_FlashBurstSheet
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_136
Definition songs.h:129
#define SE_HEAVY_IMPACT
Definition songs.h:127
void * gWorkSlot[]
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 count
targets in actors, at least 1
The running battle effect's work: its canvas image, 64 particles, the display registers it stages and...
s32 frame
frame counter some effects keep, from 0
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 point projected onto the screen, with its depth.
Definition effect_step.h:46
s32 y
screen pixels
Definition effect_step.h:59
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 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
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned short u16
Definition types.h:13
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
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