Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
whirlwind.c
Go to the documentation of this file.
1#include "common.h"
2#include "battle/action_cmd.h"
3#include "battle/action_cmd/whirlwind_bubble.png.h"
4#include "include_asset.h"
5
6#define NAMESPACE action_command_whirlwind
7
8extern s32 actionCmdTableWhirlwind[];
9
10// indices into ActionCommandStatus::hudElements for this action command
11enum {
16};
17
18// how much to add to the meter per input
19#define HUFF_FILL_TICK 500
20#define BUZZAR_FILL_TICK 600
21
22INCLUDE_IMG("battle/action_cmd/whirlwind_1.png", battle_action_cmd_whirlwind_1_png);
23INCLUDE_PAL("battle/action_cmd/whirlwind_1.pal", battle_action_cmd_whirlwind_1_pal);
24
25INCLUDE_IMG("battle/action_cmd/whirlwind_2.png", battle_action_cmd_whirlwind_2_png);
26INCLUDE_PAL("battle/action_cmd/whirlwind_2.pal", battle_action_cmd_whirlwind_2_pal);
27
28INCLUDE_IMG("battle/action_cmd/whirlwind_3.png", battle_action_cmd_whirlwind_3_png);
29INCLUDE_PAL("battle/action_cmd/whirlwind_3.pal", battle_action_cmd_whirlwind_3_pal);
30
31INCLUDE_IMG("battle/action_cmd/whirlwind_4.png", battle_action_cmd_whirlwind_4_png);
32INCLUDE_PAL("battle/action_cmd/whirlwind_4.pal", battle_action_cmd_whirlwind_4_pal);
33
34INCLUDE_IMG("battle/action_cmd/whirlwind_5.png", battle_action_cmd_whirlwind_5_png);
35INCLUDE_PAL("battle/action_cmd/whirlwind_5.pal", battle_action_cmd_whirlwind_5_pal);
36
37INCLUDE_IMG("battle/action_cmd/whirlwind_6.png", battle_action_cmd_whirlwind_6_png);
38INCLUDE_PAL("battle/action_cmd/whirlwind_6.pal", battle_action_cmd_whirlwind_6_pal);
39
40INCLUDE_IMG("battle/action_cmd/whirlwind_7.png", battle_action_cmd_whirlwind_7_png);
41INCLUDE_PAL("battle/action_cmd/whirlwind_7.pal", battle_action_cmd_whirlwind_7_pal);
42
43INCLUDE_IMG("battle/action_cmd/whirlwind_bubble.png", battle_action_cmd_whirlwind_bubble_png);
44INCLUDE_PAL("battle/action_cmd/whirlwind_bubble.pal", battle_action_cmd_whirlwind_bubble_pal);
45
46HudScript HES_Whirlwind1 = HES_TEMPLATE_CI_ENUM_SIZE(battle_action_cmd_whirlwind_1, 24, 24);
47HudScript HES_Whirlwind2 = HES_TEMPLATE_CI_ENUM_SIZE(battle_action_cmd_whirlwind_2, 24, 24);
48HudScript HES_Whirlwind3 = HES_TEMPLATE_CI_ENUM_SIZE(battle_action_cmd_whirlwind_3, 24, 24);
49HudScript HES_Whirlwind4 = HES_TEMPLATE_CI_ENUM_SIZE(battle_action_cmd_whirlwind_4, 24, 24);
50HudScript HES_Whirlwind5 = HES_TEMPLATE_CI_ENUM_SIZE(battle_action_cmd_whirlwind_5, 24, 24);
51HudScript HES_Whirlwind6 = HES_TEMPLATE_CI_ENUM_SIZE(battle_action_cmd_whirlwind_6, 24, 24);
52HudScript HES_Whirlwind7 = HES_TEMPLATE_CI_ENUM_SIZE(battle_action_cmd_whirlwind_7, 24, 24);
53
54HudScript HES_WhirlwindBubble = HES_TEMPLATE_CI_CUSTOM_SIZE(battle_action_cmd_whirlwind_bubble,
55 battle_action_cmd_whirlwind_bubble_png_width, battle_action_cmd_whirlwind_bubble_png_height);
56
57s32 N(DrainRateTable0)[] = { 0, 25, 50, 75, 100, 100 };
58s32 N(DrainRateTable1)[] = { 50, 50, 50, 50, 75, 75, 75, 100, 100, 100, 100 };
59
60// bug: the final entry is not accessible due to the way idx is calculated in these macros
61#define GET_DRAIN_RATE_HUFF(pct) (N(DrainRateTable0)[((pct) / (ONE_PCT_MASH / 5))])
62#define GET_DRAIN_RATE_BUZZAR(pct) (N(DrainRateTable1)[((pct) / (ONE_PCT_MASH / 10))])
63
64HudScript* N(HuffDigits)[] = {
66};
67
68HudScript* N(BuzzarDigits)[] = {
70};
71
72s32 N(BuzzarQuality)[] = { 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1 };
73
74API_CALLABLE(N(init)) {
76 BattleStatus* battleStatus = &gBattleStatus;
77 Bytecode* args = script->ptrReadPos;
78 HudElemID hid;
79
80 battleStatus->maxActionQuality = 5;
82 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
83 battleStatus->actionQuality = 0;
84 return ApiStatus_DONE2;
85 }
86
88 acs->variation = evt_get_variable(script, *args++);
90 acs->state = AC_STATE_INIT;
91 acs->wrongButtonPressed = FALSE;
92 acs->meterFillLevel = 0;
93 acs->meterFillWidth = 0;
94 if (acs->variation == ACV_WHIRLWIND_HUFF) {
95 battleStatus->actionProgress = 0;
96 } else {
97 battleStatus->actionProgress = 3;
98 }
99 acs->hudPosX = -48;
100 acs->hudPosY = 80;
101
103 acs->hudElemIDs[HIDX_BUTTON] = hid;
107
109 acs->hudElemIDs[HIDX_METER] = hid;
110 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
113
115 acs->hudElemIDs[HIDX_DIGIT] = hid;
116 hud_element_set_render_pos(hid, acs->hudPosX + 54, acs->hudPosY + 28);
119
121 acs->hudElemIDs[HIDX_BUBBLE] = hid;
122 hud_element_set_render_pos(hid, acs->hudPosX + 60, acs->hudPosY + 28);
125
126 return ApiStatus_DONE2;
127}
128
129API_CALLABLE(N(start)) {
131 BattleStatus* battleStatus = &gBattleStatus;
132 Bytecode* args = script->ptrReadPos;
133
134 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
135 battleStatus->actionQuality = 0;
136 return ApiStatus_DONE2;
137 }
138
140
141 acs->prepareTime = evt_get_variable(script, *args++);
142 acs->duration = evt_get_variable(script, *args++);
143 acs->difficulty = evt_get_variable(script, *args++);
145
146 acs->wrongButtonPressed = FALSE;
147 acs->meterFillLevel = 0;
148 acs->meterFillWidth = 0;
149 battleStatus->actionQuality = 0;
150 battleStatus->actionResult = ACTION_RESULT_FAIL;
151 if (acs->variation == ACV_WHIRLWIND_HUFF) {
152 battleStatus->actionProgress = 0;
153 } else {
154 battleStatus->actionProgress = 3;
155 }
156 acs->state = AC_STATE_START;
157 gBattleStatus.flags1 &= ~BS_FLAGS1_FREE_ACTION_COMMAND;
158
159 return ApiStatus_DONE2;
160}
161
162void N(update)(void) {
164 BattleStatus* battleStatus = &gBattleStatus;
165 HudElemID hid;
166 s32 cutoff;
167 s32 fillPct;
168 s32 amt;
169
170 switch (acs->state) {
171 case AC_STATE_INIT:
173
174 hid = acs->hudElemIDs[HIDX_BUTTON];
175 if (acs->showHud) {
177 }
178 hud_element_set_alpha(hid, 255);
179
180 hid = acs->hudElemIDs[HIDX_METER];
181 hud_element_set_alpha(hid, 255);
182 if (acs->showHud) {
184 }
185
186 hid = acs->hudElemIDs[HIDX_DIGIT];
187 hud_element_set_alpha(hid, 255);
188 if (acs->showHud) {
190 }
191
192 hid = acs->hudElemIDs[HIDX_BUBBLE];
193 hud_element_set_alpha(hid, 255);
194 if (acs->showHud) {
196 }
197
198 acs->state = AC_STATE_APPEAR;
199 break;
200 case AC_STATE_APPEAR:
202 acs->hudPosX += 20;
203 if (acs->hudPosX > 50) {
204 acs->hudPosX = 50;
205 }
210 break;
211 case AC_STATE_START:
213 if (acs->prepareTime != 0) {
214 acs->prepareTime--;
215 return;
216 }
218 acs->meterFillLevel = 0;
219 acs->state = AC_STATE_ACTIVE;
220 acs->stateTimer = acs->duration;
221
222 // fallthrough
223 case AC_STATE_ACTIVE:
225
226 // apply meter draining every frame
227 cutoff = acs->mashMeterCutoffs[acs->mashMeterNumIntervals];
228 fillPct = acs->meterFillLevel / cutoff;
229 if (acs->variation == ACV_WHIRLWIND_HUFF) {
230 amt = GET_DRAIN_RATE_HUFF(fillPct);
231 } else {
232 amt = GET_DRAIN_RATE_BUZZAR(fillPct);
233 }
234 acs->meterFillLevel -= amt;
235
236 if (acs->meterFillLevel < 0) {
237 acs->meterFillLevel = 0;
238 }
239
240 // check for meter-filling input
241 if (!acs->berserkerEnabled) {
242 if (battleStatus->curButtonsPressed & BUTTON_A) {
243 if (acs->variation == ACV_WHIRLWIND_HUFF) {
245 } else {
247 }
248 acs->meterFillLevel += amt;
249 }
250 } else {
251 acs->meterFillLevel += SCALE_BY_PCT(25, battleStatus->actionCmdDifficultyTable[acs->difficulty]);
253 }
254
255 // cap meter to maximum fill level
256 if (acs->meterFillLevel > cutoff * 100) {
257 acs->meterFillLevel = cutoff * 100;
258 }
259
260 if (acs->variation == ACV_WHIRLWIND_HUFF) {
261 battleStatus->actionProgress = (acs->meterFillLevel / ONE_PCT_MASH) / 20;
262 } else {
263 battleStatus->actionProgress = N(BuzzarQuality)[(acs->meterFillLevel / ONE_PCT_MASH) / 10];
264 }
265
266 if (acs->stateTimer != 0) {
267 acs->stateTimer--;
268 return;
269 }
270 battleStatus->actionResult = ACTION_RESULT_NONE;
271 battleStatus->actionQuality = battleStatus->actionProgress;
273 acs->stateTimer = 5;
274 acs->state = AC_STATE_DISPOSE;
275 break;
276 case AC_STATE_DISPOSE:
277 if (acs->stateTimer != 0) {
278 acs->stateTimer--;
279 return;
280 }
282 break;
283 }
284}
285
286void N(draw)(void) {
288 BattleStatus* battleStatus = &gBattleStatus;
289 s32 hudX, hudY;
290 HudElemID hid;
291
292 if (!acs->berserkerEnabled) {
294 }
295 hid = acs->hudElemIDs[HIDX_METER];
297 hud_element_get_render_pos(hid, &hudX, &hudY);
298
301
302 hid = acs->hudElemIDs[HIDX_DIGIT];
303 if (acs->variation == ACV_WHIRLWIND_HUFF) {
304 if (N(HuffDigits)[battleStatus->actionProgress] != hud_element_get_script(hid)) {
305 hud_element_set_script(hid, N(HuffDigits)[battleStatus->actionProgress]);
306 }
307 } else {
308 if (N(BuzzarDigits)[battleStatus->actionProgress] != hud_element_get_script(hid)) {
309 hud_element_set_script(hid, N(BuzzarDigits)[battleStatus->actionProgress]);
310 }
311 }
313}
314
BSS ActionCommandStatus gActionCommandStatus
Definition action_cmd.c:91
void action_command_free(void)
Definition action_cmd.c:446
void draw_mash_meter_multicolor_with_divisor(s32 posX, s32 posY, s32 fillValue, s32 divisor)
Definition action_cmd.c:231
s32 adjust_action_command_difficulty(s32 difficultyLevel)
Definition action_cmd.c:101
void action_command_init_status(void)
Definition action_cmd.c:256
HudScript HES_AButton
HudElemID hudElemIDs[16]
Definition action_cmd.h:83
@ AC_STATE_APPEAR
Definition action_cmd.h:35
@ AC_STATE_DISPOSE
Definition action_cmd.h:38
@ AC_STATE_INIT
Definition action_cmd.h:34
@ AC_STATE_ACTIVE
Definition action_cmd.h:37
@ AC_STATE_START
Definition action_cmd.h:36
#define ONE_PCT_MASH
Definition action_cmd.h:69
#define SCALE_BY_PCT(x, pct)
Definition action_cmd.h:77
HudScript HES_BlueMeter
HudScript HES_MashAButton
@ AC_MODE_NOT_LEARNED
Definition action_cmd.h:60
HudScript HES_Whirlwind1
Definition whirlwind.c:46
HudScript HES_Whirlwind6
Definition whirlwind.c:51
HudScript HES_Whirlwind4
Definition whirlwind.c:49
HudScript HES_Whirlwind2
Definition whirlwind.c:47
s32 actionCmdTableWhirlwind[]
Definition action_cmd.c:32
#define GET_DRAIN_RATE_HUFF(pct)
Definition whirlwind.c:61
HudScript HES_Whirlwind7
Definition whirlwind.c:52
HudScript HES_Whirlwind3
Definition whirlwind.c:48
void N free(void)
Definition whirlwind.c:315
#define BUZZAR_FILL_TICK
Definition whirlwind.c:20
@ HIDX_METER
Definition whirlwind.c:13
@ HIDX_BUTTON
Definition whirlwind.c:12
@ HIDX_BUBBLE
Definition whirlwind.c:15
@ HIDX_DIGIT
Definition whirlwind.c:14
#define GET_DRAIN_RATE_BUZZAR(pct)
Definition whirlwind.c:62
void N update(void)
Definition whirlwind.c:162
HudScript HES_WhirlwindBubble
Definition whirlwind.c:54
#define HUFF_FILL_TICK
Definition whirlwind.c:19
void N draw(void)
Definition whirlwind.c:286
HudScript HES_Whirlwind5
Definition whirlwind.c:50
s32 HudElemID
#define rand_int
@ ACTION_COMMAND_WHIRLWIND
Definition enums.h:3477
@ BUTTON_A
Definition enums.h:2790
@ ACTION_RESULT_NONE
Definition enums.h:1963
@ 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_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)
HudScript * hud_element_get_script(s32 id)
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
#define HES_TEMPLATE_CI_CUSTOM_SIZE(name, sizeX, sizeY)
Basic HudScript used for static CI images, setting size with hs_SetCustomSize.
#define HES_TEMPLATE_CI_ENUM_SIZE(name, sizeX, sizeY)
Basic HudScript used for static CI images, setting size with hs_SetTileSize.
s32 HudScript[]
Definition hud_element.h:9
#define INCLUDE_PAL(FILENAME, SYMBOLNAME)
#define INCLUDE_IMG(FILENAME, SYMBOLNAME)
#define POPUP_MSG_OFF
Definition battle.h:270
#define POPUP_MSG_ON
Definition battle.h:269
s32 * actionCmdDifficultyTable
BattleStatus gBattleStatus
Definition battle.c:11
@ ACV_WHIRLWIND_HUFF
Definition whirlwind.h:17
void N init(Npc *bombette)
Definition bombette.c:66