Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
hud.c
Go to the documentation of this file.
1/* FIGHTSTG's HUD: the fighters' names, HP and MP bars and the technique gauge. */
2
4
5/* Every frame: the hp tween of a side whose active fighter changed jumps to
6 * that fighter's hp; every interval, a side's tween starts easing (30 frames)
7 * to its fighter's hp, clamped to 0 and the max hp, when that changed. The
8 * match depends on a counter for each loop and the side's row of fighters. */
10 s32 hp;
11 s32 i;
12 s32 j;
13 BattleFighter *row;
14
15 task->timer += GFX.funcs.getFrameTime();
16 for (i = 0; i < 2; i++) {
18 if (task->hp[i].fighter != FIGHTSTG_battle.state.active[i]) {
19 task->hp[i].from = row[FIGHTSTG_battle.state.active[i]].hp;
20 task->hp[i].to = row[FIGHTSTG_battle.state.active[i]].hp;
21 task->hp[i].value = row[FIGHTSTG_battle.state.active[i]].hp;
22 task->hp[i].active = 0;
24 }
25 }
26 if (task->timer > task->interval) {
27 task->timer -= task->interval;
28 for (j = 0; j < 2; j++) {
30 hp = row[FIGHTSTG_battle.state.active[j]].hp;
31 if (hp <= 0) {
32 hp = 0;
33 }
34 if (hp > row[FIGHTSTG_battle.state.active[j]].maxHp) {
35 hp = row[FIGHTSTG_battle.state.active[j]].maxHp;
36 }
37 if (hp != task->hp[j].to) {
38 task->hp[j].from = task->hp[j].value;
39 task->hp[j].to = hp;
40 task->hp[j].active = 1;
41 task->hp[j].time = 0;
42 task->hp[j].duration = 30;
43 }
44 }
45 }
46}
47
48/* Eases an HP number towards its target over its duration, along a sine */
50 s32 t;
51
52 if (tween->active != 0) {
53 tween->time += GFX.funcs.getFrameTime();
54 if (tween->time >= tween->duration) {
55 tween->active = 0;
56 tween->from = tween->value = tween->to;
57 } else {
58 t = rsin((tween->time << 10) / tween->duration) * tween->duration / 4096;
59 tween->value = tween->from + (tween->to - tween->from) * t / tween->duration;
60 }
61 }
62}
63
64/* Shows the names of both sides' active fighters, when they changed */
66 BattleTableEntry *enemy;
67 s32 i;
68
69 if (FIGHTSTG_battle.state.active[0] != task->shown[0]) {
70 if (windows[0] == NULL) {
71 windows[0] = createTextWindow(BATTLE_LAYER_MENUS, 1, 0xAE, 0x15);
72 }
74 }
75 if (FIGHTSTG_battle.state.active[1] != task->shown[1]) {
77 if (windows[1] == NULL) {
78 windows[1] = createTextWindow(BATTLE_LAYER_MENUS, 1, 0x11, 0x15);
79 }
80 if (enemy != NULL) {
81 windows[1]->setString(windows[1], FILE_CACHE.load(TEXT_FILE(TEXT_DIGIMON_NAMES)), enemy->nameId);
82 }
83 }
84 for (i = 0; i < 2; i++) {
85 task->shown[i] = FIGHTSTG_battle.state.active[i];
86 }
87}
88
89/* FIGHTSTG_drawHud's HP bars, one row per side; the European version swaps
90 side 1's ends, so that its bar shrinks toward its right end */
91#if VERSION_US
92DVECTOR FIGHTSTG_hpBars[2][4] = {
93 { { 0xAF, 0x25 }, { 0x12F, 0x25 }, { 0xAF, 0x2B }, { 0x12F, 0x2B } },
94 { { 0x0F, 0x25 }, { 0x8F, 0x25 }, { 0x0F, 0x2B }, { 0x8F, 0x2B } },
95};
96#elif VERSION_EU || VERSION_JP
97DVECTOR FIGHTSTG_hpBars[2][4] = {
98 { { 0xAF, 0x25 }, { 0x12F, 0x25 }, { 0xAF, 0x2B }, { 0x12F, 0x2B } },
99 { { 0x8F, 0x25 }, { 0x0F, 0x25 }, { 0x8F, 0x2B }, { 0x0F, 0x2B } },
100};
101#endif
102/* the bars' colours: above and at a quarter of the HP */
104 { 0x00, 0x71, 0x28, 0x00 },
105 { 0x00, 0xC8, 0x3E, 0x00 },
106 { 0xB3, 0x37, 0x16, 0x00 },
107 { 0xFF, 0x37, 0x0D, 0x00 },
108};
109/* the technique gauge, and its colours */
110DVECTOR FIGHTSTG_techGauge[4] = {
111 { 0x109, 0x3E }, { 0x131, 0x3E }, { 0x109, 0x46 }, { 0x131, 0x46 },
112};
114 { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
115};
116/* the fighter icons' x, for each side and slot */
118 { 0x010F, 0x011A, 0x0125 },
119 { 0x0025, 0x001A, 0x000F },
120};
121
122/* Draws the battle HUD: both HP bars, the technique gauge (full at 1000) and
123 the fighters' icons */
124void FIGHTSTG_drawHud(HpDisplay *task, TextWindow **windows) {
125 SpriteDrawer drawer;
126 CVECTOR colors[4];
127 BattleFighter *fighter;
128 void *sheet;
129 s32 width;
130 s32 blink;
131 s32 member;
132 s32 frame;
133 s32 i;
134 s32 side;
135 s32 slot;
136
137 sheet = FILE_CACHE.getEntry(FILE_BATTLE_MENU << 16);
138 initSpriteDrawer(&drawer);
140 drawer.setTexture(0x200, 0);
141 drawer.draw(sheet, 0, 8, 0xF);
142 drawer.draw(sheet, 1, 0xA1, 0xF);
143 FIGHTSTG_showFighterNames(task, windows);
145 if (windows[4] == NULL) {
146 windows[4] = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x10B, 0x1A);
147 }
148 windows[4]->setNumber(windows[4], 0, task->hp[0].value);
149 windows[4]->setRightAlign(windows[4], 1);
150 if (windows[3] == NULL) {
151 windows[3] = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x12E, 0x1A);
152 }
153 windows[3]->setNumber(windows[3], 0, fighter->maxHp);
154 windows[3]->setRightAlign(windows[3], 1);
155 for (i = 0; i < 2; i++) {
157 width = (task->hp[i].value << 7) / fighter->maxHp;
158 if (task->hp[i].value > 0 && width < 4) {
159 width = 3;
160 }
161#if VERSION_EU || VERSION_JP
162 /* the match depends on testing i == 0 first (i != 0 gives 13 diffs) */
163 if (i == 0) {
164 FIGHTSTG_hpBars[i][1].vx = FIGHTSTG_hpBars[i][0].vx + width;
165 FIGHTSTG_hpBars[i][3].vx = FIGHTSTG_hpBars[i][2].vx + width;
166 } else {
167 FIGHTSTG_hpBars[i][1].vx = FIGHTSTG_hpBars[i][0].vx - width;
168 FIGHTSTG_hpBars[i][3].vx = FIGHTSTG_hpBars[i][2].vx - width;
169 }
170#else
171 FIGHTSTG_hpBars[i][1].vx = FIGHTSTG_hpBars[i][0].vx + width;
172 FIGHTSTG_hpBars[i][3].vx = FIGHTSTG_hpBars[i][2].vx + width;
173#endif
174 if ((fighter->maxHp >> 2) < task->hp[i].value) {
175 colors[0] = colors[2] = FIGHTSTG_hpBarColors[0];
176 colors[1] = colors[3] = FIGHTSTG_hpBarColors[1];
177 } else {
178 colors[0] = colors[2] = FIGHTSTG_hpBarColors[2];
179 colors[1] = colors[3] = FIGHTSTG_hpBarColors[3];
180 }
182 }
183 blink = (GFX.funcs.getTime() >> 2) & 3;
185 drawer.draw(sheet, 0x1E, 0x104, 0x3D);
186 if (BATTLE_SETUP.gauges[member] < 1000) {
187 /* the match depends on storing [2] before [0] (the other order gives 2
188 diffs) */
189 FIGHTSTG_techGauge[2].vx = FIGHTSTG_techGauge[0].vx = BATTLE_SETUP.gauges[member] / 25 + 0x109;
191 }
192 if (BATTLE_SETUP.gauges[member] < 1000) {
193 drawer.draw(sheet, blink + 0x33, 0x109, 0x3E);
194 } else {
195 drawer.draw(sheet, blink + 0x37, 0x109, 0x3E);
196 }
197 drawer.draw(sheet, 0xB, 0x104, 0x3D);
198 for (side = 0; side < 2; side++) {
199 for (slot = 0; slot < 3; slot++) {
200 if (FIGHTSTG_battle.state.kind >= BATTLE_KIND_FINAL && slot > 0 && side > 0) {
201 return;
202 }
203 fighter = &FIGHTSTG_battle.state.fighters[side][slot];
204 if (fighter->id != 0) {
205 if (fighter->flags != 0) {
206 frame = 3;
207 } else if (fighter->hp == 0) {
208 frame = 2;
209 } else {
210 frame = fighter->hp != fighter->maxHp;
211 }
212 if (FIGHTSTG_battle.state.active[side] == slot) {
213 frame += 0xC;
214 } else {
215 frame += 0x3C;
216 }
217 drawer.draw(sheet, frame, FIGHTSTG_iconX[side][slot], 0x30);
218 }
219 }
220 }
221}
222
223/* The battle HUD's task: makes its windows and starts the HP numbers at the
224 fighters' HP, then each frame eases them and draws the HUD
225 (FIGHTSTG_drawHud) */
227 s32 i;
228 BattleFighter (*fighters)[3];
229
230 switch (task->state) {
231 case TASK_INIT:
232 default:
233 task->shown[1] = -1;
234 task->shown[0] = -1;
235 FIGHTSTG_showFighterNames(task, windows);
236 windows[2] = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x10C, 0x1A);
237 windows[2]->setString(windows[2], FILE_CACHE.load(TEXT_FILE(TEXT_BATTLE_MENU)), 0x10);
238 fighters = FIGHTSTG_battle.state.fighters;
239 windows[4] = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x10B, 0x1A);
240 windows[4]->setNumber(windows[4], 0, fighters[0][FIGHTSTG_battle.state.active[0]].hp);
241 windows[4]->setRightAlign(windows[4], 1);
242 windows[3] = createTextWindow(BATTLE_LAYER_MENUS, 3, 0x12E, 0x1A);
243 windows[3]->setNumber(windows[3], 0, fighters[0][FIGHTSTG_battle.state.active[0]].maxHp);
244 windows[3]->setRightAlign(windows[3], 1);
245 for (i = 0; i < 2; i++) {
246 task->hp[i].from = fighters[i][FIGHTSTG_battle.state.active[i]].hp;
247 task->hp[i].to = fighters[i][FIGHTSTG_battle.state.active[i]].hp;
248 task->hp[i].value = fighters[i][FIGHTSTG_battle.state.active[i]].hp;
249 task->hp[i].active = 0;
250 task->hp[i].fighter = FIGHTSTG_battle.state.active[i];
251 task->hp[i].time = 0;
252 task->hp[i].duration = 0;
253 }
254 task->timer = 0;
255 task->interval = 8;
256 task->nextState(task);
257 break;
258 case TASK_RUN:
259 FIGHTSTG_updateHpTweens(task, windows);
260 FIGHTSTG_stepHpTween(&task->hp[0]);
261 FIGHTSTG_stepHpTween(&task->hp[1]);
262 FIGHTSTG_drawHud(task, windows);
263 break;
264 case TASK_DONE:
265 task->nextState(task);
266 break;
267 case TASK_KILL:
268 break;
269 }
270}
271
272/* Creates the battle HUD (FIGHTSTG_updateHud) */
274 return createTask(FIGHTSTG_updateHud, sizeof(HpDisplay), 5 * sizeof(TextWindow *));
275}
Battle FIGHTSTG_battle
the battle: its fighters, speed and drawing functions
Definition battle.c:16
#define BATTLE_KIND_FINAL
battle 0x144, the last one: its first enemy
Definition battle.h:128
#define BATTLE_LAYER_MENUS
the HUD, the menus and the messages
Definition types.h:31
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
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
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 TASK_DONE
Definition task.h:36
#define TEXT_BATTLE_MENU
MFIGHT: WFIGHTMN's.
Definition file.h:218
#define TEXT_FILE(file)
Definition file.h:190
#define TEXT_DIGIMON_NAMES
DIGNAM.
Definition file.h:211
#define FILE_BATTLE_MENU
The battle menu's files (WFIGHTMN, WFIGHTTS): FILE_BATTLE_IMAGES is an archive whose entries go throu...
Definition file.h:294
FileCache FILE_CACHE
The file cache.
Definition file_cache.c:7
DVECTOR FIGHTSTG_hpBars[2][4]
FIGHTSTG_drawHud's HP bars, one row per side; the European version swaps side 1's ends,...
Definition hud.c:97
void FIGHTSTG_stepHpTween(HpTween *tween)
Eases an HP number towards its target over its duration, along a sine.
Definition hud.c:49
CVECTOR FIGHTSTG_techGaugeColors[4]
Definition hud.c:113
CVECTOR FIGHTSTG_hpBarColors[4]
the bars' colours: above and at a quarter of the HP
Definition hud.c:103
void FIGHTSTG_updateHud(HpDisplay *task, TextWindow **windows)
The battle HUD's task: makes its windows and starts the HP numbers at the fighters' HP,...
Definition hud.c:226
void FIGHTSTG_drawHud(HpDisplay *task, TextWindow **windows)
Draws the battle HUD: both HP bars, the technique gauge (full at 1000) and the fighters' icons.
Definition hud.c:124
void FIGHTSTG_showFighterNames(HpDisplay *task, TextWindow **windows)
Shows the names of both sides' active fighters, when they changed.
Definition hud.c:65
void FIGHTSTG_updateHpTweens(HpDisplay *task, TextWindow **windows)
Every frame: the hp tween of a side whose active fighter changed jumps to that fighter's hp; every in...
Definition hud.c:9
DVECTOR FIGHTSTG_techGauge[4]
the technique gauge, and its colours
Definition hud.c:110
s16 FIGHTSTG_iconX[2][3]
the fighter icons' x, for each side and slot
Definition hud.c:117
HpDisplay * FIGHTSTG_createHud(void)
Creates the battle HUD (FIGHTSTG_updateHud)
Definition hud.c:273
BattleSetup BATTLE_SETUP
Definition items.c:886
void initSpriteDrawer(SpriteDrawer *obj)
Clears a sprite drawer to neutral (no scale, gray tint, follows the scroll), gives it its methods and...
s32 fighter
0 for none
Definition game_state.h:354
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 id
the Digimon (DIGIMON_DATA)
Definition battle.h:192
s16 gauges[8]
filled in battle, up to 1000
Definition game_state.h:393
BattleEnemy enemies[3]
Definition game_state.h:386
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
s16 nameId
string in file 0x4F
Definition battle.h:62
void(* drawQuad)(s32 layerId, s32 depth, DVECTOR *xy, CVECTOR *colors)
Definition battle.h:245
BattleState state
Definition battle.h:240
void *(* load)(u32 file)
Definition file.h:92
void *(* getEntry)(u32 fileAndIndex)
Definition file.h:96
s32(* getPartyMember)(u32 index)
Definition game_state.h:24
Partner partners[PARTNER_COUNT]
Definition game_state.h:517
GameFuncs funcs
Definition game_state.h:582
s32(* getFrameTime)(void)
Definition gfx.h:32
s32(* getTime)(void)
Definition gfx.h:31
GfxFuncs funcs
Definition gfx.h:77
FIGHTSTG_createHud's task: the names and the hp of the fighters out.
Definition menu.h:22
s32 interval
how often the hp is checked
Definition menu.h:27
s32 state
Definition menu.h:23
s32 shown[2]
the fighters the names are of
Definition menu.h:24
void(* nextState)(struct HpDisplay *task)
Definition menu.h:23
HpTween hp[2]
each side's
Definition menu.h:25
s32 timer
Definition menu.h:26
A number that eases from one value to another (FIGHTSTG_stepHpTween)
Definition menu.h:11
s16 duration
Definition menu.h:18
s16 time
Definition menu.h:17
s16 fighter
whose hp it is
Definition menu.h:16
s32 to
Definition menu.h:13
s16 active
Definition menu.h:15
s32 from
Definition menu.h:12
s32 value
the one shown
Definition menu.h:14
char name[0x18]
Definition game_state.h:304
PartnerStats info
Definition game_state.h:349
Draws sprites from a sprite sheet (such as file 0x277, the menu graphics): a sheet has a table of fra...
Definition gfx.h:223
void(* setLayerId)()
(id, depth)
Definition gfx.h:244
void(* draw)()
(sheet, frame, x, y)
Definition gfx.h:246
void(* setTexture)()
(x, y)
Definition gfx.h:242
A text window (createTextWindow): up to six text buffers (0 is shown, 1-5 are "work" buffers that con...
Definition text.h:131
void(* setRightAlign)()
no prototype: callers would truncate u8 args
Definition text.h:178
void(* setNumber)()
Definition text.h:166
void(* setString)()
Definition text.h:165
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
TextWindow * createTextWindow(s16 layerId, s16 style, s16 x, s16 y)
A text window on a layer, in a font style, at (x, y)