Alchemy
Loading...
Searching...
No Matches

lobbed_shells.c

Go to the documentation of this file.
1/// @file
2/// Lobbed shells (Mad Spatter, Decompose, Bone Chiller ...).
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7// The shells take 16 slots of PARTICLES per target, of which the first
8// flies; the shell bursts reuse the map buffer as records of their own.
9
10// Lobbed shells: a shell arcs from the user onto each target and bursts
11// into smoke or shards, in seven colourings.
12
13/// Gold shells that burst into shards.
14///
15/// Abilities: Mad Spatter (kind 347).
17 BattleFx_RunLobbedShells(effect, 4);
18}
19/// Green shells that burst into smoke.
20///
21/// Abilities: Decompose (kind 350).
23 BattleFx_RunLobbedShells(effect, 5);
24}
25/// Blue shells that burst into smoke.
26///
27/// Abilities: Bone Chiller (kind 309).
29 BattleFx_RunLobbedShells(effect, 0);
30}
31/// Shells in the spider web's colours that burst into smoke.
32///
33/// Abilities: Sticky Goo (kind 315).
35 BattleFx_RunLobbedShells(effect, 1);
36}
37/// Shells in Mars Djinn colours that burst into smoke.
38///
39/// Abilities: Poison Ink (kind 340).
41 BattleFx_RunLobbedShells(effect, 6);
42}
43/// Lime shells that burst into smoke.
44///
45/// Abilities: Sticky Poison (kind 322).
47 BattleFx_RunLobbedShells(effect, 2);
48}
49/// Green shells that burst into shards.
50///
51/// Abilities: Rotten Blood (kind 330).
53 BattleFx_RunLobbedShells(effect, 3);
54}
55/// The bursts live after the shells in PARTICLES: 32 slots a target, of
56/// which 4 smoke puffs or 16 shards are used.
57#define LOBBED_SHELLS_BURSTS ((struct EffectStep *)(Ram_MapCellBuffer + 0x1c00))
58#define LOBBED_SHELLS_SLOTS 16 ///< particles reserved for each target
59#define LOBBED_SHELLS_BURST_SLOTS 256 ///< burst particles after the shells
60#define LOBBED_SHELLS_SMOKE_CELLS 0x3e80 ///< the smoke pictures in the sheet
61
62/// Nonzero when the style's shells burst into shards instead of smoke: the
63/// first of the style's two entries in gLobbedShells_Records; the second is
64/// never read.
65#define LOBBED_SHELLS_SHATTER(mode) gLobbedShells_Records[(mode) * 2]
66
67/// Lobs a shell from the user at each target in turn, 8 frames apart. Each
68/// tumbles through ten images as it flies and, when it lands, the target
69/// flashes and the battle shows the damage; the shell bursts into 4 smoke
70/// puffs that drift up or 16 shards that fly up and fall.
71///
72/// Called by the seven handlers above, from BattleFx_RunMadSpatter to
73/// BattleFx_RunRottenBlood. Loads three palettes over the first 64
74/// background colours in turn, the style's last; uses PARTICLES 0 to 1023
75/// for the shells and LOBBED_SHELLS_BURSTS for the bursts.
76///
77/// mode : the style, 0 to 6: the colours and the row of gLobbedShells_Records.
79 struct EffectPosition position;
80 BlitterPair draw;
81 void **slots;
82 void **cursor;
83 struct BattleEffectWork *work;
84 void *canvas;
85 s32 frame;
86 s32 k;
87 s32 total;
88 struct MotionObject *source;
89 struct BattleCamera *camera;
90 u8 *palette;
91 s32 i;
92 s32 height;
93
95 cursor = slots;
96 EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas);
97 camera = EFFECT_SLOT(slots, HEAP_SLOT_CAMERA);
98 work->effect = effect;
100 REG_BLDALPHA = BLEND_ALPHA(16, 16);
101
102 // Setup. The shell images, the smoke at LOBBED_SHELLS_SMOKE_CELLS and the
103 // style's palette; mode 5 shares mode 3's green.
105 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
106 palette += 128;
107 Resource_DecodeType01(palette, work->sheet);
109 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
110 palette += 128;
111 Resource_DecodeType01(palette, work->sheet + LOBBED_SHELLS_SMOKE_CELLS);
112 if (mode == 0)
114 else if (mode == 1)
116 else if (mode == 2)
118 else if (mode == 3)
120 else if (mode == 4)
122 else if (mode == 6)
124 else
126 Iwram_CopyWords((void *)BG_PLTT, palette, 128);
127
128 // Each target's shells start 4 pixels up at the user, with a 16-frame
129 // flight to the target and an upward throw of 4 pixels a frame; only the
130 // first of each target's 16 is drawn.
132 source = GetBattleObjectSlotFar(work->effect->actor)->object;
133 height = 0x40000;
135 struct MotionObject *target =
137
138 for (i = 0; i != LOBBED_SHELLS_SLOTS; i++) {
139 struct EffectStep *shot = &PARTICLES[k * LOBBED_SHELLS_SLOTS + i];
140
141 SET_POSITION(shot, source->x, height, source->z);
142 SET_VELOCITY(shot, (target->x - source->x) >> 4, 0x40000,
143 (target->z - source->z) >> 4);
144 shot->variant = 0;
145 }
146 }
148
149 // draw[0] draws the shells facing their flight; draw[1] draws the smoke
150 // additively, or the shards mirrored the other way from draw[0].
151 if (effect->side == 0) {
154 if (LOBBED_SHELLS_SHATTER(mode) == 0) {
158 } else {
162 }
163 } else {
167 if (LOBBED_SHELLS_SHATTER(mode) == 0) {
171 } else {
175 }
176 }
177 // Trails keep 3/4 a frame. Smoke lingers 16 frames longer than shards.
179 if (LOBBED_SHELLS_SHATTER(mode) == 0)
180 total = work->effect->count * 8 + 72;
181 else
182 total = work->effect->count * 8 + 56;
184
185 for (frame = 0; frame != total; frame++) {
186 struct EffectStep *burst;
187
189 // Frame loop. The shells: target k's shell flies from frame 8k, and the
190 // target is hit on frame 8k + 17, about when its shell lands; a shell's
191 // variant turns 1 when it does.
192 k = 0;
193 if (work->effect->count != 0) {
194 do {
195 if (frame >= k * 8) {
196 struct EffectStep *shot = &PARTICLES[k * LOBBED_SHELLS_SLOTS];
197
198 if (frame == k * 8 + 17) {
202 }
203 /* FAKEMATCH: restores the CSE block boundary after the hit block, so
204 * k << 3 is recomputed; without it, 449 instructions differ in
205 * tbs-en. */
206 do {
207 } while (0);
208 if (shot->variant >= 0) {
209 // The shell tumbles through ten images, three frames each; the
210 // last five lie on their side.
211 s32 step = (frame - k * 8) / 3;
212
213 if (step > 9)
214 step = 9;
215 EffectPosition_ProjectPoint(shot, &position);
216 position.x >>= 1;
217 if (step > 4)
218 draw[0](canvas, work->sheet + step * (32 * 24), position.x - 16,
219 position.y - 12, 32, 24);
220 else
221 draw[0](canvas, work->sheet + step * (24 * 32), position.x - 12,
222 position.y - 16, 24, 32);
223 // Half a pixel of gravity a frame while it flies.
224 if (shot->variant == 0)
225 EffectStep_AdvanceWithGravity3D(shot, 63, -0x8000);
226 // On the ground: the shell stops, stays drawn where it lies, and
227 // bursts into target k's run of LOBBED_SHELLS_BURSTS.
228 if (shot->y < 0) {
229 s32 count;
230 s8 *records = gLobbedShells_Records;
231 s32 row;
232
233 shot->y = 0;
234 shot->variant = 1;
235 /* FAKEMATCH: the table address loads before the row; as
236 * gLobbedShells_Records[mode * 2] in the test, 135
237 * instructions differ in tbs-en. */
238 row = mode * 2;
239 if (records[row] == 0)
240 count = 4;
241 else
242 count = 16;
243 for (i = 0; i != count; i++) {
244 struct EffectStep *burst;
245 s32 group = k * 4;
246
247 /* FAKEMATCH: restores the CSE block boundary between group's
248 * set and group * 8; without it, 171 instructions differ in
249 * tbs-en. */
250 do {
251 } while (0);
252 burst = &LOBBED_SHELLS_BURSTS[group * 8 + i];
253
254 SET_POSITION(burst, shot->x, shot->y, shot->z);
255 if (LOBBED_SHELLS_SHATTER(mode) == 0) {
256 SET_VELOCITY(burst, ((Random16() & 63) - 32) << 11, 0,
257 ((Random16() & 63) - 32) << 11);
258 } else {
259 SET_VELOCITY(burst, ((Random16() & 63) - 32) << 13,
260 ((Random16() & 31) + 32) << 12,
261 ((Random16() & 63) - 32) << 13);
262 }
263 burst->variant = 0;
264 }
265 }
266 }
267 }
268 k++;
269 } while (k != work->effect->count);
270 }
271 // The bursts, for 45 frames: smoke through six 24x48 images, eight
272 // frames each, drifting up; or shards that tumble through nine images,
273 // five frames each, the odd shards from a second set, and fall. A burst
274 // that sinks below the ground is no longer drawn or moved.
275 for (i = 0, burst = LOBBED_SHELLS_BURSTS; i != LOBBED_SHELLS_BURST_SLOTS;
276 burst++, i++) {
277 if ((u32)burst->variant <= 44 && burst->y >= 0) {
278 EffectPosition_ProjectPoint(burst, &position);
279 position.x >>= 1;
280 if (LOBBED_SHELLS_SHATTER(mode) == 0) {
281 draw[1](canvas,
282 work->sheet + burst->variant / 8 * (24 * 48) +
284 position.x - 12, position.y - 24, 24, 48);
285 } else {
286 s32 picture = burst->variant / 5;
287 s32 flip;
288
289 if (i & 1)
290 picture += 9;
291 // Each shard faces the way it flies.
292 flip = effect->side;
293 draw[burst->velocityX > 0 ? flip ^ 1 : flip](
294 canvas,
295 work->sheet + gLobbedShells_ShardOffsets[picture] + 0x1e00,
296 position.x - gLobbedShells_ShardWidths[picture] / 2,
297 position.y - gLobbedShells_ShardHeights[picture] / 2,
300 }
301 if (LOBBED_SHELLS_SHATTER(mode) == 0)
302 EffectStep_AdvanceWithGravity3D(burst, 62, 0x800);
303 else
304 EffectStep_AdvanceWithGravity3D(burst, 62, -0x8000);
305 burst->variant++;
306 }
307 }
308 Camera_ApplyShake(2, 2);
309 EFFECT_END_FRAME(work);
310 }
311
313}
314
315#undef LOBBED_SHELLS_BURSTS
316#undef LOBBED_SHELLS_SLOTS
317#undef LOBBED_SHELLS_BURST_SLOTS
318#undef LOBBED_SHELLS_SMOKE_CELLS
319#undef LOBBED_SHELLS_SHATTER
@ 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_BeginCanvasLayer(s32 bgControl)
Opens the canvas layer: starts the background palette fade, makes BG2 the canvas, alpha-blended over ...
Definition canvas.c:314
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.
@ 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 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 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 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...
#define EFFECT_VIEW_FROM_CAMERA(camera)
Starts a frame's 3D projection from the battle camera: resets the transform, then looks from camera->...
u8 gLobbedShells_ShardWidths[]
Lobbed shells: nine tumbling images in two sets, the second (cells 9 to 17) smaller.
u16 gLobbedShells_ShardOffsets[]
u8 gLobbedShells_ShardHeights[]
s8 gLobbedShells_Records[]
Two bytes for each lobbed shell mode.
struct BattleObj * GetBattleObjectSlotFar(s32 objectId)
Far call to BattleObjGet.
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_CAMERA
Definition heap_state.h:38
@ HEAP_SLOT_BLITTER
Definition heap_state.h:46
#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
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
Definition iwram_call.h:85
void BattleFx_RunMadSpatter(struct BattleEffectArgument *effect)
Gold shells that burst into shards.
#define LOBBED_SHELLS_BURSTS
The bursts live after the shells in PARTICLES: 32 slots a target, of which 4 smoke puffs or 16 shards...
void BattleFx_RunStickyPoison(struct BattleEffectArgument *effect)
Lime shells that burst into smoke.
#define LOBBED_SHELLS_SMOKE_CELLS
the smoke pictures in the sheet
#define LOBBED_SHELLS_BURST_SLOTS
burst particles after the shells
void BattleFx_RunDecompose(struct BattleEffectArgument *effect)
Green shells that burst into smoke.
void BattleFx_RunBoneChiller(struct BattleEffectArgument *effect)
Blue shells that burst into smoke.
void BattleFx_RunStickyGoo(struct BattleEffectArgument *effect)
Shells in the spider web's colours that burst into smoke.
#define LOBBED_SHELLS_SLOTS
particles reserved for each target
void BattleFx_RunRottenBlood(struct BattleEffectArgument *effect)
Green shells that burst into shards.
#define LOBBED_SHELLS_SHATTER(mode)
Nonzero when the style's shells burst into shards instead of smoke: the first of the style's two entr...
void BattleFx_RunPoisonInk(struct BattleEffectArgument *effect)
Shells in Mars Djinn colours that burst into smoke.
void BattleFx_RunLobbedShells(struct BattleEffectArgument *effect, s32 mode)
Lobs a shell from the user at each target in turn, 8 frames apart.
#define SET_VELOCITY(p, vx, vy, vz)
Definition macros.h:18
#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_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
char ResourceId_LimePalette
char ResourceId_MarsDjinnSheet
char ResourceId_SpiderWebSheet
char ResourceId_GreenPalette
char ResourceId_GoldShellSheet
char ResourceId_SmokeSheet
char ResourceId_BluePalette
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
Definition decompress.c:31
#define SE_133
Definition songs.h:126
#define SE_103
Definition songs.h:96
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 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
struct BattleEffectArgument * effect
the command being run
struct MotionObject * object
NULL once released.
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 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
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 x
16.16 fixed-point pixels
Definition motobj.h:23
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
signed char s8
Definition types.h:10
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