Alchemy
Loading...
Searching...
No Matches

drain.c

Go to the documentation of this file.
1/// @file
2/// Break and Drain.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7#define DRAIN_ICE_SHARDS_PER_TARGET 128 ///< shards for each target
8
9/// Ice shards burst up from each target in turn, 20 frames apart, tinting the
10/// target as they go, and fall away below line 112.
11///
12/// Abilities: Break (kind 43).
13///
14/// Target n's 128 shards are PARTICLES n * 128 onwards, screen positions on
15/// the half-width canvas in 16.16; a shard's variant counts its frames and is
16/// -1 once it has gone. Loads the ice block palette into the first 64 colours
17/// of the background palette.
19 void **slots;
20 void **cursor;
21 struct BattleEffectWork *work;
22 void *canvas;
23 DrawRectangle draw;
24 u8 *sheet;
25 struct BattleCamera *camera;
26 s32 point[3];
27 struct EffectPosition screen;
28 s32 member;
29 s32 frame;
30 s32 i;
31
33 cursor = slots;
34 EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas);
35 sheet = EFFECT_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
36 camera = EFFECT_SLOT(slots, HEAP_SLOT_CAMERA);
37 work->effect = effect;
44
46
48
49 // Setup: scatter the shards around the middle of each body, a narrow
50 // ellipse taller than it is wide; each moves up to 1 pixel a frame
51 // sideways and jumps up at 2 to 4.
52 EFFECT_FOR_EACH_TARGET(member, work->effect) {
53 struct MotionObject *object;
54 s32 offset;
55 s32 height;
56 struct EffectStep *shard;
57
58 offset = member * DRAIN_ICE_SHARDS_PER_TARGET * sizeof(struct EffectStep);
59 object = GetBattleObjectSlotFar(work->effect->actors[member])->object;
60 height = BattleUnit_GetEffectHeightFar(work->effect->actors[member]) / 2;
61 SET_VECTOR(point, object->x, height, object->z);
62 EffectPosition_ProjectPoint(point, &screen);
63 screen.x >>= 1;
64 for (i = 0, shard = (struct EffectStep *)(Ram_MapCellBuffer + offset);
66 s32 radius;
67 s32 angle;
68 s32 lift;
69
70 radius = Random16() & 0xff;
71 angle = Random16() & 0xffff;
72 shard->x = ((Trig_Sin(angle) * radius) >> 7) + (screen.x << 16);
73 shard->y = ((Trig_Cos(angle) * radius) >> 3) + (screen.y << 16);
74 shard->velocityX = (128 - (Random16() & 0xff)) << 9;
75 lift = Random16() & 0xff;
76 shard->variant = 0;
77 shard->velocityY = (-lift - 128) << 10;
78 shard++;
79 }
80 }
81
83
84 // Target n starts on frame n * 20 with a sound and a 20-frame tint; the
85 // last target's shards get 56 frames to fall.
86 for (frame = 0; frame != work->effect->count * 20 + 56; frame++) {
87 if (frame == 32)
89 EFFECT_FOR_EACH_TARGET(member, work->effect) {
90 s32 offset;
91
92 offset = member * DRAIN_ICE_SHARDS_PER_TARGET * sizeof(struct EffectStep);
93 if (frame == member * 20) {
96 SPRITE_COLOR_WHITE, -1, member, 20);
97 }
98 // A shard falls with one of four gravities by its index (1/8 to 1/2
99 // pixel a frame per frame, gDrain_Gravities) and goes out once it
100 // falls back past y = 112. Its size, 1 to 3, also follows its index.
101 if (frame > member * 20) {
102 struct EffectStep *shard;
103
104 for (i = 0, shard = (struct EffectStep *)(Ram_MapCellBuffer + offset);
105 i != DRAIN_ICE_SHARDS_PER_TARGET; i++) {
106 if (shard->variant >= 0) {
107 s32 size;
108
109 size = i % 3 + 1;
110 EFFECT_DRAW_MOTE(draw, canvas, sheet, Q_16_16_TO_INT(shard->x),
111 Q_16_16_TO_INT(shard->y), size);
113 shard->variant++;
114 if (shard->velocityY > 0 && Q_16_16_TO_INT(shard->y) > 112)
115 shard->variant = -1;
116 }
117 shard++;
118 }
119 }
120 }
121 EFFECT_END_FRAME(work);
122 }
123
125}
126
127#define DRAIN_MOTES_PER_TARGET 128 ///< motes for each target
128#define DRAIN_DRAWN 32 ///< motes drawn for each target
129
130/// Drain: motes of light burst from each target in turn, 20 frames apart, and
131/// are pulled into the centre of the user's body.
132///
133/// Abilities: Drain, Psy Drain (kind 42).
134///
135/// Each target flashes in its damage pose for 42 frames as its motes burst, and
136/// the user glows from frame 40 until 20 frames before the end. Target n's
137/// motes are PARTICLES n * 128 onwards, battle positions in 16.16; only the
138/// first 32 of each 128 are moved and drawn. A negative variant marks a mote
139/// that has gone out.
140///
141/// effect: the targets; variant 0 takes the ice block palette, any other
142/// the blast palette.
144 void **slots;
145 void **cursor;
146 struct BattleEffectWork *work;
147 void *canvas;
148 DrawRectangle draw;
149 u8 *sheet;
150 struct BattleCamera *camera;
151 struct EffectPosition screen;
152 s32 alternate;
153 s32 member;
154 s32 frame;
155 s32 i;
156
158 cursor = slots;
159 EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas);
160 sheet = EFFECT_SLOT(slots, HEAP_SLOT_BATTLE_SHEET);
161 camera = ((struct BattleCamera *)WORK_SLOT(HEAP_SLOT_CAMERA));
162 if (effect->variant == 0)
163 alternate = 0;
164 else
165 alternate = 1;
166 work->effect = effect;
169 Iwram_CopyWords((void *)BG_PLTT,
170 Resource_GetTableEntry(alternate == 0
173 128);
174
175 // The motes fly out of the centre of each target's body at random speeds
176 // of up to 2 pixels a frame on each axis.
178
179 EFFECT_FOR_EACH_TARGET(member, work->effect) {
180 struct MotionObject *object;
181 s32 halfHeight;
182
183 object = GetBattleObjectSlotFar(work->effect->actors[member])->object;
184 halfHeight =
185 BattleUnit_GetEffectHeightFar(work->effect->actors[member]) / 2;
186 for (i = 0; i != DRAIN_MOTES_PER_TARGET; i++) {
187 struct EffectStep *mote = &PARTICLES[member * DRAIN_MOTES_PER_TARGET + i];
188
189 SET_POSITION(mote, object->x, object->y + halfHeight, object->z);
190 SET_VELOCITY(mote, ((Random16() & 0xff) - 128) << 10,
191 ((Random16() & 0xff) - 128) << 10,
192 ((Random16() & 0xff) - 128) << 10);
193 mote->variant = 0;
194 }
195 }
196
197 // Draw with the maximum blend, and lower every canvas pixel by 4 on each
198 // transfer so the motes leave fading trails.
203
204 // Frame 0 plays the drain sound; target n bursts on frame n * 20; frame 40
205 // starts the user's glow and frame 64 shows the damage. The last target's
206 // motes get 72 frames to reach the user.
207 for (frame = 0; frame != work->effect->count * 20 + 72; frame++) {
208 struct MotionObject *user;
209 s32 halfHeight;
210
212 halfHeight = BattleUnit_GetEffectHeightFar(work->effect->actor) / 2;
213 if (frame == 64)
216 if (frame == 40)
218 0);
219 if (frame == work->effect->count * 20 + 52)
220 ObjectGroup_UpdateMembers(work->effect->actor, 0, -1, -1, 0);
221 EFFECT_FOR_EACH_TARGET(member, work->effect) {
222 if (frame == member * 20)
224 SPRITE_COLOR_WHITE, POSE_DAMAGE, member, 42);
225 if (frame > member * 20) {
226 for (i = 0; i != DRAIN_DRAWN; i++) {
227 struct EffectStep *mote =
228 &PARTICLES[member * DRAIN_MOTES_PER_TARGET + i];
229
230 if (mote->variant >= 0) {
231 s32 size;
232
233 // The canvas is shown at double width, so halve x.
234 EffectPosition_ProjectPoint(mote, &screen);
235 screen.x >>= 1;
236 size = 6;
237 EFFECT_DRAW_MOTE(draw, canvas, sheet, screen.x, screen.y, size);
239
240 // 10 frames after it appears (one frame later for each mote), a
241 // mote accelerates towards the user by 1/256 of the distance, and
242 // goes out once it is within 16 pixels horizontally.
243 if (frame > member * 20 + i + 10) {
244 s32 dx;
245 s32 dy;
246 s32 dz;
247
248 dx = (user->x - mote->x) >> 8;
249 dy = (user->y + halfHeight - mote->y) >> 8;
250 dz = (user->z - mote->z) >> 8;
251 mote->velocityX += dx;
252 mote->velocityY += dy;
253 mote->velocityZ += dz;
254 if ((dx > -0x1000 && dx < 0x1000) &&
255 (dz > -0x1000 && dz < 0x1000))
256 mote->variant = -1;
257 }
258 }
259 }
260 }
261 }
262 EFFECT_END_FRAME(work);
263 }
264
266}
267
268#undef DRAIN_ICE_SHARDS_PER_TARGET
269#undef DRAIN_MOTES_PER_TARGET
270#undef DRAIN_DRAWN
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
@ 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 Resource_LoadAndDecompress(s32 id, void *dst, s32 skipPalette, s32 copyPalette)
Decompresses a resource whose first 128 bytes may be a palette.
#define DRAIN_MOTES_PER_TARGET
motes for each target
Definition drain.c:127
void BattleFx_RunBreak(struct BattleEffectArgument *effect)
Ice shards burst up from each target in turn, 20 frames apart, tinting the target as they go,...
Definition drain.c:18
void BattleFx_RunDrain(struct BattleEffectArgument *effect)
Drain: motes of light burst from each target in turn, 20 frames apart, and are pulled into the centre...
Definition drain.c:143
#define DRAIN_DRAWN
motes drawn for each target
Definition drain.c:128
#define DRAIN_ICE_SHARDS_PER_TARGET
shards for each target
Definition drain.c:7
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_DARKEN
copy, then darken the canvas by transferValue
@ 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_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 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->...
s32 gDrain_Gravities[]
Ice shards: shard i falls with gravity i & 3.
struct BattleObj * GetBattleObjectSlotFar(s32 objectId)
Far call to BattleObjGet.
s32 BattleUnit_GetEffectHeightFar(s32 id)
void AudioCommand_PlayFar(s32 id)
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
@ HEAP_SLOT_BATTLE_EFFECT
Definition heap_state.h:42
@ 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 WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
Definition heap_state.h:14
#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
#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
#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
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 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
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
char ResourceId_BlastSheet
char ResourceId_ParticleSpritesA
char ResourceId_IceBlockSheet
#define SE_133
Definition songs.h:126
#define SE_143
Definition songs.h:136
#define SE_142
Definition songs.h:135
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
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...
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
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 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 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