Alchemy
Loading...
Searching...
No Matches

djinni.c

Go to the documentation of this file.
1/// @file
2/// A Djinni's hop before its battle, joining the party, the effect slots.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7/// Update hook shared by the Djinni battle-start and Mercury afterimages.
9 BattleFx_MoveAfterimageHalfway(fieldObject);
10}
11
12#define DJINNI_CLONE_MAX 8 ///< afterimages of the leaping Djinni
13
14/// A Djinni's battle start: the Djinni (actor id) bounces twice, turns to face
15/// the leader, hops back 16 pixels three times, then leaps 64 pixels at the
16/// party trailing eight afterimages tinted for its element.
18 struct FieldActor *djinni;
19 struct FieldActor *copy;
20 struct FieldActor *prev;
21 void *sharedSprite;
22 s32 dir;
23 s32 back;
24 s32 dist;
25 s32 sprite;
26 s32 tint;
27 s32 i;
28 UNUSED struct FieldActor *copies[DJINNI_CLONE_MAX];
29
30 // The way the leader faces, to the nearest quarter turn.
31 djinni = Object_GetById(djinniId);
32 dir = (Object_GetById(gGameState.selectedActor)->facing + 0x2000) & 0xc000;
34 WaitFrames(10);
36 Motion_SetVarCbAndRefresh(djinniId, 1);
38 Motion_SetVarCbAndRefresh(djinniId, 1);
39 back = dir + 0x8000;
40 WaitFrames(20);
41 ObjectMotion_ArmCallback(djinniId, back, 0);
42 WaitFrames(10);
43 djinni->sprite->image.priority = 0;
44 djinni->facing = back;
45 Object_GetById(djinniId)->steeringFlags &= ~1;
46 djinni->motionFlags = 2;
47
48 // Hop 16 pixels away from the leader, three times.
49 dist = 16 << 16;
51 dist, dir);
53 ObjectMotion_Launch(djinniId, 4, 0);
56 dist, dir);
58 ObjectMotion_Launch(djinniId, 4, 0);
61 dist, dir);
63 ObjectMotion_Launch(djinniId, 4, 0);
65 WaitFrames(20);
66
67 // Afterimages of the same sprite, each chasing the one before it, tinted
68 // by the Djinni's sprite (90, 91 and 92).
69 sprite = djinni->sprite->entries[0]->animId;
70 tint = 9;
71 if (sprite == 90)
72 tint = 2;
73 if (sprite == 92)
74 tint = 10;
75 if (sprite == 91)
76 tint = 9;
77 sharedSprite = NULL;
78 prev = djinni;
79 for (i = 0; i < DJINNI_CLONE_MAX; i++) {
80 copy = (struct FieldActor *)Object_CreateFar(
81 sprite, djinni->x.fixed, djinni->y.fixed, djinni->z.fixed);
82 copies[i] = copy;
83 if (copy != NULL) {
84 copy->scaleY = 0xf000;
85 copy->scaleX = 0xf000;
86 copy->motionFlags = 0;
87 copy->priorityFlags = 2;
88 copy->steeringFlags |= 1;
90 copy->facing = djinni->facing;
91 copy->sprite->image.priority = 0;
95 sharedSprite = Sprite_ShareVramCache(copy->sprite, sharedSprite);
96 copy->linkedObject = prev;
97 prev = copy;
98 }
99 }
100
101 // Leap 64 pixels at the leader and stop there.
103 64 << 16, dir + 0x8000);
105 ObjectMotion_Launch(djinniId, 12, 0);
106 WaitFrames(24);
107 djinni->motionFlags = 0;
108 djinni->velocityX = 0;
109 djinni->velocityZ = 0;
110 djinni->velocityY = 0;
111 djinni->targetX = ACTOR_NO_TARGET;
112 djinni->targetZ = ACTOR_NO_TARGET;
113 djinni->targetY = ACTOR_NO_TARGET;
115 djinni->sprite->image.priority = 2;
117}
118
119/// A Djinni joins the party: djinn (0 to 19) of element goes to the member with
120/// the fewest Djinn, or to no one and only its flag while FLAG_DJINN_TUTORIAL
121/// is set. Unless slot is -1, the Djinni's actor slot first plays its
122/// element's capture effect and is freed. Ends with
123/// `<Djinni> joined <member>.`
124void Djinn_JoinParty(s32 slot, s32 element, s32 djinn) {
125 struct FieldWork *work;
126 s32 owner;
127
128 work = (struct FieldWork *)gEventWork;
130 owner = 0;
131 GameFlag_SetBitFar(djinn + element * 20 + FLAG_DJINNI_0);
132 } else {
133 owner = Djinn_AddToLeastLoadedOwnerFar(element, djinn);
134 }
135
136 if (owner >= 0) {
139 if (slot != -1) {
140 if (work->mode == MODE_WORLD_MAP)
142
143 if (element == 0) // Venus
145 else if (element == 1) // Mercury
147 else if (element == 2) // Mars
149 else if (element == 3) // Jupiter
151
152 work->actors[slot] = 0;
153 if (work->mode == MODE_WORLD_MAP)
155 }
156
157 Djinn_ShowJoinedMessageFar(owner, element, djinn);
160 }
161}
162
163/// Puts a Djinni's actor back where its battle started from: for a pending
164/// Djinni battle (pendingDjinnEvent 300 to 380, FLAG_KEEP_PARTY_POSITION set,
165/// the battle over) the scene actor placed for that Djinni (condition = its
166/// flag) goes back to its placement, or 32 pixels north of the leader when the
167/// event has 0x800 set.
169 s32 flags = gGameState.pendingDjinnEvent & 0xf000;
170 u32 event = gGameState.pendingDjinnEvent & 0xfff;
171 s32 id;
172
173 if (GameFlag_TestFar(FLAG_KEEP_PARTY_POSITION) != 0 && flags == 0) {
174 flags = event & 0x800;
175 event &= 0x7ff;
177 for (id = 8; id <= 65; id++) {
178 struct ScenePlacement *desc = Scene_FindActorPlacement(id);
179 struct ObjectRuntime *obj;
180
181 if (desc == NULL || desc->condition - FLAG_DJINNI_0 != event - DJINNI_0)
182 continue;
183 obj = ObjectTable_Get(id);
184 if (obj == NULL)
185 continue;
186 if (flags == 0) {
187 obj->terrainHeight = flags;
188 obj->flags = 3;
189 Object_SetPositionAndResetMotionFar(obj, desc->x, desc->y, desc->z);
190 } else {
191 struct ObjectRuntime *leader =
193
194 Object_SetPositionAndResetMotionFar(obj, leader->x, leader->y,
195 leader->z - (32 << 16));
196 }
198 }
199 }
200 }
201}
202
203/// Settles a pending Djinni battle as a scene loads. The field calls it with
204/// shown 0 while it builds the scene and with shown nonzero once the scene is
205/// on screen. After a won battle (sceneChangeReason above 0) the second call
206/// makes the Djinni join the party (Djinn_JoinParty); otherwise
207/// the first call sets flag 128 + the Djinni's number and drops the event. An
208/// event of kind 0x1000 instead sets its flag when sceneChangeReason is 1.
210 struct GameState *st = &gGameState;
211 s16 *pending = &st->pendingDjinnEvent;
212 s32 kind = *pending & 0xf000;
213 s32 flag = *pending & 0xfff;
214
215 if (shown == 0) {
216 if (kind == 0) {
217 flag &= 0x7ff;
218 if (flag < DJINNI_0 || flag > DJINNI_0 + 80)
219 return;
220 if (st->sceneChangeReason > 0 && st->sceneChangeReason != 999)
221 return;
222 GameFlag_SetBitFar(flag - 172);
223 *pending = kind;
224 } else if (kind == 0x1000) {
225 if (st->sceneChangeReason == 1)
226 GameFlag_SetBitFar(flag);
227 *pending = shown;
228 }
229 return;
230 }
231 if (kind == 0) {
232 flag &= 0x7ff;
233 if (flag >= DJINNI_0 && flag <= DJINNI_0 + 80) {
234 flag &= 0x7ff;
235 if (st->sceneChangeReason > 0) {
236 s32 djinni = flag - DJINNI_0;
237 s32 element = djinni / 20;
238 s32 index = djinni % 20;
239 s32 actor;
240
241 for (actor = 8; actor <= 65; actor++) {
242 struct ScenePlacement *found = Scene_FindActorPlacement(actor);
243 if (found != 0 &&
244 found->condition - FLAG_DJINNI_0 == flag - DJINNI_0) {
245 WaitFrames(40);
246 Djinn_JoinParty(actor, element, index);
247 break;
248 }
249 }
250 }
251 }
252 }
254}
255
256/// Scheduler callback: updates the 24 effect slots.
257void BattleFx_UpdateAllSlots(void) { FieldFx_UpdateSceneSlots(); }
258
259/// Allocates and clears the effect slots (heap block 56) and starts their
260/// update callback.
262 void *work;
263
265 Dma_Fill32(0, work, sizeof(struct BattleFxScene));
267}
268
269/// Stops the effect slots: removes their callback, frees every slot still in
270/// use and releases their heap block.
272 struct BattleFxScene *scene = gEffectWork;
273 struct EffectSlot *slot;
274 s32 i;
275
277 for (i = 0; i < PSYNERGY_EFFECT_SLOT_COUNT; i++) {
278 slot = &scene->slots[i];
279 if (slot->active != 0)
281 }
283 WaitFrames(1);
284}
285
286/// Per-frame update: spins an object 1/8 turn a frame.
287void BattleFx_AdvanceSpinAngle(union FieldObject *fieldObject) {
288 struct MotionObject *object = (struct MotionObject *)fieldObject;
289 object->angle += 0x2000;
290}
291
292/// Effect slot callback of a Jupiter Djinni's light particles: each circles
293/// its centre while it widens for 60 frames, circles 40, drifts toward a point
294/// 20 pixels over the leader for 40, closes in for 60 and is freed.
296 struct MotionObject *target;
297 struct EffectVector position;
298
300 if (particle->state == 0) {
301 particle->orbitRadius += 1;
302 particle->orbitAngle += 1;
303 if ((s16)particle->age == 60) {
304 particle->age = 0;
305 particle->state += 1;
306 }
307 } else if (particle->state == 1) {
308 particle->orbitAngle += 1;
309 if ((s16)particle->age == 40) {
310 particle->age = 0;
311 particle->state += 1;
312 }
313 } else if (particle->state == 2) {
314 particle->orbitAngle += 1;
315 position.x = target->x;
316 position.y = target->y + 0x140000;
317 position.z = target->z;
318 Camera_WorldToScreen(&position);
319 particle->originX += (position.x - particle->originX) / 8;
320 particle->originZ += (position.z - particle->originZ) / 8;
321 if ((s16)particle->age == 40) {
322 particle->age = 0;
323 particle->state += 1;
324 }
325 } else if (particle->state == 3) {
326 particle->orbitRadius -= 1;
327 particle->orbitAngle += 1;
328 if ((s16)particle->age == 60) {
329 particle->age = 0;
330 particle->state += 1;
331 }
332 } else if (particle->state == 4) {
333 BattleFx_ClearOwnedSlot(particle);
334 }
335 position.x = particle->originX;
336 position.z = particle->originZ;
337 Vector_AddPolarOffset(particle->orbitRadius << 16, particle->orbitAngle << 11,
338 &position);
339 particle->x = position.x;
340 particle->z = position.z;
341}
342
343#undef DJINNI_CLONE_MAX
void Motion_SetVarCbAndRefresh(u32 objectId, s32 count)
The event command "run repeated motion": as ObjectMotion_SetVariantCallback, then waits for it to end...
void ObjectMotion_Launch(u32 objectId, s32 speed, s32 frames)
The event command "actor jump": throws the actor upward at speed pixels per frame with a jump sound (...
void ObjectMotion_ArmCallback(s32 objectId, s32 angle, s32 wait)
The event command "actor face direction": the actor turns toward angle (0x10000 a full turn; ObjectMo...
struct FieldActor * Object_GetById(s32 actor)
Returns an actor, or NULL if it does not exist.
void * ObjectTable_Get(u32 actorIndex)
Returns the actor in slot index (0 to 65), or NULL.
Definition actors.c:462
void BattleEffect_ClearOutOfBoundsObjects(void)
Destroys the placed actors far from the view's centre: more than 160 pixels to either side,...
Definition actors.c:357
void BattleEffect_ClearAllObjects(void)
Destroys every placed actor and places the scene's actors again from its first placement table after ...
Definition actors.c:417
void ObjectMotion_MoveHalfwayTowardTarget(union FieldObject *fieldObject)
Update hook shared by the Djinni battle-start and Mercury afterimages.
Definition djinni.c:8
void Djinn_ResolvePendingEvent(s32 shown)
Settles a pending Djinni battle as a scene loads.
Definition djinni.c:209
void BattleFx_InitializeSlots(void)
Allocates and clears the effect slots (heap block 56) and starts their update callback.
Definition djinni.c:261
void Djinn_RunBattleStartHop(s32 djinniId)
A Djinni's battle start: the Djinni (actor id) bounces twice, turns to face the leader,...
Definition djinni.c:17
void BattleFx_RunAngledApproachPhases(struct EffectSlot *particle)
Effect slot callback of a Jupiter Djinni's light particles: each circles its centre while it widens f...
Definition djinni.c:295
#define DJINNI_CLONE_MAX
afterimages of the leaping Djinni
Definition djinni.c:12
void BattleFx_AdvanceSpinAngle(union FieldObject *fieldObject)
Per-frame update: spins an object 1/8 turn a frame.
Definition djinni.c:287
void BattleFx_ClearActiveSlotsAndScheduleUpdates(void)
Stops the effect slots: removes their callback, frees every slot still in use and releases their heap...
Definition djinni.c:271
void BattleFx_UpdateAllSlots(void)
Scheduler callback: updates the 24 effect slots.
Definition djinni.c:257
void FieldObject_PlaceSceneActors(void)
Puts a Djinni's actor back where its battle started from: for a pending Djinni battle (pendingDjinnEv...
Definition djinni.c:168
void Djinn_JoinParty(s32 slot, s32 element, s32 djinn)
A Djinni joins the party: djinn (0 to 19) of element goes to the member with the fewest Djinn,...
Definition djinni.c:124
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
Definition dma.h:30
void BattleFx_ClearOwnedSlot(struct EffectSlot *slot)
Frees an effect slot and its sprite.
struct ObjectRuntime * Object_CreateFar(s32 id, s32 x, s32 y, s32 z)
Far call to FieldObject_Create.
void Object_SetPositionAndResetMotionFar(struct ObjectRuntime *obj, s32 x, s32 y, s32 z)
void ObjectDispatch_SetSingleChildFlagsFar(struct DispatchObject *obj, u32 flags)
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void Animation_ApplyChildValuesFar(struct DispatchObject *obj, u32 val)
void FieldObject_WaitForMoveFar(void *fieldObject)
s32 GameFlag_TestFar(s32 flag)
s32 GameFlag_SetBitFar(s32 flag)
s32 Djinn_AddToLeastLoadedOwnerFar(s32 element, s32 djinn)
void AudioCommand_PlayFar(s32 id)
void Djinn_ShowJoinedMessageFar(s32 pc, s32 element, s32 djinn)
#define ACTOR_NO_TARGET
A target coordinate that is not set: the object has no target.
Definition field_obj.h:145
#define FLAG_DJINNI_0
the flag of Djinni 0, set once it is caught
Definition flags.h:15
#define FLAG_DJINN_TUTORIAL
Definition flags.h:69
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
struct GameState gGameState
void * gEffectWork
Slot 56: points to a scene-specific structure.
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
Definition heap.c:47
void Djinn_RunJupiterJoinEffect(s32 djinniId)
A Jupiter Djinni joins the party: it bounces three times, spins, leaps out of sight and bursts into 2...
Definition jupiter.c:10
void Djinn_RunMarsJoinEffect(s32 djinniId)
A Mars Djinni joins the party: it turns to the camera, bounces three times, spins ever faster and shr...
Definition mars.c:14
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
void Runtime_ReleaseHeapBlock(s32 slot)
void BattleFx_RunMercuryDjinnCapture(s32 djinniId)
A Mercury Djinni joins the party: the screen is tinted blue, the Djinni bounces twice and hops three ...
Definition mercury.c:14
struct ScenePlacement * Scene_FindActorPlacement(s32 id)
Returns the placement of actor id in the scene's placement tables, or NULL: for a party character (0 ...
Definition events.c:14
struct AnimationObject * Sprite_ShareVramCache(struct AnimationObject *sourceSprite, struct AnimationObject *sharedSprite)
Makes sourceSprite share sharedSprite's VRAM block, releasing its own; with no sharedSprite it keeps ...
Definition dispatch.c:346
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
void FieldEvent_End(void)
Ends an event: stops the debug fast-forward callback, gives the camera back to the leader and refresh...
Definition events.c:120
void FieldEvent_Begin(void)
The event command "begin event": closes any timed notice, stops the leader, resets the message and ti...
Definition events.c:91
void Camera_WorldToScreen(struct EffectVector *position)
Converts a world position (16.16 pixels) to the screen: x and z receive the screen's x and y and y be...
Definition setup.c:293
What every part of psynergy_effects.c shares: its includes and the macros and types more than one par...
#define DJINNI_0
gGameState.pendingDjinnEvent of Djinni 0 (requests.c, djinni.c).
#define HEAP_SLOT_FX
the Psynergy effect's work (gWorkSlot[56], gEffectWork)
#define PSYNERGY_EFFECT_SLOT_COUNT
The effect slots of a Psynergy effect's scene (gEffectWork->slots).
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_136
Definition songs.h:129
#define SE_173
Definition songs.h:168
#define SE_175
Definition songs.h:170
#define SE_JUMP
An actor jumps: ObjectMotion_Launch plays the high jump above 5 pixels a frame.
Definition songs.h:147
struct EventWork * gEventWork
#define NULL
Definition bilibin.h:6
void WorldMap_EndEvent(void)
Ends what WorldMap_BeginEvent started: on the world map, reloads the area's graphics and sets the cam...
Definition step.c:484
void WorldMap_BeginEvent(void)
Starts an event or menu on the world map: ends any colour ratio transition in progress,...
Definition step.c:464
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
struct EffectSlot slots[24]
Definition fx_scene.h:73
A field object as the object dispatcher's far calls take it.
A particle a Psynergy effect moves and draws: its sprite, its position and target,...
Definition effect_slot.h:18
s16 orbitRadius
pixels
Definition effect_slot.h:36
s8 state
the callback's own step; 0 when it is given
Definition effect_slot.h:38
s32 originX
16.16 fixed-point pixels; where the slot started
Definition effect_slot.h:24
s32 z
16.16 fixed-point pixels
Definition effect_slot.h:21
s32 x
16.16 fixed-point pixels
Definition effect_slot.h:20
s32 originZ
16.16 fixed-point pixels; where the slot started
Definition effect_slot.h:25
s8 active
nonzero while the slot is in use
Definition effect_slot.h:44
s16 orbitAngle
1/32 turns
Definition effect_slot.h:37
u16 age
frames
Definition effect_slot.h:34
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 targetX
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:59
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 targetZ
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:61
s32 velocityX
16.16 fixed-point pixels per frame
Definition field_obj.h:52
union FieldCoordinate y
16.16 fixed-point pixels
Definition field_obj.h:36
u8 priorityFlags
ActorPriorityFlag bits, read by the scrolling camera.
Definition field_obj.h:51
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
u16 facing
1/65536 turns
Definition field_obj.h:34
s32 targetY
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:60
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
s32 velocityZ
16.16 fixed-point pixels per frame
Definition field_obj.h:54
Full event work allocated by Field_RunScene (heap slot 27).
s16 event
A raised event for Scene_RunRaisedEvent, or -1 when characters fell to poison or hazard damage,...
s16 mode
MODE_WORLD_MAP (3) on the world map.
struct FieldActor * actors[66]
The actors by id: 0 to 7 the party's characters, 8 on the placed actors.
The game's state: play time, coins, the scene and the leader's position, the active party and the opt...
Definition game_state.h:14
s16 pendingDjinnEvent
The Djinni battle pending (DJINNI_0 plus its number, flags in bits 15 to 11), resolved on returning t...
Definition game_state.h:103
s16 sceneChangeReason
the last battle's result; -1 for a defeat
Definition game_state.h:104
s32 selectedActor
the leader: its unit and its actor
Definition game_state.h:59
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 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,...
s32 terrainHeight
16.16 fixed-point pixels
s32 z
16.16 fixed-point pixels
u8 flags
FieldActor.motionFlags: 3 when created, 4 for a placed actor above the ground; zero is free flight in...
s32 x
16.16 fixed-point pixels
s32 y
16.16 fixed-point pixels
An actor a scene places: its sprite, the condition for placing it, how it behaves,...
Definition field_scene.h:81
s32 x
16.16 fixed-point pixels
Definition field_scene.h:91
s16 condition
-1 always, a flag | 0x1000 set, else the flag clear; off the world map, 48 to 127 also need condition...
Definition field_scene.h:87
s32 z
16.16 fixed-point pixels
Definition field_scene.h:93
s32 y
16.16 fixed-point pixels
Definition field_scene.h:92
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
#define UNUSED
Definition types.h:22
s32 fixed
16.16 fixed-point pixels
An object on the field, read as an actor or as an effect.
#define MODE_WORLD_MAP
the world map
Definition object.h:78
void BattleFx_RunVenusDjinnCapture(s32 djinniId)
A Venus Djinni joins the party: it hops twice, spins and leaps, then shrinks away; the leader turns t...
Definition venus.c:15