Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
smack.c
Go to the documentation of this file.
1#include "battle/battle.h"
2#include "battle/action_cmd.h"
3
4#define NAMESPACE action_command_smack
5
6extern s32 actionCmdTableSmack[];
7
8// indices into ActionCommandStatus::hudElements for this action command
9enum {
13};
14
15// how much to add to the meter per input
16#define HAND_METER_FILL_TICK 1300
17#define FAN_METER_FILL_TICK 850
18#define FAIL_METER_FILL_TICK 1100
19
20s32 N(DrainRateTable)[] = { 0, 25, 50, 75, 75 };
21
22#define GET_DRAIN_RATE(pct) PCT_TO_TABLE_RATE(N(DrainRateTable), pct)
23
24// threshold meter values for additional hits
25// these correspond to values provided via SetupMashMeter
26s32 N(BasicHitThresholds)[] = { 40, 70, 99, 200 };
27s32 N(SuperHitThresholds)[] = { 35, 60, 80, 99, 200 };
28s32 N(UltraHitThresholds)[] = { 35, 35, 60, 80, 99, 200 };
29s32 N(FanHitThresholds)[] = { 35, 60, 80, 99, 200 };
30
31API_CALLABLE(N(init)) {
33 BattleStatus* battleStatus = &gBattleStatus;
34 HudElemID hid;
35
36 battleStatus->maxActionQuality = 100;
38 battleStatus->actionResult = ACTION_RESULT_NONE;
39 if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
40 battleStatus->actionQuality = 0;
41 return ApiStatus_DONE2;
42 }
45 acs->showHud = TRUE;
46 acs->hudPrepareTime = 30;
47 acs->state = AC_STATE_INIT;
48 acs->wrongButtonPressed = FALSE;
49 acs->meterFillLevel = 0;
50 acs->meterFillWidth = 0;
51 acs->isMeterFilled = FALSE;
52 battleStatus->actionQuality = 0;
53 battleStatus->actionProgress = 0;
54 acs->hudPosX = -48;
55 acs->hudPosY = 80;
56
58 acs->hudElemIDs[HIDX_STICK] = hid;
62
64 acs->hudElemIDs[HIDX_METER] = hid;
65 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
68
70 acs->hudElemIDs[HIDX_100_PCT] = hid;
71 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
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 acs->variation = evt_get_variable(script, *args++);
95
96 acs->wrongButtonPressed = FALSE;
97 acs->meterFillLevel = 0;
98 acs->meterFillWidth = 0;
99 battleStatus->actionQuality = 0;
100 battleStatus->actionResult = ACTION_RESULT_NONE;
101 battleStatus->maxActionQuality = acs->mashMeterCutoffs[(acs->mashMeterNumIntervals - 1)];
102 battleStatus->flags1 &= ~BS_FLAGS1_FREE_ACTION_COMMAND;
103 acs->state = AC_STATE_START;
104
106
107 return ApiStatus_DONE2;
108}
109
110void N(update)(void) {
112 BattleStatus* battleStatus = &gBattleStatus;
113 Actor* partnerActor = battleStatus->partnerActor;
114 HudElemID hid;
115 s32 cutoff;
116 s32 idx;
117
118 switch (acs->state) {
119 case AC_STATE_INIT:
121 hid = acs->hudElemIDs[HIDX_STICK];
122 hud_element_set_alpha(hid, 255);
123 if (acs->showHud) {
125 }
126 hid = acs->hudElemIDs[HIDX_METER];
127 hud_element_set_alpha(hid, 255);
128 if (acs->showHud) {
130 }
131 acs->state = AC_STATE_APPEAR;
132 break;
133 case AC_STATE_APPEAR:
135 if (acs->hudPrepareTime != 0) {
136 acs->hudPrepareTime--;
137 break;
138 }
139
140 acs->hudPosX += 20;
141 if (acs->hudPosX > 50) {
142 acs->hudPosX = 50;
143 }
144
147 break;
148 case AC_STATE_START:
150 if (acs->prepareTime != 0) {
151 acs->prepareTime--;
152 break;
153 }
155 acs->meterFillLevel = 0;
156 battleStatus->resultTier = 0;
157 acs->smack.holdingLeft = FALSE;
158 acs->stateTimer = acs->duration;
160 acs->state = AC_STATE_ACTIVE;
161
162 // fallthrough
163 case AC_STATE_ACTIVE:
165
166 // meter can drain if it hasn't been fully filled
167 if (!acs->isMeterFilled) {
168 cutoff = acs->mashMeterCutoffs[acs->mashMeterNumIntervals];
169 acs->meterFillLevel -= GET_DRAIN_RATE(acs->meterFillLevel / cutoff);
170 if (acs->meterFillLevel < 0) {
171 acs->meterFillLevel = 0;
172 }
173 }
174
175 // check for meter-filling input
176 if (!acs->isMeterFilled) {
177 if (battleStatus->curButtonsDown & BUTTON_STICK_LEFT) {
178 acs->smack.holdingLeft = TRUE;
179 }
180
181 if (!(battleStatus->curButtonsDown & BUTTON_STICK_LEFT)) {
182 if (acs->smack.holdingLeft) {
183 if (acs->variation == ACV_SMACK_HAND) {
184 // regular smack
186 } else {
187 // fan smack
189 }
190 acs->smack.holdingLeft = FALSE;
191 }
192 }
193 // right stick inputs actively drain the meter
194 if (battleStatus->curButtonsPressed & BUTTON_STICK_RIGHT) {
196 }
197 }
198
199 if (acs->meterFillLevel < 0) {
200 acs->meterFillLevel = 0;
201 }
202
203 // handle meter reaching 100%
204 if (acs->meterFillLevel > MAX_MASH_UNITS) {
206 acs->isMeterFilled = TRUE;
207 hid = acs->hudElemIDs[HIDX_100_PCT];
208 hud_element_set_render_pos(hid, acs->hudPosX + 50, acs->hudPosY + 28);
210 }
211
212 battleStatus->actionProgress = acs->meterFillLevel / ONE_PCT_MASH;
214
215 switch (partnerActor->actorBlueprint->level) {
217 if (battleStatus->actionProgress >= N(BasicHitThresholds)[battleStatus->resultTier]) {
218 battleStatus->resultTier++;
219 }
220
221 if (battleStatus->resultTier > 0) {
222 if (battleStatus->actionProgress < N(BasicHitThresholds)[battleStatus->resultTier - 1]) {
223 battleStatus->resultTier--;
224 }
225 }
226 break;
228 if (battleStatus->actionProgress >= N(SuperHitThresholds)[battleStatus->resultTier]) {
229 battleStatus->resultTier++;
230 }
231
232 if (battleStatus->resultTier > 0) {
233 if (battleStatus->actionProgress < N(SuperHitThresholds)[battleStatus->resultTier - 1]) {
234 battleStatus->resultTier--;
235 }
236 }
237 break;
239 if (acs->variation == ACV_SMACK_HAND) {
240 if (battleStatus->actionProgress >= N(UltraHitThresholds)[battleStatus->resultTier]) {
241 battleStatus->resultTier++;
242 }
243
244 if (battleStatus->resultTier > 0) {
245 if (battleStatus->actionProgress < N(UltraHitThresholds)[battleStatus->resultTier - 1]) {
246 battleStatus->resultTier--;
247 }
248 }
249 } else {
250 if (battleStatus->actionProgress >= N(FanHitThresholds)[battleStatus->resultTier]) {
251 battleStatus->resultTier++;
252 }
253
254 if (battleStatus->resultTier > 0) {
255 if (battleStatus->actionProgress < N(FanHitThresholds)[battleStatus->resultTier - 1]) {
256 battleStatus->resultTier--;
257 }
258 }
259 }
260 break;
261 }
262
263 if (acs->stateTimer != 0) {
264 acs->stateTimer--;
265 break;
266 }
267
268 if (acs->meterFillLevel == 0) {
269 battleStatus->actionQuality = AC_QUALITY_FAILED;
270 } else {
271 battleStatus->actionQuality = acs->meterFillLevel / ONE_PCT_MASH;
272 }
273
274 cutoff = acs->mashMeterCutoffs[acs->mashMeterNumIntervals - 1];
275 if (battleStatus->actionQuality > cutoff) {
276 battleStatus->actionResult = ACTION_RESULT_SUCCESS;
277 } else {
279 }
280
281 if (battleStatus->actionQuality == 100) {
283 }
284
287 acs->stateTimer = 5;
288 acs->state = AC_STATE_DISPOSE;
289 break;
290 case AC_STATE_DISPOSE:
291 if (acs->stateTimer != 0) {
292 acs->stateTimer--;
293 break;
294 }
296 break;
297 }
298}
299
301
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
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
HudScript HES_StickNeutral
#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_StickMashLeft
HudScript HES_100pct
@ AC_MODE_NOT_LEARNED
Definition action_cmd.h:60
#define MAX_MASH_UNITS
Definition action_cmd.h:75
struct ActorBlueprint * actorBlueprint
s32 HudElemID
@ ACTION_COMMAND_SMACK
Definition enums.h:3490
@ BUTTON_STICK_LEFT
Definition enums.h:2793
@ BUTTON_STICK_RIGHT
Definition enums.h:2794
@ PARTNER_RANK_NORMAL
Definition enums.h:2018
@ PARTNER_RANK_SUPER
Definition enums.h:2019
@ PARTNER_RANK_ULTRA
Definition enums.h:2020
@ SOUND_LOOP_CHARGE_METER
Definition enums.h:1646
@ 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_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.
@ HUD_ELEMENT_FLAG_DISABLED
Definition hud_element.h:72
@ HUD_ELEMENT_FLAG_80
Definition hud_element.h:78
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
@ HIDX_METER
Definition smack.c:11
@ HIDX_STICK
Definition smack.c:10
@ HIDX_100_PCT
Definition smack.c:12
#define GET_DRAIN_RATE(pct)
Definition smack.c:22
#define FAIL_METER_FILL_TICK
Definition smack.c:18
s32 actionCmdTableSmack[]
Definition action_cmd.c:45
#define HAND_METER_FILL_TICK
Definition smack.c:16
void N update(void)
Definition smack.c:110
#define FAN_METER_FILL_TICK
Definition smack.c:17
@ ACV_SMACK_HAND
Definition smack.h:18
#define POPUP_MSG_OFF
Definition battle.h:270
#define POPUP_MSG_ON
Definition battle.h:269
struct Actor * partnerActor
s32 * actionCmdDifficultyTable
BattleStatus gBattleStatus
Definition battle.c:11
void N init(Npc *bombette)
Definition bombette.c:66