Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
hurricane.c
Go to the documentation of this file.
1#include "common.h"
2#include "battle/action_cmd.h"
3
4#define NAMESPACE action_command_hurricane
5
6s32 D_802A98E0_42FFC0[8] = { 0, 25, 50, 75, 75, 0, 0, 0 };
7
8extern s32 actionCmdTableHurricane[];
9
10API_CALLABLE(N(init)) {
11 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
12 BattleStatus* battleStatus = &gBattleStatus;
13 s32 id;
14
15 battleStatus->unk_82 = 5;
18 battleStatus->actionSuccess = 0;
19 return ApiStatus_DONE2;
20 }
21
23
24 actionCommandStatus->actionCommandID = ACTION_COMMAND_HURRICANE;
25 actionCommandStatus->hudPrepareTime = 30;
26 actionCommandStatus->hudPosX = -48;
27 actionCommandStatus->state = 0;
28 actionCommandStatus->wrongButtonPressed = FALSE;
29 actionCommandStatus->barFillLevel = 0;
30 actionCommandStatus->barFillWidth = 0;
31 actionCommandStatus->isBarFilled = FALSE;
32 actionCommandStatus->hudPosY = 80;
33
35 actionCommandStatus->hudElements[0] = id;
37 hud_element_set_render_pos(id, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY);
39
41 actionCommandStatus->hudElements[2] = id;
43 hud_element_set_render_pos(id, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY);
45
47 actionCommandStatus->hudElements[1] = id;
48 hud_element_set_render_pos(id, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY + 28);
51
53 actionCommandStatus->hudElements[4] = id;
54 hud_element_set_render_pos(id, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY + 28);
57
58 return ApiStatus_DONE2;
59}
60
61API_CALLABLE(N(start)) {
62 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
63 BattleStatus* battleStatus = &gBattleStatus;
64 Bytecode* args = script->ptrReadPos;
65
67 battleStatus->actionSuccess = 0;
68 return ApiStatus_DONE2;
69 }
70
72
73 actionCommandStatus->prepareTime = evt_get_variable(script, *args++);
74 actionCommandStatus->duration = evt_get_variable(script, *args++);
75 actionCommandStatus->difficulty = evt_get_variable(script, *args++);
76 actionCommandStatus->difficulty = adjust_action_command_difficulty(actionCommandStatus->difficulty);
77 actionCommandStatus->targetWeakness = evt_get_variable(script, *args++);
78
79 actionCommandStatus->wrongButtonPressed = FALSE;
80 actionCommandStatus->barFillLevel = 0;
81 actionCommandStatus->barFillWidth = 0;
82 battleStatus->actionSuccess = 0;
83 battleStatus->actionResult = ACTION_RESULT_FAIL;
84 actionCommandStatus->state = 10;
85 battleStatus->flags1 &= ~BS_FLAGS1_FREE_ACTION_COMMAND;
86
88
89 return ApiStatus_DONE2;
90}
91
92// Almost identical to action_command_mega_shock_update (mega_shock)
93void N(update)(void) {
94 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
95 BattleStatus* battleStatus = &gBattleStatus;
96
97 s32 buttonsPushed;
98 s32 frameCount;
99 s32 buttonsAB;
100 s32 bufferPos;
101 s32 hudElement;
102 s32 mashMeterIndex;
103 s32 mashMeterCutoff;
104 s8 adjustedFillLevel;
105
106 switch (actionCommandStatus->state) {
107 case 0:
109
110 hudElement = actionCommandStatus->hudElements[0];
111 if (actionCommandStatus->showHud) {
113 }
114 hud_element_set_alpha(hudElement, 255);
115
116 hudElement = actionCommandStatus->hudElements[2];
117 if (actionCommandStatus->showHud) {
119 }
120 hud_element_set_alpha(hudElement, 255);
121
122 hudElement = actionCommandStatus->hudElements[1];
123 hud_element_set_alpha(hudElement, 255);
124 if (actionCommandStatus->showHud) {
126 }
127
128 actionCommandStatus->state = 1;
129 break;
130 case 1:
132 if (actionCommandStatus->hudPrepareTime != 0) {
133 actionCommandStatus->hudPrepareTime--;
134 break;
135 }
136
137 actionCommandStatus->hudPosX += 20;
138 if (actionCommandStatus->hudPosX > 50) {
139 actionCommandStatus->hudPosX = 50;
140 }
141
142 hud_element_set_render_pos(actionCommandStatus->hudElements[0], actionCommandStatus->hudPosX - 17,
143 actionCommandStatus->hudPosY);
144 hud_element_set_render_pos(actionCommandStatus->hudElements[2], actionCommandStatus->hudPosX + 23,
145 actionCommandStatus->hudPosY);
146 hud_element_set_render_pos(actionCommandStatus->hudElements[1], actionCommandStatus->hudPosX,
147 actionCommandStatus->hudPosY + 28);
148 break;
149 case 10:
151 if (actionCommandStatus->prepareTime != 0) {
152 actionCommandStatus->prepareTime--;
153 break;
154 }
155 hud_element_set_script(actionCommandStatus->hudElements[0], &HES_MashAButton);
156 hud_element_set_script(actionCommandStatus->hudElements[2], &HES_MashBButton1);
157 actionCommandStatus->barFillLevel = 0;
158 actionCommandStatus->unk_5C = 0;
159 actionCommandStatus->frameCounter = actionCommandStatus->duration;
160 actionCommandStatus->state = 11;
161 // fallthrough
162 case 11:
164 if (!actionCommandStatus->isBarFilled) {
165 s16 newFillLevel;
166
167 if (actionCommandStatus->targetWeakness != 0) {
168 s8 mashMeterIntervals = actionCommandStatus->mashMeterIntervals;
169 s16* mashMeterCutoffs = actionCommandStatus->mashMeterCutoffs;
170 s32 index;
171
172 mashMeterCutoff = mashMeterCutoffs[mashMeterIntervals];
173 index = actionCommandStatus->barFillLevel / mashMeterCutoff / 20;
174 newFillLevel = actionCommandStatus->barFillLevel - D_802A98E0_42FFC0[index];
175 } else {
176 newFillLevel = actionCommandStatus->barFillLevel - 10;
177 }
178
179 actionCommandStatus->barFillLevel = newFillLevel;
180 if (actionCommandStatus->barFillLevel < 0) {
181 actionCommandStatus->barFillLevel = 0;
182 }
183 }
184
185 bufferPos = battleStatus->inputBufferPos;
186 bufferPos -= 2;
187 if (bufferPos < 0) {
188 bufferPos += ARRAY_COUNT(battleStatus->pushInputBuffer);
189 }
190
191 buttonsPushed = 0;
192 frameCount = 1;
193
194 while (frameCount >= 0) {
195 if (bufferPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) {
196 bufferPos -= ARRAY_COUNT(battleStatus->pushInputBuffer);
197 }
198
199 buttonsPushed |= battleStatus->pushInputBuffer[bufferPos++];
200 frameCount--;
201 }
202
203 buttonsAB = BUTTON_A | BUTTON_B;
204 if ((buttonsPushed & buttonsAB) == buttonsAB) {
205 if (actionCommandStatus->targetWeakness != 0) {
206 s32 fillLevel;
207
208 fillLevel = actionCommandStatus->targetWeakness * 650;
209 fillLevel = fillLevel / 100 * battleStatus->actionCmdDifficultyTable[actionCommandStatus->difficulty];
210
211 // Perplexing reuse of buttonsPushed here, but it fixes register allocation. Likely another
212 // subexpression from above can be put into a variable and reused instead.
213 //
214 // TODO: Find a way to avoid reusing buttonsPushed.
215 buttonsPushed = fillLevel / 100;
216
217 actionCommandStatus->barFillLevel += buttonsPushed;
218 } else {
219 actionCommandStatus->barFillLevel += 100;
220
221 if (actionCommandStatus->barFillLevel >= 500) {
222 actionCommandStatus->barFillLevel = 500;
223 }
224 }
225
226 bufferPos = battleStatus->inputBufferPos;
227 bufferPos -= 2;
228 if (bufferPos < 0) {
229 bufferPos += ARRAY_COUNT(battleStatus->pushInputBuffer);
230 }
231
232 frameCount = 1;
233 while (frameCount >= 0) {
234 if (bufferPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) {
235 bufferPos -= ARRAY_COUNT(battleStatus->pushInputBuffer);
236 }
237
238 battleStatus->pushInputBuffer[bufferPos++] = 0;
239 frameCount--;
240 }
241 }
242
243 if (actionCommandStatus->barFillLevel > 10000) {
244 hudElement = actionCommandStatus->hudElements[4];
245 actionCommandStatus->barFillLevel = 10000;
246 actionCommandStatus->isBarFilled = TRUE;
247 hud_element_set_render_pos(hudElement, actionCommandStatus->hudPosX + 50,
248 actionCommandStatus->hudPosY + 28);
250 }
251
252 adjustedFillLevel = actionCommandStatus->barFillLevel / 100;
253
254 battleStatus->actionQuality = adjustedFillLevel;
255
256 if (actionCommandStatus->frameCounter == 0) {
257 s16 threshold;
258
259 // Again, reusing buttonsPushed specifically for reg-alloc. See above.
260 //
261 // TODO: Find a way to avoid reusing buttonsPushed.
262 buttonsPushed = actionCommandStatus->barFillLevel;
263 if (actionCommandStatus->targetWeakness == 0) {
264 buttonsPushed = 0;
265 }
266
267 if (buttonsPushed == 0) {
268 battleStatus->actionSuccess = -1;
269 } else {
270 battleStatus->actionSuccess = buttonsPushed / 100;
271 }
272
273 mashMeterIndex = actionCommandStatus->mashMeterIntervals - 1;
274 mashMeterCutoff = actionCommandStatus->mashMeterCutoffs[mashMeterIndex];
275 threshold = mashMeterCutoff / 2;
276
277 if (battleStatus->actionQuality <= threshold) {
278 battleStatus->actionResult = ACTION_RESULT_MINUS_4;
279 } else {
280 battleStatus->actionResult = ACTION_RESULT_SUCCESS;
281 }
282
283 if (battleStatus->actionSuccess == 100) {
285 }
286
288 actionCommandStatus->frameCounter = 5;
289 actionCommandStatus->state = 12;
290 } else {
291 actionCommandStatus->frameCounter -= 1;
292 }
293 break;
294 case 12:
295 if (actionCommandStatus->targetWeakness == 0) {
296 actionCommandStatus->barFillLevel -= 100;
297 if (actionCommandStatus->barFillLevel < 0) {
298 actionCommandStatus->barFillLevel = 0;
299 }
300 }
301
302 if (actionCommandStatus->frameCounter != 0) {
303 actionCommandStatus->frameCounter -= 1;
304 } else {
306 }
307 break;
308 }
309}
310
311void N(draw)(void) {
312 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
313 s32 hudY;
314 s32 hudX;
315 s32 id;
316
317 hud_element_draw_clipped(actionCommandStatus->hudElements[0]);
318 hud_element_draw_clipped(actionCommandStatus->hudElements[2]);
319
320 id = actionCommandStatus->hudElements[1];
322 hud_element_get_render_pos(id, &hudX, &hudY);
323
324 if (!actionCommandStatus->isBarFilled) {
325 draw_mash_meter_multicolor(hudX, hudY, actionCommandStatus->barFillLevel / 100);
326 } else {
327 draw_mash_meter_blink(hudX, hudY, actionCommandStatus->barFillLevel / 100);
328 }
329
330 hud_element_draw_clipped(actionCommandStatus->hudElements[4]);
331}
332
BSS ActionCommandStatus gActionCommandStatus
Definition action_cmd.c:91
void draw_mash_meter_multicolor(s32 posX, s32 posY, s32 fillValue)
Definition action_cmd.c:226
void func_80269160(void)
Definition action_cmd.c:655
void action_command_free(void)
Definition action_cmd.c:446
s32 adjust_action_command_difficulty(s32 arg0)
Definition action_cmd.c:101
void draw_mash_meter_blink(s32 posX, s32 posY, s32 fillValue)
Definition action_cmd.c:246
void action_command_init_status(void)
Definition action_cmd.c:256
void func_80269118(void)
Definition action_cmd.c:641
HudScript HES_MashBButton1
HudScript HES_BButton
HudScript HES_AButton
HudScript HES_BlueMeter
HudScript HES_MashAButton
HudScript HES_100pct
@ ACTION_COMMAND_MODE_NOT_LEARNED
Definition action_cmd.h:38
@ ACTION_COMMAND_HURRICANE
Definition enums.h:3492
@ BUTTON_A
Definition enums.h:2790
@ BUTTON_B
Definition enums.h:2789
@ ACTION_RESULT_SUCCESS
Definition enums.h:1968
@ ACTION_RESULT_MINUS_4
Definition enums.h:1964
@ ACTION_RESULT_FAIL
Definition enums.h:1967
#define ApiStatus_DONE2
Definition evt.h:118
s32 Bytecode
Definition evt.h:7
void btl_set_popup_duration(s32 duration)
s32 evt_get_variable(Evt *script, Bytecode var)
Definition evt.c:1690
void hud_element_get_render_pos(s32 id, s32 *x, s32 *y)
void hud_element_set_alpha(s32 id, s32 opacity)
void hud_element_set_script(s32 id, HudScript *anim)
void hud_element_set_render_depth(s32 id, s32 z)
void hud_element_set_render_pos(s32 id, s32 x, s32 y)
s32 hud_element_create(HudScript *anim)
Creates a new HUD element and returns its ID.
void hud_element_set_flags(s32 id, s32 flags)
Turns on the given flags.
void hud_element_clear_flags(s32 id, s32 flags)
Turns off the given flags.
void hud_element_draw_clipped(s32 id)
void hud_element_free(s32 id)
@ HUD_ELEMENT_FLAG_DISABLED
Definition hud_element.h:74
@ HUD_ELEMENT_FLAG_80
Definition hud_element.h:80
s32 actionCmdTableHurricane[]
Definition action_cmd.c:47
void N free(void)
Definition hurricane.c:333
s32 D_802A98E0_42FFC0[8]
Definition hurricane.c:6
void N update(void)
Definition hurricane.c:93
void N draw(void)
Definition hurricane.c:311
#define ARRAY_COUNT(arr)
Definition macros.h:40
s32 * actionCmdDifficultyTable
s32 pushInputBuffer[64]
BattleStatus gBattleStatus
Definition battle.c:11
void N init(Npc *bombette)
Definition bombette.c:66