Alchemy
Loading...
Searching...
No Matches

setup.c

Go to the documentation of this file.
1/// @file
2/// The battle camera each frame, the opening announcement, the unit lists,
3/// and the party's battle state and Djinn as a battle starts and ends.
4/// Part of battle.c, the battle object, compiled only through it.
5
7
8/// Runs each frame of a battle. In a link battle it first checks the link:
9/// a connection lost for more than LINK_MAX_MISSED_FRAMES frames, or a
10/// console whose link number changed, pauses the battle. Then it turns the
11/// camera a sixteenth of the way toward a transition's yaw, places the camera
12/// at its position (or at the one it follows) with its yaw, pitch and
13/// distance, and, unless a transition owns the background, refreshes the
14/// background's perspective. Runs as a scheduler callback (priority 0xc7f)
15/// that Battle_RunEncounter adds. Changes work->linkMisses and linkPaused,
16/// the camera's yaw and the transition's frame count, the transform state,
17/// and through BattleCamera_SetRange the background's affine page.
19 // UB: indexing past scalar gCameraWork reaches other work slots. Named
20 // slots add four bytes in the native EN trial (0xf8 to 0xfc).
21#ifdef UBFIX
22 struct BattleCamera *camera = gCameraWork;
23 struct BattlePresentationTransition *transition =
25 struct BattleWork *work = gBattleWork;
26#else
27 void **slot = (void **)&gCameraWork;
28 struct BattleCamera *camera = slot[0];
29 struct BattlePresentationTransition *transition =
31 struct BattleWork *work = slot[HEAP_SLOT_BATTLE - HEAP_SLOT_CAMERA];
32#endif
33 struct FixedPointPosition eyeOffset;
34 s32 *focus;
35 s16 delta;
36 u32 linkId;
37
38 // The link check: a missed frame counts only while the link is down, and
39 // any frame with it up resets the count.
40 if (work->twoSided != 0) {
42 work->linkMisses++;
44 work->linkPaused = 1;
45 }
46 } else {
47 linkId = SIO_MULTI_PLAYER_ID();
48 if (work->linkSide != linkId) {
49 work->linkPaused = 1;
50 }
51 work->linkMisses = 0;
52 }
53 }
54
55 // Each frame of a turn closes a sixteenth of the gap that remains, so the
56 // camera slows as it nears targetYaw.
57 if (transition->frames != 0) {
58 delta = transition->targetYaw - camera->yaw;
59 delta /= 16;
60 camera->yaw += delta;
61 transition->frames--;
62 }
63
64 focus = camera->pos;
65 if (camera->followPos != 0) {
66 focus = camera->followPos;
67 }
68
73
74 // The eye sits distance behind the focus, along the turned view.
75 eyeOffset.x = 0;
76 eyeOffset.y = 0;
77 eyeOffset.z = camera->distance;
78 Iwram_TransformVector(&eyeOffset.x, (s32 *)camera);
79
80 // The view centred at (120, 120) in 16.16 pixels, at scale 1.
81 if (transition->flag == 0) {
82 BattleCamera_SetRange(0x780000, 0x780000, 0, 0, 0x10000);
83 }
84}
85
86/// Announces the enemies at the start of a battle, then whether the party
87/// strikes first or is caught by surprise. Each of the first enemyCount enemies
88/// gets `<enemy> appeared!`, the last one's message a different line. Called
89/// by BattlePres_RunEntryTransition. Rewrites the message argument tables.
91 s16 enemies[8];
92 struct BattleWork *battle;
93 s16 *enemy;
94 s32 announced;
95
96 battle = gBattleWork;
98 BattleEnemyList(enemies);
99
100 announced = 0;
101 if (enemyCount != 0) {
102 enemy = enemies;
103 do {
105 if (announced == enemyCount - 1)
106 UiText_ShowMessageAndWaitCoreFar(MsgLastEnemyAppeared);
107 else
108 UiText_ShowMessageAndWaitCoreFar(MsgEnemyAppeared);
109 announced++;
111 } while (announced != enemyCount);
112 }
113
115 // Unit 0's name stands for the party in either message.
119 UiText_ShowMessageAndWaitCoreFar(MsgPartyStrikesFirst);
121 } else if (battle->encounterMode == BATTLE_ENCOUNTER_ENEMIES_FIRST) {
124 UiText_ShowMessageAndWaitCoreFar(MsgPartySurprised);
126 }
127}
128
129/// Fills the battle's two unit lists, each ended by BATTLE_UNIT_LIST_END:
130/// the party members in their order, and the enemies, left to right for a
131/// random formation or, for a fixed one, alternating out from the centre
132/// (gBattleParty_CenterOrderOffsets). Called by Battle_RunEncounter as the
133/// battle is set up. Writes gBattleWork->partyUnits and enemyIds, and marks
134/// each party member's side.
136 u16 unitIds[14];
137 struct BattleWork *battle;
138 s32 count;
139 s32 i;
140 s32 position;
141 s32 formation;
142
143 battle = gBattleWork;
144 count = BattleParty_PrepareActiveOwners(unitIds);
145 for (i = 0; i < count; i++)
146 battle->partyUnits[i] = unitIds[i];
147 battle->partyUnits[count] = BATTLE_UNIT_LIST_END;
148
149 // The shuffled and interleaved formations (a link battle's included)
150 // keep the enemies in unit order; the others place the first enemy in
151 // the centre and the rest alternately either side of it.
152 count = BattleEnemyList(unitIds);
153 formation = battle->battleType;
154 if (formation >= FORMATION_SHUFFLED) {
155 if (formation <= FORMATION_INTERLEAVED) {
156 for (i = 0; i < count; i++)
157 battle->enemyIds[i] = unitIds[i];
158 goto done;
159 }
160 }
161 for (i = 0; i < count; i++) {
162 position = gBattleParty_CenterOrderOffsets[i] + count / 2;
163 battle->enemyIds[position] = unitIds[i];
164 }
165done:
166 battle->enemyIds[count] = BATTLE_UNIT_LIST_END;
167}
168
169/// Moves the 16 bytes at VRAM 0x06000290 down to 0x06000280 and clears the
170/// 20 bytes from 0x0600028c. Nothing in the source calls it.
171/// XXX: what the tiles at 0x06000280 are; a caller in another image, or the
172/// picture loaded there, would settle it.
174 Dma_Set((const void *)0x06000290, (void *)0x06000280, DMA_COPY_HALFWORDS(8),
175 REG_DMA3);
176 return Iwram_ClearWords((void *)0x0600028c, 20);
177}
178
179/// Nothing in the source calls it.
181 u32 zero = 0;
182
183 REG_BG0VOFS = zero;
184}
185
186/// Does nothing; Battle_RunEncounter calls it with 1 as the battle is set
187/// up.
189
190/// Clears every battle-only state of the party members (stat stages and
191/// their turns, statuses, Djinn element boosts, the countdowns) and
192/// recalculates their stats, as a battle ends. Called by Battle_RunEncounter
193/// on every way out of the battle.
194#ifdef UBFIX
196#else
198#endif
199 u16 owners[10];
200 s32 count;
201 s32 i;
202
203 count = BattleParty_PrepareActiveOwners(owners);
204
205 i = 0;
206 if (i < count) {
207 struct BattleUnit *unit;
208 u8 *level;
209 s32 remaining;
210
211 do {
212 unit = UnitGetFar(owners[i]);
213
214 // The four element levels, cleared from the last.
215 level = (u8 *)&unit->elementLevels[NUM_ELEMENTS - 1];
216 remaining = NUM_ELEMENTS - 1;
217 do {
218 remaining--;
219 *level-- = 0;
220 } while (remaining >= 0);
221
222 unit->attackTurns = 0;
223 unit->attackStage = 0;
224 unit->defenseTurns = 0;
225 unit->defenseStage = 0;
226 unit->resistanceTurns = 0;
227 unit->resistanceStage = 0;
228 unit->delusion = 0;
229 unit->confusion = 0;
230 unit->charm = 0;
231 unit->stun = 0;
232 unit->sleep = 0;
233 unit->psySeal = 0;
234 unit->refrain = 0;
235 unit->reflect = 0;
236 unit->grimReaper = 0;
237 unit->equipBonus[0] = 0;
238 unit->equipBonus[1] = 0;
239 unit->ready = 0;
240 unit->immobile = 0;
241 unit->agilityTurns = 0;
242 unit->agilityStage = 0;
243 unit->challenge = 0;
244
245 UnitCalcFar(owners[i]);
246 i++;
247 } while (i < count);
248 }
249}
250
251/// Brings the Djinn recovery list up to date as a battle starts: every
252/// Djinni a party member has on standby that the list lacks joins it. Then,
253/// outside a link battle, each Djinni waiting for a battle to end whose
254/// owner has no battle object is Set again and leaves the list. Called by
255/// Battle_RunEncounter once the unit lists and battle objects are in place.
256/// Changes the party's and the opponent's recovery lists and Djinn states.
257#ifdef UBFIX
259#else
261#endif
262 u16 owners[10];
263 s32 count;
264 s32 i;
265 s32 owner;
266 s32 element;
267 s32 djinni;
268
269 count = BattleParty_PrepareActiveOwners(owners);
270
271 // Owners 0 to 7 use the party's list, any other the opponent's.
272 for (i = 0; i < count; i++) {
273 owner = owners[i];
274 for (element = 0; element < NUM_ELEMENTS; element++) {
275 for (djinni = 0; djinni < DJINN_PER_ELEMENT; djinni++) {
276 if (Djinn_IsReadyFar(owner, element, djinni) != 0) {
277 struct DjinnRecoveryList *list =
279 (owner < 0 || owner > 7) ? DJINN_RECOVERY_OPPONENT
281 ->list;
282 s32 j;
283
284 for (j = 0; j < list->count; j++) {
285 if (element == list->entries[j].element &&
286 djinni == list->entries[j].index)
287 break;
288 }
289 if (j == list->count)
290 DjinnRecovery_AddStandbyFar(owner, element, djinni);
291 }
292 }
293 }
294 }
295
296 // Link battles leave the Djinn waiting on the list.
298 return;
299
300 {
301 struct DjinnRecoveryList *list =
304 ->list;
305 struct DjinnRecoveryEntry *entry;
306
307 i = 0;
308 if (i < list->count) {
309 s32 afterBattle = DJINN_RECOVERY_AFTER_BATTLE;
310
311 entry = list->entries;
312 do {
313 if (entry->turns == afterBattle && BattleObjGet(entry->unitId) == 0) {
314 u8 id = entry->unitId;
315 u8 element = entry->element;
316 u8 index = entry->index;
317
320 }
321 i++;
322 entry++;
323 } while (i < list->count);
324 }
325 }
326}
327
328/// The summon ids the mask covers, one bit each.
329#define NUM_SUMMONS 32
330
331/// Works out which summons the party can call: one whose Djinn requirement
332/// of every element is met by the party's Djinn of that element, all
333/// members together. Stores the mask of them (bit n for summon n) and
334/// returns the state that holds it. Called by Battle_RunEncounter as the
335/// battle is set up and at the start of each round. Writes the party
336/// recovery table's availableMask.
338 u8 totals[NUM_ELEMENTS];
339 u16 partyMembers[10];
340 s32 partySize;
341 s32 element;
343
344 partySize = BattleParty_PrepareActiveOwners(partyMembers);
345 availableMask = 0;
346
347 // The party's Djinn of each element.
348 element = 0;
349 do {
350 totals[element] = 0;
351 {
352 s32 partySlot;
353
354 for (partySlot = 0; partySlot < partySize; partySlot++) {
355 struct BattleUnit *member = UnitGetFar(partyMembers[partySlot]);
356
357 totals[element] += member->djinnOwnedCounts[element];
358 }
359 }
360 element++;
361 } while (element < NUM_ELEMENTS);
362
363 // element walks the summon ids here. The inner loop stops at the first
364 // element whose requirement is not met.
365 element = 0;
366 do {
367 const struct SummonDefinition *summon = SummonDefinition_Get(element);
368 s32 elementsMet;
369
370 if (summon != 0) {
371 const u8 *required = summon->djinnRequired;
372
373 elementsMet = 0;
374 if (totals[0] >= required[0]) {
375 u8 *total = totals;
376
377 do {
378 elementsMet++;
379 if (elementsMet >= NUM_ELEMENTS)
380 break;
381 total++;
382 required++;
383 } while (*total >= *required);
384 }
385
386 if (elementsMet == NUM_ELEMENTS)
387 availableMask |= 1u << element;
388 }
389 element++;
390 } while (element < NUM_SUMMONS);
391
392 {
393 struct BattleSummonState *state =
396 return state;
397 }
398}
399
400/// Does nothing; nothing in the source calls it.
void BattleCamera_SetRange(s32 centerX, s32 centerY, s32 offsetX, s32 offsetY, s32 scale)
Builds the perspective plane's next page for a zoom of scale about centerX and centerY (all 16....
Definition background.c:224
s32 BattleEnemyList(s16 *unitIds)
Lists the enemy units present, ended by BATTLE_UNIT_LIST_END, and returns how many there are (0 when ...
Definition encounter.c:401
s32 BattleParty_PrepareActiveOwners(u16 *owners)
Lists the party members who fight (the first four of the party, three in a link battle) and marks eac...
Definition encounter.c:371
s32 BattlePresentation_WaitForAdvance(void)
Shows the bobbing arrow at the message window and waits for the player to go on (B,...
Definition events.c:90
struct BattleObj * BattleObjGet(s32 unitId)
Returns unitId's battle object, through its place, or null for a unit with no place.
Definition objects.c:480
#define NUM_SUMMONS
The summon ids the mask covers, one bit each.
Definition setup.c:329
void BattleParty_CollectUnitList(void)
Fills the battle's two unit lists, each ended by BATTLE_UNIT_LIST_END: the party members in their ord...
Definition setup.c:135
void BattleIntro_AnnounceEncounter(s32 enemyCount)
Announces the enemies at the start of a battle, then whether the party strikes first or is caught by ...
Definition setup.c:90
s32 BattlePresentation_InitializeTilePattern(void)
Moves the 16 bytes at VRAM 0x06000290 down to 0x06000280 and clears the 20 bytes from 0x0600028c.
Definition setup.c:173
void BattlePresentation_UpdateCamera(void)
Runs each frame of a battle.
Definition setup.c:18
struct BattleSummonState * BattleSummon_UpdateAvailability(void)
Works out which summons the party can call: one whose Djinn requirement of every element is met by th...
Definition setup.c:337
void Party_ReservedNoOp5B14(s32 unused)
Does nothing; Battle_RunEncounter calls it with 1 as the battle is set up.
Definition setup.c:188
s32 BattleParty_ReconcileDjinnRecovery(void)
Brings the Djinn recovery list up to date as a battle starts: every Djinni a party member has on stan...
Definition setup.c:260
s32 BattleParty_ResetActiveRuntimeFields(void)
Clears every battle-only state of the party members (stat stages and their turns, statuses,...
Definition setup.c:197
void BattlePresentation_ClearBg0VerticalOffset(void)
Nothing in the source calls it.
Definition setup.c:180
void BattleSummon_ReservedNoOp(void)
Does nothing; nothing in the source calls it.
Definition setup.c:401
s8 gBattleParty_CenterOrderOffsets[]
struct BattleCamera * gCameraWork
What every part of the battle object shares: its includes, in their original order,...
#define VALUE_UNIT_NAME
#define FORMATION_INTERLEAVED
#define DJINN_RECOVERY_OPPONENT
#define DJINN_RECOVERY_AFTER_BATTLE
DjinnRecoveryEntry.turns of a Djinni waiting for the battle to end.
#define FORMATION_SHUFFLED
BattleWork.battleType, from the enemy formation (BattleFormation_BuildEnemyList): the random formatio...
#define SIO_MULTI_PLAYER_ID()
This console's number in a link session (SIOCNT bits 4 and 5, which the hardware sets in multi-player...
#define DJINN_RECOVERY_PARTY
The Djinn recovery list's two tables (Djinn_GetRecoveryTableFar): the party's and the link opponent's...
#define LINK_MAX_MISSED_FRAMES
The frames a link battle tolerates without a connection before it gives up.
#define LINK_BOTH_CONNECTED
gLinkStatus: both consoles are connected.
#define DJINN_PER_ELEMENT
@ BATTLE_ENCOUNTER_ENEMIES_FIRST
@ BATTLE_ENCOUNTER_PARTY_FIRST
@ BATTLE_UNIT_LIST_END
ends the list
@ NUM_ELEMENTS
Definition battle_unit.h:41
struct BattleWork * gBattleWork
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
struct BattleUnit * UnitGetFar(u32 owner)
s32 GameFlag_TestFar(s32 flag)
u32 * DjinnRecovery_AddStandbyFar(u32 kind, u32 first, u32 second)
void * Djinn_GetRecoveryTableFar(s32 arg0)
s32 DjinnRecovery_RemoveFar(s32 owner, s32 index, s32 bit)
const struct SummonDefinition * SummonDefinition_Get(u32 summon_id)
Far call to SummonDefinition_GetNear.
s32 Djinn_IsReadyFar(s32 owner, s32 index, s32 bit)
s32 Djinn_ActivateFar(s32 owner, s32 index, s32 bit)
void UnitCalcFar(s32 owner)
void UiWork_FinalizeSharedSlotFar(void)
void UiWork_PushValueSlotFar(u32 value, u32 kind)
void UiText_ShowMessageAndWaitCoreFar(s32 argument)
void UiWork_ClearValueNameTablesFar(void)
#define FLAG_LINK_BATTLE
Definition flags.h:68
@ HEAP_SLOT_BATTLE_BACKGROUND
Definition heap_state.h:45
@ HEAP_SLOT_CAMERA
Definition heap_state.h:38
@ HEAP_SLOT_BATTLE
Definition heap_state.h:37
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
Definition heap_state.h:14
#define DMA_COPY_HALFWORDS(n)
Definition io_reg.h:227
#define REG_BG0VOFS
Definition io_reg.h:262
#define REG_DMA3
Definition io_reg.h:153
static s32 Iwram_TransformVector(const void *vector, s32 *result)
Definition iwram_call.h:65
static s32 Iwram_ClearWords(void *destination, s32 size)
Definition iwram_call.h:55
volatile u16 gLinkStatus
Link status, updated by the VBlank exchange handler.
The battle camera: its eye, the focus it turns about, and its pitch, yaw and distance.
u16 pitch
1/65536 turns
s32 distance
eye to focus, 16.16 fixed-point pixels
u16 yaw
1/65536 turns
s32 * followPos
when set, the focus followed instead of pos
s32 pos[3]
the focus, 16.16 fixed-point pixels
The battle background's work slot as the camera reads it: the yaw the camera eases toward and the fra...
s32 frames
frames left to ease the yaw, a sixteenth a frame
s32 flag
0 lets the camera update set the background's range each frame; 1 for a critical hit's zoom and once ...
The party's Djinn recovery table as summons read it: the mask of summons the party can call,...
u32 availableMask
nonzero offers the Summon command
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 agilityTurns
the Agility change's turns left, 5 when cast
u8 immobile
set by Ground: the next action is lost
s8 elementLevels[4]
A summon's boost to each element: the Djinn of that element the summon spent, adding (n * n + n) * 5 ...
u8 djinnOwnedCounts[4]
the Djinn held in each element, at most 10
u8 grimReaper
The Grim Reaper's countdown: 7 when cursed, down one at each turn's end; at 0 the unit falls.
u8 psySeal
bits: 7..3 Luff (16 when cast, minus 8 a turn) | 2..0 Bind's turns (7 when cast).
struct BattleElementStats element[4]
Power and resistance in each element, 0 to 200, after equipment, element levels and Resistance stages...
s8 challenge
Set by the challenge effect: an enemy with it never chooses to flee.
s8 agilityStage
The Agility stage: -4 (Vine) to 8 (Zephyr, twice the Agility).
u8 refrain
Regenerate's turns left, 7 when cast.
s8 reflect
Reflect's turns left, 7 when cast.
u8 equipBonus[2]
The totals of equipment effects 23 (unleash chance) and 24 that UnitCalc sums; TBS never reads them b...
u8 level
1 to 99 for a character
u8 attackTurns
Each stat change: the turns it has left, and its stage (UnitCalc: an eighth of Attack,...
u8 delusion
Delusion to sleep: the turns each status has left, 7 when it lands; each may end sooner at the end of...
u8 ready
Kite's extra action: 2 when cast, down one at each turn's end; while nonzero UnitCalc gives the unit ...
The battle's own work: its enemies, units and their objects, the turn's actions, the spoils,...
Definition battle_work.h:71
u8 twoSided
1 in a link battle
Definition battle_work.h:90
u8 encounterMode
BATTLE_ENCOUNTER_: who strikes first.
Definition battle_work.h:91
s16 partyUnits[7]
ends with BATTLE_UNIT_LIST_END
u8 battleType
FORMATION_SHUFFLED or FORMATION_INTERLEAVED.
Definition battle_work.h:87
u8 linkPaused
set when the link drops or the console's id changes
u8 linkSide
this console's multiplayer id
Definition battle_work.h:98
u8 linkMisses
frames the link has been down
Definition battle_work.h:99
s16 enemyIds[BATTLE_ENEMY_CAPACITY+1]
ends with BATTLE_UNIT_LIST_END
A Djinni on standby or recovering: its element and index, its owner, and the turns until it is set ag...
u8 unitId
its owner
s8 turns
Turns until it is set again; -1 on standby (DJINN_RECOVERY_AFTER_BATTLE), -2 while a summon uses it.
u8 element
enum Element
u8 index
the Djinni within its element, 0 to 19
One side's Djinn recovery list: up to 64 entries and their count.
struct DjinnRecoveryEntry entries[64]
s32 count
entries in use
One side's Djinn recovery table, as Djinn_GetRecoveryTable returns it.
struct DjinnRecoveryList list
A position in three coordinates, each in 16.16 fixed point.
s32 z
16.16 fixed point
s32 x
16.16 fixed point
s32 y
16.16 fixed point
A summon: its name's message and the Djinn of each element it needs.
u8 djinnRequired[4]
standby Djinn needed, by element
void SceneTransform_ApplyYaw(s32 angle)
Rotates gTransform about the Y axis by angle.
Definition transform.c:113
void SceneTransform_ApplyPitch(s32 angle)
Rotates gTransform about the X axis by angle.
Definition transform.c:97
void SceneTransform_ApplyPosition(const s32 *position)
Translates gTransform by position (x, y, z in 16.16).
Definition transform.c:145
void Render_ResetTransformState(void)
Allocates the one-level save area (heap slot HEAP_SLOT_TRANSFORM_STACK), clears gTransformStackDepth ...
Definition transform.c:19
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