Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
item.c
Go to the documentation of this file.
1/* FIGHTSTG's items used in battle: an item's script and its task. */
2
4
5/* Item 0x58's setup: lowers the higher of the enemy's attack and defense
6 (when that is the defense, the USA version raises it instead), unless the
7 battle blocks it, and picks the script's effect */
8static inline void lowerEnemyStat(BattleItem *task, BattleChild *children) {
9 BattleFighter *fighter;
10 BattleStats *stats;
11 s32 atk;
12 s32 def;
13 s32 min;
14
17 if (stats->stats[BATTLE_STAT_ATTACK] > stats->stats[BATTLE_STAT_DEFENSE]) {
19 task->lowered = 1;
20 atk = stats->stats[BATTLE_STAT_ATTACK];
21 def = stats->stats[BATTLE_STAT_DEFENSE];
22 if (fighter->boosts[0] != 0) {
23 stats->stats[BATTLE_STAT_ATTACK] -= fighter->boosts[0];
24 }
25 min = -(stats->stats[BATTLE_STAT_ATTACK] / 2);
26 fighter->boosts[0] -= atk - def;
27 if (fighter->boosts[0] < min) {
28 fighter->boosts[0] = min;
29 }
30 }
31 } else if (stats->stats[BATTLE_STAT_ATTACK] < stats->stats[BATTLE_STAT_DEFENSE]) {
33 task->lowered = 2;
34 atk = stats->stats[BATTLE_STAT_ATTACK];
35 def = stats->stats[BATTLE_STAT_DEFENSE];
36 if (fighter->boosts[1] != 0) {
37 stats->stats[BATTLE_STAT_DEFENSE] -= fighter->boosts[1];
38 }
39 min = -(stats->stats[BATTLE_STAT_DEFENSE] / 2);
40#if VERSION_EU || VERSION_JP
41 fighter->boosts[1] -= def - atk;
42#else
43 fighter->boosts[1] -= atk - def; /* raises it */
44#endif
45 if (fighter->boosts[1] < min) {
46 fighter->boosts[1] = min;
47 }
48 }
49 }
50 children[0].script->index = 0x11;
51 children[0].script->stage = -1;
52 if (task->lowered == 1) {
53 children[0].script->effect = 0x25;
54 children[0].script->sound = 0x31;
55 } else if (task->lowered == 2) {
56 children[0].script->effect = 0x27;
57 children[0].script->sound = 0x31;
58 } else {
59 children[0].script->effect = 0x2E;
60 children[0].script->sound = 0x1E;
61 }
62}
63
64/* Item 0x55's setup: its drain of 20 percent of the enemy's max HP, unless
65 the battle blocks draining */
66static inline void setUpDrain(BattleItem *task, BattleChild *children) {
67 BattleFighter *enemy;
68
69 children[0].script->index = 0xE;
70 children[0].script->stage = -1;
71 children[0].script->effect = 0x1C;
72 children[0].script->sound = 0x27;
75 task->damage = enemy->maxHp * 20 / 100;
76 if (enemy->hp - task->damage <= 0) {
77 children[0].script->hits[3] = 2;
78 task->counter = 1;
79 } else {
80 children[0].script->hits[3] = 1;
83 }
84 } else {
85 children[0].script->hits[3] = 3;
86 }
87}
88
89/* Item 0x5A's setup: the script of technique 0x89 and its magic damage to
90 the enemy */
91static inline void setUpItemTech(BattleItem *task, BattleChild *children) {
92 BattleFighter *row;
93 TechData *tech;
94
95 children[0].script->index = 0xE;
96 tech = &TECHS[0x88];
97 children[0].script->stage = tech->scriptStage;
98 children[0].script->effect = tech->scriptEffect;
99 children[0].script->sound = tech->scriptSound;
102 if (task->damage > 0) {
103 if (row[FIGHTSTG_battle.state.active[1]].hp - task->damage <= 0) {
104 children[0].script->hits[3] = 2;
105 } else {
106 children[0].script->hits[3] = 1;
108 }
109 } else {
110 children[0].script->hits[3] = 3;
111 }
112}
113
114/* The other items' setup: their effect and sound from FIGHTSTG_itemScripts,
115 and the partner's idle motion after what items 0x2B-0x2E and 0x47 heal */
116static inline void setItemScript(BattleItem *task, BattleChild *children) {
117 s32 i;
118
119 children[0].script->index = 0xA;
120 children[0].script->stage = -1;
121 for (i = 0; FIGHTSTG_itemScripts[i].item != -1; i++) {
122 if (FIGHTSTG_itemScripts[i].item == task->item) {
123 children[0].script->effect = FIGHTSTG_itemScripts[i].effect;
124 children[0].script->sound = FIGHTSTG_itemScripts[i].sound;
125 break;
126 }
127 }
128 if (task->item >= 0x2B && task->item < 0x2F) {
130 } else if (task->item == 0x47) {
131 WFIGHTMN_setIdleMotion(0, -(ACTIVE_FIGHTER(0)->maxHp >> 1));
132 }
133}
134
135/* An item's script (FIGHTSTG_updateItem): step 0 sets it up and deals the
136 damage (lowerEnemyStat, setUpDrain, setUpItemTech, setItemScript), 1 plays
137 item 0x55's second part when the enemy is still standing, 2 waits.
138 The match depends on item 0x55's damage being 20 percent, on the row
139 pointer of item 0x5A, on the stage being written out in each case and on
140 the table being walked by index. */
142 switch (task->step) {
143 case 0:
144 default:
145 children[0].script = FIGHTSTG_createBattleScript();
146 children[0].script->enemy = 0;
147 switch (task->item) {
148 case 0x4D:
149 case 0x4E:
150 case 0x4F:
151 case 0x50:
152 case 0x51:
153 case 0x52:
154 case 0x53:
155 children[0].script->index = 0xF;
156 children[0].script->stage = (task->item - 0x4D) * 3 + 0x22;
157 children[0].script->effect = 2;
158 children[0].script->sound = 0x39;
159 break;
160 case 0x54:
162 children[0].script->index = 0xF;
163 children[0].script->stage = (task->element - ELEMENT_FIRST) * 3 + 0x22;
164 children[0].script->effect = 2;
165 children[0].script->sound = 0x39;
166 break;
167 case 0x56:
168 children[0].script->index = 0x11;
169 children[0].script->stage = -1;
170 children[0].script->effect = 0x15;
171 children[0].script->sound = 0x1B;
172 break;
173 case 0x57:
174 children[0].script->index = 0x11;
175 children[0].script->stage = -1;
176 children[0].script->effect = 0x27;
177 children[0].script->sound = 0x31;
178 break;
179 case 0x59:
180 children[0].script->index = 0x11;
181 children[0].script->stage = -1;
182 children[0].script->effect = 0x29;
183 children[0].script->sound = 0x31;
184 break;
185 case 0x58:
186 lowerEnemyStat(task, children);
187 break;
188 case 0x55:
189 setUpDrain(task, children);
190 break;
191 case 0x5A:
192 setUpItemTech(task, children);
193 break;
194 default:
195 setItemScript(task, children);
196 break;
197 }
198 task->step++;
200 if (task->item == 0x5A) {
201 WFIGHTMN_countHit(0, task->damage);
202 } else {
204 }
205 }
206 break;
207 case 1:
208 if (children[0].script == NULL) {
209 if (task->item != 0x55 || task->counter != 0 || BATTLE_SETUP.blocks[BATTLE_BLOCK_DRAIN] != 0) {
210 return 1;
211 }
212 children[0].script = FIGHTSTG_createBattleScript();
213 children[0].script->enemy = 0;
214 children[0].script->index = 0xA;
215 children[0].script->effect = 0x21;
216 children[0].script->sound = 0x1F;
217 task->step++;
218 }
219 break;
220 case 2:
221 if (children[0].script == NULL) {
222 return 1;
223 }
224 break;
225 }
226 return 0;
227}
228
229/* what items 0x42-0x45 cure (FIGHTSTG_updateItem, below) */
231 { 0x28, 0x01, 190 },
232 { 0x29, 0x02, 192 },
233 { 0x2A, 0x04, 194 },
234 { 0x2C, 0x3F, 196 },
235};
236/* the items' script settings (FIGHTSTG_runItemScript, above) */
238 { 0x2B, 0x21, 0x1F },
239 { 0x2C, 0x21, 0x1F },
240 { 0x2D, 0x21, 0x1F },
241 { 0x2E, 0x21, 0x1F },
242 { 0x42, 0x22, 0x1F },
243 { 0x43, 0x22, 0x1F },
244 { 0x44, 0x22, 0x1F },
245 { 0x45, 0x22, 0x1F },
246 { 0x46, 0x23, 0x1F },
247 { 0x47, 0x21, 0x1F },
248 { 0x48, 0x28, 0x1F },
249 { 0x49, 0x24, 0x1F },
250 { 0x4A, 0x26, 0x1F },
251 { 0x4B, 0x2E, 0x1E },
252 { 0x4C, 0x2E, 0x1E },
253 { -1, 0, 0 },
254};
255
256/* Items 0x2B-0x41: heal the partner by the item's amount, up to its max HP */
257static inline void healPartner(BattleItem *task, BattleChild *children) {
258 BattleFighter *fighter;
259 ItemEffect *effect;
260 s32 heal;
261
263 effect = ITEM_FUNCS.get(task->item)->data.effect;
264 if (fighter->maxHp == fighter->hp) {
265 children[0].message = FIGHTSTG_createMessage();
266 task->lines[0] = 0x2F;
267 children[0].message->show(children[0].message, 1, task->lines);
268 task->nextSubstate(task);
269 return;
270 }
271 if (fighter->hp + effect->amount <= fighter->maxHp) {
272 heal = effect->amount;
273 fighter->hp += heal;
274 } else {
275 heal = fighter->maxHp - fighter->hp;
276 fighter->hp = fighter->maxHp;
277 }
278 children[0].message = FIGHTSTG_createMessage();
279 task->lines[0] = 0;
280 task->lines[1] = heal;
281 children[0].message->show(children[0].message, 8, task->lines);
282 task->nextSubstate(task);
283}
284
285/* Items 0x42-0x45: cure the partner of what FIGHTSTG_itemCures says, or say
286 they do nothing */
287static inline void cureStatus(BattleItem *task, BattleChild *children) {
288 BattleFighter *fighter;
289 StatusCure *cure;
290
292 switch (task->item) {
293 case 0x42:
294 default:
295 cure = &FIGHTSTG_itemCures[0];
296 break;
297 case 0x43:
298 cure = &FIGHTSTG_itemCures[1];
299 break;
300 case 0x44:
301 cure = &FIGHTSTG_itemCures[2];
302 break;
303 case 0x45:
304 cure = &FIGHTSTG_itemCures[3];
305 break;
306 }
307 children[0].message = FIGHTSTG_createMessage();
308 if (fighter->flags & cure->flag) {
309 fighter->flags &= ~cure->flag;
311 task->lines[0] = cure->message;
312 task->lines[1] = 0;
313 children[0].message->show(children[0].message, 2, task->lines);
314 } else {
315 task->lines[0] = 0x2F;
316 children[0].message->show(children[0].message, 1, task->lines);
317 }
318 task->nextSubstate(task);
319}
320
321/* Item 0x46: revives the partners knocked out to their max HP, then is taken
322 from the bag and ends the task */
323static inline void reviveParty(BattleItem *task, BattleChild *children) {
324 s32 i;
325
326 switch (task->step) {
327 case 0:
328 children[0].message = FIGHTSTG_createMessage();
329 task->lines[0] = 0;
330 task->lines[1] = 5;
331 children[0].message->show(children[0].message, 9, task->lines);
332 task->nextStep(task);
333 break;
334 case 1:
335 if (children[0].task == NULL) {
336 for (i = 0; i < 3; i++) {
337 if (FIGHTSTG_battle.state.fighters[0][i].hp == 0) {
340 }
341 }
342 task->nextStep(task);
343 }
344 break;
345 case 2:
346 if (children[0].task == NULL) {
347 GAME.items[task->item]--;
348 task->state = TASK_KILL;
349 }
350 break;
351 }
352}
353
354/* Item 0x47: restores half the partner's max HP and MP, or says it does
355 nothing when both are full */
356static inline void restoreHalfHpMp(BattleItem *task, BattleChild *children) {
357 BattleFighter *fighter;
358
360 children[0].message = FIGHTSTG_createMessage();
361 if (fighter->hp != fighter->maxHp || fighter->mp != fighter->maxMp) {
362 s32 half;
363 s32 halfMp;
364
365 half = fighter->maxHp / 2;
366 halfMp = fighter->maxMp / 2;
367 if (fighter->hp + half >= fighter->maxHp) {
368 fighter->hp = fighter->maxHp;
369 } else {
370 fighter->hp += half;
371 }
372 if (fighter->maxMp <= fighter->mp + halfMp) {
373 fighter->mp = fighter->maxMp;
374 } else {
375 fighter->mp += halfMp;
376 }
377 task->lines[0] = 0x3B;
378 task->lines[1] = 0;
379 children[0].message->show(children[0].message, 2, task->lines);
380 } else {
381 task->lines[0] = 0x2F;
382 children[0].message->show(children[0].message, 1, task->lines);
383 }
384 task->nextSubstate(task);
385}
386
387/* Item 0x48: raises the partner's speed by the item's amount in 128ths, up to
388 double */
389static inline void boostSpeed(BattleItem *task, BattleChild *children) {
390 BattleFighter *fighter;
391 BattleStats *stats;
392 ItemEffect *effect;
393 s32 max;
394
395 effect = ITEM_FUNCS.get(task->item)->data.effect;
398 if (fighter->boosts[2] != 0) {
399 stats->stats[BATTLE_STAT_SPEED] -= fighter->boosts[2];
400 }
401 max = stats->stats[BATTLE_STAT_SPEED];
402 fighter->boosts[2] += max * effect->amount / 128;
403 if (fighter->boosts[2] > max) {
404 fighter->boosts[2] = max;
405 }
407 children[0].message = FIGHTSTG_createMessage();
408 task->lines[0] = 0x32;
409 task->lines[1] = 0;
410 task->lines[2] = FIGHTSTG_battle.state.active[0];
411 children[0].message->show(children[0].message, 7, task->lines);
412 task->nextSubstate(task);
413}
414
415/* Item 0x49: raises the partner's attack and lowers its defense */
416static inline void boostAttack(BattleItem *task, BattleChild *children) {
417 BattleFighter *fighter;
418 BattleStats *stats;
419 ItemEffect *effect;
420 s32 max;
421 s32 min;
422
423 effect = ITEM_FUNCS.get(task->item)->data.effect;
426 if (fighter->boosts[0] != 0) {
427 stats->stats[BATTLE_STAT_ATTACK] -= fighter->boosts[0];
428 }
429 if (fighter->boosts[1] != 0) {
430 stats->stats[BATTLE_STAT_DEFENSE] -= fighter->boosts[1];
431 }
432 max = stats->stats[BATTLE_STAT_ATTACK];
433 fighter->boosts[0] += max * effect->amount / 128;
434 if (fighter->boosts[0] > max) {
435 fighter->boosts[0] = max;
436 }
437 min = -(stats->stats[BATTLE_STAT_DEFENSE] / 2);
438 fighter->boosts[1] -= stats->stats[BATTLE_STAT_DEFENSE] * effect->amount / 512;
439 if (fighter->boosts[1] < min) {
440 fighter->boosts[1] = min;
441 }
444 children[0].message = FIGHTSTG_createMessage();
445 task->lines[0] = 0x3C;
446 task->lines[1] = 0;
447 children[0].message->show(children[0].message, 2, task->lines);
448 task->nextSubstate(task);
449}
450
451/* Item 0x4A: raises the partner's defense and lowers its attack */
452static inline void boostDefense(BattleItem *task, BattleChild *children) {
453 BattleFighter *fighter;
454 BattleStats *stats;
455 ItemEffect *effect;
456 s32 max;
457 s32 min;
458
459 effect = ITEM_FUNCS.get(task->item)->data.effect;
462 if (fighter->boosts[0] != 0) {
463 stats->stats[BATTLE_STAT_ATTACK] -= fighter->boosts[0];
464 }
465 if (fighter->boosts[1] != 0) {
466 stats->stats[BATTLE_STAT_DEFENSE] -= fighter->boosts[1];
467 }
468 max = stats->stats[BATTLE_STAT_DEFENSE];
469 fighter->boosts[1] += max * effect->amount / 128;
470 if (fighter->boosts[1] > max) {
471 fighter->boosts[1] = max;
472 }
473 min = -(stats->stats[BATTLE_STAT_ATTACK] / 2);
474 fighter->boosts[0] -= stats->stats[BATTLE_STAT_ATTACK] * effect->amount / 512;
475 if (fighter->boosts[0] < min) {
476 fighter->boosts[0] = min;
477 }
480 children[0].message = FIGHTSTG_createMessage();
481 task->lines[0] = 0x3D;
482 task->lines[1] = 0;
483 children[0].message->show(children[0].message, 2, task->lines);
484 task->nextSubstate(task);
485}
486
487/* Item 0x4B: puts the partner in its special state, which doubles its
488 effects */
489static inline void startSpecial(BattleItem *task, BattleChild *children) {
490 ACTIVE_FIGHTER(0)->special = 1;
491#if VERSION_US
493#endif
494 children[0].message = FIGHTSTG_createMessage();
495 task->lines[0] = 0x3E;
496 task->lines[1] = 0;
497 children[0].message->show(children[0].message, 2, task->lines);
498 task->nextSubstate(task);
499}
500
501/* Item 0x4C: fills the partner's gauge by the item's amount, up to 999 */
502static inline void fillGauge(BattleItem *task, BattleChild *children) {
503 ItemEffect *effect;
504 s32 i;
505
506 effect = ITEM_FUNCS.get(task->item)->data.effect;
508 BATTLE_SETUP.gauges[i] += effect->amount;
509 if (BATTLE_SETUP.gauges[i] >= 999) {
510 BATTLE_SETUP.gauges[i] = 999;
511 }
512 children[0].message = FIGHTSTG_createMessage();
513 task->lines[0] = 0x3F;
514 task->lines[1] = 0;
515 children[0].message->show(children[0].message, 2, task->lines);
516 task->nextSubstate(task);
517}
518
519/* Items 0x4D-0x53: boost one element on the field */
520static inline void boostElement(BattleItem *task, BattleChild *children) {
522 FIGHTSTG_battle.state.boost.element = task->item - 0x4B;
524 children[0].message = FIGHTSTG_createMessage();
525 task->lines[0] = task->item + 0x16;
526 children[0].message->show(children[0].message, 1, task->lines);
527 task->nextSubstate(task);
528}
529
530/* Item 0x54: boosts the element its script picked at random on the field */
531static inline void boostRandomElement(BattleItem *task, BattleChild *children) {
535 children[0].message = FIGHTSTG_createMessage();
536 task->lines[0] = task->element + 0x61;
537 children[0].message->show(children[0].message, 1, task->lines);
538 task->nextSubstate(task);
539}
540
541/* Item 0x55: drains the damage from the enemy to the partner, or says it
542 does nothing when the battle blocks draining */
543static inline void drainEnemy(BattleItem *task, BattleChild *children) {
544 BattleFighter *fighter;
545
547 children[0].message = FIGHTSTG_createMessage();
548 task->lines[0] = 0x10;
549 task->lines[1] = task->damage;
551 if (fighter->hp - task->damage <= 0) {
552 children[0].message->show(children[0].message, 4, task->lines);
553 fighter->hp = 0;
555 } else {
556 children[0].message->show(children[0].message, 0x14, task->lines);
557 fighter->hp -= task->damage;
559 fighter->hp += task->damage;
560 if (fighter->hp > fighter->maxHp) {
561 fighter->hp = fighter->maxHp;
562 }
563 }
564 } else {
565 children[0].message = FIGHTSTG_createMessage();
566 task->lines[0] = 0x2F;
567 children[0].message->show(children[0].message, 1, task->lines);
568 }
569 task->nextSubstate(task);
570}
571
572/* Item 0x56: confuses the enemy half of the time, unless the battle blocks
573 it, and then the partner a quarter of those times */
574static inline void confuseFighters(BattleItem *task, BattleChild *children) {
575 BattleFighter *fighter;
576 BattleFighter *enemy;
577 ItemEffect *effect;
578
579 effect = ITEM_FUNCS.get(task->item)->data.effect;
582 switch (task->step) {
583 case 0:
584 default:
586 FIGHTSTG_inflictConfusion(0x10, 0, effect->amount);
587 children[0].message = FIGHTSTG_createMessage();
588 task->lines[0] = 0x20;
589 task->lines[1] = 0x10;
590 children[0].message->show(children[0].message, 2, task->lines);
591 if ((RANDOM.next() & 3) == 0) {
592 task->nextStep(task);
593 } else {
594 task->nextSubstate(task);
595 }
596 enemy->flags |= FIGHTER_CONFUSED;
597 } else {
598 children[0].message = FIGHTSTG_createMessage();
599 task->lines[0] = 0x2F;
600 children[0].message->show(children[0].message, 1, task->lines);
601 task->nextSubstate(task);
602 }
603 break;
604 case 1:
605 if (children[0].task == NULL) {
606 fighter->flags |= FIGHTER_CONFUSED;
607 FIGHTSTG_inflictConfusion(0, 0, effect->amount);
608 children[0].message = FIGHTSTG_createMessage();
609 task->lines[0] = 0x20;
610 task->lines[1] = 0;
611 children[0].message->show(children[0].message, 2, task->lines);
612 task->nextSubstate(task);
613 }
614 break;
615 }
616}
617
618/* Item 0x57: raises the enemy's attack and lowers its defense, or says it
619 does nothing when the battle blocks it */
620static inline void weakenEnemyDefense(BattleItem *task, BattleChild *children) {
621 BattleFighter *enemy;
622 BattleStats *stats;
623 s32 max;
624 s32 atk;
625 s32 def;
626
630 atk = stats->stats[BATTLE_STAT_ATTACK];
631 def = stats->stats[BATTLE_STAT_DEFENSE];
632 if (enemy->boosts[0] != 0) {
633 stats->stats[BATTLE_STAT_ATTACK] -= enemy->boosts[0];
634 }
635 if (enemy->boosts[1] != 0) {
636 stats->stats[BATTLE_STAT_DEFENSE] -= enemy->boosts[1];
637 }
638 enemy->boosts[0] += atk * 3 / 10;
639 enemy->boosts[1] -= def / 2;
640 max = stats->stats[BATTLE_STAT_ATTACK];
641 if (enemy->boosts[0] > max) {
642 enemy->boosts[0] = max;
643 }
644 if (enemy->boosts[1] < -stats->stats[BATTLE_STAT_DEFENSE] / 2) {
645 enemy->boosts[1] = -stats->stats[BATTLE_STAT_DEFENSE] / 2;
646 }
649 children[0].message = FIGHTSTG_createMessage();
650 task->lines[0] = 0x40;
651 task->lines[1] = 0x10;
652 children[0].message->show(children[0].message, 2, task->lines);
653 task->nextSubstate(task);
654 return;
655 }
656 children[0].message = FIGHTSTG_createMessage();
657 task->lines[0] = 0x2F;
658 children[0].message->show(children[0].message, 1, task->lines);
659 task->nextSubstate(task);
660}
661
662/* Item 0x58: says which of the enemy's stats its script lowered */
663static inline void showLoweredStat(BattleItem *task, BattleChild *children) {
664 switch (task->lowered) {
665 case 1:
667 children[0].message = FIGHTSTG_createMessage();
668 task->lines[0] = 0x33;
669 task->lines[1] = 0x10;
670 task->lines[2] = FIGHTSTG_battle.state.active[1];
671 children[0].message->show(children[0].message, 2, task->lines);
672 break;
673 case 2:
675 children[0].message = FIGHTSTG_createMessage();
676 task->lines[0] = 0x34;
677 task->lines[1] = 0x10;
678 task->lines[2] = FIGHTSTG_battle.state.active[1];
679 children[0].message->show(children[0].message, 2, task->lines);
680 break;
681 default:
682 children[0].message = FIGHTSTG_createMessage();
683 task->lines[0] = 0x2F;
684 children[0].message->show(children[0].message, 1, task->lines);
685 break;
686 }
687 task->nextSubstate(task);
688}
689
690/* Item 0x59: lowers the enemy's speed, or says it does nothing when the
691 battle blocks it */
692static inline void lowerEnemySpeed(BattleItem *task, BattleChild *children) {
693 BattleFighter *enemy;
694 BattleStats *stats;
695 ItemEffect *effect;
696 s32 min;
697
699 effect = ITEM_FUNCS.get(task->item)->data.effect;
702 if (enemy->boosts[2] != 0) {
703 stats->stats[BATTLE_STAT_SPEED] -= enemy->boosts[2];
704 }
705 min = -(stats->stats[BATTLE_STAT_SPEED] / 2);
706 enemy->boosts[2] -= stats->stats[BATTLE_STAT_SPEED] * effect->amount / 128;
707 if (enemy->boosts[2] < min) {
708 enemy->boosts[2] = min;
709 }
711 children[0].message = FIGHTSTG_createMessage();
712 task->lines[0] = 0x35;
713 task->lines[1] = 0x10;
714 task->lines[2] = FIGHTSTG_battle.state.active[1];
715 children[0].message->show(children[0].message, 2, task->lines);
716 task->nextSubstate(task);
717 return;
718 }
719 children[0].message = FIGHTSTG_createMessage();
720 task->lines[0] = 0x2F;
721 children[0].message->show(children[0].message, 1, task->lines);
722 task->nextSubstate(task);
723}
724
725/* Item 0x5A: deals its technique's damage to the enemy */
726static inline void damageEnemy(BattleItem *task, BattleChild *children) {
727 BattleFighter *enemy;
728
729 if (task->damage > 0) {
730 children[0].message = FIGHTSTG_createMessage();
731 task->lines[0] = 0x10;
732 task->lines[1] = task->damage;
733 children[0].message->show(children[0].message, 4, task->lines);
735 if (enemy->hp - task->damage <= 0) {
736 enemy->hp = 0;
738 } else {
739 enemy->hp -= task->damage;
740 }
741 } else {
742 children[0].message = FIGHTSTG_createMessage();
743 task->lines[0] = 0x1D;
744 task->lines[1] = 0x10;
745 children[0].message->show(children[0].message, 2, task->lines);
746 }
747 task->nextSubstate(task);
748}
749
750/* An item used in battle (FIGHTSTG_startItem): its message,
751 FIGHTSTG_runItemScript's script, then substate 1 does what the item does
752 (healPartner to damageEnemy, one per item) and 2 takes it from the bag
753 (item 0x55 attacks again in BATTLE_KIND_FINAL_LAST). The match depends on
754 each case's variables being its own, on item 0x47's halves being declared in
755 its `if`, on its MP test being written `maxMp <= mp + halfMp`, on item
756 0x57's cap being read after the boosts change and on the cases that say
757 the item does nothing ending on their own (item 0x2B's, 0x57's and
758 0x59's). */
760 s8 unused[0x90]; /* unused, but it is in the original stack frame */
761
762 switch (task->state) {
763 case TASK_INIT:
764 default:
765 switch (task->substate) {
766 case 0:
767 default:
768 children[0].message = FIGHTSTG_createMessage();
769 task->lines[0] = 0;
770 task->lines[1] = task->item;
771 children[0].message->show(children[0].message, 0xE, task->lines);
772 task->substate++;
773 break;
774 case 1:
775 if (children[0].task == NULL && FIGHTSTG_runItemScript(task, children)) {
776 task->nextState(task);
777 }
778 break;
779 }
780 break;
781 case TASK_RUN:
782 switch (task->substate) {
783 case 0:
784 default:
785 if (children[0].task == NULL) {
786 task->substate++;
787 }
788 break;
789 case 1:
790 switch (task->item) {
791 case 0x2B ... 0x41:
792 default:
793 healPartner(task, children);
794 break;
795 case 0x42 ... 0x45:
796 cureStatus(task, children);
797 break;
798 case 0x46:
799 reviveParty(task, children);
800 break;
801 case 0x47:
802 restoreHalfHpMp(task, children);
803 break;
804 case 0x48:
805 boostSpeed(task, children);
806 break;
807 case 0x49:
808 boostAttack(task, children);
809 break;
810 case 0x4A:
811 boostDefense(task, children);
812 break;
813 case 0x4B:
814 startSpecial(task, children);
815 break;
816 case 0x4C:
817 fillGauge(task, children);
818 break;
819 case 0x4D ... 0x53:
820 boostElement(task, children);
821 break;
822 case 0x54:
823 boostRandomElement(task, children);
824 break;
825 case 0x55:
826 drainEnemy(task, children);
827 break;
828 case 0x56:
829 confuseFighters(task, children);
830 break;
831 case 0x57:
832 weakenEnemyDefense(task, children);
833 break;
834 case 0x58:
835 showLoweredStat(task, children);
836 break;
837 case 0x59:
838 lowerEnemySpeed(task, children);
839 break;
840 case 0x5A:
841 damageEnemy(task, children);
842 break;
843 }
844 break;
845 case 2:
846 if (children[0].task == NULL) {
847 GAME.items[task->item]--;
848 if (task->item == 0x55 && FIGHTSTG_battle.state.kind == BATTLE_KIND_FINAL_LAST) {
849 children[0].enemyAttack = FIGHTSTG_startEnemyAttack(1, 0);
850 task->nextSubstate(task);
851 } else {
852 task->state = TASK_KILL;
853 }
854 }
855 break;
856 case 3:
857 if (children[0].task == NULL) {
858 task->setState(task, TASK_KILL);
859 }
860 break;
861 }
862 break;
863 case 2:
864 case TASK_KILL:
865 break;
866 }
867}
868
869/* Starts an item's script (FIGHTSTG_updateItem) */
871 BattleItem *task = createTask(FIGHTSTG_updateItem, sizeof(BattleItem), sizeof(Task *));
872
873 task->item = item;
874 return task;
875}
Battle FIGHTSTG_battle
the battle: its fighters, speed and drawing functions
Definition battle.c:16
void FIGHTSTG_queueSpecialEnd(void)
Queues the end of the partner's special state (event 21): the USA version pushes back the one already...
Definition battle.c:117
BattleFuncs FIGHTSTG_battleFuncs
the battle's stats and the functions that compute with them
Definition battle.c:25
void FIGHTSTG_queueKnockOut(u8 side)
Queues the fall of side's active fighter (event 20), first.
Definition battle.c:107
#define BATTLE_STAT_ATTACK
BattleStats.stats' indices: the partner's first five battle stats.
Definition battle.h:29
#define BATTLE_STAT_SPEED
physical accuracy, evasion and running away
Definition battle.h:33
#define ACTIVE_FIGHTER(side)
SIDE's active fighter as its row plus the index, which GCC adds with the row's address first.
Definition battle.h:493
#define BATTLE_KIND_FINAL_LAST
its third enemy; winning plays the ending
Definition battle.h:130
#define ELEMENT_COUNT
Definition battle.h:38
#define BATTLE_STAT_DEFENSE
against it
Definition battle.h:30
#define SIDE_PLAYER
The battle's sides, as the functions that take a side want them: side >> 4 is its row of FIGHTSTG_bat...
Definition battle.h:177
#define SIDE_ENEMY
Definition battle.h:178
#define ELEMENT_FIRST
The elements (TechData.element, BattleStats.element) and the families (TechData.family,...
Definition battle.h:37
#define FIGHTER_CONFUSED
Definition battle.h:184
void FIGHTSTG_inflictConfusion(u8 side, s32 fromTech, u8 strength)
Confuses side's active fighter (FIGHTER_CONFUSED) with a strength, and queues its end (put off by the...
Definition events.c:506
void FIGHTSTG_queueClearField(s32 time)
Queues the field's clearing in time (at most 0x7FFF), or moves the one already queued to it.
Definition events.c:436
EventQueue FIGHTSTG_events
the battle's events and their functions
Definition events.c:43
void FIGHTSTG_queueBoostEnd(u8 side, s32 fighter, s32 kind, s32 tech)
Queues the end of a fighter's boost of stat kind, 12 frames on when a technique (tech) gave it and 8 ...
Definition events.c:565
FIGHTSTG.PRO: the battle.
BattleScript * FIGHTSTG_createBattleScript(void)
Creates a battle script, which plays a technique (FIGHTSTG_updateBattleScript)
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
signed char s8
Definition common.h:7
EnemyAttack * FIGHTSTG_startEnemyAttack(s32 kind, s32 noKnockout)
Starts an attack on the player's active fighter (FIGHTSTG_updateEnemyAttack): kind 0 for the enemy's ...
GameState GAME
The save data, the game mode and the methods.
Definition state.c:64
#define TASK_RUN
Definition task.h:35
#define TASK_KILL
Definition task.h:37
#define TASK_INIT
Tasks: every game object is a task, a heap block that starts with this header and is updated once per...
Definition task.h:34
#define BATTLE_BLOCK_LOWER_ATTACK
to 10: attack, defense, speed (a technique's boost stat + 8)
Definition game_state.h:371
#define BATTLE_BLOCK_LOWER_SPEED
Definition game_state.h:373
#define BATTLE_BLOCK_CONFUSION
Definition game_state.h:366
#define BATTLE_BLOCK_LOWER_DEFENSE
Definition game_state.h:372
#define BATTLE_BLOCK_DRAIN
Definition game_state.h:369
static void lowerEnemyStat(BattleItem *task, BattleChild *children)
Item 0x58's setup: lowers the higher of the enemy's attack and defense (when that is the defense,...
Definition item.c:8
static void boostRandomElement(BattleItem *task, BattleChild *children)
Item 0x54: boosts the element its script picked at random on the field.
Definition item.c:531
static void boostDefense(BattleItem *task, BattleChild *children)
Item 0x4A: raises the partner's defense and lowers its attack.
Definition item.c:452
s32 FIGHTSTG_runItemScript(BattleItem *task, BattleChild *children)
An item's script (FIGHTSTG_updateItem): step 0 sets it up and deals the damage (lowerEnemyStat,...
Definition item.c:141
static void setUpDrain(BattleItem *task, BattleChild *children)
Item 0x55's setup: its drain of 20 percent of the enemy's max HP, unless the battle blocks draining.
Definition item.c:66
BattleItem * FIGHTSTG_startItem(s32 item)
Starts an item's script (FIGHTSTG_updateItem)
Definition item.c:870
static void boostAttack(BattleItem *task, BattleChild *children)
Item 0x49: raises the partner's attack and lowers its defense.
Definition item.c:416
static void confuseFighters(BattleItem *task, BattleChild *children)
Item 0x56: confuses the enemy half of the time, unless the battle blocks it, and then the partner a q...
Definition item.c:574
StatusCure FIGHTSTG_itemCures[4]
what items 0x42-0x45 cure (FIGHTSTG_updateItem, below)
Definition item.c:230
static void fillGauge(BattleItem *task, BattleChild *children)
Item 0x4C: fills the partner's gauge by the item's amount, up to 999.
Definition item.c:502
static void showLoweredStat(BattleItem *task, BattleChild *children)
Item 0x58: says which of the enemy's stats its script lowered.
Definition item.c:663
ItemScript FIGHTSTG_itemScripts[]
the items' script settings (FIGHTSTG_runItemScript, above)
Definition item.c:237
static void setItemScript(BattleItem *task, BattleChild *children)
The other items' setup: their effect and sound from FIGHTSTG_itemScripts, and the partner's idle moti...
Definition item.c:116
static void drainEnemy(BattleItem *task, BattleChild *children)
Item 0x55: drains the damage from the enemy to the partner, or says it does nothing when the battle b...
Definition item.c:543
static void boostElement(BattleItem *task, BattleChild *children)
Items 0x4D-0x53: boost one element on the field.
Definition item.c:520
void FIGHTSTG_updateItem(BattleItem *task, BattleChild *children)
An item used in battle (FIGHTSTG_startItem): its message, FIGHTSTG_runItemScript's script,...
Definition item.c:759
static void cureStatus(BattleItem *task, BattleChild *children)
Items 0x42-0x45: cure the partner of what FIGHTSTG_itemCures says, or say they do nothing.
Definition item.c:287
static void weakenEnemyDefense(BattleItem *task, BattleChild *children)
Item 0x57: raises the enemy's attack and lowers its defense, or says it does nothing when the battle ...
Definition item.c:620
static void reviveParty(BattleItem *task, BattleChild *children)
Item 0x46: revives the partners knocked out to their max HP, then is taken from the bag and ends the ...
Definition item.c:323
static void restoreHalfHpMp(BattleItem *task, BattleChild *children)
Item 0x47: restores half the partner's max HP and MP, or says it does nothing when both are full.
Definition item.c:356
static void setUpItemTech(BattleItem *task, BattleChild *children)
Item 0x5A's setup: the script of technique 0x89 and its magic damage to the enemy.
Definition item.c:91
static void lowerEnemySpeed(BattleItem *task, BattleChild *children)
Item 0x59: lowers the enemy's speed, or says it does nothing when the battle blocks it.
Definition item.c:692
static void damageEnemy(BattleItem *task, BattleChild *children)
Item 0x5A: deals its technique's damage to the enemy.
Definition item.c:726
static void healPartner(BattleItem *task, BattleChild *children)
Items 0x2B-0x41: heal the partner by the item's amount, up to its max HP.
Definition item.c:257
static void boostSpeed(BattleItem *task, BattleChild *children)
Item 0x48: raises the partner's speed by the item's amount in 128ths, up to double.
Definition item.c:389
static void startSpecial(BattleItem *task, BattleChild *children)
Item 0x4B: puts the partner in its special state, which doubles its effects.
Definition item.c:489
ItemFuncs ITEM_FUNCS
Definition items.c:890
TechData TECHS[443]
The techniques, from 1: technique n is TECHS[n - 1].
Definition items.c:906
BattleSetup BATTLE_SETUP
Definition items.c:886
BattleMessageBox * FIGHTSTG_createMessage(void)
Creates a battle message box (FIGHTSTG_updateMessage)
Definition message.c:440
Random RANDOM
Definition random.c:533
void WFIGHTMN_checkEquip(s32 member)
Queues a recovery (FIGHTSTG_queueRecovery) for party member MEMBER's partner when it has WFIGHTMN_REC...
Definition setup.c:81
One of the battle's fighters, three on each side (WFIGHTMN's BattleUnit): a partner's HP and MP go ba...
Definition battle.h:191
u8 flags
FIGHTER_*.
Definition battle.h:204
s16 boosts[4]
added to the stats FIGHTSTG_boostStats picks
Definition battle.h:200
s32(* computeMagicDamage)(u8 side, s32 id)
Definition battle.h:333
BattleStats *(* computeStats)(u8 side, s32 which, s32 index)
Definition battle.h:331
FIGHTSTG_updateItem's task: an item used in battle, FIGHTSTG_runItemScript its script.
Definition action.h:22
s32 damage
the damage
Definition action.h:27
s32 substate
Definition action.h:23
void(* nextState)(struct BattleItem *task)
Definition action.h:23
void(* nextSubstate)(struct BattleItem *task)
Definition action.h:23
s32 element
item 0x54's element, 2-8
Definition action.h:26
void(* setState)(struct BattleItem *task, s32 state)
Definition action.h:23
s32 lines[8]
FIGHTSTG_updateMessage's, 0 ends them.
Definition action.h:24
void(* nextStep)(struct BattleItem *task)
Definition action.h:23
s32 counter
Definition action.h:23
s32 step
Definition action.h:23
s32 lowered
item 0x58's: 1 it lowered the enemy's first stat, 2 its second
Definition action.h:28
s32 state
Definition action.h:23
s32 item
the item
Definition action.h:25
void(* show)()
FIGHTSTG_showMessage: (task, type, data)
Definition menu.h:182
s32 enemy
the script is the enemy's (nonzero) or the partner's
Definition effect.h:146
s32 sound
what the sound commands' 0x62 and 0x63 stand for on a hit
Definition effect.h:151
s32 effect
the sprite effect the effect command's 9999 stands for
Definition effect.h:150
s32 hits[4]
0 a hit, 3 a miss; [3] how it ended
Definition effect.h:148
s32 index
the script, in the fighter's archive
Definition effect.h:147
s32 stage
what the stage command's 0x38 stands for
Definition effect.h:149
s16 gauges[8]
filled in battle, up to 1000
Definition game_state.h:393
u8 blocks[12]
by BATTLE_BLOCK_*: what the player can't do in the battle
Definition game_state.h:389
s32 active[2]
each side's fighter
Definition battle.h:226
BattleFighter fighters[2][3]
Definition battle.h:227
s16 kind
the kind of battle
Definition battle.h:230
ElementBoost boost
Definition battle.h:228
A side's stats as FIGHTSTG_computeStats works them out.
Definition battle.h:305
s16 stats[5]
with the fighter's boosts
Definition battle.h:307
BattleState state
Definition battle.h:240
s16 amount
in 128ths
Definition battle.h:220
s16 element
under ELEMENT_FIRST: none
Definition battle.h:219
s32(* getDelay)(u8 side, s32 kind)
FIGHTSTG_getEventDelay: when an event of side's runs.
Definition battle.h:148
void(* cureStatus)(u8 side, s32 fighter, s32 item)
FIGHTSTG_cureStatus: an item's cure.
Definition battle.h:149
EventQueueFuncs funcs
Definition battle.h:171
s32(* getPartyMember)(u32 index)
Definition game_state.h:24
s8 items[0x193]
counts, up to 99
Definition game_state.h:512
GameFuncs funcs
Definition game_state.h:582
What a usable item does (its ItemInfo.data, an ITEM_EFFECT_*)
Definition game_state.h:200
u16 amount
the HP it heals, the gauge it fills, a boost in 128ths
Definition game_state.h:203
struct ItemInfo *(* get)(s32 item)
getItem
Definition game_state.h:670
ItemRecord data
the type's record, or the usable items' effect
Definition game_state.h:226
An item's script settings (FIGHTSTG_itemScripts, ended by -1)
Definition action.h:32
s16 item
Definition action.h:33
s16 effect
BattleScript's.
Definition action.h:34
s16 sound
Definition action.h:35
s32(* next)(void)
0 to RANDOM_COUNT - 1
Definition random.h:15
What an item cures (FIGHTSTG_itemCures, items 0x42-0x45)
Definition action.h:51
s16 flag
in BattleFighter.flags
Definition action.h:53
s32 item
FIGHTSTG_events.funcs.cureStatus's.
Definition action.h:54
s16 message
Definition action.h:52
Any task, seen through its header.
Definition task.h:62
A technique (TECHS, from 1: technique n is TECHS[n - 1])
Definition game_state.h:110
u8 scriptSound
its script's hit sound (BattleScript.sound)
Definition game_state.h:124
u8 scriptEffect
its script's sprite effect (BattleScript.effect)
Definition game_state.h:123
u8 scriptStage
its script's stage (BattleScript.stage)
Definition game_state.h:122
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
s32 WFIGHTMN_limitDamage(u8 side, s32 damage, s32 hits)
In BATTLE_KIND_ESCAPE and BATTLE_KIND_UNK2, cuts the damage that the partner's hits do so that the en...
Definition techs.c:321
void WFIGHTMN_countHit(u8 side, s32 damage)
In BATTLE_KIND_FINAL_LAST, the partner's third hit that does damage weakens the enemy (FIGHTSTG's FIG...
Definition techs.c:301
void WFIGHTMN_endWeakness(u8 side)
In BATTLE_KIND_FINAL_LAST, anything the partner does but an attack ends the enemy's weakness (FIGHTST...
Definition techs.c:312
s32 WFIGHTMN_setIdleMotion(u8 id, s32 damage)
Sets the idle motion of side id >> 4's fighter: 1 (weak) if damage leaves it with a quarter of its HP...
Definition techs.c:280
A turn's or a counterattack's one child, and what WFIGHTMN's battle menu waits for (NULL when it is d...
Definition task.h:16
BattleMessageBox * message
FIGHTSTG_createMessage.
Definition task.h:18
BattleScript * script
a technique's (FIGHTSTG_createBattleScript)
Definition task.h:19
EnemyAttack * enemyAttack
an attack on the player's fighter (FIGHTSTG_startEnemyAttack)
Definition task.h:25
ItemEffect * effect
Definition game_state.h:211