Alchemy
Loading...
Searching...
No Matches

use.c

Go to the documentation of this file.
1/// @file
2/// Using an item or Psynergy from the menu: what it does to the party, and the
3/// sound it plays.
4/// Part of menu.c, the menu object, compiled only through it.
5
6#include "../menu_internal.h"
7
8/// Copies and lightens the palette used by the item-use animation.
12}
13
14/// Reserved empty callback during an item's menu animation.
16
17/// Applies the slot's action, then consumes or transforms the item on success.
18s32 Item_Use(s32 slot, s32 ownerId, s32 targetId) {
19 struct InventoryMenuState *menu;
20 s32 useResult;
21 s32 itemId;
22 struct BattleUnit *unit;
23 struct ItemDefinition *item;
24
25 unit = UnitGetFar(ownerId);
26 menu = gMenuWork;
27 itemId = ITEM_ID_MASK & unit->inventory[slot];
28 item = Item_GetDirectFar(itemId);
30 ownerId, targetId, 1);
31 if (useResult != -1) {
32 item = Item_GetDirectFar(unit->inventory[slot]);
33 if (item->useType == 1) {
34 Inventory_RemoveFar(ownerId, slot);
35 menu->itemCount = ItemMenu_CollectItems(unit, menu->items, 0);
36 }
37 if (item->useType == 4) {
38 if (itemId == 0xb8)
39 itemId = 0xb9;
40 unit->inventory[slot] = itemId;
41 }
42 useResult = 0;
43 }
44 return useResult;
45}
46
47s32 Item_ReturnOne(void) { return 1; }
48
49/// Applies healing or permanent-stat effects to one member or the whole party.
50/// The result message is kept in menu work; -1 reports that nothing changed.
51s32 BattleEffect_ApplyToTargets(s32 effectId, s32 sourceId, s32 targetId,
52 s32 fixedScale) {
53 struct BattleAct *effect;
54 struct InventoryMenuState *menu;
55 struct BattleUnit *target;
56 struct BattleUnit *caster;
57 s32 partyResultShown;
58 s32 changed;
59 u8 targetIndex;
60 s16 elementPower;
61 s32 randomAdjust;
62 s32 randomDifference;
63 s32 amount;
64 s32 messageOffset;
65
66 effect = BattleActGet(effectId);
67 menu = gMenuWork;
68 changed = 0;
69 messageOffset = 0;
70 partyResultShown = 0;
71
72 if (targetId != MENU_TARGET_WHOLE_PARTY)
73 target = UnitGetFar(targetId);
74 else
75 target = UnitGetFar(0);
76
77 /* FAKEMATCH(dead): a test that is never true (partyResultShown is still
78 * 0), which emits nothing but loads effect->range ahead of the loop's count
79 * guard; without it, 21 of 485 instructions differ in tbs-en. */
80 if (effect->range == 0xff && partyResultShown != 0)
81 messageOffset = 3;
82
83 // A party-wide action keeps the first useful message while visiting targets.
84 for (targetIndex = 0; targetIndex < menu->partyCount; targetIndex++) {
85 if (effect->range == 0xff) {
86 targetId = menu->ownerIds[targetIndex];
87 target = UnitGetFar(targetId);
88 }
89
90 amount = effect->power;
91 switch (effect->flags & 0xf) {
93 if (fixedScale == 0) {
94 if (effect->element != 4) {
95 s32 elementIndex;
96
97 caster = UnitGetFar(sourceId);
98 elementIndex = effect->element;
99 elementPower = caster->element[elementIndex].power;
100 } else
101 elementPower = 100;
102 amount = BattleRecoveryCalc(amount, elementPower, 0x100);
103 }
104
105 if (target->hp <= 0) {
106 if (partyResultShown == 0)
107 messageOffset = 2;
108 } else {
109 if (target->hp == target->maxHp) {
110 if (partyResultShown == 0)
111 messageOffset = 4;
112 } else {
113 target->hp += amount;
114 if (target->hp > target->maxHp) {
115 amount -= target->hp - target->maxHp;
116 target->hp = target->maxHp;
117 if (partyResultShown == 0)
118 messageOffset = 0;
119 } else if (partyResultShown == 0) {
120 messageOffset = 1;
121 }
122 UnitRatioFar(targetId);
123 changed = 1;
124 if (effect->range == 0xff) {
125 partyResultShown = 1;
126 messageOffset = 3;
127 }
128 }
129 }
130 break;
131
132 case 9:
133 randomAdjust = (Random16() * 4) >> 16;
134 if (randomAdjust == 0) {
135 randomAdjust = -1;
136 } else {
137 randomDifference = 1 ^ randomAdjust;
138 randomAdjust = (u32)((-randomDifference) | randomDifference) >> 31;
139 randomAdjust = 1 - randomAdjust;
140 }
141
142 switch (effectId & OWNER_ACTION_ID_MASK) {
143 case 0x104:
144 target->baseHp += amount + randomAdjust;
145 messageOffset = 0x10;
146 changed = 1;
147 break;
148 case 0x105:
149 target->basePp += amount + randomAdjust;
150 messageOffset = 0x11;
151 changed = 1;
152 break;
153 case 0x108:
154 target->baseAgility += amount + randomAdjust;
155 messageOffset = 0x12;
156 changed = 1;
157 break;
158 case 0x109:
159 target->baseLuck += amount;
160 messageOffset = 0x13;
161 changed = 1;
162 break;
163 case 0x106:
164 target->baseAttack += amount + randomAdjust;
166 messageOffset = 0x14;
167 changed = 1;
168 break;
169 case 0x107:
170 target->baseDefense += amount + randomAdjust;
172 messageOffset = 0x15;
173 changed = 1;
174 break;
175 }
176 break;
177
179 if (target->pp == target->maxPp) {
180 if (partyResultShown == 0)
181 messageOffset = 7;
182 } else {
183 target->pp += amount;
184 if (target->pp > target->maxPp) {
185 amount -= target->pp - target->maxPp;
186 target->pp = target->maxPp;
187 if (partyResultShown == 0)
188 messageOffset = 5;
189 } else if (partyResultShown == 0) {
190 messageOffset = 6;
191 }
192 UnitRatioFar(targetId);
193 changed = 1;
194 if (effect->range == 0xff) {
195 partyResultShown = 1;
196 messageOffset = 8;
197 }
198 }
199 break;
200
201 case 2:
202 case 3:
203 case 4:
204 case 5:
205 case 6:
206 case 7:
207 case 8:
208 case 10:
209 break;
210 }
211
212 switch (effect->effect) {
213 case 1:
214 if (target->hp <= 0 || target->hp == target->maxHp) {
215 if (partyResultShown == 0)
216 messageOffset = 2;
217 } else {
218 target->hp += amount;
219 if (target->hp > target->maxHp) {
220 target->hp = target->maxHp;
221 if (partyResultShown == 0)
222 messageOffset = 0;
223 } else if (partyResultShown == 0) {
224 messageOffset = 1;
225 }
226 UnitRatioFar(targetId);
227 changed = 1;
228 }
229 break;
230
231 case 2:
232 if (target->pp == target->maxPp) {
233 if (partyResultShown == 0)
234 messageOffset = 7;
235 } else {
236 target->pp += amount;
237 if (target->pp > target->maxPp) {
238 target->pp = target->maxPp;
239 if (partyResultShown == 0)
240 messageOffset = 5;
241 } else if (partyResultShown == 0) {
242 messageOffset = 6;
243 }
244 UnitRatioFar(targetId);
245 changed = 1;
246 }
247 break;
248
250 if (target->hp == 0) {
251 target->hp = target->maxHp;
252 UnitRatioFar(targetId);
253 changed = 1;
254 if (partyResultShown == 0)
255 messageOffset = 0xc;
256 } else if (partyResultShown == 0) {
257 messageOffset = 0xd;
258 }
259 break;
260
262 if (target->hp == 0) {
263 target->hp = target->maxHp / 2;
264 UnitRatioFar(targetId);
265 if (partyResultShown == 0)
266 messageOffset = 0xc;
267 } else if (partyResultShown == 0) {
268 messageOffset = 0xd;
269 }
270 break;
271
273 if (target->hp == 0) {
274 target->hp = target->maxHp * 7 / 10;
275 UnitRatioFar(targetId);
276 if (partyResultShown == 0)
277 messageOffset = 0xc;
278 } else if (partyResultShown == 0) {
279 messageOffset = 0xd;
280 }
281 break;
282
284 if (target->poison != 0) {
285 target->poison = 0;
286 changed = 1;
287 if (partyResultShown == 0)
288 messageOffset = 0xa;
289 } else if (partyResultShown == 0) {
290 messageOffset = 0xb;
291 }
292 break;
293 }
294
295 if (effect->range != 0xff)
296 break;
297 }
298
299 if (changed == 0) {
300 menu->messageOffset = messageOffset;
301 return -1;
302 }
303
304 for (targetIndex = 0; targetIndex < menu->partyCount; targetIndex++)
305 UnitCalcFar(menu->ownerIds[targetIndex]);
306 menu->messageOffset = messageOffset;
307 return 0;
308}
309
310/// Runs the animation selected by the item's action definition.
314}
315
316/// Starts the action's menu animation and waits for its completion.
318 s32 animationType;
319 u32 targetType;
320 struct BattleAct *actionDefinition;
321
322 actionDefinition = BattleActGet(action);
323 animationType = 0xf & actionDefinition->flags;
324 switch (animationType) {
325 case 1:
326 // XXX: with no break the recovery sound is started twice; whether that
327 // was meant would show only in the sound driver's handling of a cue
328 // started again in the same frame.
330 // Fall through.
331 case 11:
333 return;
334 default:
335 targetType = actionDefinition->effect - 1;
336 switch (targetType) {
337 case 4:
339 return;
340 case 2:
342 return;
343 default:
344 case 3:
345 case 5:
346 case 6:
347 case 7:
348 case 8:
349 case 9:
350 case 10:
351 case 11:
352 case 12:
353 case 13:
354 case 14:
355 case 15:
356 case 16:
357 case 17:
358 case 18:
359 case 19:
360 case 20:
361 case 21:
362 case 22:
363 case 23:
364 case 24:
365 case 25:
366 case 26:
367 case 27:
368 case 28:
369 case 29:
371
372 case 0:
373 case 1:
374 case 30:
375 case 31:
376 return;
377 }
378 break;
379 }
380}
381
382s32 Menu_ReservedStatusZero(void) { return 0; }
@ BATTLE_DAMAGE_PP_HEAL
@ BATTLE_DAMAGE_HP_HEAL
@ ABILITY_EFFECT_REVIVE_HALF
Quartz.
@ ABILITY_EFFECT_REVIVE_80
Dew: 80% of max HP.
@ ABILITY_EFFECT_REVIVE
Revive, Water of Life: full HP.
Definition battle_unit.h:81
@ ABILITY_EFFECT_CURE_POISON
Cure Poison, Antidote.
Definition battle_unit.h:79
@ OWNER_ACTION_ID_MASK
Definition battle_unit.h:14
void Palette_LightenBankHighlight(s32 bank)
Copies the last background palette (15) into background palette bank and lightens its colour 4 by 9 s...
Definition common.c:1012
void Palette_CopyObjectBankToBackground14(void)
Copies the first sprite palette into background palette 14, then colour 4 of background palette 15 ov...
Definition common.c:1121
s32 Audio_PlayCueReturnOne(s32 cue)
Definition common.c:1182
struct BattleUnit * UnitGetFar(u32 owner)
struct ItemDefinition * Item_GetDirectFar(s32 item)
void UnitRatioFar(s32 owner_id)
struct BattleAct * BattleActGet(s32 actionId)
Far call to BattleAction_GetDirect.
s32 Inventory_RemoveFar(s32 owner, s32 slot)
s32 BattleRecoveryCalc(s32 power, s32 element, s32 rate)
Far call to Battle_CalcRecovery.
void UnitCalcFar(s32 owner)
void UiWork_PushValueSlotFar(u32 value, u32 kind)
void * gMenuWork
s32 ItemMenu_CollectItems(struct BattleUnit *unit, u16 *items, s32 mode)
Copies the unit's items into the list items (32 entries), skipping empty slots and clearing the rest.
Definition item.c:1409
@ ITEM_ID_MASK
Definition item.h:16
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
What every part of the menu object shares: its includes, and the macros and types more than one part ...
#define MENU_TARGET_WHOLE_PARTY
The target id of Psynergy or an item used on the whole party.
#define SE_RECOVERY
Definition songs.h:119
#define MUS_084
Definition songs.h:83
#define MUS_091
Definition songs.h:89
#define MUS_082
Definition songs.h:81
An ability's definition, a row of gBattleAction_DefinitionTable: its targeting, kind,...
u8 effect
enum AbilityEffect
u8 range
the aimed unit and range - 1 either side, or ABILITY_RANGE_ALL
u8 element
enum Element
u8 flags
bits: 7 usable in battle | 6 usable in the field | 5..4 clear in every row | 3..0 kind (ABILITY_KIND_...
u16 power
what the kind applies, 0 for none
s16 power
Elemental power in the element.
Definition battle_unit.h:28
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u16 baseDefense
before equipment, Djinn, class and stages
u16 baseAttack
before equipment, Djinn, class and stages
u16 baseAgility
before equipment, Djinn, class and stages
s16 maxPp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
s8 poison
1 poisoned, 2 deadly poison
s16 hp
current HP, 0 when downed
struct BattleElementStats element[4]
Power and resistance in each element, 0 to 200, after equipment, element levels and Resistance stages...
s16 pp
current PP
u8 baseLuck
before equipment, Djinn and class
s16 basePp
before equipment, Djinn and class (UnitCalc)
s16 maxHp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
s16 baseHp
before equipment, Djinn and class (UnitCalc)
u16 inventory[15]
Items held, one entry each: bits 15..11 quantity | 10 broken | 9 equipped | 8..0 item id (INVENTORY_*...
The item menu's work, in the HEAP_SLOT_MENU work slot: its windows, the party figures,...
s16 messageOffset
the item use's result, after MsgItemUseResult
u16 items[32]
the inventory entries listed
u16 ownerIds[8]
the party in order (Party_ListActiveOwners)
An item's definition: its price, type, who can equip it, its bonuses and unleash, its effects and the...
Definition item.h:104
u8 useType
what using it costs (ITEM_USE_), or 0 for nothing
Definition item.h:113
u16 actionId
the ability used, or taught as Psynergy
Definition item.h:120
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned char u8
Definition types.h:11
void Item_PlayUseAnimation(u32 item)
Runs the animation selected by the item's action definition.
Definition use.c:311
void Item_PrepareUsePalette(void)
Copies and lightens the palette used by the item-use animation.
Definition use.c:9
void Ability_PlayUseAnimation(s32 action)
Starts the action's menu animation and waits for its completion.
Definition use.c:317
s32 Menu_ReservedStatusZero(void)
Definition use.c:382
void Item_UseNoOpCallback(void)
Reserved empty callback during an item's menu animation.
Definition use.c:15
s32 Item_Use(s32 slot, s32 ownerId, s32 targetId)
Applies the slot's action, then consumes or transforms the item on success.
Definition use.c:18
s32 BattleEffect_ApplyToTargets(s32 effectId, s32 sourceId, s32 targetId, s32 fixedScale)
Applies healing or permanent-stat effects to one member or the whole party.
Definition use.c:51
s32 Item_ReturnOne(void)
Definition use.c:47