Alchemy
Loading...
Searching...
No Matches

classes.c

Go to the documentation of this file.
1/// @file
2/// Element levels and classes.
3/// Part of game.c, the game object, compiled only through it.
4
5#include "../game_internal.h"
6
7/// The elemental power and resistance of one element level.
9 u16 power; ///< base power, before the tenths of a level
10 u16 res; ///< base resistance, likewise
11};
12
14
15/// Returns the class series of a character whose strongest element is
16/// `primaryElement` and second `secondaryElement`, from the 4 by 4 table.
17/// Called by Class_Determine.
18s32 Class_GetSeries(s32 primaryElement, s32 secondaryElement) {
19 return gOwner_FourColumnValues[(primaryElement * 4) + secondaryElement];
20}
21
22/// Writes ten times each element level to `output`: an enemy's from its
23/// element preset, a character's from the Djinn set on it (`source` is its
24/// Djinn bits) plus its own element bonus. Called by Class_Determine,
25/// Unit_GetElementLevel and Unit_CalcBaseElements.
26s32 Unit_GetElementLevels(s32 record, const u8 *source, s32 output[4]) {
27 s32 i;
28 s32 *cursor;
29
30 if (record > 7) {
31 u32 index;
32
33 index = ((const struct EnemyDefinition *)Enemy_GetDefinition(record))
35 if (index > 43)
36 index = 0;
37
38 i = 0;
39 cursor = output;
40 for (; i < NUM_ELEMENTS; i++)
41 *cursor++ = gEnemy_ElementPresetTable[index].digits[i] * 10;
42 } else {
43 cursor = output;
44 // `source` points at the unit's Djinn bits; the counts of set Djinn by
45 // element follow them in the unit.
46 source += (u8 *)&((struct BattleUnit *)0)->djinnActiveCounts -
47 (u8 *)&((struct BattleUnit *)0)->djinnAvailable;
48 for (i = 3; i >= 0; i--) {
49 u32 value = *source;
50 source++;
51 *cursor++ = value * 10;
52 }
53
54 if (record <= 7) {
55 for (i = 0; i < NUM_ELEMENTS; i++) {
56 *output += Character_GetDefinition(record)->elementBonus[i];
57 output++;
58 }
59 }
60 }
61
62 return 0;
63}
64
65/// Returns a unit's level in `element` (0 to 3). Called by the two status
66/// screens to show the element levels, and by Battle_IsReviveEffect.
68 struct BattleUnit *unit = UnitGet(owner);
70 s32 result = 0;
71
72 if (element < NUM_ELEMENTS) {
75 result = elementLevels[element] / 10;
76 }
77 return result;
78}
79
80/// Returns the element an enemy attacks with, from its element preset. Called
81/// by Item_GetEquippedElement for an enemy, which has no weapon.
83 const struct EnemyDefinition *enemy =
84 (const struct EnemyDefinition *)Enemy_GetDefinition(unit->classId);
85 u8 presetIndex = enemy->elementPreset;
86
87 if (presetIndex > 43)
88 presetIndex = 0;
89 return gEnemy_ElementPresetTable[presetIndex].first;
90}
91
92// Writes a unit's base power and resistance in each element: an enemy's come
93// from its preset, a character's from its element levels.
94// Both callers ignore the result. The matching return type preserves r0;
95// plain void changes the two return instructions (tbs-en: differ 4).
96// Its array view keeps the table-address addition after the first store;
97// using the typed fields in that build differs 2 in tbs-en.
98#ifdef UBFIX
99void Unit_CalcBaseElements(s32 owner, struct BattleElementStats *destination) {
100#else
101u32 Unit_CalcBaseElements(s32 owner, s16 destination[4][2]) {
102#endif
103 struct BattleUnit *state = UnitGet(owner);
104 u32 index;
105 s32 values[4];
106 s32 i;
107
108 if (state->classIndex == 0) {
109 index =
110 ((const struct EnemyDefinition *)Enemy_GetDefinition(state->classId))
112 if (index > 43)
113 index = 0;
114
115#ifdef UBFIX
116 // Copy the packed pairs without accessing halfword members as words.
117 memcpy(destination, gEnemy_ElementPresetTable[index].values,
118 sizeof(gEnemy_ElementPresetTable[index].values));
119 return;
120#else
121 i = 0;
122 for (;;) {
123 ((s32 *)destination)[i] = gEnemy_ElementPresetTable[index].values[i];
124 i++;
125 if (i > 3) {
126 return index;
127 }
128 }
129#endif
130 }
131
132 Unit_GetElementLevels(state->classId, (u8 *)state->djinnAvailable, values);
133 for (i = 0; i < NUM_ELEMENTS; i++) {
134 s32 value;
135 s32 ones;
136 s32 tens;
137
138 value = values[i];
139 ones = value % 10;
140 tens = value / 10;
141
142 if (tens > 15)
143 tens = 15;
144 if (tens < 0)
145 tens = 0;
146
147#ifdef UBFIX
148 destination[i].power = gElement_PowerResistByLevel[tens].power + ones;
149 destination[i].resistance = gElement_PowerResistByLevel[tens].res + ones;
150#else
151 destination[i][0] = gElement_PowerResistByLevel[tens].power + ones;
152 destination[i][1] = gElement_PowerResistByLevel[tens].res + ones;
153#endif
154 }
155}
156
157/// Returns the class a character has with `djinn` set: the series is chosen by
158/// its two strongest elements, and the class is the last of the series whose
159/// element requirements it meets. Isaac and Garet as children and Jenna have
160/// fixed classes. Called by Unit_UpdateClass.
161s32 Class_Determine(s32 character, const u8 *djinn) {
162 s32 levels[4];
163 s32 primary;
164 s32 best;
165 s32 series;
166 s32 result;
167 s32 j;
168 s32 i;
169
170 result = -1;
171 if (character > 7)
172 return 0;
173 Unit_GetElementLevels(character, djinn, levels);
175 if (character == ISAAC)
176 return 200;
177 if (character == GARET)
178 return 201;
179 }
180 if (character == JENNA)
181 return 202;
182 if (result != -1)
183 return result;
184 best = result;
185 primary = result;
186 for (i = 0; i < NUM_ELEMENTS; i++) {
187 if (best < levels[i]) {
188 best = levels[i];
189 primary = i;
190 }
191 }
192 j = -1;
193 best = -1;
194 for (i = 0; i < NUM_ELEMENTS; i++) {
195 if (i != primary && best < levels[i]) {
196 best = levels[i];
197 j = i;
198 }
199 }
200 // A second element below level 1 does not count: the series is then the
201 // primary element's alone.
202 series = Class_GetSeries(primary, levels[j] > 9 ? j : primary);
203 // The last class of the series that the element levels reach.
204 for (i = 202; i >= 0; i--) {
205 if (gClass_DefinitionTable[i].series != series)
206 continue;
207 for (j = 0; j < NUM_ELEMENTS; j++) {
208 if (levels[j] < gClass_DefinitionTable[i].required[j] * 10)
209 break;
210 }
211 if (j == 4) {
212 result = i;
213 break;
214 }
215 }
216 if (result == -1)
217 result = 0;
218 return result;
219}
220
221/// Returns class `classId`'s definition: its series, element requirements,
222/// stat multipliers and the Psynergy it teaches by level.
224 return &gClass_DefinitionTable[classId];
225}
226
227/// Works out a character's class again after its Djinn change, then its
228/// Psynergy list and its base elements. Writes the unit's classIndex,
229/// actionSlots and baseElement. Called when a Djinni is set or put on
230/// standby, at the prologue's start and end, at a new game and around the
231/// Colosso's inventory snapshot.
232void Unit_UpdateClass(s32 ownerId) {
233 struct BattleUnit *owner = UnitGet(ownerId);
234
235 owner->classIndex =
236 Class_Determine(owner->classId, (u8 *)owner->djinnAvailable);
237 Unit_RefreshPsynergy(ownerId);
238#ifdef UBFIX
239 Unit_CalcBaseElements(ownerId, owner->baseElement);
240#else
241 Unit_CalcBaseElements(ownerId, (s16 (*)[2])owner->baseElement);
242#endif
243}
@ NUM_ELEMENTS
Definition battle_unit.h:41
struct ClassDefinition gClass_DefinitionTable[]
#define GARET
Jerald.
#define ISAAC
Robin.
#define JENNA
Jasmine.
s32 GameFlag_Test(s32 flag)
Returns 1 when flag is set.
Definition flags.c:13
#define FLAG_CHILDHOOD
the prologue: Isaac and Garet are children
Definition flags.h:10
void Unit_UpdateClass(s32 ownerId)
Works out a character's class again after its Djinn change, then its Psynergy list and its base eleme...
Definition classes.c:232
struct ElementLevelBonus gElement_PowerResistByLevel[16]
struct ClassDefinition * Class_GetDefinition(s32 classId)
Returns class classId's definition: its series, element requirements, stat multipliers and the Psyner...
Definition classes.c:223
s32 Class_Determine(s32 character, const u8 *djinn)
Returns the class a character has with djinn set: the series is chosen by its two strongest elements,...
Definition classes.c:161
s32 Enemy_GetAttackElement(struct BattleUnit *unit)
Returns the element an enemy attacks with, from its element preset.
Definition classes.c:82
u32 Unit_CalcBaseElements(s32 owner, s16 destination[4][2])
Definition classes.c:101
s32 Unit_GetElementLevel(s32 owner, s32 element)
Returns a unit's level in element (0 to 3).
Definition classes.c:67
s32 Unit_GetElementLevels(s32 record, const u8 *source, s32 output[4])
Writes ten times each element level to output: an enemy's from its element preset,...
Definition classes.c:26
s32 Class_GetSeries(s32 primaryElement, s32 secondaryElement)
Returns the class series of a character whose strongest element is primaryElement and second secondar...
Definition classes.c:18
s32 gOwner_FourColumnValues[]
struct PresetValues gEnemy_ElementPresetTable[]
What every part of the game object shares: its includes and the inventory helper two parts use.
s32 Unit_RefreshPsynergy(s32 owner)
Rebuilds a character's Psynergy list: drops the actions its class and items gave, closes up the list,...
Definition levels.c:68
struct CharacterDefinition * Character_GetDefinition(s32 index)
Returns character index's definition: growth curves, starting level and equipment.
Definition levels.c:242
A unit's elemental power and resistance in one element.
Definition battle_unit.h:27
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
s8 elementLevels[4]
A summon's boost to each element: the Djinn of that element the summon spent, adding (n * n + n) * 5 ...
struct BattleElementStats element[4]
Power and resistance in each element, 0 to 200, after equipment, element levels and Resistance stages...
u8 classId
Who the unit is: a character's id (ISAAC to JENNA, below 8) or an enemy's id (BattleUnitSet).
struct BattleElementStats baseElement[4]
Power and resistance before equipment and stages: an enemy's from its element preset,...
u8 classIndex
The character's class, worked out from its Djinn (Unit_UpdateClass); 0 marks an enemy,...
u32 djinnAvailable[4]
The Djinn held, one bit per Djinni (by its index) in each element's word.
u8 elementBonus[4]
Added to ten times the Djinn set in each element to give the character's element levels (Unit_GetElem...
Definition character.h:32
A class: its series, the element levels it needs, its stat multipliers and the abilities it teaches.
Definition character.h:50
The elemental power and resistance of one element level.
Definition classes.c:8
u16 power
base power, before the tenths of a level
Definition classes.c:9
u16 res
base resistance, likewise
Definition classes.c:10
An enemy's definition: its level and stats, items, element preset, the actions it chooses from and it...
Definition character.h:89
u8 elementPreset
row of gEnemy_ElementPresetTable, 0 to 43
Definition character.h:111
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
void * memcpy(void *destination, const void *source, unsigned long size)
const u8 * Enemy_GetDefinition(s32 selector)
Returns the definition of enemy selector - 8; an id past the first 250 gives the first.
Definition units.c:103
struct BattleUnit * UnitGet(u32 owner)
Returns the unit record of owner: 0 to 7 are the playable characters in the game state,...
Definition units.c:73