Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
tidal_wave.c
Go to the documentation of this file.
1#include "common.h"
2#include "battle/action_cmd.h"
3
4#define NAMESPACE action_command_tidal_wave
5
6extern s32 actionCmdTableTidalWave[];
7
8// indices into ActionCommandStatus::hudElements for this action command
9enum {
12 // remaining HIDX are for the sequence of buttons
13};
14
15// states for this action command
16enum {
17 TIDAL_WAVE_STATE_INIT = 0, // create hud elements
18 TIDAL_WAVE_STATE_APPEAR = 1, // hud elements move into position
20 TIDAL_WAVE_STATE_NEXT_BUTTON = 11, // choose the next required input
21 TIDAL_WAVE_STATE_AWAIT_INPUT = 12, // wait for the player's response
22 TIDAL_WAVE_STATE_WRAPUP = 13, // tally overall success
23 TIDAL_WAVE_STATE_DISPOSE = 14, // delay and disappear
24};
25
26enum {
31};
32
35
36API_CALLABLE(N(init)) {
38 BattleStatus* battleStatus = &gBattleStatus;
39 HudElemID hid;
40 s32 i;
41
42 battleStatus->maxActionQuality = 5;
44
45 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
46 battleStatus->actionQuality = 0;
47 return ApiStatus_DONE2;
48 }
49
51
54 acs->wrongButtonPressed = FALSE;
55 acs->meterFillLevel = 0;
56 acs->meterFillWidth = 0;
57 battleStatus->actionProgress = 0;
58 acs->hudPosX = -48;
59 acs->hudPosY = 80;
60
62 acs->hudElemIDs[HIDX_METER] = hid;
63 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
66
67 for (i = HIDX_FIRST_BUTTON; i < ARRAY_COUNT(acs->hudElemIDs) - 1; i++) {
69 acs->hudElemIDs[i] = hid;
73 }
74
75 return ApiStatus_DONE2;
76}
77
78API_CALLABLE(N(start)) {
80 BattleStatus* battleStatus = &gBattleStatus;
81 Bytecode* args = script->ptrReadPos;
82
83 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
84 battleStatus->actionQuality = 0;
85 return ApiStatus_DONE2;
86 }
87
89
90 acs->prepareTime = evt_get_variable(script, *args++);
91 acs->duration = evt_get_variable(script, *args++);
92 acs->difficulty = evt_get_variable(script, *args++);
94
95 acs->wrongButtonPressed = FALSE;
96 acs->meterFillLevel = 0;
97 acs->meterFillWidth = 0;
98 battleStatus->actionQuality = 0;
99 battleStatus->actionProgress = 0;
100 battleStatus->actionResult = ACTION_RESULT_FAIL;
102 battleStatus->flags1 &= ~BS_FLAGS1_FREE_ACTION_COMMAND;
103
105
106 return ApiStatus_DONE2;
107}
108
109void N(update)(void) {
111 BattleStatus* battleStatus = &gBattleStatus;
112 HudElemID hid;
113 s8 oldButton;
114 s8 newButton;
115 s32 numLookbackFrames;
116 s32 bufferPos;
117 s32 buttonsPressed;
118 s32 success;
119 s32 i;
120
121 switch (acs->state) {
124 hid = acs->hudElemIDs[HIDX_METER];
125 if (acs->showHud) {
127 }
128 hud_element_set_alpha(hid, 255);
130 break;
133 acs->hudPosX += 20;
134 if (acs->hudPosX > 50) {
135 acs->hudPosX = 50;
136 }
138 break;
141 if (acs->prepareTime != 0) {
142 acs->prepareTime--;
143 break;
144 }
145 acs->tidalWave.inputCount = 1;
146 acs->stateTimer = acs->duration;
147 acs->tidalWave.prevButton = rand_int(TIDAL_WAVE_INPUT_COUNT - 1);
149 acs->wrongInputFrameCounter = 0;
150
151 // fallthrough
154
155 // Pick a new button that doesn't match the old one.
156 oldButton = acs->tidalWave.prevButton;
157 do {
158 newButton = rand_int(TIDAL_WAVE_INPUT_COUNT - 1);
159 acs->tidalWave.prevButton = newButton;
160 } while (oldButton == newButton);
161
162 hid = acs->hudElemIDs[acs->tidalWave.inputCount];
163 hud_element_set_script(hid, HudButtonsUp[newButton]);
164 hud_element_set_render_pos(hid, acs->hudPosX + ((acs->tidalWave.inputCount - 1) * 20) + 16, acs->hudPosY);
167 acs->lookBackCounter = 1;
169
170 // fallthrough
173
174 acs->stateTimer--;
175 if (acs->stateTimer == 0) {
177 break;
178 }
179
180 // Stops checking for input if on the 15th button.
181 if (acs->tidalWave.inputCount == 15) {
182 break;
183 }
184
185 // Number of frames until input possible (if negative, used to look backward;
186 // allows correct presses to be buffered after an incorrect press).
187 acs->lookBackCounter--;
188 // Wrong-input lockout frame counter
190
191 if (acs->lookBackCounter <= 0) {
192 // Determine number of frames to look back in input buffer (up to 20).
193 numLookbackFrames = abs(acs->lookBackCounter);
194 if (numLookbackFrames > 20) {
195 numLookbackFrames = 20;
196 }
197
198 // Determine starting point in input buffer.
199 bufferPos = battleStatus->inputBufferPos - numLookbackFrames;
200 if (bufferPos < 0) {
201 bufferPos += ARRAY_COUNT(battleStatus->pushInputBuffer);
202 }
203
204 // If determined that 0 frames should be searched, search a minimum of 1.
205 if (numLookbackFrames == 0) {
206 numLookbackFrames = 1;
207 }
208
209 // Check buffer for past N frames' worth of button presses.
210 for (i = 0; i < numLookbackFrames; i++) {
211 if (bufferPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) {
212 bufferPos -= ARRAY_COUNT(battleStatus->pushInputBuffer);
213 }
214
215 // If not locked out from previous wrong press...
216 if (acs->wrongInputFrameCounter > 0) {
217 break;
218 };
219
220 success = FALSE;
221 acs->wrongButtonPressed = FALSE;
222
223 // Check for presses of the current button.
224 switch (acs->tidalWave.prevButton) {
226 if (acs->autoSucceed) {
227 success = TRUE;
228 } else {
229 buttonsPressed = battleStatus->pushInputBuffer[bufferPos];
230 if (buttonsPressed != 0) {
231 if (buttonsPressed & ~BUTTON_A) {
232 acs->wrongButtonPressed = TRUE;
233 } else {
234 success = TRUE;
235 }
236 }
237 }
238 break;
240 if (acs->autoSucceed) {
241 success = TRUE;
242 } else {
243 buttonsPressed = battleStatus->pushInputBuffer[bufferPos];
244 if (buttonsPressed != 0) {
245 if (buttonsPressed & ~BUTTON_B) {
246 acs->wrongButtonPressed = TRUE;
247 } else {
248 success = TRUE;
249 }
250 }
251 }
252 break;
254 if (acs->autoSucceed) {
255 success = TRUE;
256 } else {
257 buttonsPressed = battleStatus->pushInputBuffer[bufferPos];
258 if (buttonsPressed != 0) {
259 if (buttonsPressed & ~BUTTON_C_DOWN) {
260 acs->wrongButtonPressed = TRUE;
261 } else {
262 success = TRUE;
263 }
264 }
265 }
266 break;
267 }
268
269 if (acs->wrongButtonPressed) {
270 // Wrong; prevent successful inputs for 10 frames.
271 acs->wrongInputFrameCounter = 10;
273 acs->lookBackCounter = 0;
274 }
275
276 if (success) {
277 // Correct; shrink button, set up next button press, etc.
278 hid = acs->hudElemIDs[acs->tidalWave.inputCount];
279 hud_element_set_script(hid, HudButtonsDown[acs->tidalWave.prevButton]);
280 hud_element_set_scale(hid, 0.5f);
281 hud_element_set_render_pos(hid, acs->hudPosX + ((acs->tidalWave.inputCount - 1) * 20), acs->hudPosY + 7);
282 acs->tidalWave.inputCount++;
283 acs->meterFillLevel += battleStatus->actionCmdDifficultyTable[acs->difficulty] * 18;
284 if (acs->meterFillLevel > MAX_MASH_UNITS) {
286 }
288 battleStatus->actionProgress++;
290 return;
291 }
292
293 bufferPos++;
294 }
295 }
296 break;
298 if (battleStatus->actionProgress == 0) {
299 battleStatus->actionQuality = AC_QUALITY_FAILED;
300 } else {
301 battleStatus->actionQuality = battleStatus->actionProgress;
302 }
303 battleStatus->actionResult = ACTION_RESULT_SUCCESS;
304 if (battleStatus->actionQuality >= 10) {
306 }
308 acs->stateTimer = 5;
310 break;
312 if (acs->stateTimer != 0) {
313 acs->stateTimer--;
314 } else {
316 }
317 break;
318 }
319}
320
321void N(draw)(void) {
322 s32 i;
323
326 }
327}
328
BSS ActionCommandStatus gActionCommandStatus
Definition action_cmd.c:91
void action_command_free(void)
Definition action_cmd.c:446
void increment_action_command_attempt_count(void)
Definition action_cmd.c:641
s32 adjust_action_command_difficulty(s32 difficultyLevel)
Definition action_cmd.c:101
void increment_action_command_success_count(void)
Definition action_cmd.c:655
void action_command_init_status(void)
Definition action_cmd.c:256
#define AC_QUALITY_FAILED
Definition action_cmd.h:66
HudScript HES_AButton
HudElemID hudElemIDs[16]
Definition action_cmd.h:83
HudScript HES_CDownButtonHeld
HudScript HES_BlueMeter
HudScript HES_BButtonHeld
HudScript HES_PressAButton
HudScript HES_AButtonDown
HudScript HES_PressBButton
@ AC_MODE_NOT_LEARNED
Definition action_cmd.h:60
HudScript HES_PressCDownButton
#define MAX_MASH_UNITS
Definition action_cmd.h:75
s32 HudElemID
#define rand_int
@ ACTION_COMMAND_TIDAL_WAVE
Definition enums.h:3495
@ BUTTON_A
Definition enums.h:2790
@ BUTTON_C_DOWN
Definition enums.h:2779
@ BUTTON_B
Definition enums.h:2789
@ SOUND_TIMING_BAR_TICK
Definition enums.h:952
@ SOUND_APPROVE
Definition enums.h:932
@ SOUND_MENU_ERROR
Definition enums.h:933
@ ACTION_RESULT_SUCCESS
Definition enums.h:1968
@ 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:1689
void hud_element_set_scale(s32 index, f32 scale)
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:72
@ HUD_ELEMENT_FLAG_80
Definition hud_element.h:78
s32 HudScript[]
Definition hud_element.h:9
void sfx_play_sound(s32 soundID)
Definition sfx.c:517
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define POPUP_MSG_OFF
Definition battle.h:270
#define POPUP_MSG_ON
Definition battle.h:269
s32 * actionCmdDifficultyTable
s32 pushInputBuffer[64]
@ TIDAL_WAVE_STATE_AWAIT_INPUT
Definition tidal_wave.c:21
@ TIDAL_WAVE_STATE_WRAPUP
Definition tidal_wave.c:22
@ TIDAL_WAVE_STATE_NEXT_BUTTON
Definition tidal_wave.c:20
@ TIDAL_WAVE_STATE_START
Definition tidal_wave.c:19
@ TIDAL_WAVE_STATE_INIT
Definition tidal_wave.c:17
@ TIDAL_WAVE_STATE_DISPOSE
Definition tidal_wave.c:23
@ TIDAL_WAVE_STATE_APPEAR
Definition tidal_wave.c:18
@ HIDX_METER
Definition tidal_wave.c:10
@ HIDX_FIRST_BUTTON
Definition tidal_wave.c:11
HudScript * HudButtonsUp[TIDAL_WAVE_INPUT_COUNT]
Definition tidal_wave.c:33
s32 actionCmdTableTidalWave[]
Definition action_cmd.c:50
@ TIDAL_WAVE_INPUT_COUNT
Definition tidal_wave.c:30
@ TIDAL_WAVE_INPUT_A
Definition tidal_wave.c:27
@ TIDAL_WAVE_INPUT_C_DOWN
Definition tidal_wave.c:29
@ TIDAL_WAVE_INPUT_B
Definition tidal_wave.c:28
void N free(void)
Definition tidal_wave.c:329
HudScript * HudButtonsDown[TIDAL_WAVE_INPUT_COUNT]
Definition tidal_wave.c:34
void N update(void)
Definition tidal_wave.c:109
void N draw(void)
Definition tidal_wave.c:321
BattleStatus gBattleStatus
Definition battle.c:11
void N init(Npc *bombette)
Definition bombette.c:66