Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
mega_shock.c
Go to the documentation of this file.
1#include "common.h"
2#include "audio/public.h"
3#include "battle/action_cmd.h"
4
5#define NAMESPACE action_command_mega_shock
6
7s32 D_802A9930_42E340[] = { 0, 25, 50, 75, 75, 0, 0, 0 };
8
9extern s32 actionCmdTableMegaShock[];
10
11API_CALLABLE(N(init)) {
12 BattleStatus* battleStatus = &gBattleStatus;
13 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
14 s32 elementID;
15
16 battleStatus->unk_82 = 5;
19 battleStatus->actionSuccess = 0;
20 return ApiStatus_DONE2;
21 }
23
24 actionCommandStatus->actionCommandID = ACTION_COMMAND_MEGA_SHOCK;
25 actionCommandStatus->state = 0;
26 actionCommandStatus->hudPrepareTime = 30;
27 actionCommandStatus->wrongButtonPressed = FALSE;
28 actionCommandStatus->barFillLevel = 0;
29 actionCommandStatus->barFillWidth = 0;
30 actionCommandStatus->isBarFilled = FALSE;
31 actionCommandStatus->hudPosX = -48;
32 actionCommandStatus->hudPosY = 80;
33
34 elementID = hud_element_create(&HES_AButton);
35 actionCommandStatus->hudElements[0] = elementID;
37 hud_element_set_render_pos(elementID, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY);
38 hud_element_set_render_depth(elementID, 0);
39
40 elementID = hud_element_create(&HES_BButton);
41 actionCommandStatus->hudElements[2] = elementID;
43 hud_element_set_render_pos(elementID, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY);
44 hud_element_set_render_depth(elementID, 0);
45
47 actionCommandStatus->hudElements[1] = elementID;
48 hud_element_set_render_pos(elementID, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY + 0x1C);
49 hud_element_set_render_depth(elementID, 0);
51
52 elementID = hud_element_create(&HES_100pct);
53 actionCommandStatus->hudElements[4] = elementID;
54 hud_element_set_render_pos(elementID, actionCommandStatus->hudPosX, actionCommandStatus->hudPosY + 0x1C);
55 hud_element_set_render_depth(elementID, 0);
57
58 return ApiStatus_DONE2;
59}
60
61API_CALLABLE(N(start)) {
62 Bytecode* readPos = script->ptrReadPos;
63 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
64 BattleStatus* battleStatus = &gBattleStatus;
65
66 s16 arg;
67 ApiStatus result;
68
71
72 actionCommandStatus->prepareTime = evt_get_variable(script, *readPos++);
73 actionCommandStatus->duration = evt_get_variable(script, *readPos++);
74 arg = evt_get_variable(script, *readPos++);
75
76 actionCommandStatus->difficulty = arg;
77 actionCommandStatus->difficulty = adjust_action_command_difficulty(arg);
78 actionCommandStatus->targetWeakness = evt_get_variable(script, *readPos++);
79 actionCommandStatus->wrongButtonPressed = FALSE;
80 actionCommandStatus->barFillLevel = 0;
81 actionCommandStatus->barFillWidth = 0;
82
83 battleStatus->actionSuccess = 0;
84 battleStatus->actionResult = ACTION_RESULT_FAIL;
85 actionCommandStatus->state = 10;
86 battleStatus->flags1 &= ~BS_FLAGS1_FREE_ACTION_COMMAND;
87
89 result = ApiStatus_DONE2;
90 } else {
91 battleStatus->actionSuccess = 0;
92 result = ApiStatus_DONE2;
93 }
94
95 return result;
96}
97
98void N(update)(void) {
99 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
100 BattleStatus* battleStatus = &gBattleStatus;
101
102 s32 buttonsPushed;
103 s32 frameCount;
104 s32 buttonsAB;
105 s32 bufferPos;
106 s32 hudElement;
107 s32 mashMeterIndex;
108 s32 mashMeterCutoff;
109 s8 adjustedFillLevel;
110
111 switch (actionCommandStatus->state) {
112 case 0:
114
115 hudElement = actionCommandStatus->hudElements[0];
116 if (actionCommandStatus->showHud) {
118 }
119 hud_element_set_alpha(hudElement, 255);
120
121 hudElement = actionCommandStatus->hudElements[2];
122 if (actionCommandStatus->showHud) {
124 }
125 hud_element_set_alpha(hudElement, 255);
126
127 hudElement = actionCommandStatus->hudElements[1];
128 hud_element_set_alpha(hudElement, 255);
129 if (actionCommandStatus->showHud) {
131 }
132
133 actionCommandStatus->state = 1;
134 break;
135 case 1:
137 if (actionCommandStatus->hudPrepareTime != 0) {
138 actionCommandStatus->hudPrepareTime--;
139 break;
140 }
141
142 actionCommandStatus->hudPosX += 20;
143 if (actionCommandStatus->hudPosX > 50) {
144 actionCommandStatus->hudPosX = 50;
145 }
146
147 hud_element_set_render_pos(actionCommandStatus->hudElements[0], actionCommandStatus->hudPosX - 17,
148 actionCommandStatus->hudPosY);
149 hud_element_set_render_pos(actionCommandStatus->hudElements[2], actionCommandStatus->hudPosX + 23,
150 actionCommandStatus->hudPosY);
151 hud_element_set_render_pos(actionCommandStatus->hudElements[1], actionCommandStatus->hudPosX,
152 actionCommandStatus->hudPosY + 28);
153 break;
154 case 10:
156 if (actionCommandStatus->prepareTime != 0) {
157 actionCommandStatus->prepareTime--;
158 break;
159 }
160 hud_element_set_script(actionCommandStatus->hudElements[0], &HES_MashAButton);
161 hud_element_set_script(actionCommandStatus->hudElements[2], &HES_MashBButton1);
162 actionCommandStatus->barFillLevel = 0;
163 actionCommandStatus->unk_5C = 0;
164 actionCommandStatus->frameCounter = actionCommandStatus->duration;
166 actionCommandStatus->state = 11;
167 case 11:
169 if (!actionCommandStatus->isBarFilled) {
170 s16 newFillLevel;
171
172 if (actionCommandStatus->targetWeakness != 0) {
173 s8 mashMeterIntervals = actionCommandStatus->mashMeterIntervals;
174 s16* mashMeterCutoffs = actionCommandStatus->mashMeterCutoffs;
175 s32 index;
176
177 mashMeterCutoff = mashMeterCutoffs[mashMeterIntervals];
178 index = actionCommandStatus->barFillLevel / mashMeterCutoff / 20;
179 newFillLevel = actionCommandStatus->barFillLevel - D_802A9930_42E340[index];
180 } else {
181 newFillLevel = actionCommandStatus->barFillLevel - 10;
182 }
183
184 actionCommandStatus->barFillLevel = newFillLevel;
185 if (actionCommandStatus->barFillLevel < 0) {
186 actionCommandStatus->barFillLevel = 0;
187 }
188 }
189
190 bufferPos = battleStatus->inputBufferPos;
191 bufferPos -= 2;
192 if (bufferPos < 0) {
193 bufferPos += ARRAY_COUNT(battleStatus->pushInputBuffer);
194 }
195
196 buttonsPushed = 0;
197 frameCount = 1;
198
199 while (frameCount >= 0) {
200 if (bufferPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) {
201 bufferPos -= ARRAY_COUNT(battleStatus->pushInputBuffer);
202 }
203
204 buttonsPushed |= battleStatus->pushInputBuffer[bufferPos++];
205 frameCount--;
206 }
207
208 buttonsAB = BUTTON_A | BUTTON_B;
209 if ((buttonsPushed & buttonsAB) == buttonsAB) {
210 if (actionCommandStatus->targetWeakness != 0) {
211 s32 fillLevel;
212
213 fillLevel = actionCommandStatus->targetWeakness * 780;
214 fillLevel = fillLevel / 100 * battleStatus->actionCmdDifficultyTable[actionCommandStatus->difficulty];
215
216 // Perplexing reuse of buttonsPushed here, but it fixes register allocation. Likely another
217 // subexpression from above can be put into a variable and reused instead.
218 //
219 // TODO: Find a way to avoid reusing buttonsPushed.
220 buttonsPushed = fillLevel / 100;
221
222 actionCommandStatus->barFillLevel += buttonsPushed;
223 } else {
224 actionCommandStatus->barFillLevel += 100;
225
226 if (actionCommandStatus->barFillLevel >= 500) {
227 actionCommandStatus->barFillLevel = 500;
228 }
229 }
230
231 bufferPos = battleStatus->inputBufferPos;
232 bufferPos -= 2;
233 if (bufferPos < 0) {
234 bufferPos += ARRAY_COUNT(battleStatus->pushInputBuffer);
235 }
236
237 frameCount = 1;
238 while (frameCount >= 0) {
239 if (bufferPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) {
240 bufferPos -= ARRAY_COUNT(battleStatus->pushInputBuffer);
241 }
242
243 battleStatus->pushInputBuffer[bufferPos++] = 0;
244 frameCount--;
245 }
246 }
247
248 if (actionCommandStatus->barFillLevel > 10000) {
249 hudElement = actionCommandStatus->hudElements[4];
250 actionCommandStatus->barFillLevel = 10000;
251 actionCommandStatus->isBarFilled = TRUE;
252 hud_element_set_render_pos(hudElement, actionCommandStatus->hudPosX + 50,
253 actionCommandStatus->hudPosY + 28);
255 }
256
257 adjustedFillLevel = actionCommandStatus->barFillLevel / 100;
258
259 battleStatus->actionQuality = adjustedFillLevel;
260 sfx_adjust_env_sound_params(SOUND_LOOP_CHARGE_BAR, 0, 0, adjustedFillLevel * 12);
261
262 if (actionCommandStatus->frameCounter == 0) {
263 s16 threshold;
264
265 // Again, reusing buttonsPushed specifically for reg-alloc. See above.
266 //
267 // TODO: Find a way to avoid reusing buttonsPushed.
268 buttonsPushed = actionCommandStatus->barFillLevel;
269 if (actionCommandStatus->targetWeakness == 0) {
270 buttonsPushed = 0;
271 }
272
273 if (buttonsPushed == 0) {
274 battleStatus->actionSuccess = -1;
275 } else {
276 battleStatus->actionSuccess = buttonsPushed / 100;
277 }
278
279 mashMeterIndex = actionCommandStatus->mashMeterIntervals - 1;
280 mashMeterCutoff = actionCommandStatus->mashMeterCutoffs[mashMeterIndex];
281 threshold = mashMeterCutoff / 2;
282
283 if (battleStatus->actionQuality <= threshold) {
284 battleStatus->actionResult = ACTION_RESULT_MINUS_4;
285 } else {
286 battleStatus->actionResult = ACTION_RESULT_SUCCESS;
287 }
288
289 if (battleStatus->actionSuccess == 100) {
291 }
292
295 actionCommandStatus->frameCounter = 5;
296 actionCommandStatus->state = 12;
297 } else {
298 actionCommandStatus->frameCounter -= 1;
299 }
300 break;
301 case 12:
302 if (actionCommandStatus->targetWeakness == 0) {
303 actionCommandStatus->barFillLevel -= 100;
304 if (actionCommandStatus->barFillLevel < 0) {
305 actionCommandStatus->barFillLevel = 0;
306 }
307 }
308
309 if (actionCommandStatus->frameCounter != 0) {
310 actionCommandStatus->frameCounter -= 1;
311 } else {
313 }
314 break;
315 }
316}
317
318void N(draw)(void) {
319 ActionCommandStatus* actionCommandStatus = &gActionCommandStatus;
320
321 s32 hudElement;
322 s32 hudElementX;
323 s32 hudElementY;
324
325 hud_element_draw_clipped(actionCommandStatus->hudElements[0]);
326 hud_element_draw_clipped(actionCommandStatus->hudElements[2]);
327
328 hudElement = actionCommandStatus->hudElements[1];
329 hud_element_draw_clipped(hudElement);
330 hud_element_get_render_pos(hudElement, &hudElementX, &hudElementY);
331
332 if (!actionCommandStatus->isBarFilled) {
333 draw_mash_meter_multicolor(hudElementX, hudElementY, actionCommandStatus->barFillLevel / 100);
334 } else {
335 draw_mash_meter_blink(hudElementX, hudElementY, actionCommandStatus->barFillLevel / 100);
336 }
337
338 hud_element_draw_clipped(actionCommandStatus->hudElements[4]);
339}
340
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_MEGA_SHOCK
Definition enums.h:3489
@ BUTTON_A
Definition enums.h:2790
@ BUTTON_B
Definition enums.h:2789
@ SOUND_LOOP_CHARGE_BAR
Definition enums.h:1646
@ ACTION_RESULT_SUCCESS
Definition enums.h:1968
@ ACTION_RESULT_MINUS_4
Definition enums.h:1964
@ ACTION_RESULT_FAIL
Definition enums.h:1967
s32 ApiStatus
Definition evt.h:115
#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
void N free(void)
Definition mega_shock.c:341
s32 actionCmdTableMegaShock[]
Definition action_cmd.c:44
s32 D_802A9930_42E340[]
Definition mega_shock.c:7
void N update(void)
Definition mega_shock.c:98
void N draw(void)
Definition mega_shock.c:318
void sfx_stop_sound(s32 soundID)
Definition sfx.c:507
void sfx_adjust_env_sound_params(s32 soundID, u8 volume, u8 pan, s16 pitchShift)
Definition sfx.c:492
void sfx_play_sound_with_params(s32 soundID, u8 volume, u8 pan, s16 pitchShift)
Definition sfx.c:458
#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