Alchemy
Loading...
Searching...
No Matches

carry.c

Go to the documentation of this file.
1/// @file
2/// Carry: two hands lift the target, move it with the d-pad and drop it.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7STATIC_ASSERT(sizeof(struct EffectVector) == 0x0c);
8
9/// Per-frame update: drops one particle round the lifted object, 8 to 24
10/// pixels above it and 0 to 48 pixels away in a random direction.
12 struct FieldActor *liftedObject;
13 struct EffectVector position;
14 struct ItemBreakFragmentObject *fragment;
15 u32 radius;
16
17 liftedObject = ((struct BattleFxScene *)gEffectWork)->child;
18 position.x = liftedObject->x.fixed;
19 position.y = liftedObject->y.fixed - Random16() * 16 + (24 << 16);
20 position.z = liftedObject->z.fixed;
21
22 radius = Random16() * 3;
23 Vector_AddPolarOffset(radius * 16, Random16(), &position);
24
25 fragment = (struct ItemBreakFragmentObject *)Object_Spawn(
26 0x11d, position.x, position.y, position.z);
27 BattleFx_InitializeFallingFragment(fragment);
28}
29
30#define CARRY_SHARD_MAX 20 ///< shards
31
32/// Tests the target's move with its terrain reference raised 16 pixels.
33/// Restore the reference before returning the collision result.
34static __inline__ s32
36 struct EffectVector *position) {
37 s32 collision;
38
39 target->terrainHeight += 16 << 16;
40 collision = Map_CheckObjectStepFar((struct ObjectRuntime *)target,
41 (struct FieldPosition *)position);
42 target->terrainHeight -= 16 << 16;
43 return collision;
44}
45
46/// Two hands lift it to 24 pixels above the ground; the d-pad moves it 16
47/// pixels at a time and A, B, L or R drops it where it is.
48///
49/// Abilities: Carry (field kind 11), cast on a target.
50///
51/// Where the way is blocked a buzzer sounds.
53 struct BattleFxScene *work;
54 struct FieldActor *src;
55 struct FieldActor *target;
56 struct FieldActor *shards[CARRY_SHARD_MAX];
57 struct EffectVector pos;
58 struct FieldActor *hands[2];
59 struct FieldActor *obj;
60 struct FieldActor *right;
61 s32 i;
62 s32 angle;
63 s32 dist;
64 struct EffectVector *p;
65
66 work = gEffectWork;
67 src = work->mainObject;
68 target = work->child;
69 if (target == NULL)
70 return;
72 src->linkedObject = target;
75
76 // The hands appear 32 pixels to either side and move to 16 pixels.
77 /* FAKEMATCH(temporary): the position reached through p everywhere but in
78 * the steering loop's first part, which names it; as pos named
79 * everywhere, 10 of 531 instructions differ in tbs-en. */
80 p = &pos;
81 SET_POSITION(p, work->x, work->y + (16 << 16), work->z);
82 obj = (struct FieldActor *)BattleFx_SpawnItemBreakMode1(p->x + (32 << 16),
83 p->y, p->z, 0x8000);
84 hands[0] = obj;
85 right = (struct FieldActor *)BattleFx_SpawnItemBreakMode1(p->x - (32 << 16),
86 p->y, p->z, 0);
87 hands[1] = right;
88 if (hands[0] == NULL || right == NULL) {
90 return;
91 }
92 WaitFrames(15);
93 SET_POSITION(p, target->x.fixed, target->y.fixed + (16 << 16),
94 target->z.fixed);
95 Object_SetMoveTargetFar((struct ObjectRuntime *)obj, p->x + (16 << 16), p->y,
96 p->z);
97 Object_SetMoveTargetFar((struct ObjectRuntime *)right, p->x - (16 << 16),
98 p->y, p->z);
101 obj->x.fixed = p->x + (16 << 16);
102 obj->velocityX = 0;
103 right->x.fixed = p->x - (16 << 16);
104 right->velocityX = 0;
105
106 // Lift to 24 pixels above the ground.
110 target->motionFlags = 4;
112 if (hands[0] != NULL && hands[1] != NULL) {
113 while (target->y.fixed - target->terrainHeight <= 24 << 16) {
114 obj->y.fixed += 0x6000;
115 right->y.fixed += 0x6000;
116 target->y.fixed += 0x6000;
117 WaitFrames(1);
118 }
119 }
120 hands[0]->speed = 4 << 16;
121 hands[0]->acceleration = 0x8000;
122 hands[1]->speed = 4 << 16;
123 hands[1]->acceleration = 0x8000;
124 target->speed = 0x6666;
125 target->acceleration = 0x3333;
126 target->steeringFlags = 0;
127 target->terrainId = 2;
128
129 //------------------------------------------------------------------
130 // Move with the d-pad.
131 //------------------------------------------------------------------
132 for (;;) {
133 WaitFrames(1);
134 if ((gKeysPressed & (KEY_A | KEY_B | KEYS_SHOULDERS)) != 0)
135 break;
136
137 // No direction held: the hands go back to the target's sides.
139 if (angle == 0xffff) {
140 pos.x = target->x.fixed;
141 pos.y = target->y.fixed + (16 << 16);
142 pos.z = target->z.fixed;
143 Object_SetMoveTargetFar((struct ObjectRuntime *)hands[0],
144 pos.x + (16 << 16), pos.y, pos.z);
145 Object_SetMoveTargetFar((struct ObjectRuntime *)hands[1],
146 pos.x - (16 << 16), pos.y, pos.z);
149 continue;
150 }
151
152 // The hands lean 2 pixels that way; check the ground 16 pixels on.
153 pos.x = target->x.fixed;
154 pos.y = target->y.fixed + (16 << 16);
155 pos.z = target->z.fixed;
156 Vector_AddPolarOffset(2 << 16, angle, &pos);
157 Object_SetMoveTargetFar((struct ObjectRuntime *)hands[0],
158 pos.x + (16 << 16), pos.y, pos.z);
159 Object_SetMoveTargetFar((struct ObjectRuntime *)hands[1],
160 pos.x - (16 << 16), pos.y, pos.z);
163 pos.x = target->x.fixed;
164 pos.y = target->terrainHeight;
165 pos.z = target->z.fixed;
166 Vector_AddPolarOffset(16 << 16, angle, &pos);
168 (s32 *)&pos);
169 // Both tests jump into the blocked path, which keeps it ahead of the drop
170 // path as the ROM lays them out; written as one || test, 407 of 531
171 // instructions differ in tbs-en.
172 if (i != 0)
173 goto blocked;
174 if (BattleFx_CheckRaisedTargetCollision(target, p) > 0) {
175 blocked: // the way is blocked: a buzzer every 16 frames
178 if ((gFrameCount & 15) == 0)
180 continue;
181 }
182 // The way is free: move the target there.
183 {
184 struct FieldActor *second;
185 s32 x;
186 s32 z;
187
189 x = p->x;
190 z = p->z;
193 WaitFrames(15);
194 target->paused = i;
195 target->speed = 0x3333;
196 target->acceleration = 0x3333;
197 Object_SetMoveTargetFar((struct ObjectRuntime *)target, p->x, p->y, p->z);
198 hands[0]->speed = 0x3333;
199 hands[0]->acceleration = 0x3333;
200 second = hands[1];
201 second->speed = 0x3333;
202 second->acceleration = 0x3333;
203 Object_SetMoveTargetFar((struct ObjectRuntime *)hands[0],
204 p->x + (16 << 16), p->y, p->z);
205 Object_SetMoveTargetFar((struct ObjectRuntime *)second, p->x - (16 << 16),
206 p->y, p->z);
208 target->x.fixed = x;
209 target->z.fixed = z;
210 target->velocityX = i;
211 target->velocityZ = i;
212 WaitFrames(10);
213 break;
214 }
215 }
216
217 //------------------------------------------------------------------
218 // Shards fly from the target, the hands vanish, and the target hops and
219 // drops.
220 //------------------------------------------------------------------
225 WaitFrames(15);
227 WaitFrames(15);
228 SET_POSITION(p, target->x.fixed, target->y.fixed + (16 << 16),
229 target->z.fixed);
230 {
231 struct FieldActor **walk = shards;
232
233 // Shards: 2 to 3 pixels a frame, 8 to 32 pixels in a random direction.
234 for (i = 0; i < CARRY_SHARD_MAX; i++) {
235 obj = (struct FieldActor *)Object_Spawn(0x11d, p->x, p->y, p->z);
236 *walk++ = obj;
237 if (obj != NULL) {
240 obj->speed = Random16() + (2 << 16);
241 obj->acceleration = 2 << 16;
242 obj->motionFlags = 0;
243 dist = Random16() * 24 + (8 << 16);
245 dist, Random16());
246 }
247 }
248 }
250 ObjectDispatch_ReleaseFar((struct DispatchObject *)hands[0]);
251 ObjectDispatch_ReleaseFar((struct DispatchObject *)hands[1]);
252
253 // Restore the target's look and motion, and throw it up at 10 pixels a
254 // frame.
256 work->savedPalette);
258 work->savedScript);
259 target->update = work->savedCallback;
260 target->motionFlags = 3;
261 target->velocityY = 10 << 16;
262 target->bounce = 0x3333;
263 target->terrainId = 0;
264 src->update = 0;
266 if (work->childOption != 0) {
267 // Wait for it to rise and land (at most 90 frames each), then a ring.
268 for (i = 0; i < 90 && target->velocityY >= 0; i++)
269 WaitFrames(1);
270 WaitFrames(1);
271 for (i = 0; i < 90 && target->velocityY < 0; i++)
272 WaitFrames(1);
275 WaitFrames(30);
276 } else {
278 }
279}
280
281/// Carry cast with no target: objects appear above the caster and to either
282/// side, move apart and scatter into shards.
283///
284/// Abilities: Carry (field kind 11), cast with no target.
286
287/// Spawns object 215 with the item break sound, in animation 1, and grows it,
288/// spinning, from a quarter to full size over 24 frames; angle is the way it
289/// faces once grown.
291 s32 angle) {
292 struct MotionObject *fragment;
293 s32 scale;
294
296 fragment = (struct MotionObject *)Object_Spawn(215, x, y, z);
297 if (fragment != NULL) {
298 fragment->scaleY = 0x4000;
299 fragment->scaleX = 0x4000;
300 fragment->speedLimit = 0x30000;
301 fragment->acceleration = 0x30000;
302 fragment->autoFaceMotion = 0;
304 scale = fragment->scaleX;
305 if (scale < 0x10000) {
306 do {
307 scale += 0x800;
308 fragment->scaleY = scale;
309 fragment->scaleX = scale;
310 fragment->angle += 0x2000;
311 WaitFrames(1);
312 scale = fragment->scaleX;
313 } while (scale <= 0xffff);
314 }
315 fragment->angle = angle;
316 }
317 return fragment;
318}
319
320#undef CARRY_SHARD_MAX
#define CARRY_SHARD_MAX
shards
Definition carry.c:30
static __inline__ s32 BattleFx_CheckRaisedTargetCollision(struct FieldActor *target, struct EffectVector *position)
Tests the target's move with its terrain reference raised 16 pixels.
Definition carry.c:35
void BattleFx_SteerLiftedTarget(s32 targetId)
Two hands lift it to 24 pixels above the ground; the d-pad moves it 16 pixels at a time and A,...
Definition carry.c:52
struct MotionObject * BattleFx_SpawnItemBreakMode1(s32 x, s32 y, s32 z, s32 angle)
Spawns object 215 with the item break sound, in animation 1, and grows it, spinning,...
Definition carry.c:290
void FieldFx_RunCarry(void)
Carry cast with no target: objects appear above the caster and to either side, move apart and scatter...
Definition carry.c:285
void BattleFx_SpawnFallingParticles(void)
Per-frame update: drops one particle round the lifted object, 8 to 24 pixels above it and 0 to 48 pix...
Definition carry.c:11
void ObjectDispatch_ReleaseFar(struct DispatchObject *obj)
void ObjectDispatch_SetSingleChildFlagsFar(struct DispatchObject *obj, u32 flags)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void ObjectDispatch_InitializeFar(struct DispatchObject *obj, const s32 *script)
void Object_SetMoveTargetFar(struct ObjectRuntime *object, s32 x, s32 y, s32 z)
void Animation_ApplyChildValuesFar(struct DispatchObject *obj, u32 val)
s32 ScriptObject_CheckOverlapFar(struct ScriptObjectEntry *object, s32 *values)
s32 Map_CheckObjectStepFar(struct ObjectRuntime *object, struct FieldPosition *position)
void FieldObject_WaitForMoveFar(void *fieldObject)
void AudioCommand_PlayFar(s32 id)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
volatile u32 gFrameCount
Frames WaitFrames has finished.
const s32 gBattleFx_FragmentScript[]
Definition fxdata.c:456
const s32 gBattleFx_SourceHoldScript[]
Definition fxdata.c:450
void * gEffectWork
Slot 56: points to a scene-specific structure.
@ KEY_B
Definition io_reg.h:244
@ KEY_A
Definition io_reg.h:243
@ KEYS_SHOULDERS
Definition io_reg.h:256
volatile u32 gKeysHeld
Keys down now.
volatile u32 gKeysPressed
Keys that went down this frame.
#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
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
s32 Input_GetDpadAngle(u32 unused)
Returns the direction of the d-pad (0x10000 a full turn): right 0, down 0x4000, left 0x8000,...
Definition move.c:9
void Motion_SetTargetPositionFromMagnitudeAngle(struct ObjectRuntime *object, s32 magnitude, s32 angle)
Sends an object toward the point magnitude (16.16 pixels) away from it in direction angle: sets its m...
Definition dispatch.c:308
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 ObjectGroup_ApplyRandomChildValues(union FieldObject *fieldObject)
Per-frame update: sets every part of an object's sprite to param frame % 6, which cycles its colours.
Definition dispatch.c:270
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 DEFINE_ITEM_BREAK_EFFECT(name, spawn)
Defines an effect cast with no target: spawn makes an object 16 pixels above the effect's position an...
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...
Definition scheduler.c:102
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
#define SE_131
Definition songs.h:124
#define SE_175
Definition songs.h:170
#define SE_MENU_ERROR
Definition songs.h:107
#define SE_130
Definition songs.h:123
#define SE_ITEM_BREAK
Definition songs.h:131
#define SE_135
Definition songs.h:128
#define NULL
Definition bilibin.h:6
#define STATIC_ASSERT(condition)
C89 permits repeated extern declarations of the same array.
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
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.
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
s32 speed
speed limit, 16.16 fixed-point pixels per frame
Definition field_obj.h:55
struct FieldActor * linkedObject
The object its action script follows or faces.
Definition field_obj.h:114
u8 steeringFlags
ActorSteeringFlag bits.
Definition field_obj.h:92
u8 motionFlags
ActorMotionFlag bits; zero is free flight in 3D, and 3 is set on creation.
Definition field_obj.h:83
union FieldCoordinate x
16.16 fixed-point pixels
Definition field_obj.h:35
s32 velocityX
16.16 fixed-point pixels per frame
Definition field_obj.h:52
s32 bounce
The share of its falling speed kept as it bounces on landing, 16.16 fixed point (0x4000 when created)...
Definition field_obj.h:64
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
s32 terrainHeight
16.16 fixed-point pixels
Definition field_obj.h:38
s32 velocityY
16.16 fixed-point pixels per frame
Definition field_obj.h:53
union FieldCoordinate z
16.16 fixed-point pixels
Definition field_obj.h:37
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
Definition field_obj.h:58
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
u8 terrainId
The map layer (0 to 3) its ground height is read from, which the scrolling camera updates from the ce...
Definition field_obj.h:47
A position on the field.
A FieldActor seen with the halfword at 0x5e (its lifetime), which FieldActor does not name.
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 speedLimit
16.16 fixed-point pixels per frame
Definition motobj.h:34
s32 z
16.16 fixed-point pixels
Definition motobj.h:25
s32 y
16.16 fixed-point pixels
Definition motobj.h:24
u16 angle
1/65536 turns
Definition motobj.h:22
s32 acceleration
Horizontal speed gained each frame towards the target, or lost braking without one,...
Definition motobj.h:37
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition motobj.h:28
s32 x
16.16 fixed-point pixels
Definition motobj.h:23
u8 autoFaceMotion
bit 0 turns the object to face where it moves
Definition motobj.h:59
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
s32 velocityZ
16.16 fixed-point pixels per frame
s32 velocityX
16.16 fixed-point pixels per frame
s32 z
16.16 fixed-point pixels
s32 acceleration
Added toward the target each frame, or taken off the speed when there is none, in 16....
s32 x
16.16 fixed-point pixels
A field object as the script commands' overlap checks see it.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned short u16
Definition types.h:13
s32 fixed
16.16 fixed-point pixels
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