98 for (i = 0; i != 64; i++) {
131 SET_VECTOR(step, (goal[0] - center[0]) / 40, (goal[1] - center[1]) / 40,
132 (goal[2] - center[2]) / 40);
133 for (frame = 0; frame != frameCount; frame++) {
143 if (frame >= 6 && frame <= 45) {
144 center[0] += step[0];
145 center[1] += step[1];
146 center[2] += step[2];
159 for (i = 0; i != 32; i++) {
162 if (frame >= i / 8 && spark->
variant == 0) {
185 size = 8 - (position.
depth - 250) / 64;
188 if (frame >= i / 8 + 24) {
189 s32 pullX = -spark->
x >> 7;
190 s32 pullY = -spark->
y >> 7;
191 s32 pullZ = -spark->
z >> 7;
198 if ((pullX > -2048 && pullX < 2048) &&
199 (pullZ > -2048 && pullZ < 2048))
206 if (frame >= 54 && frame <= 69) {
212 draw[0](canvas, work->sheet, position.
x - 10, position.
y - 20, 20, 40);
218 for (i = 0; i != 64; i++) {
223 mote->
x = *outX << 15;
224 mote->
y = *outY << 16;
232 for (i = 0; i != 64; i++) {
260#define PROJECTILE_VOLLEY_ANIMATION_STEP_FAST 0x30
262#define PROJECTILE_VOLLEY_ANIMATION_STEP_NORMAL 0x10
361#define PROJECTILE_VOLLEY_PARTICLE_COUNT 1024
373#define PROJECTILE_VOLLEY_COMET_CELLS 0x1000
374#define PROJECTILE_VOLLEY_STREAK_CELLS 0x2000
376#define PROJECTILE_VOLLEY_FLASH_TURNED 0x128a
379#define PROJECTILE_VOLLEY_MEDIUM_SPARK_CELLS (12 * 8)
380#define PROJECTILE_VOLLEY_LARGE_SPARK_CELLS (12 * 8 + 18 * 13)
381#define PROJECTILE_VOLLEY_DJINNI_CELLS 0x65c0
382#define PROJECTILE_VOLLEY_FIRST_SPARK 100
383#define PROJECTILE_VOLLEY_FIRST_TRAIL 512
470 if (mode == 0 || mode == 5 || mode == 8) {
500 }
else if (mode == 1) {
505 }
else if (mode == 2) {
511 }
else if (mode == 3 || mode == 4 || mode == 11) {
515 }
else if (mode == 6) {
553 for (j = 0; j != shots; j++) {
558 shot->
y = user->
y + ((
Random16() & 15) << 16) + 0x3a0000;
560 shot->
y = user->
y + height / 2;
562 shot->
y = user->
y + height / 2;
564 shot->
y = user->
y + height / 2 + ((16 - (
Random16() & 31)) << 16);
565 else if ((
u32)(mode - 3) <= 1)
566 shot->
y = user->
y + height / 2 + ((16 - (
Random16() & 31)) << 16);
568 shot->
y = user->
y + height / 2 + ((32 - (
Random16() & 63)) << 16);
570 shot->
y = user->
y + height / 2;
572 shot->
y = user->
y + height;
577 (
s32)(target->
y + ((
Random16() & 63) << 16) - shot->
y - 0xc0000) /
581 (
s32)(target->
y + ((
Random16() & 7) << 16) - shot->
y + 0x160000) /
585 (
s32)(target->
y + ((64 - (
Random16() & 63)) << 16) - shot->
y) /
589 (
s32)(target->
y + ((
Random16() & 31) << 16) - shot->
y + 0x40000) /
591 else if ((
u32)(mode - 3) <= 1 || mode == 11 || mode == 5)
611 total = work->
effect->
count * delay + shots * stagger + 32;
613 total = work->
effect->
count * delay + shots * stagger + 16;
617 for (frame = 0; frame != total; frame++) {
622 if (soundCooldown > 0)
629 }
else if (mode == 7) {
632 }
else if (mode != 5) {
641 s32 x = ((-
Trig_Sin(frame << 11) * 4) >> 16) + screenX / 2 - 10;
642 s32 y = ((
Trig_Cos(frame << 11) * 2) >> 16) + screenY - 24;
645 y =
y - frame * 2 + 138;
671 for (j = 0; j != shots; j++, index++) {
672 if (j * stagger + i * delay < frame) {
678 screenPosition->
x >>= 1;
690 particle->
x = position.
x << 16;
691 particle->
y = position.
y << 16;
696 if (trailsOrShift == 2)
735 }
else if (mode != 6 && soundCooldown == 0) {
759 if (mode != 7 && mode != 9 && mode != 10) {
769 trailsOrShift = mode == 5 ? 12 : 11;
775 particle->
x = position.
x << 16;
776 particle->
y = position.
y << 16;
792 if (mode == 0 || mode == 5 || mode == 8) {
804 screenPosition->
x - 16,
818 screenPosition->
x - 16, screenPosition->
y, 32,
821 }
else if (mode == 1) {
824 draw[0](canvas, work->sheet + frame % 6 * (32 * 24),
825 screenPosition->
x - 16, screenPosition->
y - 12, 32, 24);
826 }
else if (mode == 7 || mode == 9 || mode == 10) {
829 screenPosition->
x - 4, screenPosition->
y - 4, 8, 8);
830 }
else if (mode == 2) {
831 draw[0](canvas, work->sheet + j % 6 * (8 * 16),
832 screenPosition->
x - 4, screenPosition->
y - 8, 8, 16);
833 }
else if (mode == 3) {
836 screenPosition->
x - 9, screenPosition->
y - 7, 18, 13);
837 }
else if (mode == 4) {
838 draw[0](canvas, work->sheet, screenPosition->
x - 6,
839 screenPosition->
y - 4, 12, 8);
840 }
else if (mode == 11) {
842 screenPosition->
x - 15, screenPosition->
y - 12, 29, 23);
844 draw[0](canvas, work->sheet, screenPosition->
x - 20,
845 screenPosition->
y - 32, 40, 64);
854 if (mode == 0 || mode == 5 || mode == 8) {
855 for (i = 0; i != work->
effect->
count * shots; i++) {
859 s32 step = flash->
z / 2;
926 if (particle->
y > 0x700000)
965 object->speedLimit = 0x80000;
966 object->velocityY = 0x40000;
967 object->verticalMotionStrength = 0xab85;
968 object->verticalMotionPhase = 0;
969 object->autoFaceMotion = 0;
970 object->snapToTarget = 1;
990 s32 diffX = target->
x -
object->x;
991 s32 startX =
object->x;
992 s32 dx = rate * diffX / 100;
993 s32 diffZ = target->
z -
object->z;
994 s32 startZ =
object->z;
995 s32 dz = rate * diffZ / 100;
1002 speed =
Iwram_Sqrt(stepX * stepX + stepZ * stepZ);
1003 speed = (speed << 8) / frames;
1004 object->acceleration = speed;
1005 object->speedLimit = speed;
1006 object->snapToTarget = 1;
1007 object->verticalMotionStrength = 0xab85;
1008 object->velocityY = 0;
1009 object->verticalMotionPhase = 0;
1010 object->autoFaceMotion = 1;
1016#undef PROJECTILE_VOLLEY_ANIMATION_STEP_FAST
1017#undef PROJECTILE_VOLLEY_ANIMATION_STEP_NORMAL
1018#undef PROJECTILE_VOLLEY_PARTICLE_COUNT
1019#undef PROJECTILE_VOLLEY_COMET_CELLS
1020#undef PROJECTILE_VOLLEY_STREAK_CELLS
1021#undef PROJECTILE_VOLLEY_FLASH_TURNED
1022#undef PROJECTILE_VOLLEY_MEDIUM_SPARK_CELLS
1023#undef PROJECTILE_VOLLEY_LARGE_SPARK_CELLS
1024#undef PROJECTILE_VOLLEY_DJINNI_CELLS
1025#undef PROJECTILE_VOLLEY_FIRST_SPARK
1026#undef PROJECTILE_VOLLEY_FIRST_TRAIL
@ SPRITE_COLOR_WHITE
solid colour 15, white
@ POSE_DAMAGE
taking damage
struct BattleCamera * gCameraWork
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 Palette_StepFadeTransfer(void)
Darkens the battle backdrop while the canvas is open: for fadeFrames frames, writes the backdrop's co...
void BattleFx_ProcessPendingGraphicsTransfer(void)
Copies the canvas to VRAM once the effect has finished drawing a frame (transferPending): the 128x128...
void BattleFx_BeginCanvasLayer(s32 bgControl)
Opens the canvas layer: starts the background palette fade, makes BG2 the canvas, alpha-blended over ...
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.
What every part of the battle effect object shares: its includes, macros and frame-loop helpers.
#define EFFECT_RELEASE_BLITTERS()
Frees the two blitters, the alternate first.
#define EFFECT_DRAW_MOTE(draw, canvas, sheet, x, y, size)
Particle sheets hold ten mote cells, 1x2 to 10x20 pixels.
#define EFFECT_PRESENT_FRAME(work)
Ends a frame of a canvas effect: marks the canvas ready for the transfer callback,...
#define EFFECT_SET_TRANSFER(work, mode, value)
Sets how the canvas transfer treats what is left in the canvas after each copy: mode with value (see ...
@ CANVAS_COPY_AND_CLEAR
copy, then fill the canvas with transferValue
@ 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_CALLBACK_ORDER
The scheduler order of every per-frame effect callback (Scheduler_AddOrUpdateCallback sorts the frame...
#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_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...
#define EFFECT_VIEW_FROM_CAMERA(camera)
Starts a frame's 3D projection from the battle camera: resets the transform, then looks from camera->...
u8 gProjectiles_FlashSteps[]
u8 gProjectiles_FlashHeights[]
u8 gProjectiles_FlashRises[]
u8 gProjectiles_CometHeights[]
Comet picture heights, by comet kind.
u8 gProjectiles_Modes[][5]
Each projectile volley mode, by the PROJECTILE_VOLLEY_ columns (projectiles.c).
u16 gProjectiles_PelletOffsets[]
Ice chip pictures, by shot index & 3.
u16 gProjectiles_FlashOffsets[]
u8 gProjectiles_FlashWidths[]
struct BattleObj * GetBattleObjectSlotFar(s32 objectId)
Far call to BattleObjGet.
s32 BattleUnit_GetEffectHeightFar(s32 id)
void BattleMotion_ApplyVariantMotionFar(s32 id, s32 variant)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void ObjectDispatch_SetAnimationSpeedFar(struct DispatchObject *obj, s32 val)
void Object_SetMoveTargetFar(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
void ObjectDispatch_StartIdleFar(struct DispatchObject *obj)
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 ...
@ HEAP_SLOT_BLITTER_ALTERNATE
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
static s32 Iwram_Sqrt(s32 value)
static s32 Iwram_ClearWords(void *destination, s32 size)
#define SET_VELOCITY(p, vx, vy, vz)
#define ABS(v)
The magnitude of v. v is read twice.
#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.
#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,...
#define CLAMP(v, low, high)
Keeps v within low to high, the low bound tested first.
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
void Runtime_ReleaseHeapBlock(s32 slot)
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,...
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...
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...
void BattleFx_RunWingBeat(struct BattleEffectArgument *effect)
Ten small yellow sparks stream level at each target, one a frame.
UNUSED void BattleFx_InitializeRisingObject(s32 id)
Sends a battler back to its place (its anchor) with a hop.
void BattleFx_RunWingFlutter(struct BattleEffectArgument *effect)
Five yellow sparks fly level at each target, five frames apart.
void BattleFx_RunCuttingEdge(struct BattleEffectArgument *effect)
From the user's action pose, one large comet in ice colours flies at each target and bursts into 80 s...
#define PROJECTILE_VOLLEY_ANIMATION_STEP_FAST
the user's, while firing
void BattleFx_RunDjinniEntrance(struct BattleEffectArgument *effect, s32 mode, s32 side, s32 anchor, s32 *outX, s32 *outY)
Djinni entrance: sparks swirl around a point that travels from the user to the goal and gather into t...
#define PROJECTILE_VOLLEY_LARGE_SPARK_CELLS
void BattleFx_RunProjectileVolley(struct BattleEffectArgument *effect, s32 mode)
Projectile volley: shots fly from the user to each target and burst into a flash and sparks when they...
void BattleFx_RunIceBlessing(struct BattleEffectArgument *effect)
Sixty ice chips stream at each target, one a frame, without knocking it back.
void BattleFx_RunSleet(struct BattleEffectArgument *effect)
Thirty ice chips fall from high above the user onto each target, without shaking the screen or knocki...
#define PROJECTILE_VOLLEY_STREAK_CELLS
wind streaks
void BattleFx_RunHeatWave(struct BattleEffectArgument *effect)
From the user's action pose, seven fireballs trailing embers fly at each target, two frames apart,...
void BattleFx_RunSlash(struct BattleEffectArgument *effect)
Six comets fly at each target, three frames apart, and burst into a flash and sparks; the effect's va...
VolleyField
The bytes of a gProjectiles_Modes row.
@ PROJECTILE_VOLLEY_DELAY
frames between targets
@ PROJECTILE_VOLLEY_SHOTS
shots at each target
@ PROJECTILE_VOLLEY_STEPS
frames a shot takes to reach its target
@ PROJECTILE_VOLLEY_STAGGER
frames between shots
@ PROJECTILE_VOLLEY_SPARKS
sparks thrown on each hit
void BattleFx_RunBlizzard(struct BattleEffectArgument *effect)
From the user's action pose, sixty ice chips stream at each target, one a frame, scattered up and dow...
#define PROJECTILE_VOLLEY_ANIMATION_STEP_NORMAL
The user's animation step after the volley: the usual speed.
void BattleFx_RunCrazyVoice(struct BattleEffectArgument *effect)
Ten pellets fly slowly at each target and bounce off it, up or down at random.
#define PROJECTILE_VOLLEY_PARTICLE_COUNT
PARTICLES holds the hit flashes from 0, the sparks from 100 and the fireball trails from 512.
#define PROJECTILE_VOLLEY_FIRST_TRAIL
the first trail in PARTICLES
void BattleFx_RunShuriken(struct BattleEffectArgument *effect)
Four spinning shurikens fly at each target, five frames apart, and vanish once past it.
#define PROJECTILE_VOLLEY_COMET_CELLS
comets: the top half of each
void BattleFx_RunWingStroke(struct BattleEffectArgument *effect)
Ten large yellow sparks stream level at each target, one a frame, spread up and down.
#define PROJECTILE_VOLLEY_MEDIUM_SPARK_CELLS
The yellow spark sheet: the small spark (12x8) first, then the medium one (18x13),...
void BattleFx_SetApproachMotion(s32 id, s32 targetId, s32 frames)
Moves a battler 80% of the way to another one over a number of frames, in its action pose.
#define PROJECTILE_VOLLEY_DJINNI_CELLS
the small Mercury djinni
static void BattleFx_RunVolleyWithAction(struct BattleEffectArgument *effect, s32 mode)
Puts the user into its action pose (2) and fires the volley in this mode while its animation runs fas...
#define PROJECTILE_VOLLEY_FIRST_SPARK
the first spark in PARTICLES
#define PROJECTILE_VOLLEY_FLASH_TURNED
The hit flashes turned on their side, after the upright ones.
char ResourceId_CometSheetC
char ResourceId_VenusDjinnSmallSheet
char ResourceId_MarsDjinnSmallSheet
char ResourceId_ShurikenSheet
char ResourceId_MercuryDjinnSmallSheet
char ResourceId_IceChipSheet
char ResourceId_CometSheetA
char ResourceId_ParticleSpritesA
char ResourceId_FireballSheet
char ResourceId_ProjectileVolleyImage
char ResourceId_CometSheetB
char ResourceId_IceBlockSheet
char ResourceId_JupiterDjinnSmallSheet
char ResourceId_WindStreakSheet
char ResourceId_YellowSparkSheet
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
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 variant
the ability's size, from 0 (Quake, then Earthquake)
s32 count
targets in actors, at least 1
s32 prelude
1 plays a prelude: in some effects a Djinni appears
The running battle effect's work: its canvas image, 64 particles, the display registers it stages and...
s32 fadeFrames
backdrop fade frames left (Palette_StepFadeTransfer)
s32 frame
frame counter some effects keep, from 0
s32 fadeStep
CANVAS_FADE_STEPs the backdrop has darkened so far.
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 unit's place on the battlefield: its sprite object, resources and animations, its anchor spot and s...
struct MotionObject * object
NULL once released.
s32 anchorZ
16.16 fixed-point pixels
s32 anchorX
16.16 fixed-point pixels
A field object as the object dispatcher's far calls take it.
A point projected onto the screen, with its depth.
s32 depth
projected depth, larger further away
A moving point of an effect: its position, its velocity and a value each effect uses its own way (a s...
s32 velocityX
16.16 fixed-point pixels per frame
s32 z
16.16 fixed-point pixels
s32 variant
each effect's own: a size, a countdown, -1 for idle
s32 x
16.16 fixed-point pixels
s32 y
16.16 fixed-point pixels
s32 velocityY
16.16 fixed-point pixels per frame
s32 velocityZ
16.16 fixed-point pixels per frame
An effect object that moves and draws one sprite: its position, scale, velocity and target,...
s32 z
16.16 fixed-point pixels
s32 y
16.16 fixed-point pixels
u16 height
half the sprite's box height; FieldActor's radius
s32 acceleration
Horizontal speed gained each frame towards the target, or lost braking without one,...
s32 x
16.16 fixed-point pixels
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
#define EFFECT_CLIP_BOUNDS
Clips overflow on all four sides.
#define Q_16_16_TO_INT(v)
#define PARTICLES
The map cell buffer (gMapCellBuffer), which the effects borrow, has two views here: Ram_MapCellBuffer...
DrawRectangle BlitterPair[2]
A blitter pair: [0] built in HEAP_SLOT_BLITTER and [1] in HEAP_SLOT_BLITTER_ALTERNATE (BattleFx_Fetch...