Alchemy
Loading...
Searching...
No Matches

ray.c

Go to the documentation of this file.
1/// @file
2/// Ray.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7#define RAY_SPARK_COUNT 1024 ///< sparks in PARTICLES
8
9#define RAY_CELLS 0x60e ///< the bolt pictures in the sheet
10#define RAY_COUNT 4 ///< bolts
11
12/// Closing bolts: four bolts turn in towards the centre for 16 frames,
13/// scattering sparks from their roots; the sparks fly on until frame 64.
14///
15/// Abilities: Ray, Storm Ray, Destruct Ray (kind 17).
16///
17/// The targets flash white 4 frames apart from frame 4. Writes REG_BG2PA and
18/// REG_BG2X, sets work->shakeFrames over the first 16 frames, and ends with
19/// the transfer callback removed, the blitters freed and the canvas layer
20/// closed.
21///
22/// effect: the targets. variant 2 shows the canvas at double width;
23/// variant 0 draws every bolt with the maximum blend, the others
24/// alternate it with additive. The variant also sets the sparks
25/// each bolt throws a frame (gRay_Sparks).
27 void **slots;
28 void **cursor;
29 struct BattleEffectWork *work;
30 void *canvas;
31 s32 frame;
32 u8 *sheet;
33 s32 bolt;
34 s32 thrown;
35 BlitterPair draw;
36 s32 i;
37
39 cursor = slots;
40 EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas);
41 // The motes for the sparks are in the battle sheet's slot.
42 sheet = EFFECT_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
43 work->effect = effect;
45 // Destruct Ray stretches the canvas across the screen; the others show it
46 // at its own width over the targets' half (on side 1, moved 128 pixels).
47 if (work->effect->variant == 2)
48 REG_BG2PA = Q_8_8(0.5);
49 else
50 REG_BG2PA = Q_8_8(1);
58 work->sheet + RAY_CELLS, 1, 1);
60 if (work->effect->variant == 2) {
61 if (work->effect->side == 1)
62 REG_BG2X = -0x1000;
63 else
64 REG_BG2X = 0x1000;
65 } else {
66 if (work->effect->side == 1)
67 REG_BG2X = -0x8000;
68 }
69
70 // Every spark starts free (variant 0); its place and velocity here are
71 // overwritten when a bolt throws it.
72 for (i = 0; i != RAY_SPARK_COUNT; i++) {
73 struct EffectStep *spark = &PARTICLES[i];
74 s32 speed;
75 s32 angle;
76
77 speed = (Random16() & 0x3ff) + 256;
78 angle = (Random16() & 0x7fff) - 0x4000;
79 SET_POSITION(spark, 0x4000, 0x7000, (Trig_Sin(angle) * speed) >> 16);
80 spark->velocityZ = -(Trig_Cos(angle) * speed * 2) >> 16;
81 spark->variant = 0;
82 }
83
86
87 for (frame = 0; frame != 64; frame++) {
88 if (frame == 20)
90 // The bolts, over the first 16 frames.
91 if (frame < 16) {
92 // Fill the canvas with level 16, not 0, on frames 2, 7 and 12.
93 if (frame % 5 == 2)
94 Iwram_FillWords(canvas, CANVAS_BYTES, 0x10101010);
95 for (bolt = 0; bolt != RAY_COUNT; bolt++) {
96 s32 angle;
97 s32 x;
98 s32 y;
99
100 // The radius across shrinks from 32 by a pixel a frame; bolt n starts
101 // a quarter turn further round than bolt n - 1 and turns n times as
102 // fast. Each frame a bolt picks one of four pictures and jitters up
103 // to 7 pixels across.
104 thrown = 0;
105 angle = ((frame << 11) + 0x4000) * bolt;
106 x = (((32 - frame) * Trig_Sin(angle)) >> 16) + 64;
107 y = -(((Trig_Cos(angle) * 8)) >> 16) - 8;
108 if (work->effect->variant == 0)
109 draw[0](canvas,
110 work->sheet + (Random16() & 3) * LIGHTNING_BOLT_CELL_BYTES +
111 RAY_CELLS,
112 x + (Random16() & 7) - 16, y, 24, 120);
113 else
114 draw[bolt & 1](canvas,
115 work->sheet +
117 RAY_CELLS,
118 x + (Random16() & 7) - 16, y, 24, 120);
119
120 // Throw sparks from the bolt's root, 112 pixels down its 120-pixel
121 // picture: the first free ones, up to the variant's count, each
122 // living 32 to 39 frames.
123 for (i = 0; i != RAY_SPARK_COUNT; i++) {
124 struct EffectStep *spark = &PARTICLES[i];
125
126 if (spark->variant == 0) {
127 s32 speed;
128 s32 spread;
129
130 speed = (Random16() & 0x1ff) + 128;
131 spread = (Random16() & 0x7fff) - 0x4000;
132 spark->x = x << 16;
133 spark->y = (y + 112) << 16;
134 spark->velocityX = (Trig_Sin(spread) * speed) >> 9;
135 spark->velocityY = -(Trig_Cos(spread) * speed * 2) >> 7;
136 spark->variant = (Random16() & 7) + 32;
137 thrown++;
138 if (thrown == gRay_Sparks[work->effect->variant][1])
139 break;
140 }
141 }
142 }
143 work->shakeFrames = 1;
144 }
145
146 // Move the sparks, bouncing them off the bottom (y 120) at half speed;
147 // a spark is drawn only inside the canvas, and shrinks as it ages.
148 for (i = 0; i != RAY_SPARK_COUNT; i++) {
149 struct EffectStep *spark = &PARTICLES[i];
150
151 if (spark->variant > 0) {
152 spark->variant--;
153 EffectStep_AdvanceWithGravity2D(spark, 60, -0x800);
154 if (spark->y > 0x780000) {
155 spark->velocityY = -spark->velocityY / 2;
156 } else if (spark->x >= 0 && spark->x < 0x7f0000 && spark->y >= 0) {
157 s32 x = spark->x >> 16;
158 s32 y = spark->y >> 16;
159 s32 size = spark->variant / 8 + 1;
160
161 EFFECT_DRAW_MOTE(draw[0], canvas, sheet, x, y, size);
162 }
163 }
164 }
165
166 // The targets are hit 4 frames apart. The bound of 96 is past the last
167 // frame (63), so it never limits.
168 if (frame >= 4 && frame < 96) {
170 if (frame == i * 4 + 4)
172 POSE_DAMAGE, i, 10);
173 }
174 }
175 Camera_ApplyShake(2, 4);
176 EFFECT_END_FRAME(work);
177 }
178
180}
181
182#undef RAY_SPARK_COUNT
183#undef RAY_CELLS
184#undef RAY_COUNT
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
@ COMPOSITE_FLIP_X
@ 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 BattleFx_BeginTiledCanvas(s32 bgControl)
Opens the canvas layer with BG2 a wrapping 256x256 map: each row of the map is the canvas's 16 tiles ...
Definition canvas.c:463
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 EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas)
The work block and canvas occupy adjacent slots, starting at HEAP_SLOT_BATTLE_EFFECT.
#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()
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_START_TRANSFER(work, mode, value)
Sets the transfer, then starts copying the canvas to VRAM once a frame.
#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_END_FRAME(work)
The usual end of an effect frame: counts down the targets' flash timers (ObjectGroup_TickMemberTimers...
u8 gRay_Sparks[][2]
Sparks by variant; [1] is how many each bolt throws a frame.
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_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
#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_BG2X
Definition io_reg.h:65
#define REG_BG2PA
Definition io_reg.h:61
static s32 Iwram_FillWords(void *destination, s32 size, u32 value)
Definition iwram_call.h:59
#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
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
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 BattleFx_RunRay(struct BattleEffectArgument *effect)
Closing bolts: four bolts turn in towards the centre for 16 frames, scattering sparks from their root...
Definition ray.c:26
#define RAY_SPARK_COUNT
sparks in PARTICLES
Definition ray.c:7
#define RAY_COUNT
bolts
Definition ray.c:10
#define RAY_CELLS
the bolt pictures in the sheet
Definition ray.c:9
char ResourceId_LightningBoltSheet
char ResourceId_ParticleSpritesA
#define SE_133
Definition songs.h:126
#define SE_ITEM_BREAK
Definition songs.h:131
void * gWorkSlot[]
The command shared by an effect's caller, dispatcher and handlers.
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)
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
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
s32 velocityZ
16.16 fixed-point pixels per frame
Definition effect_step.h:30
signed int s32
Definition types.h:14
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