Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
break_free.c
Go to the documentation of this file.
1#include "common.h"
2#include "battle/action_cmd.h"
3
4#define NAMESPACE action_command_break_free
5
6extern s32 actionCmdTableBreakFree[];
7
8// indices into ActionCommandStatus::hudElements for this action command
9enum {
14};
15
16// how much to add to the meter per input if all modifiers are neutral
17#define METER_FILL_RATE 100
18
19API_CALLABLE(N(init)) {
21 BattleStatus* battleStatus = &gBattleStatus;
22 HudElemID hid;
23
24 battleStatus->maxActionQuality = 0;
26 battleStatus->actionResult = ACTION_RESULT_NONE;
27
28 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
29 battleStatus->actionQuality = 0;
30 return ApiStatus_DONE2;
31 }
32
34
36 acs->showHud = TRUE;
37 acs->state = AC_STATE_INIT;
38 acs->wrongButtonPressed = FALSE;
39 acs->meterFillLevel = 0;
40 acs->escapeThreshold = 0;
41 acs->meterFillWidth = 0;
42 battleStatus->actionQuality = 0;
43 acs->hudPosX = -48;
44 acs->hudPosY = 80;
45
47 acs->hudElemIDs[HIDX_BUTTON] = hid;
51
53 acs->hudElemIDs[HIDX_METER] = hid;
54 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
57
59 acs->hudElemIDs[HIDX_RUN_AWAY] = hid;
60 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
63
65 acs->hudElemIDs[HIDX_OK] = hid;
66 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
69
70 return ApiStatus_DONE2;
71}
72
73API_CALLABLE(N(start)) {
75 BattleStatus* battleStatus = &gBattleStatus;
76 Bytecode* args = script->ptrReadPos;
77
78 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
79 battleStatus->actionQuality = 0;
80 return ApiStatus_DONE2;
81 }
82
84
85 acs->prepareTime = evt_get_variable(script, *args++);
86 acs->duration = evt_get_variable(script, *args++);
87 acs->escapeChance = evt_get_variable(script, *args++);
88 acs->difficulty = evt_get_variable(script, *args++);
90
91 acs->wrongButtonPressed = FALSE;
92 acs->meterFillLevel = 0;
93 acs->escapeThreshold = 0;
94 acs->meterFillWidth = 0;
95
96 battleStatus->actionQuality = 0;
97 battleStatus->actionResult = ACTION_RESULT_NONE;
98 battleStatus->maxActionQuality = acs->mashMeterCutoffs[acs->mashMeterNumIntervals - 1];
99
101 acs->breakFree.dir = 0;
102 acs->state = AC_STATE_START;
103 battleStatus->flags1 &= ~BS_FLAGS1_FREE_ACTION_COMMAND;
104
105 return ApiStatus_DONE2;
106}
107
108void N(update)(void) {
110 BattleStatus* battleStatus = &gBattleStatus;
111 HudElemID hid;
112
113 switch (acs->state) {
114 case AC_STATE_INIT:
116
117 hid = acs->hudElemIDs[HIDX_BUTTON];
118 hud_element_set_alpha(hid, 255);
119 if (acs->showHud) {
121 }
122
123 hid = acs->hudElemIDs[HIDX_METER];
124 hud_element_set_alpha(hid, 255);
125 if (acs->showHud) {
127 }
128
129 hid = acs->hudElemIDs[HIDX_RUN_AWAY];
130 hud_element_set_alpha(hid, 255);
131 if (acs->showHud) {
133 }
134
135 hid = acs->hudElemIDs[HIDX_OK];
136 hud_element_set_alpha(hid, 255);
137 if (acs->showHud) {
139 }
140
141 acs->state = AC_STATE_APPEAR;
142 break;
143 case AC_STATE_APPEAR:
145 acs->hudPosX += 20;
146 if (acs->hudPosX > 50) {
147 acs->hudPosX = 50;
148 }
152 hud_element_set_render_pos(acs->hudElemIDs[HIDX_OK], acs->hudPosX + 31, acs->hudPosY + 17);
153 break;
154 case AC_STATE_START:
156 if (acs->prepareTime != 0) {
157 acs->prepareTime--;
158 return;
159 }
161 acs->state = AC_STATE_ACTIVE;
162 acs->stateTimer = acs->duration;
163
164 // fallthrough
165 case AC_STATE_ACTIVE:
167
168 // update the position of the 'OK' tick
169 if (acs->breakFree.dir == 0) {
170 acs->escapeThreshold++;
171 if (acs->escapeThreshold >= acs->escapeChance) {
172 acs->escapeThreshold = acs->escapeChance;
173 acs->breakFree.dir = 1;
174 }
175 } else {
176 acs->escapeThreshold--;
177 if (acs->escapeThreshold <= 0) {
178 acs->escapeThreshold = 0;
179 acs->breakFree.dir = 0;
180 }
181 }
182
183 // unlike most other mash inputs, this command doesn't just increment meterFillLevel with inputs
184 // instead we sum the total number of inputs during the last N frames of the input buffer
185 if (!acs->berserkerEnabled) {
186 s32 inputBufPos = battleStatus->inputBufferPos;
187 s32 windowLen = acs->duration - acs->stateTimer;
188 s32 i;
189
190 acs->meterFillLevel = 0;
191
192 inputBufPos -= windowLen;
193 if (inputBufPos < 0) {
194 inputBufPos += ARRAY_COUNT(battleStatus->pushInputBuffer);
195 }
196
197 for (i = 0; i < windowLen; i++, inputBufPos++) {
198 if (inputBufPos >= ARRAY_COUNT(battleStatus->pushInputBuffer)) {
199 inputBufPos -= ARRAY_COUNT(battleStatus->pushInputBuffer);
200 }
201 if (battleStatus->pushInputBuffer[inputBufPos] & BUTTON_A) {
203 }
204 }
205 } else {
206 acs->meterFillLevel += SCALE_BY_PCT(25, battleStatus->actionCmdDifficultyTable[acs->difficulty]);
208 }
209
210 battleStatus->actionQuality = acs->meterFillLevel / ONE_PCT_MASH;
211 if (acs->stateTimer != 0) {
212 acs->stateTimer--;
213 break;
214 }
215
216 if (battleStatus->actionQuality >= acs->mashMeterCutoffs[acs->mashMeterNumIntervals] - acs->escapeThreshold) {
217 battleStatus->actionResult = ACTION_RESULT_SUCCESS;
218 battleStatus->actionQuality = 1;
219 } else {
221 battleStatus->actionQuality = AC_QUALITY_FAILED;
222 }
223
225 acs->stateTimer = 20;
226 acs->state = AC_STATE_DISPOSE;
227 break;
228 case AC_STATE_DISPOSE:
229 if (acs->stateTimer != 0) {
230 acs->stateTimer--;
231 break;
232 }
234 break;
235 }
236}
237
238void N(draw)(void) {
240 s32* hudElements = acs->hudElemIDs;
241 s32 hudX, hudY;
242 HudElemID hid;
243 s16 maxMeterValue;
244
245 // equivalent to 60 * acs->escapeThreshold / maxMeterValue
246 maxMeterValue = acs->mashMeterCutoffs[acs->mashMeterNumIntervals];
247 hudX = 60 - ((maxMeterValue - acs->escapeThreshold) * 60 / maxMeterValue);
248
249 hud_element_set_render_pos(hudElements[HIDX_OK], acs->hudPosX + 31 - hudX, acs->hudPosY + 17);
250 hud_element_set_render_pos(hudElements[HIDX_RUN_AWAY], acs->hudPosX + 31 - hudX, acs->hudPosY - 1);
251
252 if (!acs->berserkerEnabled) {
254 }
255
256 hid = hudElements[HIDX_METER];
258 hud_element_get_render_pos(hid, &hudX, &hudY);
259
262 hud_element_draw_clipped(hudElements[HIDX_OK]);
263}
264
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 action_command_free(void)
Definition action_cmd.c:446
s32 adjust_action_command_difficulty(s32 difficultyLevel)
Definition action_cmd.c:101
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
@ 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_RunAwayOK
HudScript HES_MashAButton
@ AC_MODE_NOT_LEARNED
Definition action_cmd.h:60
HudScript HES_RunningAway
@ HIDX_RUN_AWAY
Definition break_free.c:12
@ HIDX_METER
Definition break_free.c:11
@ HIDX_BUTTON
Definition break_free.c:10
@ HIDX_OK
Definition break_free.c:13
#define METER_FILL_RATE
Definition break_free.c:17
void N free(void)
Definition break_free.c:265
s32 actionCmdTableBreakFree[]
Definition action_cmd.c:31
void N update(void)
Definition break_free.c:108
void N draw(void)
Definition break_free.c:238
s32 HudElemID
#define rand_int
@ ACTION_COMMAND_BREAK_FREE
Definition enums.h:3476
@ BUTTON_A
Definition enums.h:2790
@ ACTION_RESULT_NONE
Definition enums.h:1963
@ ACTION_RESULT_METER_NOT_ENOUGH
Definition enums.h:1965
@ ACTION_RESULT_SUCCESS
Definition enums.h:1968
#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)
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 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]
BattleStatus gBattleStatus
Definition battle.c:11
void N init(Npc *bombette)
Definition bombette.c:66