Alchemy
Loading...
Searching...
No Matches

bolt.c

Go to the documentation of this file.
1/// @file
2/// Bolt.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7/// The second blitter, made anew for each glint with its random flip.
8#define BOLT_GLINT_BLITTER \
9 ((DrawRectangle *) \
10 gBattleFxWork)[HEAP_SLOT_BLITTER_ALTERNATE - HEAP_SLOT_BATTLE_EFFECT]
11
12/// The columns of a gBolt_Counts row.
13enum {
14 BOLT_SPARKS, ///< sparks thrown from each bolt's foot
15 BOLT_GLINTS, ///< glints a frame around each target
16 BOLT_GLINT_SPREAD, ///< how high and wide the glints spread
17 BOLT_STRIKES ///< bolts drawn over each other
18};
19
20/// The bolt pictures in the sheet, after the tornado.
21#define BOLT_CELLS 0xc56
22
23/// A bolt of lightning strikes each target in turn, 8 frames apart.
24///
25/// Abilities: Bolt, Flash Bolt, Blue Bolt (kind 16).
26///
27/// Target i's turn starts on frame 8i with a flash of the canvas. The bolt
28/// drops from the top, 64 pixels a frame down to y 104, and the screen shakes
29/// the frame after; on frame 8i + 2 sparks fly up from its foot and glints
30/// flicker there for 22 frames; on frame 8i + 4 the target recoils. The
31/// battle moves on to the results on frame 24.
32///
33/// PARTICLES holds the sparks, 128 for each target. Sets work->shakeFrames on
34/// each strike, and ends with the transfer callback removed, the blitter
35/// freed and the canvas layer closed; the glints' blitter is built and freed
36/// for each glint.
37///
38/// effect: the targets; variant picks the row of gBolt_Counts
39/// and the glints' blend.
41 void **slots;
42 void **cursor;
43 struct BattleEffectWork *work;
44 void *canvas;
45 s32 i;
46 s32 frame;
47 /* FAKEMATCH: frame local: the unused second blitter word fills four bytes of
48 * the frame; as one DrawRectangle, 66 instructions differ in tbs-en. */
49 BlitterPair draw;
50 u8 *sprites;
51 struct EffectPosition screen;
52 s32 j;
53
54 EFFECT_GET_SLOTS(slots, cursor, work, canvas);
55 sprites = EFFECT_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
56 work->effect = effect;
59 draw[0] = EFFECT_SLOT(slots, HEAP_SLOT_BLITTER);
62 work->sheet + BOLT_CELLS, 1, 1);
64 // A spark's variant is its life left, 0 when free. work->particles is
65 // marked free too, though nothing here uses it.
66 for (j = 0; j != 1024; j++)
67 PARTICLES[j].variant = 0;
68 EFFECT_FREE_PARTICLES(j, work->particles, 64);
71 for (frame = 0; frame != work->effect->count * 8 + 40; frame++) {
72 if (frame == 24)
74 // The flash at each turn's start: the whole canvas set to level 16.
76 if (frame == i * 8)
77 Iwram_FillWords(canvas, CANVAS_BYTES, 0x10101010);
78 }
79 // Each target's turn, 8 frames after the one before.
81 s32 start = i * 8;
82
84 screen.x /= 2;
85 if (frame == start + 1)
86 work->shakeFrames = 4;
87 if (frame == start + 4) {
89 POSE_DAMAGE, i, 6);
91 }
92
93 // The bolt (24 wide) grows 64 pixels a frame and stops at 104; it is
94 // drawn the variant's number of times over itself, each pass picking
95 // one of the four pictures by target, frame and pass, so the picture
96 // changes every 2 frames.
97 if (frame >= start && frame < start + 16) {
98 s32 height = (frame - start) << 6;
99
100 if (height > 104)
101 height = 104;
102 for (j = 0; j != gBolt_Counts[work->effect->variant][BOLT_STRIKES];
103 j++) {
104 draw[0](canvas,
105 work->sheet +
106 (((i + frame + j) / 2) & 3) * LIGHTNING_BOLT_CELL_BYTES +
108 screen.x - 12, 0, 24, height);
109 }
110
111 // Throw sparks upwards, within 90 degrees, from the foot (y = 104).
112 if (frame == start + 2) {
113 for (j = 0; j != gBolt_Counts[work->effect->variant][BOLT_SPARKS];
114 j++) {
115 struct EffectStep *spark = &PARTICLES[i * 128 + j];
116 s32 speed = (Random16() & 0x1ff) + 64;
117 s32 angle = (Random16() & 0x7fff) - 0x4000;
118
119 spark->x = screen.x << 16;
120 spark->y = 104 << 16;
121 spark->velocityX = (Trig_Sin(angle) * speed) >> 5;
122 spark->velocityY = -(Trig_Cos(angle) * speed) >> 6;
123 spark->variant = (Random16() & 7) + 32;
124 }
125 }
126 }
127
128 // Glints for 22 frames: at random spots above the foot, flipped at
129 // random, in the variant's blend; the higher a glint, the narrower
130 // the band it may fall in across.
131 if (frame >= start + 2 && frame < start + 24) {
132 for (j = 0; j != gBolt_Counts[work->effect->variant][BOLT_GLINTS];
133 j++) {
134 s32 kind = j & 3;
135 s32 drop = Random16() %
137 s32 spread =
138 gBolt_Counts[work->effect->variant][BOLT_GLINT_SPREAD] - drop + 1;
139 s32 y = screen.y - drop - (gBattleFx_GlintCellHeights[kind] >> 1) + 8;
140 u32 random = Random16();
141 s32 x = screen.x;
142
143 x += random % spread;
144 x -= spread / 2;
145 x -= (gBattleFx_GlintCellWidths[kind] >> 1);
146
151 BOLT_GLINT_BLITTER(canvas, work->sheet + gBattleFx_GlintCells[kind],
155 }
156 }
157 }
158
159 // Sparks bounce off the ground at half speed and shrink as they die out.
160 for (j = 0; j != 1024; j++) {
161 struct EffectStep *spark = &PARTICLES[j];
162
163 if (spark->variant > 0) {
164 spark->variant--;
165 EffectStep_AdvanceWithGravity2D(spark, 60, 0x1000);
166 if (spark->y > 104 << 16) {
167 spark->velocityY = -spark->velocityY / 2;
168 } else if ((spark->x >= 0 && spark->x < 127 << 16) && spark->y >= 0) {
169 s32 size = spark->variant / 16 + 1;
170 s32 x = spark->x >> 16;
171 s32 y = spark->y >> 16;
172
173 EFFECT_DRAW_MOTE(draw[0], canvas, sprites, x, y, size);
174 }
175 }
176 }
177 Camera_ApplyShake(2, 8);
178 EFFECT_END_FRAME(work);
179 }
181}
182
183#undef BOLT_GLINT_BLITTER
184#undef BOLT_CELLS
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
@ COMPOSITE_MAX
#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 ...
@ BOLT_GLINTS
glints a frame around each target
Definition bolt.c:15
@ BOLT_GLINT_SPREAD
how high and wide the glints spread
Definition bolt.c:16
@ BOLT_SPARKS
sparks thrown from each bolt's foot
Definition bolt.c:14
@ BOLT_STRIKES
bolts drawn over each other
Definition bolt.c:17
void BattleFx_RunBolt(struct BattleEffectArgument *effect)
A bolt of lightning strikes each target in turn, 8 frames apart.
Definition bolt.c:40
#define BOLT_CELLS
The bolt pictures in the sheet, after the tornado.
Definition bolt.c:21
#define BOLT_GLINT_BLITTER
The second blitter, made anew for each glint with its random flip.
Definition bolt.c:8
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_DRAW_MOTE(draw, canvas, sheet, x, y, size)
Particle sheets hold ten mote cells, 1x2 to 10x20 pixels.
@ 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_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_FREE_PARTICLES(i, particles, count)
Marks particles[0] to particles[count - 1] free: a particle whose variant is -1 is not drawn or moved...
#define LIGHTNING_BOLT_CELL_BYTES
Closing bolts and lightning columns use the same 24x120 picture cells.
#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...
u8 gBattleFx_GlintCellHeights[]
u8 gBolt_GlintModes[]
u8 gBolt_GlintFlips[]
u8 gBolt_Counts[][4]
Bolt, by variant: sparks each bolt throws, glints a frame around each target, how far the glints spre...
u16 gBattleFx_GlintCells[]
u8 gBattleFx_GlintCellWidths[]
void BattleMotion_ApplyVariantMotionFar(s32 id, s32 variant)
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_BLITTER
Definition heap_state.h:46
static s32 Iwram_FillWords(void *destination, s32 size, u32 value)
Definition iwram_call.h:59
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 EffectPosition_ProjectBattler(s32 id, struct EffectPosition *position)
The screen position of a battler, 16 pixels higher.
Definition positions.c:100
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
char ResourceId_TornadoSheet
char ResourceId_LightningBoltSheet
char ResourceId_ParticleSpritesA
#define SE_133
Definition songs.h:126
#define SE_ITEM_BREAK
Definition songs.h:131
The command shared by an effect's caller, dispatcher and handlers.
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
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
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned char u8
Definition types.h:11
#define EFFECT_CLIP_BOUNDS
Clips overflow on all four sides.
Definition effect.h:224
#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