Alchemy
Loading...
Searching...
No Matches

whirlwind.c

Go to the documentation of this file.
1/// @file
2/// Whirlwind.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7enum {
18};
19
20/// A FieldActor seen with the halfword at 0x64 unsigned and the one at 0x66
21/// signed, as the bytes read them (FieldActor's own types change the code).
22/// Whirlwind particles (object 0xf9) use this view.
25 u16 angle; ///< heading or orbit angle, in 1/65536 turns
26 s32 x; ///< 16.16 pixels
27 s32 y; ///< 16.16 pixels
28 s32 z; ///< 16.16 pixels
29 u8 unk14[20];
30 s32 velocityY; ///< applied by the engine, in 16.16 pixels per frame
31 u8 unk2c[28];
32 s32 gravity; ///< vertical deceleration, in 16.16 pixels per frame squared
33 u8 unk4c[24];
34 u16 timer; ///< frames so far
35 s16 pause; ///< frames left of a sharp turn
36 struct WhirlwindOrbit *anchor; ///< orb at the centre of the orbit
37 void (*update)(union FieldObject *object); ///< engine's per-frame callback
38};
39
40/// The shared effect-spawning source, at its place in the ROM.
41#define EFFECT_SPAWN_RESIDENT
43#undef EFFECT_SPAWN_RESIDENT
44
45/// Per-frame update of a particle: moves by its velocity, slowing its x and z
46/// velocity a little, and changes its scale and spin. Assigned by
47/// BattleFx_SpawnRadialParticleRing for Carry's landing particles.
49 struct FieldEffect *effect = &object->effect;
50
51 effect->x += effect->velocity.x;
52 effect->y += effect->velocity.y;
53 effect->z += effect->velocity.z;
54 effect->velocity.x -= effect->velocity.x / 18;
55 effect->velocity.z -= effect->velocity.z / 16;
56 effect->scaleX += effect->scaleRateX;
57 effect->scaleY += effect->scaleRateY;
58 effect->sprite->rotation += effect->spin;
59}
60
61/// Spawns 17 particles that spread from origin in a flat ring, their x
62/// velocity 1.5 times their z velocity, so the ring is wider than deep as the
63/// field is drawn. Carry's BattleFx_SteerLiftedTarget spawns it where it sets
64/// its load down.
66 struct EffectOptions opt;
67 s32 vel[3];
68 s32 vz;
69 s32 angle;
70 u32 i;
71
72 opt.palette = 0;
74 opt.startScaleX = 0xcccc; // 0.8
75 opt.startScaleY = 0xcccc;
76 i = 0;
77 do {
79 vel[0] = Trig_Cos(angle) * 3 / 2;
80 vel[1] = 0;
81 vz = Trig_Sin(angle);
82 vel[2] = vz;
83 Effect_SpawnResident(origin->x, origin->y, origin->z, vel[0], vel[1], vz,
84 0x01090001, &opt);
85 i++;
86 } while (i <= WHIRLWIND_RADIAL_DIRECTIONS);
87}
88
89/// Per-frame update: wanders away from the anchor, 2 to 3 pixels a frame,
90/// now and then turning sharply; after 101 frames it hands over to the
91/// common particle script. BattleFx_CircleAnchor switches a particle to it.
92/// While it wanders, the engine's own motion lifts the particle (the velocity
93/// and gravity BattleFx_CircleAnchor gave it); this only moves it across the
94/// ground.
95void BattleFx_WanderAroundAnchor(union FieldObject *fieldObject) {
96 struct WhirlwindOrbit *effect = (struct WhirlwindOrbit *)fieldObject;
97 s32 len;
98 s32 angle;
99 s32 dx;
100 s32 dz;
101
102 // Random16 is 0 to 1 in 16.16, so 2 to 3 pixels.
103 len = Random16() + 0x20000;
104 angle = effect->angle;
105 dx = Iwram_MulQ16(len, Trig_Cos(angle));
106 dz = Iwram_MulQ16(len, Trig_Sin(angle));
107 effect->x += dx;
108 effect->z += dz;
109 // The u16 angle wraps: 0xfff0 gives a small backwards drift. A turn burst
110 // adds 1/32 of a turn each frame without stopping the outward motion.
111 effect->angle += 0xfff0;
112 if (effect->pause != 0) {
113 effect->pause--;
114 effect->angle += 0x800;
115 } else if ((Random16() << 5) >> 16 == 0) // one chance in 32
116 {
117 effect->pause = ((Random16() << 4) >> 16) + 8; // 8 to 23 frames
118 }
119 if (++effect->timer == WHIRLWIND_WANDER_FRAMES)
122}
123
124/// Per-frame update: circles the anchor at 8 pixels; after 121 frames it
125/// starts to wander (BattleFx_WanderAroundAnchor). FieldFx_RunWhirlwind gives
126/// it to each of the 16 particles it spawns round the orb.
127void BattleFx_CircleAnchor(union FieldObject *fieldObject) {
128 struct WhirlwindOrbit *effect = (struct WhirlwindOrbit *)fieldObject;
129 struct WhirlwindOrbit *anchor;
130 s32 angle;
131 s32 radius;
132 s32 dx;
133 s32 dz;
134
135 anchor = effect->anchor;
136 radius = WHIRLWIND_ORBIT_RADIUS;
137 angle = effect->angle;
138 dx = Iwram_MulQ16(radius, Trig_Cos(angle));
139 dz = Iwram_MulQ16(radius, Trig_Sin(angle));
140 effect->x = anchor->x + dx;
141 effect->z = anchor->z + dz;
143 if (++effect->timer == WHIRLWIND_ORBIT_FRAMES) {
144 // The engine integrates height after this callback. Supply upward speed
145 // and gravity here; the wandering callback only changes x and z.
147 effect->timer = 0;
148 effect->pause = 0;
149 effect->gravity = 0x1999;
150 effect->velocityY = 0x30000;
151 effect->angle = Random16();
152 }
153}
154
155/// Shrinks a scene-selected Whirlwind target each frame; below half size,
156/// moves it to the origin, stops it and removes the update.
157/// The scale falls by 1/512 each frame. From unit scale the strict lower bound
158/// takes 257 updates.
160 struct MotionObject *obj = (struct MotionObject *)fieldObject;
161 s32 scale;
162
163 scale = obj->scaleX - WHIRLWIND_TARGET_SCALE_STEP;
164 obj->scaleY = scale;
165 obj->scaleX = scale;
166 if (scale < WHIRLWIND_TARGET_MIN_SCALE) {
168 ((struct ScriptMotionObject *)obj)->hook = 0;
169 }
170}
171
172/// Runs Whirlwind using the target already stored in the effect scene.
173/// Abilities: Whirlwind, Gale (field kind 14), cast on a target.
174/// BattleFx_DispatchRequestKind passes an argument this adapter ignores;
175/// the shared runner reads scene->child instead.
177
178/// An orb is carried from the caster to 4 pixels above the effect's position
179/// over 10 frames, growing from 0.25.
180///
181/// Abilities: Whirlwind, Gale (field kind 14).
182///
183/// Without scene->enabled the target shrinks, and 16 particles appear round the
184/// orb, one every 6 frames, and circle it.
185///
186/// Called by BattleFx_Run and FieldFx_RunWhirlwindOnTarget. Fades the palettes
187/// to an effect colour and back, and gives the target its shrinking update;
188/// the orb is released at the end, the particles finish on their own.
190 struct BattleFxScene *scene = gEffectWork;
191 struct FieldActor *src = scene->mainObject;
192 struct FieldActor *target = scene->child;
193 struct EffectVector pos;
194 struct EffectVector from;
195 struct EffectVector to;
196 struct FieldActor *ball;
197 s32 step;
198 struct FieldActor *particle;
199 s32 steps = WHIRLWIND_TRAVEL_FRAMES + 1;
200
201 step = 0;
202 from.x = src->x.fixed;
203 from.y = src->y.fixed;
204 from.z = src->z.fixed;
205 to.x = scene->x;
206 to.y = scene->y - (4 << 16);
207 to.z = scene->z;
208 // Include both endpoints of the ten-frame interpolation.
209 ball = (struct FieldActor *)Object_Spawn(0xda, 0, 0, 0);
210 if (ball == 0) {
211 return;
212 }
215 do {
216 s32 scale;
217 ball->x.fixed = from.x + step * (to.x - from.x) / WHIRLWIND_TRAVEL_FRAMES;
218 ball->y.fixed = from.y + step * (to.y - from.y) / WHIRLWIND_TRAVEL_FRAMES;
219 ball->z.fixed = from.z + step * (to.z - from.z) / WHIRLWIND_TRAVEL_FRAMES;
220 scale =
221 0x4000 + step * 0x10ccc / WHIRLWIND_TRAVEL_FRAMES; // from 0.25 to 1.3
222 ball->scaleX = scale;
223 ball->scaleY = scale;
224 WaitFrames(1);
225 step++;
226 } while (step < steps);
227 ball->scaleX = 0x1b333; // 1.7 wide
228 ball->scaleY = 0x14ccc; // 1.3 high
230 WaitFrames(20);
231 // Cleared by BattleFx_DispatchRequestKind: cast on a target a scene event
232 // names, the target is blown away.
233 if (scene->enabled == 0) {
234 if (target != 0)
236
237 // Particles from 4 pixels above the orb, each 0.8 pixel higher, 3 to 8
238 // pixels away.
239 step = 0;
240 do {
241 s32 dist;
242
243 pos.x = ball->x.fixed;
244 pos.y = ball->y.fixed + step * 0xcccc + (4 << 16);
245 pos.z = ball->z.fixed;
246 dist = Random16() * 5 + (3 << 16);
247 Vector_AddPolarOffset(dist, Random16(), &pos);
248 particle = (struct FieldActor *)Object_Spawn(0xf9, pos.x, pos.y, pos.z);
249 if (particle != 0) {
250 particle->update = BattleFx_CircleAnchor;
251 particle->linkedObject = ball;
252 particle->timer = 0;
253 particle->work = 0;
254 particle->facing = Random16();
255 }
256 WaitFrames(6);
257 step++;
258 } while (step <= WHIRLWIND_ORBIT_PARTICLES - 1);
259 WaitFrames(20);
260 WaitFrames(120);
261 }
263 WaitFrames(30);
265 WaitFrames(20);
266 // Every particle has left its orbit by now. Its wandering callback no
267 // longer reads the anchor, so the orb can be released independently.
270}
void ObjectDispatch_ReleaseFar(struct DispatchObject *obj)
void Object_SetPositionAndResetMotionFar(struct ObjectRuntime *obj, s32 x, s32 y, s32 z)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void ObjectDispatch_InitializeFar(struct DispatchObject *obj, const s32 *script)
void AudioCommand_PlayFar(s32 id)
void Effect_SpawnResident(s32 x, s32 y, s32 z, s32 velocityX, s32 velocityY, s32 velocityZ, u32 flags, const struct EffectOptions *options)
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
const s32 gBattleFx_CommonParticleScript[]
[0] only frees the actor, +1 waits for it to arrive and frees it; +3 is gBattleFx_SourceHoldScript,...
Definition fxdata.c:444
void * gEffectWork
Slot 56: points to a scene-specific structure.
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
void Vector_AddPolarOffset(s32 radius, s32 angle, void *position)
Moves the point position by radius in direction angle on the ground plane: x by the cosine,...
Definition math.c:23
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
struct ObjectRuntime * Object_Spawn(s32 kind, s32 x, s32 y, s32 z)
Creates an object for an effect, at the caster's ground height, with sprite priority 0 and animation ...
Definition dispatch.c:371
void BattleEffect_InitializeSharedScene(void)
Saves the palettes for the effect (once, unless an effect is already shown) and fades them toward one...
Definition setup.c:236
void BattleFx_PrepareBufferInterpolation(void)
Fades the palettes back from an effect's colours to the saved ones (or to palette 0x10001 while an ef...
Definition setup.c:275
What every part of psynergy_effects.c shares: its includes and the macros and types more than one par...
#define SE_163
Definition songs.h:158
#define SE_136
Definition songs.h:129
u16 rotation
1/65536 turns
Definition animspr.h:118
The work of a Psynergy effect scene: its caster and target, where it takes place, the map state it re...
Definition fx_scene.h:31
s32 y
16.16 fixed-point pixels
Definition fx_scene.h:34
void * mainObject
the caster's object
Definition fx_scene.h:36
void * child
the target's object, or NULL
Definition fx_scene.h:37
s8 enabled
Set at the start: Force then aims in front of the caster; cleared once the target has been dispatched...
Definition fx_scene.h:44
s32 x
16.16 fixed-point pixels
Definition fx_scene.h:33
s32 z
16.16 fixed-point pixels
Definition fx_scene.h:35
A field object as the object dispatcher's far calls take it.
The options of a spawned field effect, each used when its EFFECT_USE_ flag (or EFFECT_SCALE_TO_TARGET...
s32 palette
passed to ObjectGroup_SetChildValue
s32 startScaleY
16.16 fixed point, 0x10000 full size
s32 startScaleX
16.16 fixed point, 0x10000 full size
void(*) update(union FieldObject *object)
replaces the update hook
A world position, as Camera_WorldToScreen converts it to the screen.
Definition battle.h:73
s32 y
16.16 fixed-point pixels
Definition battle.h:75
s32 z
16.16 fixed-point pixels
Definition battle.h:76
s32 x
16.16 fixed-point pixels
Definition battle.h:74
A field actor: a person or thing on the field with a position, motion toward a target,...
Definition field_obj.h:30
s16 timer
The parameter its action script reads (a follow distance or an angle to face), the player's frames to...
Definition field_obj.h:109
struct FieldActor * linkedObject
The object its action script follows or faces.
Definition field_obj.h:114
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition field_obj.h:39
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition field_obj.h:40
void(*) update(union FieldObject *object)
Called each frame before the object's script, while the object is live.
Definition field_obj.h:116
u16 work
The side of the player's next footprint (2 after a stop), or scene scratch.
Definition field_obj.h:112
A field effect: a small object on the field that moves at its velocity and grows and spins at its rat...
struct Vector3 velocity
Added to x, y and z each frame by the update hooks, in 16.16 fixed-point pixels per frame; FieldActor...
s32 z
16.16 fixed-point pixels
struct AnimationObject * sprite
the sprite spin turns
s32 scaleRateX
Added to scaleX each frame by the update hooks, in 16.16 fixed point a frame; zeroed by the spawner.
s32 scaleY
16.16 fixed point, 0x10000 full size
s32 scaleX
16.16 fixed point, 0x10000 full size
s32 y
16.16 fixed-point pixels
s32 x
16.16 fixed-point pixels
s32 scaleRateY
as scaleRateX, for scaleY
u16 spin
Added to the sprite's rotation each frame by the update hooks, in 1/65536 turns per frame; Imil's ris...
An effect object that moves and draws one sprite: its position, scale, velocity and target,...
Definition motobj.h:20
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition motobj.h:27
s32 z
16.16 fixed-point pixels
Definition motobj.h:25
s32 y
16.16 fixed-point pixels
Definition motobj.h:24
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition motobj.h:28
s32 x
16.16 fixed-point pixels
Definition motobj.h:23
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
A field object as the motion code sees it: its script, position, motion toward a target,...
void(*) hook(union FieldObject *object)
Called each frame before its script.
s32 z
Definition vector3.h:24
s32 x
Definition vector3.h:22
s32 y
Definition vector3.h:23
A FieldActor seen with the halfword at 0x64 unsigned and the one at 0x66 signed, as the bytes read th...
Definition whirlwind.c:23
s32 z
16.16 pixels
Definition whirlwind.c:28
s16 pause
frames left of a sharp turn
Definition whirlwind.c:35
u16 angle
heading or orbit angle, in 1/65536 turns
Definition whirlwind.c:25
u16 timer
frames so far
Definition whirlwind.c:34
s32 velocityY
applied by the engine, in 16.16 pixels per frame
Definition whirlwind.c:30
s32 gravity
vertical deceleration, in 16.16 pixels per frame squared
Definition whirlwind.c:32
s32 x
16.16 pixels
Definition whirlwind.c:26
struct WhirlwindOrbit * anchor
orb at the centre of the orbit
Definition whirlwind.c:36
s32 y
16.16 pixels
Definition whirlwind.c:27
void(*) update(union FieldObject *object)
engine's per-frame callback
Definition whirlwind.c:37
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
s32 fixed
16.16 fixed-point pixels
An object on the field, read as an actor or as an effect.
void BattleFx_ShrinkObjectScaleUntilHalf(union FieldObject *fieldObject)
Shrinks a scene-selected Whirlwind target each frame; below half size, moves it to the origin,...
Definition whirlwind.c:159
void BattleFx_WanderAroundAnchor(union FieldObject *fieldObject)
Per-frame update: wanders away from the anchor, 2 to 3 pixels a frame, now and then turning sharply; ...
Definition whirlwind.c:95
void FieldFx_RunWhirlwind(void)
An orb is carried from the caster to 4 pixels above the effect's position over 10 frames,...
Definition whirlwind.c:189
@ WHIRLWIND_TARGET_MIN_SCALE
Definition whirlwind.c:16
@ WHIRLWIND_TRAVEL_FRAMES
Definition whirlwind.c:17
@ WHIRLWIND_RADIAL_ANGLE_SHIFT
Definition whirlwind.c:9
@ WHIRLWIND_ORBIT_RADIUS
Definition whirlwind.c:11
@ WHIRLWIND_ORBIT_PARTICLES
Definition whirlwind.c:10
@ WHIRLWIND_ORBIT_ANGLE_STEP
Definition whirlwind.c:12
@ WHIRLWIND_TARGET_SCALE_STEP
Definition whirlwind.c:15
@ WHIRLWIND_ORBIT_FRAMES
Definition whirlwind.c:13
@ WHIRLWIND_RADIAL_DIRECTIONS
Definition whirlwind.c:8
@ WHIRLWIND_WANDER_FRAMES
Definition whirlwind.c:14
void BattleFx_CircleAnchor(union FieldObject *fieldObject)
Per-frame update: circles the anchor at 8 pixels; after 121 frames it starts to wander (BattleFx_Wand...
Definition whirlwind.c:127
void FieldFx_RunWhirlwindOnTarget(s32 unused)
Runs Whirlwind using the target already stored in the effect scene.
Definition whirlwind.c:176
void FieldFx_UpdateParticleMotionAndScale(union FieldObject *object)
Per-frame update of a particle: moves by its velocity, slowing its x and z velocity a little,...
Definition whirlwind.c:48
void BattleFx_SpawnRadialParticleRing(struct MotionObject *origin)
Spawns 17 particles that spread from origin in a flat ring, their x velocity 1.5 times their z veloci...
Definition whirlwind.c:65