Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
enemy_turn.c
Go to the documentation of this file.
1/* FIGHTSTG's enemy turn: the enemy's pick of its action from its battle
2 table entry, and its conditions. */
3
5
6/* The enemy that the enemy's turn (FIGHTSTG_updateEnemyTurn) switches to:
7 task->target's, or one of the others at random (not the active one), -1
8 for none */
11 s32 found[2];
12 s32 count;
13 s32 active;
14 s32 i;
15
16 switch (task->target) {
17 case -2:
18 if (enemies[0].id == enemies[FIGHTSTG_battle.state.active[1]].id) {
19 break;
20 }
21 if (enemies[0].hp != 0) {
22 return 0;
23 }
24 break;
25 case -3:
26 if (enemies[1].id == enemies[FIGHTSTG_battle.state.active[1]].id) {
27 break;
28 }
29 if (enemies[1].hp != 0) {
30 return 1;
31 }
32 break;
33 case -4:
34 if (enemies[2].id == enemies[FIGHTSTG_battle.state.active[1]].id) {
35 break;
36 }
37 if (enemies[2].hp != 0) {
38 return 2;
39 }
40 break;
41 default:
42 count = 0;
43 found[0] = -1;
44 found[1] = -1;
45 active = FIGHTSTG_battle.state.active[1];
46 for (i = 0; i < 3; i++) {
47 enemies = &FIGHTSTG_battle.state.fighters[1][i];
48 if (active != i && enemies->id != 0 && enemies->hp != 0) {
49 found[count++] = i;
50 }
51 }
52 /* the match depends on case 0 and on reusing enemies */
53 switch (count) {
54 case 0:
55 break;
56 case 1:
57 return found[0];
58 case 2:
59 return found[RANDOM.next() & 1];
60 }
61 break;
62 }
63 return -1;
64}
65
66/* In BATTLE_KIND_ESCAPE, the enemy flees once its HP is under a tenth;
67 otherwise its turn goes on to the next state. */
68static inline void fleeWhenWeak(EnemyTurn *task, BattleChild *children) {
71
72 if (enemy->hp < (s16)(enemy->maxHp / 10)) {
73 children->message = FIGHTSTG_createMessage();
74 task->lines[0] = 0x5F;
75 task->lines[1] = 0x10;
76 children->message->show(children->message, 2, task->lines);
78 task->substate++;
79 } else {
80 task->nextState(task);
81 }
82 } else {
83 task->nextState(task);
84 }
85}
86
87/* Shows the enemy's run-away event, if it has one, and clears it before its
88 turn goes on. */
89static inline void showRunAway(EnemyTurn *task, BattleChild *children) {
90 s32 index;
91
92 switch (task->step) {
93 case 0:
94 default:
96 if (index >= 0) {
97 children->message = FIGHTSTG_createMessage();
98 task->lines[0] = 0x60;
99 task->lines[1] = 0x10;
100 children->message->show(children->message, 2, task->lines);
101 FIGHTSTG_events.events[index].type = 0;
102 task->step++;
103 } else {
104 task->nextSubstate(task);
105 }
106 break;
107 case 1:
108 if (children->message == NULL) {
109 task->nextSubstate(task);
110 }
111 break;
112 }
113}
114
115/* Starts the enemy's attack (target 1) or technique TARGET, paying its MP,
116 or shows the message for an enemy without the MP for it. */
117static inline void useEnemyTech(EnemyTurn *task, BattleChild *children) {
118 BattleFighter *fighter;
119 TechData *tech;
120
121 if (task->target == 1) {
122 children->attack = FIGHTSTG_startFirstTech(0x10);
123 } else {
125 tech = &TECHS[task->target - 1];
126 if (fighter->mp >= tech->mp) {
128 fighter->mp -= tech->mp;
129 } else {
130 children->message = FIGHTSTG_createMessage();
131 task->lines[0] = 0x8D;
132 task->lines[1] = 0x10;
133 children->message->show(children->message, 2, task->lines);
134 }
135 }
136}
137
138/* Says the name of the enemy that came in. */
139static inline void showEnemyName(EnemyTurn *task, BattleChild *children) {
142
143 children->message = FIGHTSTG_createMessage();
144 task->lines[0] = enemy->nameId;
145 children->message->show(children->message, 0xD, task->lines);
146}
147
148/* Picks the enemy to switch in (FIGHTSTG_pickEnemySwitch) and shows the
149 switch's message, or the one for no enemy to switch in. */
150static inline void switchEnemyOut(EnemyTurn *task, BattleChild *children) {
151 s32 pick = FIGHTSTG_pickEnemySwitch(task);
152
153 if (pick != -1) {
154 task->switchTo = pick;
155 children->message = FIGHTSTG_createMessage();
156 task->lines[0] = 0x4D;
157 children->message->show(children->message, 1, task->lines);
158 task->substate = 5;
159 } else {
160 children->message = FIGHTSTG_createMessage();
161 task->lines[0] = 0x8E;
162 task->lines[1] = 0x10;
163 children->message->show(children->message, 2, task->lines);
164 task->substate = 3;
165 }
166}
167
168/* The enemy's turn: a message when its HP is under a tenth, then one when it is asleep,
169 paralyzed or confused, or else the first action of its battle table entry whose condition holds,
170 and what its target makes it do: attack, a technique, a switch to another enemy
171 (FIGHTSTG_pickEnemySwitch) or a message. The match depends on the goto into the confusion
172 branch, the case -1 next to default, and the enemies pointers of showEnemyName and
173 substate 5. */
175 BattleFighter *fighter;
176 BattleTableEntry *entry;
177 s32 message;
178 s32 i;
179
180 switch (task->state) {
181 case 0:
182 default:
183 switch (task->substate) {
184 case 0:
185 default:
186 fleeWhenWeak(task, children);
187 break;
188 case 1:
189 if (children->message == NULL) {
190 task->state = 3;
191 }
192 break;
193 }
194 break;
195 case 1:
196 switch (task->substate) {
197 case 0:
198 default:
199 showRunAway(task, children);
200 break;
201 case 1:
203 if (fighter->flags & FIGHTER_ASLEEP) {
204 children->message = FIGHTSTG_createMessage();
205 message = 0x90;
206 goto show;
207 }
209 children->message = FIGHTSTG_createMessage();
210 message = 0x56;
211 goto show;
212 }
213 if (fighter->flags & FIGHTER_CONFUSED) {
214 children->message = FIGHTSTG_createMessage();
215 message = RANDOM.next() % 8 + 0x83;
216 show:
217 task->lines[0] = message;
218 task->lines[1] = 0x10;
219 children->message->show(children->message, 2, task->lines);
220 task->setSubstate(task, 3);
221 break;
222 }
223 i = 0;
224 entry = FIGHTSTG_battleTableFunc(fighter->id);
225 for (; i < BATTLE_TABLE_FALLBACK; i++) {
226 if (FIGHTSTG_testEnemyCondition(entry->actions[i].condition, entry->actions[i].conditionArg) != 0) {
227 break;
228 }
229 }
230 task->target = FIGHTSTG_getEnemyAction(entry->actions[i].target);
231 task->substate++;
232 break;
233 case 2:
234 if (task->target > 0) {
235 useEnemyTech(task, children);
236 task->substate = 3;
237 } else if (task->target < 0) {
238 switch (task->target) {
239 case -1:
240 default:
242 children->message = FIGHTSTG_createMessage();
243 task->lines[0] = 0x5E;
244 task->lines[1] = 0x10;
245 children->message->show(children->message, 2, task->lines);
246 task->substate = 3;
247 break;
248 case -2:
249 case -3:
250 case -4:
251 case -5:
252 switchEnemyOut(task, children);
253 break;
254 }
255 }
256 break;
257 case 3:
258 if (children->message == NULL) {
259 task->state = 3;
261 }
262 break;
263 case 4:
264 if (children->message == NULL) {
265 showEnemyName(task, children);
266 task->substate = 3;
267 }
268 break;
269 case 5:
270 if (children->message == NULL) {
272
273 children->entrance = FIGHTSTG_startEntrance(enemies[task->switchTo].id, 1, 0);
275 task->substate = 6;
276 }
277 break;
278 case 6:
279 if (children->entrance->done) {
281 task->substate = 4;
282 }
283 break;
284 }
285 break;
286 case 2:
287 case 3:
288 break;
289 }
290}
291
292/* Starts the enemy's turn (FIGHTSTG_updateEnemyTurn) */
294 return createTask(FIGHTSTG_updateEnemyTurn, sizeof(EnemyTurn), 2 * sizeof(Task *));
295}
296
297/* Whether the condition of an enemy's action holds (BattleTableAction): always, a
298 chance in 128, the enemy's or the partner's HP over or under a share, its MP, the
299 partner's Digimon or flags, the other enemies, the battle and the enemy's boosts.
300 The match depends on the one fighter pointer that the cases set as they need it,
301 on case 1 keeping its roll in the same variable as the HP share, and on case 10's
302 own loop counter. */
305 s32 result = 0;
306 s32 percent;
307 s32 j;
308 DigimonData *digimon;
309 s32 i;
310
311 switch (condition) {
312 case 0:
313 default:
314 result = 1;
315 break;
316 case 1:
317 percent = RANDOM.next() % 128;
318 if (percent < arg) {
319 result = 1;
320 }
321 break;
322 case 2:
323 percent = arg * 100 / 128;
324 if (fighter->hp < (s16)(fighter->maxHp / 100) * percent) {
325 result = 1;
326 }
327 break;
328 case 3:
329 percent = arg * 100 / 128;
330 if (fighter->hp >= (s16)(fighter->maxHp / 100) * percent) {
331 result = 1;
332 }
333 break;
334 case 4:
335 if (fighter->mp < arg) {
336 result = 1;
337 }
338 break;
339 case 5:
340 if (fighter->mp >= arg) {
341 result = 1;
342 }
343 break;
344 case 6:
346 percent = arg * 100 / 128;
347 if (fighter->hp < (s16)(fighter->maxHp / 100) * percent) {
348 result = 1;
349 }
350 break;
351 case 7:
353 percent = arg * 100 / 128;
354 if (fighter->hp >= (s16)(fighter->maxHp / 100) * percent) {
355 result = 1;
356 }
357 break;
358 case 8:
360 for (i = 0, digimon = DIGIMON_DATA; i < 8; i++, digimon++) {
361 if (fighter->id == digimon->id) {
362 result = 1;
363 break;
364 }
365 }
366 break;
367 case 9:
369 if (fighter->flags & FIGHTER_ASLEEP) {
370 result = 1;
371 }
372 break;
373 case 10:
374 fighter = FIGHTSTG_battle.state.fighters[1];
375 if (arg == 0) {
376 for (j = 0; j < 3; j++) {
377 if (j != FIGHTSTG_battle.state.active[1] && fighter[j].id != 0 && fighter[j].hp != 0) {
378 result = 1;
379 break;
380 }
381 }
382 } else {
383 for (j = 0; j < 3; j++) {
384 if (j != FIGHTSTG_battle.state.active[1] && fighter[j].id == arg && fighter[j].hp != 0) {
385 result = 1;
386 break;
387 }
388 }
389 }
390 break;
391 case 11:
392 if (FIGHTSTG_battle.state.boost.element == arg) {
393 result = 1;
394 }
395 break;
396 case 12:
397 if (BATTLE_SETUP.battle == arg) {
398 result = 1;
399 }
400 break;
401 case 13:
402 if (BATTLE_SETUP.encounterKind == arg) {
403 result = 1;
404 }
405 break;
406 case 14:
407 if (fighter->charge != 0) {
408 result = 1;
409 }
410 break;
411 case 15:
412 if (fighter->boosts[0] < 0) {
413 result = 1;
414 }
415 break;
416 case 16:
417 if (fighter->boosts[1] < 0) {
418 result = 1;
419 }
420 break;
421 case 17:
422 if (fighter->boosts[2] < 0) {
423 result = 1;
424 }
425 break;
426 case 18:
427 if (fighter->turns % arg == 0) {
428 result = 1;
429 }
430 break;
431 }
432 return result;
433}
434
435/* What an enemy's action target makes it do (EnemyTurn.target): 1 its first
436 technique, its battle table entry's second or third technique, or -1 to -5
437 for the other actions */
440 s32 value = 0;
442
443 switch (kind) {
444 case 1:
445 value = 1;
446 break;
447 case 2:
448 value = entry->techs[1];
449 break;
450 case 3:
451 value = entry->techs[2];
452 break;
453 case 4:
454 value = -1;
455 break;
456 case 5:
457 value = -2;
458 break;
459 case 6:
460 value = -3;
461 break;
462 case 7:
463 value = -4;
464 break;
465 case 8:
466 value = -5;
467 break;
468 }
469 return value;
470}
Battle FIGHTSTG_battle
the battle: its fighters, speed and drawing functions
Definition battle.c:16
BattleFuncs FIGHTSTG_battleFuncs
the battle's stats and the functions that compute with them
Definition battle.c:25
#define FIGHTER_PARALYZED
loses turns at random (FIGHTSTG_battleFuncs.testParalysis)
Definition battle.h:183
#define BATTLE_KIND_ESCAPE
the enemy runs away under a tenth of its HP
Definition battle.h:125
#define EVENT_RUN_AWAY
Definition battle.h:84
#define BATTLE_FLED
How a battle ends (FIGHTSTG_endBattle)
Definition battle.h:133
#define BATTLE_TABLE_FALLBACK
BattleTableEntry.actions' last one, which the enemy takes when none of the others' conditions holds: ...
Definition battle.h:56
#define FIGHTER_ASLEEP
can't act or run away; a hit may wake it up
Definition battle.h:185
#define SIDE_ENEMY
Definition battle.h:178
#define FIGHTER_CONFUSED
Definition battle.h:184
void FIGHTSTG_endBattle(s32 result)
Ends the battle: queues event 1 ahead of the others, with how it ended (BATTLE_FLED,...
Definition events.c:377
void FIGHTSTG_queueRunAway(u8 side)
Queues side's attempt to run away (event 4)
Definition events.c:386
EventQueue FIGHTSTG_events
the battle's events and their functions
Definition events.c:43
void FIGHTSTG_queueEnemyTurn(s32 delay)
Queues the enemy's turn (event 3) in delay.
Definition events.c:368
FIGHTSTG.PRO: the battle.
BattleTableEntry *(* FIGHTSTG_battleTableFunc)(s32 id)
how the fight stage and WFIGHTMN read the battle table
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
signed short s16
Definition common.h:9
unsigned char u8
Definition common.h:8
DigimonData DIGIMON_DATA[55]
55 entries: the 52 Digimon, then three placeholders (0x1D4-0x1D6)
Definition digimon.c:7
s32 FIGHTSTG_getEnemyAction(u8 kind)
What an enemy's action target makes it do (EnemyTurn.target): 1 its first technique,...
Definition enemy_turn.c:438
s32 FIGHTSTG_testEnemyCondition(u8 condition, s16 arg)
Whether the condition of an enemy's action holds (BattleTableAction): always, a chance in 128,...
Definition enemy_turn.c:303
void FIGHTSTG_updateEnemyTurn(EnemyTurn *task, BattleChild *children)
The enemy's turn: a message when its HP is under a tenth, then one when it is asleep,...
Definition enemy_turn.c:174
static void useEnemyTech(EnemyTurn *task, BattleChild *children)
Starts the enemy's attack (target 1) or technique TARGET, paying its MP, or shows the message for an ...
Definition enemy_turn.c:117
s32 FIGHTSTG_pickEnemySwitch(EnemyTurn *task)
The enemy that the enemy's turn (FIGHTSTG_updateEnemyTurn) switches to: task->target's,...
Definition enemy_turn.c:9
static void switchEnemyOut(EnemyTurn *task, BattleChild *children)
Picks the enemy to switch in (FIGHTSTG_pickEnemySwitch) and shows the switch's message,...
Definition enemy_turn.c:150
static void showRunAway(EnemyTurn *task, BattleChild *children)
Shows the enemy's run-away event, if it has one, and clears it before its turn goes on.
Definition enemy_turn.c:89
static void showEnemyName(EnemyTurn *task, BattleChild *children)
Says the name of the enemy that came in.
Definition enemy_turn.c:139
static void fleeWhenWeak(EnemyTurn *task, BattleChild *children)
In BATTLE_KIND_ESCAPE, the enemy flees once its HP is under a tenth; otherwise its turn goes on to th...
Definition enemy_turn.c:68
EnemyTurn * FIGHTSTG_startEnemyTurn(void)
Starts the enemy's turn (FIGHTSTG_updateEnemyTurn)
Definition enemy_turn.c:293
Entrance * FIGHTSTG_startEntrance(s32 id, s32 side, s32 weak)
Starts a fighter's entrance: Digimon id on the player's side (side 0) or the enemy's.
Definition entrance.c:175
FirstTech * FIGHTSTG_startFirstTech(s32 side)
Starts side's first technique (FIGHTSTG_updateFirstTech)
Definition first_tech.c:238
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
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 charge
added in 64ths to its next technique's damage, which uses it up
Definition battle.h:199
s16 id
the Digimon (DIGIMON_DATA)
Definition battle.h:192
s16 boosts[4]
added to the stats FIGHTSTG_boostStats picks
Definition battle.h:200
s16 turns
an enemy's, for its battle table's conditions
Definition battle.h:194
s32(* testParalysis)(u8 side)
whether side's paralysis costs it the turn
Definition battle.h:358
void(* show)()
FIGHTSTG_showMessage: (task, type, data)
Definition menu.h:182
s32 battle
the battle (BattleResult.battle)
Definition game_state.h:384
u8 encounterKind
Encounter.kind; only the enemies' condition 13 reads it.
Definition game_state.h:388
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
s16 nameId
string in file 0x4F
Definition battle.h:62
BattleTableAction actions[3+1]
the first whose condition holds (FIGHTSTG_testEnemyCondition)
Definition battle.h:67
s16 techs[3]
its first, then those of FIGHTSTG_getEnemyAction's kinds 2 and 3
Definition battle.h:63
BattleState state
Definition battle.h:240
Digimon definition (DIGIMON_DATA, 52 of them; the first 8 are the partners)
Definition game_state.h:86
s16 element
under ELEMENT_FIRST: none
Definition battle.h:219
FIGHTSTG_startEnemyTurn's task.
Definition battle.h:72
s32 step
Definition battle.h:73
void(* nextSubstate)(struct EnemyTurn *task)
Definition battle.h:73
void(* setSubstate)(struct EnemyTurn *task, s32 substate)
Definition battle.h:73
s32 state
Definition battle.h:73
void(* nextState)(struct EnemyTurn *task)
Definition battle.h:73
s32 lines[10]
FIGHTSTG_updateMessage's, 0 ends them.
Definition battle.h:74
s32 switchTo
the enemy fighter it brings in (FIGHTSTG_pickEnemySwitch)
Definition battle.h:76
s32 substate
Definition battle.h:73
s32 target
-2 to -4 for an enemy, else any but the active one
Definition battle.h:75
s32 done
Definition effect.h:133
s32(* getDelay)(u8 side, s32 kind)
FIGHTSTG_getEventDelay: when an event of side's runs.
Definition battle.h:148
s32(* find)(s32 type, u8 side, s32 fighter)
Definition battle.h:146
EventQueueFuncs funcs
Definition battle.h:171
QueuedEvent events[99]
Definition battle.h:165
s16 type
0 for a free entry
Definition battle.h:110
s32(* next)(void)
0 to RANDOM_COUNT - 1
Definition random.h:15
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
u16 mp
its cost
Definition game_state.h:111
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
TechAction * FIGHTSTG_startTechAction(s32 side, s32 tech)
Starts side's (0 or 0x10) technique or item tech.
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
Entrance * entrance
a fighter's (FIGHTSTG_startEntrance)
Definition task.h:20
BattleMessageBox * message
FIGHTSTG_createMessage.
Definition task.h:18
FirstTech * attack
FIGHTSTG_startFirstTech.
Definition task.h:22
TechAction * tech
a technique or an item (FIGHTSTG_startTechAction)
Definition task.h:23