Alchemy
Loading...
Searching...
No Matches

quake.c

Go to the documentation of this file.
1/// @file
2/// Quake.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7/// The columns of a gQuake_Timings row.
8enum {
9 QUAKE_TIMING_FRAMES, ///< frames in the whole effect
10 QUAKE_TIMING_RISE_FRAMES, ///< frames each pillar stands
11 QUAKE_TIMING_SHAKE ///< how far the screen shakes
12};
13
14/// The heights of Quake's rock pillars.
16 s32 column[4]; ///< each pillar's height in pixels
17};
18
19#define QUAKE_PILLAR_WIDTH 40 ///< a pillar's width in pixels
20/// The rock picture in the sheet; the sheet starts with the 40x16 strip of
21/// ground cut from the background.
22#define QUAKE_WALL_CELLS 0x1e00
23
24/// Rock wall: three rock pillars rise from the left, 4 frames apart, and sink
25/// again, throwing the targets standing on them into the air.
26///
27/// Abilities: Quake, Earthquake, Quake Sphere (kind 1).
28///
29/// Each pillar is capped with a strip of ground cut from the background.
30///
31/// Writes REG_BG2PA, REG_BLDCNT and, on side 1, REG_BG2X; overwrites the
32/// first 0x8000 bytes of Ram_MapCellBuffer with BG tiles; sets the targets'
33/// vertical velocity and gravity; arms work->shakeFrames. Ends with the
34/// transfer callback removed, the blitter freed and the canvas layer closed.
35///
36/// effect: the targets; variant picks the row of gQuake_Timings.
38 static s32 wallHeights[4] = {
39 -32,
40 -32,
41 -32,
42 -32,
43 };
44 void **slots;
45 void **cursor;
46 struct BattleEffectWork *work;
47 void *canvas;
48 s32 frame;
49 s32 column;
50 DrawRectangle draw;
51 struct BattleCamera *camera;
52 s32 xOffset;
53 struct RockWallHeights heights;
54 s32 point[3];
55 struct EffectPosition screen;
56 s32 member;
57 s32 row;
58 s32 col;
59 s32 y;
60
62 cursor = slots;
63 EFFECT_GET_WORK_AND_CANVAS(cursor, work, canvas);
64 camera = ((struct BattleCamera *)WORK_SLOT(HEAP_SLOT_CAMERA));
65 work->effect = effect;
67 // The canvas at its own width, opaque: the pillars hide what is behind.
68 REG_BG2PA = Q_8_8(1);
69 REG_BLDCNT = 0;
71 work->sheet + QUAKE_WALL_CELLS, 1, 1);
72
73 // Copy the background tiles (0x8000 bytes from VRAM 0x06008000) and cut
74 // the strip at x 32 to 71, y 96 to 111 into the start of the sheet: the
75 // ground that caps each pillar.
77 for (row = 0; row != 16; row++) {
78 y = row + 96;
79 for (col = 0; col != QUAKE_PILLAR_WIDTH; col++) {
80 // Pixel (col + 32, y) in 8bpp tiles laid out 32 tiles across.
81 s32 pixel = (((col + 32) & 7) + (((col + 32) / 8) << 6) + ((y & 7) << 3) +
82 ((y / 8) << 11));
83
84 work->sheet[row * QUAKE_PILLAR_WIDTH + col] = Ram_MapCellBuffer[pixel];
85 }
86 }
87
88 // On side 1 the canvas moves 112 pixels right, and the targets' positions
89 // with it.
90 if (work->effect->side == 1) {
91 REG_BG2X = -(112 << 8);
92 xOffset = -112;
93 } else {
94 xOffset = 0;
95 }
99 // particles[member].variant becomes 1 once that target has landed.
100 EFFECT_FOR_EACH_TARGET(member, work->effect)
101 work->particles[member].variant = 0;
102 // Each transfer clears the canvas: the pillars are redrawn every frame.
104 // The heights are negative; the sine below is taken as its size, so each
105 // pillar still rises up to 32 pixels.
106 heights = (*(const struct RockWallHeights *)&wallHeights);
107 // The screen shakes for 128 frames: all of Quake (80) and Earthquake (112),
108 // and all but the last 16 of Quake Sphere (144).
109 work->shakeFrames = 128;
111
112 for (frame = 0;
114 frame++) {
116 // The damage shows 16 frames before the end.
117 if (frame ==
120
121 // The pillars rise from frames 16, 20 and 24.
122 for (column = 0; column != 3; column++) {
123 s32 riseFrame = column * 4 + 16;
124
125 // Never true: the left side is 32 or more and riseFrame at most 24.
126 if ((frame & 31) + 32 == riseFrame)
127 heights.column[column] += 32;
128 if (frame >= riseFrame &&
129 frame < riseFrame + gQuake_Timings[work->effect->variant]
131 s32 height;
132 s32 top;
133
134 // The height rises and falls along a sine, 1/64 of a turn a frame.
135 height =
136 (heights.column[column] * Trig_Sin((frame - riseFrame) << 10)) >>
137 16;
138 if (height < 0)
139 height = -height;
140 top = 112 - height;
141 draw(canvas, work->sheet + QUAKE_WALL_CELLS,
142 column * QUAKE_PILLAR_WIDTH + 8, top, QUAKE_PILLAR_WIDTH, height);
143 draw(canvas, work->sheet, column * QUAKE_PILLAR_WIDTH + 8, 96 - height,
145
146 // Throw up the targets standing on the pillar.
147 EFFECT_FOR_EACH_TARGET(member, work->effect) {
148 struct MotionObject *object;
149
150 object = GetBattleObjectSlotFar(work->effect->actors[member])->object;
151 SET_VECTOR(point, object->x, object->y, object->z);
152 EffectPosition_ProjectPoint(point, &screen);
153 screen.x += xOffset;
154 if (screen.x >= column * QUAKE_PILLAR_WIDTH + 8 &&
155 screen.x <=
156 column * QUAKE_PILLAR_WIDTH + 8 + QUAKE_PILLAR_WIDTH &&
157 screen.y >= top) {
158 // 12 pixels a frame upwards, under the gravity the battle's own
159 // motions use (ObjMotRst in battle/motion.c).
160 object->velocityY = 12 << 16;
161 object->verticalMotionStrength = 0xab85;
162 }
163 if (object->y < 0)
164 ObjectGroup_UpdateMembers(work->effect->actors[member], 0,
165 POSE_DAMAGE, -1, 0);
166 }
167 }
168 }
169
170 // A target that lands flashes white for 5 frames.
171 EFFECT_FOR_EACH_TARGET(member, work->effect) {
172 struct MotionObject *object;
173 struct EffectStep *state;
174
175 object = GetBattleObjectSlotFar(work->effect->actors[member])->object;
176 state = &work->particles[member];
177 if (state->variant == 0 && object->y <= 0 && object->velocityY < 0) {
178 state->variant = 1;
180 SPRITE_COLOR_WHITE, POSE_DAMAGE, member, 5);
181 }
182 }
186 EFFECT_END_FRAME(work);
187 }
188
190}
191
192#undef QUAKE_PILLAR_WIDTH
193#undef QUAKE_WALL_CELLS
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
@ COMPOSITE_TRANSPARENT
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.
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_CLEAR
copy, then fill the canvas with transferValue
#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_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_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 gQuake_Timings[][3]
Rock wall timing, by variant: frames in the effect, frames each pillar stands, and how far the screen...
struct BattleObj * GetBattleObjectSlotFar(s32 objectId)
Far call to BattleObjGet.
void AudioCommand_PlayFar(s32 id)
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_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 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 BG_CHAR_BLOCK(n)
Definition io_reg.h:166
#define REG_BG2X
Definition io_reg.h:65
#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
#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
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
@ QUAKE_TIMING_FRAMES
frames in the whole effect
Definition quake.c:9
@ QUAKE_TIMING_RISE_FRAMES
frames each pillar stands
Definition quake.c:10
@ QUAKE_TIMING_SHAKE
how far the screen shakes
Definition quake.c:11
#define QUAKE_WALL_CELLS
The rock picture in the sheet; the sheet starts with the 40x16 strip of ground cut from the backgroun...
Definition quake.c:22
#define QUAKE_PILLAR_WIDTH
a pillar's width in pixels
Definition quake.c:19
void BattleFx_RunQuake(struct BattleEffectArgument *effect)
Rock wall: three rock pillars rise from the left, 4 frames apart, and sink again, throwing the target...
Definition quake.c:37
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
char ResourceId_RockWallSheet
#define SE_133
Definition songs.h:126
#define SE_141
Definition songs.h:134
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 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
struct EffectStep particles[64]
free while variant is -1
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 variant
each effect's own: a size, a countdown, -1 for idle
Definition effect_step.h:31
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
s32 velocityY
16.16 fixed-point pixels per frame
Definition motobj.h:32
s32 x
16.16 fixed-point pixels
Definition motobj.h:23
The heights of Quake's rock pillars.
Definition quake.c:15
s32 column[4]
each pillar's height in pixels
Definition quake.c:16
signed int s32
Definition types.h:14
#define EFFECT_CLIP_BOUNDS
Clips overflow on all four sides.
Definition effect.h:224