Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
sneaky_parasol.c
Go to the documentation of this file.
1#include "common.h"
2#include "npc.h"
3#include "effects.h"
4#include "sprite/player.h"
5
8
9typedef struct TransformationData {
10 /* 0x00 */ Npc* npc;
11 /* 0x04 */ s32 reverted;
12 /* 0x08 */ s32 disguiseTime;
13 /* 0x0C */ s32 revertTime;
14 /* 0x10 */ Vec3f pos;
15 /* 0x1C */ f32 playerRotationRate;
16 /* 0x20 */ f32 playerYawOffset;
18
20
21enum {
23 SUBSTATE_USE_PARASOL = 1, // get parasol out and try copying an npc
24 SUBSTATE_PUT_AWAY = 2, // put the parasol away
31 SUBSTATE_REVERT_INIT = 20, // begin undisguise process
38 SUBSTATE_BLOCKED = 50, // cant raise parasol due to collisions with world
39};
40
41void parasol_update_spin(void);
42
44 Npc* npc = NULL;
45 f32 angle;
46
48 return NULL;
49 }
50
52 gGameStatusPtr->peachFlags &= ~PEACH_FLAG_BLOCK_NEXT_DISGUISE;
53 return NULL;
54 }
55
57 if (npc == NULL) {
58 return NULL;
59 }
60
61 if (fabs(npc->pos.y - gPlayerStatus.pos.y) > 1.0) {
62 return NULL;
63 }
64
65 angle = clamp_angle(atan2(gPlayerStatus.pos.x, gPlayerStatus.pos.z, npc->pos.x, npc->pos.z));
66 if (fabs(angle - player_get_side_angle()) > 30.0) {
67 return NULL;
68 }
69
70 return npc;
71}
72
74 PlayerStatus* playerStatus = &gPlayerStatus;
77 Npc* disguiseNpc;
78 f32 prevFacingAngle;
79 s32 reachedTangentAngle;
80 f32 angle;
81 f32 radius;
82
83 if (playerStatus->flags & PS_FLAG_ACTION_STATE_CHANGED) {
84 playerStatus->flags &= ~PS_FLAG_ACTION_STATE_CHANGED;
87
88 playerStatus->timeInAir = 0;
89 playerStatus->peakJumpTime = 0;
90 playerStatus->curSpeed = 0;
91 playerStatus->pitch = 0;
92
93 if (playerStatus->spriteFacingAngle >= 90 && playerStatus->spriteFacingAngle < 270) {
94 transformation->playerRotationRate = 2;
95 } else {
96 transformation->playerRotationRate = -2;
97 }
98
99 if (!(playerStatus->animFlags & PA_FLAG_INVISIBLE)) {
100 playerStatus->curStateTime = 20;
102 transformation->disguiseTime = 15;
103 transformation->npc = parasol_get_npc();
104 } else {
105 playerStatus->actionSubstate = SUBSTATE_REVERT_INIT;
106 playerStatus->curStateTime = 40;
107 transformation->reverted = 1;
108 transformation->revertTime = 12;
111 playerStatus->flags |= PS_FLAG_ROTATION_LOCKED;
113 }
114 }
115
116 switch (playerStatus->actionSubstate) {
118 if (playerStatus->flipYaw[CAM_DEFAULT] == 0) {
120 suggest_player_anim_allow_backward(ANIM_Peach2_UseParasol);
122 playerStatus->actionSubstate++; // SUBSTATE_USE_PARASOL
123 } else {
124 suggest_player_anim_allow_backward(ANIM_Peach2_CantFitParasol);
125 playerStatus->actionSubstate = SUBSTATE_BLOCKED;
126 playerStatus->curStateTime = 10;
127 transformation->disguiseTime = 0;
128 }
129 }
131 if (--playerStatus->curStateTime == 0) {
132 suggest_player_anim_allow_backward(ANIM_Peach2_PutAwayParasol);
133 playerStatus->actionSubstate = SUBSTATE_PUT_AWAY;
134 if (transformation->npc == NULL) {
135 playerStatus->actionSubstate = SUBSTATE_FAILED;
136 } else {
138 }
139 }
140 break;
142 if (playerStatus->animNotifyValue != 0) {
143 playerStatus->curStateTime = 12;
144 playerStatus->flags |= PS_FLAG_ROTATION_LOCKED;
145 playerStatus->actionSubstate++; // SUBSTATE_DISGUISE_BEGIN
147 }
148 break;
150 if (--playerStatus->curStateTime == 0) {
151 playerStatus->curStateTime = 10;
152 transformation->revertTime = 10;
153 playerStatus->actionSubstate++; // SUBSTATE_DISGUISE_WAIT_FOR_ANGLE
154 }
156 break;
158 prevFacingAngle = playerStatus->spriteFacingAngle;
160 playerStatus->targetYaw = clamp_angle((cam->curYaw - playerStatus->spriteFacingAngle) - 90);
161 if (playerStatus->curStateTime == 0) {
162 // wait for the sprite to rotate into a position where it's tangent to the camera
163 reachedTangentAngle = FALSE;
164 if (transformation->playerRotationRate > 0) {
165 if (prevFacingAngle < 270 && playerStatus->spriteFacingAngle >= 270) {
166 reachedTangentAngle = TRUE;
167 }
168 }
169 if (transformation->playerRotationRate < 0) {
170 if (prevFacingAngle > 270 && playerStatus->spriteFacingAngle <= 270) {
171 reachedTangentAngle = TRUE;
172 }
173 }
174 if (reachedTangentAngle) {
176 playerStatus->curStateTime = 2;
177 if (peach_make_disguise_npc(playerStatus->availableDisguiseType) != NULL) {
180 }
181 }
182 } else {
183 playerStatus->curStateTime--;
184 }
185 break;
187 playerStatus->animFlags |= PA_FLAG_INVISIBLE;
189 playerStatus->actionSubstate++; // SUBSTATE_DISGUISE_SPIN_DOWN
191 if (--playerStatus->curStateTime == 0) {
192 playerStatus->actionSubstate++; // SUBSTATE_DISGUISE_FINISH_SPIN
193 }
195 break;
197 if (transformation->playerRotationRate > 0.0f) {
198 transformation->playerYawOffset -= 2.35;
199 if (transformation->playerYawOffset <= 0) {
200 transformation->playerYawOffset = 0;
201 playerStatus->curStateTime = 10;
202 playerStatus->actionSubstate++; // SUBSTATE_DISGUISE_DONE
203 playerStatus->spriteFacingAngle = 180;
205 disguiseNpc->isFacingAway = TRUE;
206 disguiseNpc->yaw = clamp_angle((cam->curYaw - playerStatus->spriteFacingAngle) - 90);
207 disguiseNpc->yawCamOffset = disguiseNpc->yaw;
208 }
209 } else {
210 transformation->playerYawOffset += 2.35;
211 if (transformation->playerYawOffset >= 0) {
212 transformation->playerYawOffset = 0;
213 playerStatus->curStateTime = 10;
214 playerStatus->spriteFacingAngle = 0;
215 playerStatus->actionSubstate++; // SUBSTATE_DISGUISE_DONE
217 disguiseNpc->isFacingAway = FALSE;
218 disguiseNpc->yaw = clamp_angle((cam->curYaw - playerStatus->spriteFacingAngle) - 90);
219 disguiseNpc->yawCamOffset = disguiseNpc->yaw;
220 }
221 }
222 playerStatus->spriteFacingAngle = clamp_angle(playerStatus->spriteFacingAngle + transformation->playerYawOffset);
223 playerStatus->targetYaw = clamp_angle((cam->curYaw - playerStatus->spriteFacingAngle) - 90);
224 break;
226 if (--playerStatus->curStateTime == 0) {
229 disguiseNpc->flags &= ~NPC_FLAG_IGNORE_CAMERA_FOR_YAW;
230 playerStatus->flags &= ~PS_FLAG_ROTATION_LOCKED;
233 }
234 break;
236 if (--playerStatus->curStateTime == 0) {
237 playerStatus->actionSubstate++; // SUBSTATE_REVERT_WAIT_FOR_ANGLE
238 }
240 playerStatus->targetYaw = clamp_angle(cam->curYaw - playerStatus->spriteFacingAngle - 90);
241 break;
243 prevFacingAngle = playerStatus->spriteFacingAngle;
245 playerStatus->targetYaw = clamp_angle((cam->curYaw - playerStatus->spriteFacingAngle) - 90);
246 if (playerStatus->curStateTime == 0) {
247 // wait for the sprite to rotate into a position where it's tangent to the camera
248 reachedTangentAngle = FALSE;
249 if (transformation->playerRotationRate > 0) {
250 if (prevFacingAngle < 270 && playerStatus->spriteFacingAngle >= 270) {
251 reachedTangentAngle = TRUE;
252 }
253 }
254 if (transformation->playerRotationRate < 0) {
255 if (prevFacingAngle > 270 && playerStatus->spriteFacingAngle <= 270) {
256 reachedTangentAngle = TRUE;
257 }
258 }
259 if (reachedTangentAngle) {
260 playerStatus->curStateTime = 2;
261 playerStatus->actionSubstate++; // SUBSTATE_SPIN_DOWN
262 playerStatus->animFlags &= ~PA_FLAG_INVISIBLE;
263 gGameStatus.peachFlags &= ~PEACH_FLAG_DISGUISED;
264 playerStatus->peachDisguise = 0;
266 playerStatus->colliderHeight = 55;
267 playerStatus->colliderDiameter = 38;
268 }
269 } else {
270 playerStatus->curStateTime--;
271 }
272 break;
274 if (--playerStatus->curStateTime == 0) {
275 playerStatus->actionSubstate++; // SUBSTATE_FINISH_SPIN
276 }
278 break;
280 if (transformation->playerRotationRate > 0) {
281 transformation->playerYawOffset -= 2.35;
282 if (transformation->playerYawOffset <= 0) {
283 transformation->playerYawOffset = 0;
284 playerStatus->curStateTime = 10;
285 playerStatus->actionSubstate++; // SUBSTATE_REVERT_DONE
286 playerStatus->spriteFacingAngle = 180;
288 playerStatus->curYaw = clamp_angle((cam->curYaw - 180) - 90);
289 PrevPlayerCamRelativeYaw = playerStatus->curYaw;
290 }
291 } else {
292 transformation->playerYawOffset += 2.35;
293 if (transformation->playerYawOffset >= 0) {
294 transformation->playerYawOffset = 0;
295 playerStatus->curStateTime = 10;
296 playerStatus->spriteFacingAngle = 0;
297 playerStatus->actionSubstate++; // SUBSTATE_REVERT_DONE
299 playerStatus->curYaw = clamp_angle((cam->curYaw - 0) - 90);
300 PrevPlayerCamRelativeYaw = playerStatus->curYaw;
301 }
302 }
303 playerStatus->spriteFacingAngle = clamp_angle(playerStatus->spriteFacingAngle + transformation->playerYawOffset);
304 playerStatus->targetYaw = clamp_angle(cam->curYaw - playerStatus->spriteFacingAngle - 90);
305 break;
307 if (--playerStatus->curStateTime == 0) {
309 playerStatus->flags &= ~PS_FLAG_ROTATION_LOCKED;
312 }
313 break;
314 case SUBSTATE_ABORT:
317 break;
318 case SUBSTATE_FAILED:
319 if (playerStatus->animNotifyValue != 0) {
322 }
323 break;
324 case SUBSTATE_BLOCKED:
325 if (--playerStatus->curStateTime == 0) {
328 }
329 break;
330 }
331
332 if (transformation->disguiseTime > 0) {
333 if (--transformation->disguiseTime == 10) {
334 if (playerStatus->spriteFacingAngle >= 90 && playerStatus->spriteFacingAngle < 270) {
335 angle = DEG_TO_RAD(cam->curYaw - 270);
336 radius = 46;
337 } else {
338 angle = DEG_TO_RAD(cam->curYaw - 90);
339 radius = 30;
340 }
341 transformation->pos.x = playerStatus->pos.x + (radius * sin_rad(angle));
342 transformation->pos.z = playerStatus->pos.z - (radius * cos_rad(angle));
343 transformation->pos.y = playerStatus->pos.y - 20;
344 }
345 if (transformation->disguiseTime <= 10 && transformation->disguiseTime & 1) {
346 fx_sparkles(FX_SPARKLES_3,
347 transformation->pos.x - 8,
348 transformation->pos.y + 50,
349 transformation->pos.z,
350 2);
351
352 angle = DEG_TO_RAD((cam->curYaw + playerStatus->spriteFacingAngle) - 90);
353 transformation->pos.x += (10.0 * sin_rad(angle));
354 transformation->pos.z -= (10.0 * cos_rad(angle));
355 }
356 } else if (transformation->disguiseTime == 0) {
357 transformation->disguiseTime = -1;
358 if (transformation->npc != NULL) {
359 fx_pink_sparkles(playerStatus->availableDisguiseType - 1,
360 transformation->npc->pos.x,
361 transformation->npc->pos.y,
362 transformation->npc->pos.z,
363 1, transformation->npc->yawCamOffset);
364 }
365 }
366 if (transformation->revertTime != 0) {
367 if (transformation->revertTime <= 10) {
368 if (transformation->revertTime == 10) {
370 }
371 if ((transformation->revertTime & 3) == 0) {
372 fx_stars_shimmer(4,
373 playerStatus->pos.x,
374 playerStatus->pos.y,
375 playerStatus->pos.z,
376 50, 50, 40, 30);
377 }
378 }
379 transformation->revertTime--;
380 }
381}
382
384 PlayerStatus* playerStatus = &gPlayerStatus;
385 TransformationData* transformation = &ParasolTransformation;
386
387 transformation->playerYawOffset += transformation->playerRotationRate;
388 if (transformation->playerYawOffset > 50.0f) {
389 transformation->playerYawOffset = 50.0f;
390 } else if (transformation->playerYawOffset < -50.0f) {
391 transformation->playerYawOffset = -50.0f;
392 }
393
394 playerStatus->spriteFacingAngle = clamp_angle(playerStatus->spriteFacingAngle + transformation->playerYawOffset);
395}
s8 availableDisguiseType
set in main map scripts
#define clamp_angle
#define atan2
#define mem_clear
@ FX_SPARKLES_3
Definition effects.h:237
@ PEACH_FLAG_DISGUISED
Definition enums.h:2489
@ PEACH_FLAG_BLOCK_NEXT_DISGUISE
Definition enums.h:2491
@ PEACH_DISGUISE_NONE
Definition enums.h:2518
@ PS_FLAG_ROTATION_LOCKED
Definition enums.h:3065
@ PS_FLAG_ACTION_STATE_CHANGED
Definition enums.h:3084
@ PA_FLAG_INVISIBLE
Definition enums.h:3104
@ TIME_FREEZE_FULL
Definition enums.h:3466
@ TIME_FREEZE_NONE
Definition enums.h:3464
@ SOUND_KKJ_USE_SNEAKY_PARASOL
Definition enums.h:660
@ SOUND_SNEAKY_PARASOL_TRANSFORM
Definition enums.h:740
@ SOUND_SNEAKY_PARASOL_COPY
Definition enums.h:739
@ ACTION_STATE_IDLE
Definition enums.h:2426
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
@ CAM_DEFAULT
Definition enums.h:1800
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
Definition enums.h:3016
f64 fabs(f64 f)
s32 disable_player_static_collisions(void)
Definition 77480.c:972
f32 cos_rad(f32 x)
Definition 43F0.c:717
f32 player_get_side_angle(void)
Definition 7BB60.c:1178
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
void peach_sync_disguise_npc(void)
Definition 7E9D0.c:555
void suggest_player_anim_allow_backward(AnimID anim)
Definition 77480.c:894
f32 sin_rad(f32 x)
Definition 43F0.c:713
void set_time_freeze_mode(s32)
Time freeze modes: 0: none 1: NPCs move, can't be interacted with 2: NPCs don't move,...
Definition main_loop.c:358
s32 enable_player_static_collisions(void)
Definition 77480.c:980
Npc * peach_make_disguise_npc(s32 peachDisguise)
Definition 7E9D0.c:573
void free_npc_by_index(s32 listIndex)
Definition npc.c:202
Npc * npc_find_closest(f32 x, f32 y, f32 z, f32 radius)
Finds the closest NPC to a given point within a radius.
Definition npc.c:1969
Npc * get_npc_by_index(s32 listIndex)
Definition npc.c:271
void sfx_play_sound_at_player(s32 soundID, s32 arg1)
Definition sfx.c:521
#define BSS
Definition macros.h:7
#define DEG_TO_RAD(deg)
Definition macros.h:134
@ SUBSTATE_DISGUISE_INIT
@ SUBSTATE_DISGUISE_MAKE_NPC
@ SUBSTATE_USE_PARASOL
@ SUBSTATE_BLOCKED
@ SUBSTATE_DISGUISE_SPIN_DOWN
@ SUBSTATE_REVERT_WAIT_FOR_ANGLE
@ SUBSTATE_DISGUISE_BEGIN
@ SUBSTATE_DISGUISE_FINISH_SPIN
@ SUBSTATE_SPIN_DOWN
@ SUBSTATE_FINISH_SPIN
@ SUBSTATE_DISGUISE_DONE
@ SUBSTATE_REVERT_DONE
@ SUBSTATE_DISGUISE_WAIT_FOR_ANGLE
@ SUBSTATE_PUT_AWAY
@ SUBSTATE_REVERT_INIT
@ SUBSTATE_FAILED
@ SUBSTATE_ABORT
Npc * parasol_get_npc(void)
BSS TransformationData ParasolTransformation
s32 peach_disguise_check_overlaps(void)
Definition 7E9D0.c:614
void peach_force_disguise_action(s32)
Definition 7E9D0.c:514
void action_update_parasol(void)
void parasol_update_spin(void)
s32 flags
b16 isFacingAway
s16 yawCamOffset
Vec3f pos
GameStatus gGameStatus
Definition main_loop.c:21
s32 PrevPlayerDirection
Definition 7B440.c:7
GameStatus * gGameStatusPtr
Definition main_loop.c:32
Camera gCameras[4]
Definition cam_main.c:17
s32 PrevPlayerCamRelativeYaw
Definition 7E9D0.c:31
PlayerStatus gPlayerStatus
Definition 77480.c:39
s32 gCurrentCameraID
Definition cam_math.c:4
s32 PeachDisguiseNpcIndex
Definition 7B440.c:4