Alchemy
Loading...
Searching...
No Matches

setup.c

Go to the documentation of this file.
1/// @file
2/// An effect's work: setting it up, its caster and target, cleaning up.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7/// Scheduler callback: updates the 24 effect slots.
8void BattleFx_UpdateAllEffectSlots(void) { FieldFx_UpdateSceneSlots(); }
9
10/// Prepares the work of the Psynergy effect for ability (heap slot 56) and
11/// loads its spark tiles. Called again while an effect resolves, it only
12/// switches the ability.
14 struct FieldWork *ev = *(gWorkSlot + HEAP_SLOT_EVENT);
15 struct MapScrollWork *map = *(gWorkSlot + 8);
16 struct BattleFxScene *work;
17 s32 running;
18
19 running = ev->resolvingAction;
20 if (running == 0) {
21 work = Runtime_AllocateHeapBlock(HEAP_SLOT_FX, sizeof *work);
22 Dma_Fill32(running, work, sizeof *work);
23 } else {
24 work = *(gWorkSlot + HEAP_SLOT_FX);
25 }
26 work->action = abilityId;
27 work->fieldKind = BattleActGet(abilityId)->type0c;
28 running = ev->resolvingAction;
29 if (running != 0)
30 return;
32 work->mode = mode;
33 work->visible = 1;
34 work->enabled = 1;
35 work->active = 1;
36 work->messageMode = 1;
37 // Keep the map's shake and its decay, to restore after the effect.
38 work->savedShakeX = map->shakeX;
39 work->savedShakeY = map->shakeY;
40 work->savedShakeDecay = map->shakeDecay;
42 work->lit = 1;
44 work->lit = 1;
46 if (work->fieldKind != FIELD_KIND_REVEAL)
47 ev->effectTimerRunning = running;
51}
52
53/// Records the caster and the target of an effect. With no target, the effect
54/// takes place 16 pixels in front of the caster (facing to the nearest
55/// quarter turn).
56void BattleFx_SetupObjectPair(s32 userId, s32 targetId) {
57 struct ScriptMotionObject *user;
58 struct ScriptMotionObject *target;
59 s32 dir;
60 struct BattleFxScene *work;
61
62 work = gEffectWork;
63 work->firstObjectId = userId;
64 user = ObjectTable_Get((s16)userId);
65 work->secondObjectId = targetId;
66 work->mainObject = user;
67 target = ObjectTable_Get((s16)targetId);
68 dir = (user->facing + 0x2000) & 0xc000; // to the nearest quarter turn
69 work->child = target;
70 work->angle = dir;
71 if (target != NULL) {
72 // Keep the target's motion and colours, to restore them later.
73 work->savedCallback = target->hook;
74 work->savedScript = (const s32 *)target->script;
75 {
76 struct AnimationObject *anim =
77 ((struct ObjectRuntime *)target)->animation;
78 u8 pal = anim->entries[0]->param;
79
80 work->savedPalette = pal;
81 }
82 work->x = target->x;
83 work->z = target->z;
84 work->y = target->y;
85 return;
86 }
87 work->x = user->x;
88 work->z = user->z;
89 work->y = user->y;
90 Vector_AddPolarOffset(0x100000, dir, &work->x);
91}
92
93/// Stops the caster's per-frame hook and restores its colours.
95 struct BattleFxScene *work = gEffectWork;
96 struct ScriptMotionObject *user = work->mainObject;
97
98 user->hook = NULL;
100 WaitFrames(1);
101}
102
103#define SETUP_OBJECT_SLOTS ((struct ScriptMotionObject *)gObjectSlots)
104
105/// Ends a Psynergy effect: frees the effect slots still in use and, unless
106/// another effect is being resolved, waits (at most 30 frames) for the
107/// swelling arcs to end, stops the slot callback, releases the effect's
108/// tiles, restores the map's shake, plays the queued sound and releases the
109/// effect's work.
111#ifndef UBFIX
112 struct BattleFxScene **sceneCell;
113#endif
114 struct BattleFxScene *scene;
115 struct FieldWork *runtime;
116 struct MapScrollWork *map;
117 struct EffectSlot *sceneObject;
118 s32 remaining;
119
120#ifdef UBFIX
121 scene = gEffectWork;
122 runtime = (struct FieldWork *)gEventWork;
123 map = gMapWork[0];
124#else
125 // Indexing beyond the scalar global is undefined in C. Named slots add
126 // 8 bytes to this function in the forced native EN build (0xf8 -> 0x100).
127 sceneCell = (struct BattleFxScene **)&gEffectWork;
128 scene = *sceneCell;
129 runtime = *(struct FieldWork **)((u8 *)sceneCell - 116);
130 map = *(struct MapScrollWork **)((u8 *)sceneCell - 192);
131#endif
132 for (remaining = 0; remaining < 24; remaining++) {
133 sceneObject = &scene->slots[remaining];
134 if (sceneObject->active != 0)
135 BattleFx_ClearOwnedSlot(sceneObject);
136 }
137
138 if (runtime->resolvingAction == 0) {
139 s32 waited = 0;
140 void (*firstActiveUpdate)(union FieldObject *) =
142 void (*secondActiveUpdate)(union FieldObject *) =
144 s32 active;
145
146 do {
148
149 active = 0;
150 remaining = 0;
151 while (remaining <= 63) {
152 void (*update)(union FieldObject *) = slot->hook;
153
154 if (update == firstActiveUpdate || update == secondActiveUpdate) {
155 active = 1;
156 break;
157 }
158 remaining++;
159 slot++;
160 }
161
162 if (active != 0) {
163 waited++;
164 WaitFrames(1);
165 }
166 } while (active != 0 && waited <= 29);
167
168 runtime->castStarted = 0;
171 map->shakeX = scene->savedShakeX;
172 map->shakeY = scene->savedShakeY;
173 map->shakeDecay = scene->savedShakeDecay;
174 if (scene->fieldKind != FIELD_KIND_REVEAL)
175 runtime->effectTimerRunning = 1;
178 }
179}
180
181/// Starts casting: the caster takes its casting pose (animation 20) and
182/// stops. Unless the effect is silent the caster flashes with a sound; unless
183/// it is quiet, the ability's name is shown while every other object stands
184/// still. With flag 0x140 the caster's colours keep cycling and it
185/// takes pose 21; otherwise the caster's hook stops.
187 s32 ability;
188 s32 announcedAbility;
189 struct FieldActor *caster;
190 struct BattleFxScene *scene;
191 void *renderState;
192
193 scene = *(void **)Ram_EffectWork;
194 renderState = *(void **)Ram_EventWork;
195 caster = scene->mainObject;
196 ability = (s16)scene->action;
197 announcedAbility = ability;
199 caster->targetX = caster->x.fixed;
200 caster->targetY = caster->y.fixed;
201 caster->targetZ = caster->z.fixed;
202 SET_VELOCITY(caster, 0, 0, 0);
203 if (scene->visible != 0) {
206 }
207 if (scene->active != 0) {
208 ObjectGroup_SetActionForOthers((struct ObjectRuntime *)caster, 1, 0);
209 UiWork_PushValueSlotFar(announcedAbility, 4);
210 // The mode branches currently show the same message. Merging them shrinks
211 // the native English function by 32 bytes, so keep this existing form.
212 if ((s8)scene->mode != 0) {
214 scene->messageMode);
215 } else {
217 scene->messageMode);
218 }
219 ObjectGroup_SetActionForOthers((struct ObjectRuntime *)caster, 0, 0x10);
220 }
221 if (GameFlag_TestFar(0x140) != 0) {
222 if (scene->visible != 0) {
224 }
226 } else {
228 }
229 ((struct FieldWork *)renderState)->castStarted = 1;
230}
231
232/// Saves the palettes for the effect (once, unless an effect is already
233/// shown) and fades them toward one of the eight effect colours
234/// (gBattleFx_TargetColors), picked by the frame counter or forced by flags
235/// 0x148 to 0x14f, over 8 frames.
237 u8 *scene;
238 struct BattleEffectBuffers *work;
239 s32 no;
240
241 scene = *(gWorkSlot + HEAP_SLOT_EVENT);
242 work = *(gWorkSlot + 32);
243 Dma_Set(&work->target[0x2a0], scene + 0x776,
244 (DMA_ENABLE | DMA_32BIT) << 16 | 0x150, REG_DMA3);
245 if (((struct FieldWork *)scene)->revealActive == 0)
246 Dma_Set(work->target, scene + 0x236, (DMA_ENABLE | DMA_32BIT) << 16 | 0x150,
247 REG_DMA3);
248 Dma_Set(work->target, work->current,
249 (DMA_ENABLE | DMA_32BIT) << 16 | (sizeof work->current / 4),
250 REG_DMA3);
251
252 no = gFrameCount & 7;
253 if (GameFlag_TestFar(0x148))
254 no = 0;
255 if (GameFlag_TestFar(0x149))
256 no = 1;
257 if (GameFlag_TestFar(0x14a))
258 no = 2;
259 if (GameFlag_TestFar(0x14b))
260 no = 3;
261 if (GameFlag_TestFar(0x14c))
262 no = 4;
263 if (GameFlag_TestFar(0x14d))
264 no = 5;
265 if (GameFlag_TestFar(0x14e))
266 no = 6;
267 if (GameFlag_TestFar(0x14f))
268 no = 7;
271}
272
273/// Fades the palettes back from an effect's colours to the saved ones (or to
274/// palette 0x10001 while an effect is shown) over 8 frames.
276 s32 savedPalettes;
277 u8 *field;
278
279 field = (u8 *)gEventWork;
280 savedPalettes = (s32)(field + 0x236);
281 BattleFx_ApplyColorToTargetBuffer(savedPalettes, 2);
282 if (((struct FieldWork *)field)->revealActive != 0) {
284 } else {
285 BattleFx_ApplyColorToTargetBuffer(savedPalettes, 1);
286 }
288}
289
290/// Converts a world position (16.16 pixels) to the screen: x and z receive
291/// the screen's x and y and y becomes 0. The world map uses its perspective
292/// projection.
293void Camera_WorldToScreen(struct EffectVector *position) {
294#ifdef UBFIX
295 struct FieldWork *event = (struct FieldWork *)gEventWork;
296
297 if (event->mode == MODE_WORLD_MAP) {
298#else
299 struct FieldWork **eventCell = (struct FieldWork **)&gEventWork;
300
301 if ((*eventCell)->mode == MODE_WORLD_MAP) {
302#endif
303 s32 result[3];
304
305 Render_ProjectPoint(position, result);
306 position->x = result[0] << 16;
307 position->z = result[1] << 16;
308 position->y = 0;
309 } else {
310#ifdef UBFIX
311 struct MapScrollWork *state = gMapWork[0];
312#else
313 // The named map slot avoids stepping outside gEventWork. In forced native
314 // EN it replaces the address copy/subtract with a separate literal load
315 // and changes register allocation; the extent remains 0x68 bytes.
316 struct MapScrollWork *state =
317 *(struct MapScrollWork **)((u8 *)eventCell - 76);
318#endif
319 s32 x = state->viewX & 0xffff0000;
320 s32 z = state->viewY & 0xffff0000;
321
322 position->x -= x;
323 position->z -= position->y;
324 position->z -= z;
325 position->y = 0;
326 }
327}
328
329// From here on positions are passed in each function's own structures.
330
331#undef SETUP_OBJECT_SLOTS
void * ObjectTable_Get(u32 actorIndex)
Returns the actor in slot index (0 to 65), or NULL.
Definition actors.c:462
void BattleFx_FlickerObjectAndTick(union FieldObject *fieldObject)
Per-frame update: flashes an object between sprite param 7 and 0 every 2 frames and spawns the swelli...
Definition arcs.c:134
void FieldFx_CycleObjectValueByCounter(union FieldObject *fieldObject)
Per-frame update: cycles an object through sprite params 0 to 5, one step every 2 frames,...
Definition arcs.c:148
void FieldFx_UpdateScaledArcObjectA(union FieldObject *fieldObject)
Per-frame update of arc A: over 32 frames it swells and shrinks again (scale sin(frame / 64 turn)) wh...
Definition arcs.c:11
void FieldFx_UpdateScaledArcObjectB(union FieldObject *fieldObject)
Per-frame update of arc B: arc A upside down, 16 pixels in front of the object and up to 5 pixels nea...
Definition arcs.c:36
const u8 gBattleFx_SparkTiles[]
const s32 gBattleFx_TargetColors[]
void BattleFx_ApplyColorToTargetBuffer(s32 mode, s32 half)
Sets the colours the buffer moves toward (see BattleFx_BuildBuffer); does nothing without a colour bu...
Definition color.c:398
void BattleFx_StartBufferInterpolation(s32 frames)
Starts moving the shown colours to the target colours over frames frames: sets work->duration,...
Definition color.c:431
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
Definition dma.h:62
#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.
void ObjectDispatch_SelectAnimationFar(void *raw, s32 no)
void Animation_ApplyChildValuesFar(struct DispatchObject *obj, u32 val)
s32 GameFlag_TestFar(s32 flag)
struct BattleAct * BattleActGet(s32 actionId)
Far call to BattleAction_GetDirect.
void AudioCommand_PlayFar(s32 id)
void UiText_ShowPositionedMessageAndWaitFar(s32 no, s32 flags)
void UiWork_PushValueSlotFar(u32 value, u32 kind)
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.
struct GameState gGameState
void * gMapWork[]
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
@ HEAP_SLOT_EVENT
Definition heap_state.h:40
#define DMA_32BIT
Definition io_reg.h:210
#define REG_DMA3
Definition io_reg.h:153
#define DMA_ENABLE
Definition io_reg.h:217
#define SET_VELOCITY(p, vx, vy, vz)
Definition macros.h:18
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 ObjectGroup_SetActionForOthers(struct ObjectRuntime *except, s32 state, s32 value)
Sets the movement state and animation timer steps of every object but the player's and except.
Definition dispatch.c:395
s32 ResourceTable_CountFreeBlocks(void)
Counts the free blocks (owner 0xff) of the 512 resource blocks.
Definition dispatch.c:324
void BattleFx_UpdateAllEffectSlots(void)
Scheduler callback: updates the 24 effect slots.
Definition setup.c:8
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
void BattleFx_SetupObjectPair(s32 userId, s32 targetId)
Records the caster and the target of an effect.
Definition setup.c:56
void EffectRuntime_StopCurrentObject(void)
Stops the caster's per-frame hook and restores its colours.
Definition setup.c:94
void BattleEffect_CleanupSceneObjects(void)
Ends a Psynergy effect: frees the effect slots still in use and, unless another effect is being resol...
Definition setup.c:110
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
#define SETUP_OBJECT_SLOTS
Definition setup.c:103
void EventObject_Initialize(void)
Starts casting: the caster takes its casting pose (animation 20) and stops.
Definition setup.c:186
void BattleFx_LoadActionEffectResources(s32 abilityId, s32 mode)
Prepares the work of the Psynergy effect for ability (heap slot 56) and loads its spark tiles.
Definition setup.c:13
@ FIELD_KIND_REVEAL
What every part of psynergy_effects.c shares: its includes and the macros and types more than one par...
#define HEAP_SLOT_FX
the Psynergy effect's work (gWorkSlot[56], gEffectWork)
#define Ram_EventWork
Definition ram_buffer.h:50
#define Ram_EffectWork
Definition ram_buffer.h:54
void BattleFx_PlayQueuedSound(void)
Plays the sound BattleFx_SetQueuedSoundAndPlay remembered, if any.
Definition requests.c:102
char SceneId_MercuryLighthouseEntrance
char SceneId_MercuryLighthouse2
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_212
Definition songs.h:207
struct EventWork * gEventWork
#define NULL
Definition bilibin.h:6
void * gWorkSlot[]
u8 param
SpriteColorMode its pixels are drawn with; 0 when taken.
Definition animspr.h:45
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationEntry * entries[4]
its layers; empty ones null
Definition animspr.h:130
u8 type0c
The field Psynergy the ability works as, 1 (Move) to 16 (Avoid); 0 for none.
The colour buffer (heap block 32) that fades the BG and OBJ palettes: the source palette,...
Definition palbuf.h:40
u16 current[0x540]
The shown colours, as B, G and R channels shifted up 10 bits, three a colour.
Definition palbuf.h:46
u16 target[0x540]
the colours current moves toward, as current
Definition palbuf.h:47
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
u16 freeBlocks
512 less the free resource blocks at the start
Definition fx_scene.h:66
u8 mode
where the effect runs; MODE_WORLD_MAP on the world map
Definition fx_scene.h:45
s32 y
16.16 fixed-point pixels
Definition fx_scene.h:34
s32 savedShakeDecay
Definition fx_scene.h:71
s16 firstObjectId
the caster's object id
Definition fx_scene.h:38
u16 action
the ability id
Definition fx_scene.h:40
void(*) savedCallback(union FieldObject *object)
The target's update hook and script, saved at the start and restored when Move or Carry lets it go.
Definition fx_scene.h:58
s8 visible
set at the start: the caster flashes with a sound
Definition fx_scene.h:46
u8 savedPalette
the target's first sprite's param, saved likewise
Definition fx_scene.h:62
s32 angle
1/65536 turns
Definition fx_scene.h:32
struct EffectSlot slots[24]
Definition fx_scene.h:73
const s32 * savedScript
Definition fx_scene.h:59
u16 tileSlot
resource entry holding the spark tiles
Definition fx_scene.h:64
void * mainObject
the caster's object
Definition fx_scene.h:36
s32 savedShakeX
The map's shake and its decay, restored when the effect ends.
Definition fx_scene.h:69
u8 lit
set in two Mercury Lighthouse maps; not read by name
Definition fx_scene.h:63
s16 fieldKind
the ability's field kind (FIELD_KIND_)
Definition fx_scene.h:41
s8 messageMode
the announcement's box mode: 1, a scene adds 8
Definition fx_scene.h:76
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 savedShakeY
Definition fx_scene.h:70
s32 x
16.16 fixed-point pixels
Definition fx_scene.h:33
s8 active
set at the start: the ability's name is announced
Definition fx_scene.h:47
s32 z
16.16 fixed-point pixels
Definition fx_scene.h:35
s16 secondObjectId
the target's object id, -1 for none
Definition fx_scene.h:39
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
s8 active
nonzero while the slot is in use
Definition effect_slot.h:44
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
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
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
s32 targetY
16.16 fixed-point pixels; ACTOR_NO_TARGET when unset
Definition field_obj.h:60
void(*) update(union FieldObject *object)
Called each frame before the object's script, while the object is live.
Definition field_obj.h:116
Full event work allocated by Field_RunScene (heap slot 27).
s8 resolvingAction
set while Psynergy takes effect
s16 event
A raised event for Scene_RunRaisedEvent, or -1 when characters fell to poison or hazard damage,...
s16 effectTimerRunning
Nonzero lets the Reveal countdown advance; menus and other effects pause it.
s8 castStarted
set once a cast has been announced
s16 map
the scene's map; SceneId_Clear for the world map
Definition game_state.h:49
s32 selectedActor
the leader: its unit and its actor
Definition game_state.h:59
The field map's work: the followed position, screen shake, tile animations, blend script,...
Definition map_scroll.h:27
s32 viewY
the view's top left, 16.16 fixed-point pixels
Definition map_scroll.h:40
s32 shakeX
Screen shake amplitudes in 16.16 fixed-point pixels, and the 16.16 factor that scales them each frame...
Definition map_scroll.h:33
One of the 64 field objects in the object pool (heap slot 5): its script, position,...
void * animation
its sprite, or its list of four, by animationKind
A field object as the motion code sees it: its script, position, motion toward a target,...
s32 x
16.16 fixed-point pixels
void(*) hook(union FieldObject *object)
Called each frame before its script.
u16 facing
1/65536 turns
const ScriptMotionWords * script
null when the object is free
s32 y
16.16 fixed-point pixels
s32 z
16.16 fixed-point pixels
s32 Render_ProjectPoint(const void *point, s32 *screen)
Reads three word-aligned coordinates from point, transforms them by gTransform and projects them to t...
Definition transform.c:364
signed int s32
Definition types.h:14
signed char s8
Definition types.h:10
signed short s16
Definition types.h:12
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.
#define MODE_WORLD_MAP
the world map
Definition object.h:78
s32 Resource_ResetEntry(u32 no)
Frees cache entry no: its blocks go back and the entry is marked free (offset 0xffff).
Definition vram_cache.c:106
s32 Resource_FindFreeEntry(void)
Returns the number of the first free cache entry, or VRAM_CACHE_ENTRY_COUNT when all are taken.
Definition vram_cache.c:211
s32 VramCache_Load(u32 no, u32 size, const void *src)
Gives cache entry no size bytes of sprite VRAM and copies src there.
Definition vram_cache.c:143