Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
air_lift.c
Go to the documentation of this file.
1#include "common.h"
2#include "effects.h"
3#include "battle/action_cmd.h"
4
5#define NAMESPACE action_command_air_lift
6
7extern s32 actionCmdTableAirLift[];
8
9// indices into ActionCommandStatus::hudElements for this action command
10enum {
14};
15
16// how much to add to the meter per input if all modifiers are neutral
17#define METER_FILL_RATE 820
18
19s32 N(DrainRateTable)[] = { 0, 25, 50, 75, 75 };
20
21#define GET_DRAIN_RATE(pct) PCT_TO_TABLE_RATE(N(DrainRateTable), pct)
22
23BSS b32 N(HasStarted);
24
25API_CALLABLE(N(init)) {
26 s32 *args = script->ptrReadPos;
27 BattleStatus* battleStatus = &gBattleStatus;
29 HudElemID hid;
30
32 battleStatus->maxActionQuality = 0;
33 battleStatus->actionResult = ACTION_RESULT_NONE;
34
36
37 // effectiveness for this move comes from AirLiftChance, which ultimately depends on
38 // the target actor's HP and status. this value will ONLY be zero if the target actor
39 // is transparent, in which case a dummy version of the action command is played out
40 // which is guaranteed to fail.
41 acs->escapeChance = evt_get_variable(script, *args++);
42
44 acs->showHud = TRUE;
45 acs->state = AC_STATE_INIT;
46 acs->wrongButtonPressed = FALSE;
47 acs->meterFillLevel = 0;
48 acs->meterFillWidth = 0;
49 acs->isMeterFilled = FALSE;
50 battleStatus->actionQuality = 0;
51 battleStatus->actionProgress = 0;
52
53 N(HasStarted) = FALSE;
54 acs->hudPrepareTime = 30;
55 acs->hudPosX = -48;
56 acs->hudPosY = 80;
57
59 acs->hudElemIDs[HIDX_BUTTON] = hid;
63
65 acs->hudElemIDs[HIDX_METER] = hid;
66 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
69
71 acs->hudElemIDs[HIDX_100_PCT] = hid;
72 hud_element_set_render_pos(hid, acs->hudPosX, acs->hudPosY + 28);
75
76 return ApiStatus_DONE2;
77}
78
79API_CALLABLE(N(start)) {
81 BattleStatus* battleStatus = &gBattleStatus;
82 Bytecode* args = script->ptrReadPos;
83
85
86 acs->prepareTime = evt_get_variable(script, *args++);
87 acs->duration = evt_get_variable(script, *args++);
88 acs->difficulty = evt_get_variable(script, *args++);
90 acs->variation = evt_get_variable(script, *args++);
91
92 acs->wrongButtonPressed = FALSE;
93 battleStatus->actionQuality = 0;
94 battleStatus->actionResult = ACTION_RESULT_NONE;
95 battleStatus->maxActionQuality = acs->mashMeterCutoffs[acs->mashMeterNumIntervals - 1];
96
97 acs->any.unk_5C = 0;
98
99 battleStatus->flags1 &= ~BS_FLAGS1_FREE_ACTION_COMMAND;
100 acs->state = AC_STATE_START;
101
103
104 return ApiStatus_DONE2;
105}
106
107void N(update)(void) {
109 BattleStatus* battleStatus = &gBattleStatus;
110 HudElemID hid;
111
112 switch (acs->state) {
113 case AC_STATE_INIT:
115
116 hid = acs->hudElemIDs[HIDX_BUTTON];
117 hud_element_set_alpha(hid, 255);
118 if (acs->showHud) {
120 }
121
122 hid = acs->hudElemIDs[HIDX_METER];
123 hud_element_set_alpha(hid, 255);
124 if (acs->showHud) {
126 }
127
128 acs->state = AC_STATE_APPEAR;
129 break;
130 case AC_STATE_APPEAR:
132
133 if (acs->hudPrepareTime != 0) {
134 acs->hudPrepareTime--;
135 return;
136 }
137
138 acs->hudPosX += 20;
139 if (acs->hudPosX > 50) {
140 acs->hudPosX = 50;
141 }
142
145 break;
146 case AC_STATE_START:
148
149 if (acs->prepareTime != 0) {
150 acs->prepareTime--;
151 return;
152 }
153
155 N(HasStarted) = TRUE;
156 acs->stateTimer = acs->duration;
158 acs->state = AC_STATE_ACTIVE;
159
160 // fallthrough
161 case AC_STATE_ACTIVE:
163
164 // meter can drain if it hasn't been fully filled
165 if (!acs->isMeterFilled) {
166 if (acs->escapeChance != 0) {
167 s32 maxFillLevel = acs->mashMeterCutoffs[acs->mashMeterNumIntervals];
168 acs->meterFillLevel -= GET_DRAIN_RATE(acs->meterFillLevel / maxFillLevel);
169 if (acs->meterFillLevel < 0) {
170 acs->meterFillLevel = 0;
171 }
172 } else {
173 acs->meterFillLevel -= 10;
174 if (acs->meterFillLevel < 0) {
175 acs->meterFillLevel = 0;
176 }
177 }
178 }
179
180 // check for meter-filling input
181 if (battleStatus->actionCommandMode != AC_MODE_NOT_LEARNED && (battleStatus->curButtonsPressed & BUTTON_A)) {
182 if (acs->escapeChance != 0) {
183 // fill rate = 820 multiplied by two values expressed as percentages
184 s32 difficultyPct = battleStatus->actionCmdDifficultyTable[acs->difficulty];
185 s32 effectivenessPct = METER_FILL_RATE * acs->escapeChance;
186 // divide by 100 for each percent-based multiplier
187 acs->meterFillLevel += (difficultyPct * effectivenessPct) / (100 * 100);
188 } else {
190 if (acs->meterFillLevel >= 5 * ONE_PCT_MASH) {
191 acs->meterFillLevel = 5 * ONE_PCT_MASH;
192 }
193 }
194 }
195
196 // handle meter reaching 100%
197 if (acs->meterFillLevel > MAX_MASH_UNITS) {
199 acs->isMeterFilled = TRUE;
200 hid = acs->hudElemIDs[HIDX_100_PCT];
201 hud_element_set_render_pos(hid, acs->hudPosX + 50, acs->hudPosY + 28);
203 }
204
205 battleStatus->actionQuality = acs->meterFillLevel / ONE_PCT_MASH;
206 if (battleStatus->actionProgress < battleStatus->actionQuality) {
207 battleStatus->actionProgress = battleStatus->actionQuality;
208 }
210
211 if (acs->stateTimer != 0) {
212 acs->stateTimer--;
213 break;
214 }
215
216 if (acs->escapeChance == 0) {
217 battleStatus->actionProgress = 0;
218 }
219
220 // threshold for success is completely random, only guaranteed if the meter is 100% filled
221 battleStatus->actionQuality = battleStatus->actionProgress;
222 if (rand_int(99) < battleStatus->actionQuality) {
223 battleStatus->actionResult = ACTION_RESULT_SUCCESS;
224 battleStatus->actionQuality = 1;
225 } else {
227 battleStatus->actionQuality = AC_QUALITY_FAILED;
228 }
229
230 if (battleStatus->actionQuality == 1) {
232 }
233
236 acs->stateTimer = 20;
237 acs->state = AC_STATE_DISPOSE;
238 break;
239 case AC_STATE_DISPOSE:
240 if (acs->escapeChance == 0) {
242 if (acs->meterFillLevel < 0) {
243 acs->meterFillLevel = 0;
244 }
245 }
246 if (acs->stateTimer != 0) {
247 acs->stateTimer--;
248 break;
249 }
251 break;
252 }
253}
254
255void N(draw)(void) {
257 s32 hudX, hudY;
258 HudElemID hid;
259
262 }
263
264 hid = acs->hudElemIDs[HIDX_METER];
266 hud_element_get_render_pos(hid, &hudX, &hudY);
267
268 if (!N(HasStarted)) {
270 } else if (!acs->isMeterFilled) {
272 } else {
274 }
275
277}
278
void draw_mash_meter_blink_with_divisor(s32 posX, s32 posY, s32 fillValue, s32 divisor)
Definition action_cmd.c:251
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
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 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
@ 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
HudScript HES_BlueMeter
HudScript HES_MashAButton
HudScript HES_100pct
@ AC_MODE_NOT_LEARNED
Definition action_cmd.h:60
#define MAX_MASH_UNITS
Definition action_cmd.h:75
@ HIDX_METER
Definition air_lift.c:12
@ HIDX_BUTTON
Definition air_lift.c:11
@ HIDX_100_PCT
Definition air_lift.c:13
#define GET_DRAIN_RATE(pct)
Definition air_lift.c:21
#define METER_FILL_RATE
Definition air_lift.c:17
void N free(void)
Definition air_lift.c:279
void N update(void)
Definition air_lift.c:107
void N draw(void)
Definition air_lift.c:255
s32 actionCmdTableAirLift[]
Definition action_cmd.c:40
s32 HudElemID
s32 b32
#define rand_int
@ ACTION_COMMAND_AIR_LIFT
Definition enums.h:3485
@ BUTTON_A
Definition enums.h:2790
@ 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_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
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 BSS
Definition macros.h:7
#define POPUP_MSG_OFF
Definition battle.h:270
#define POPUP_MSG_ON
Definition battle.h:269
s32 * actionCmdDifficultyTable
BattleStatus gBattleStatus
Definition battle.c:11
void N init(Npc *bombette)
Definition bombette.c:66