Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
spin.c
Go to the documentation of this file.
1#include "common.h"
2#include "effects.h"
3#include "sprite/player.h"
4
5extern s32 gSpinHistoryBufferPos;
6extern s32 gSpinHistoryPosY[5];
7extern s32 gSpinHistoryPosX[5];
8extern s32 gSpinHistoryPosZ[5];
9extern s16 gSpinHistoryPosAngle[5];
10
12
13enum {
18};
19
26
28 PlayerSpinState* playerSpinState = &gPlayerSpinState;
29 PlayerStatus* playerStatus = &gPlayerStatus;
30 f32 angle, magnitude, speedModifier;
31
32 s32 spinFlags, nonDizzyFlags;
33 s32 effectType;
34 AnimID anim;
35 s32 firstCall = FALSE;
36
37 // initialization
38 if (playerStatus->flags & PS_FLAG_ACTION_STATE_CHANGED) {
40 playerStatus->animFlags &= ~PA_FLAG_INTERRUPT_SPIN;
41 playerStatus->animFlags |= PA_FLAG_SPINNING;
42 playerStatus->flags |= PS_FLAG_SPINNING;
43 playerStatus->curStateTime = 0;
44 playerStatus->actionSubstate = SUBSTATE_SPIN_0;
45 playerSpinState->stopSoundTimer = 0;
46 playerSpinState->hasBufferedSpin = FALSE;
47 playerSpinState->spinDirectionMagnitude = 0.0f;
48 playerSpinState->spinDirection.x = 0.0f;
49 playerSpinState->spinDirection.y = 0.0f;
50 playerSpinState->hitWallTime = 0;
51 playerSpinState->bufferedStickAxis.x = 0;
52 playerSpinState->bufferedStickAxis.y = 0;
53 playerSpinState->spinSoundID = 0;
54 playerStatus->specialDecorationEffect = NULL;
55 playerSpinState->initialSpinTime = 25;
56 playerSpinState->fullSpeedSpinTime = 15;
57 playerSpinState->spinRate = 40.0f;
58 playerSpinState->speedScale = 2.0f;
59 playerSpinState->frictionScale = 0.5f;
60 playerSpinState->spinCountdown = playerSpinState->initialSpinTime;
61 spinFlags = SPIN_TYPE_DEFAULT;
62 firstCall = TRUE;
63
65 spinFlags |= SPIN_TYPE_ATTACK;
66 }
67
69 spinFlags |= SPIN_TYPE_DIZZY;
70 }
71
73 playerSpinState->initialSpinTime = 30;
74 playerSpinState->spinRate = 40.0f;
75 playerSpinState->fullSpeedSpinTime = 20;
76 playerSpinState->spinCountdown = playerSpinState->initialSpinTime;
77 playerSpinState->speedScale = 2.7f;
78 playerSpinState->frictionScale = 0.9f;
79 spinFlags |= SPIN_TYPE_SPEEDY;
80 }
81
82 effectType = -1;
83 anim = ANIM_Mario1_Spin;
84
85 if (spinFlags) {
86 if (spinFlags & SPIN_TYPE_ATTACK) {
87 effectType = 2;
88 anim = ANIM_Mario1_SpinAttack;
89 } else if (spinFlags & SPIN_TYPE_DIZZY) {
90 effectType = 4;
91 anim = ANIM_Mario1_Spin;
92 } else if (spinFlags & SPIN_TYPE_SPEEDY) {
93 effectType = 0;
94 anim = ANIM_Mario1_SpeedySpin;
95 }
96 }
97
98 playerSpinState->spinSoundID = SOUND_SPIN;
99 nonDizzyFlags = spinFlags & ~SPIN_TYPE_DIZZY;
100
101 if (nonDizzyFlags == SPIN_TYPE_ATTACK) {
102 playerSpinState->spinSoundID = SOUND_SPIN_ATTACK;
103 }
104 if (nonDizzyFlags == SPIN_TYPE_SPEEDY) {
105 playerSpinState->spinSoundID = SOUND_SPEEDY_SPIN;
106 }
107 if (nonDizzyFlags == (SPIN_TYPE_ATTACK | SPIN_TYPE_SPEEDY)) {
108 playerSpinState->spinSoundID = SOUND_SPEEDY_SPIN_ATTACK;
109 }
110
113
114 if ((clamp_angle(playerStatus->targetYaw - gCameras[gCurrentCameraID].curYaw) <= 180.0f)) {
115 playerStatus->spinRate = playerSpinState->spinRate;
116 } else {
117 effectType++;
118 playerStatus->spinRate = -playerSpinState->spinRate;
119 }
120 if (spinFlags != 0) {
121 playerStatus->specialDecorationEffect = fx_effect_46(effectType, playerStatus, 1.0f, 1000);
122 }
123
125 player_input_to_move_vector(&angle, &magnitude);
126 playerStatus->targetYaw = angle;
127 playerSpinState->inputMagnitude = magnitude;
128 }
129
130 // update saved position and rotation values for motion blur effect
134 }
142 }
143
144 // check for spin cancel
145 if (!firstCall && (check_input_hammer() || check_input_jump())) {
146 playerStatus->animFlags &= ~PA_FLAG_SPINNING;
147 playerStatus->flags &= ~PS_FLAG_SPINNING;
148 sfx_stop_sound(playerSpinState->spinSoundID);
149 player_input_to_move_vector(&angle, &magnitude);
150 playerStatus->targetYaw = angle;
151 return;
152 }
153
154 // check for buffered next spin
155 if (playerSpinState->spinCountdown < 11 && playerStatus->pressedButtons & BUTTON_Z) {
156 playerSpinState->hasBufferedSpin = TRUE;
157 playerSpinState->prevActionState = playerStatus->prevActionState;
158 playerSpinState->bufferedStickAxis.x = playerStatus->stickAxis[0];
159 playerSpinState->bufferedStickAxis.y = playerStatus->stickAxis[1];
160 }
161
162 // check for action finished
163 if (playerStatus->actionSubstate >= SUBSTATE_SPIN_2) {
164 playerSpinState->spinDirectionMagnitude -= 1.0f;
165 if (playerSpinState->spinDirectionMagnitude < 0.0f) {
166 playerSpinState->spinDirectionMagnitude = 0.0f;
167 }
168
169 angle = clamp_angle(playerStatus->targetYaw - gCameras[gCurrentCameraID].curYaw);
170 playerSpinState->spinDirection.x = sin_rad(DEG_TO_RAD(angle)) * playerSpinState->spinDirectionMagnitude;
171 playerSpinState->spinDirection.y = -cos_rad(DEG_TO_RAD(angle)) * playerSpinState->spinDirectionMagnitude;
172 playerStatus->curStateTime--;
173 if (playerStatus->curStateTime == 0) {
174 playerSpinState->stopSoundTimer = 4;
176 playerStatus->flags &= ~PS_FLAG_SPINNING;
177 playerStatus->animFlags &= ~PA_FLAG_SPINNING;
178 sfx_stop_sound(playerSpinState->spinSoundID);
179 }
180 playerStatus->curSpeed = 0.0f;
181 return;
182 }
183
184 if (playerStatus->actionSubstate == SUBSTATE_SPIN_0) {
185 if (playerStatus->animFlags & PA_FLAG_INTERRUPT_SPIN) {
186 playerStatus->actionSubstate = SUBSTATE_SPIN_1;
188 playerSpinState->hitWallTime++;
189 if (playerSpinState->hitWallTime >= 10) {
190 playerStatus->actionSubstate = SUBSTATE_SPIN_1;
191 }
192 }
193 }
194
195 if (!(playerStatus->curStateTime > playerSpinState->fullSpeedSpinTime)) {
196 speedModifier = (playerSpinState->inputMagnitude) ? playerSpinState->speedScale : 0.0f;
197 playerSpinState->spinDirectionMagnitude = playerSpinState->spinDirectionMagnitude + 0.9;
198
199 if (playerSpinState->spinDirectionMagnitude > 9.0f) {
200 playerSpinState->spinDirectionMagnitude = 9.0f;
201 }
202
203 angle = clamp_angle(playerStatus->targetYaw - gCameras[gCurrentCameraID].curYaw);
204 playerSpinState->spinDirection.x = sin_rad(DEG_TO_RAD(angle)) * playerSpinState->spinDirectionMagnitude;
205 playerSpinState->spinDirection.y = -cos_rad(DEG_TO_RAD(angle)) * playerSpinState->spinDirectionMagnitude;
206 } else {
207 speedModifier = playerSpinState->speedScale - (playerStatus->curStateTime - playerSpinState->fullSpeedSpinTime - 1) * playerSpinState->frictionScale;
208 if (speedModifier < 0.1) {
209 speedModifier = 0.1f;
210 }
211
212 if (playerSpinState->inputMagnitude == 0.0f) {
213 speedModifier = 0.0f;
214 }
215
216 playerSpinState->spinDirectionMagnitude -= 1.0f;
217 if (playerSpinState->spinDirectionMagnitude < 0.0f) {
218 playerSpinState->spinDirectionMagnitude = 0.0f;
219 }
220 }
221
222 playerStatus->curStateTime++;
223
224 switch (playerStatus->prevActionState) {
226 player_input_to_move_vector(&angle, &magnitude);
228 if (check_input_jump()) {
229 if (magnitude != 0.0f || playerStatus->targetYaw != angle) {
230 playerStatus->targetYaw = angle;
231 }
232 }
233 playerStatus->curSpeed = (magnitude != 0.0f) ? playerStatus->runSpeed * speedModifier : 0.0f;
234 break;
236 case ACTION_STATE_RUN:
237 playerStatus->curSpeed = playerStatus->runSpeed * speedModifier;
238 break;
239 }
240 if (playerStatus->actionSubstate == SUBSTATE_SPIN_0) {
241 playerSpinState->spinCountdown--;
242 if (playerSpinState->spinCountdown > 0) {
243 if (playerStatus->curStateTime >= 2) {
244 playerStatus->spriteFacingAngle = clamp_angle(playerStatus->spriteFacingAngle + playerStatus->spinRate);
245 }
246 return;
247 } else {
248 playerStatus->actionSubstate = SUBSTATE_SPIN_1;
249 }
250 }
251
252 if (playerStatus->actionSubstate == SUBSTATE_SPIN_1) {
253 angle = playerStatus->spriteFacingAngle;
254 playerStatus->spriteFacingAngle = angle + playerStatus->spinRate;
255
256 if (playerSpinState->hasBufferedSpin) {
257 playerStatus->curStateTime = 2;
258 playerStatus->actionSubstate = SUBSTATE_SPIN_2;
259 playerStatus->flags &= ~PS_FLAG_SPINNING;
260 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
261 } else if (angle < playerStatus->spriteFacingAngle) {
262 if (playerStatus->spriteFacingAngle >= 180.0f && angle < 180.0f) {
263 playerStatus->spriteFacingAngle = 180.0f;
264 playerStatus->curStateTime = 2;
265 playerStatus->actionSubstate = SUBSTATE_SPIN_2;
266 playerStatus->flags &= ~PS_FLAG_SPINNING;
267 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
268 }
269 } else if (playerStatus->spriteFacingAngle <= 0.0f && angle < 90.0f) {
270 playerStatus->spriteFacingAngle = 0.0f;
271 playerStatus->curStateTime = 2;
272 playerStatus->actionSubstate = SUBSTATE_SPIN_2;
273 playerStatus->flags &= ~PS_FLAG_SPINNING;
274 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
275 }
276 playerStatus->spriteFacingAngle = clamp_angle(playerStatus->spriteFacingAngle);
277 }
278}
struct EffectInstance * specialDecorationEffect
u32 AnimID
#define clamp_angle
@ BUTTON_Z
Definition enums.h:2788
@ PS_FLAG_ACTION_STATE_CHANGED
Definition enums.h:3084
@ PS_FLAG_ARMS_RAISED
Definition enums.h:3063
@ PS_FLAG_SPINNING
Definition enums.h:3058
@ PA_FLAG_INTERRUPT_SPIN
Definition enums.h:3110
@ PA_FLAG_SPINNING
Definition enums.h:3107
@ ABILITY_SPIN_ATTACK
Definition enums.h:476
@ ABILITY_DIZZY_ATTACK
Definition enums.h:481
@ ABILITY_SPEEDY_SPIN
Definition enums.h:475
@ SOUND_SPEEDY_SPIN_ATTACK
Definition enums.h:1553
@ SOUND_SPEEDY_SPIN
Definition enums.h:1551
@ SOUND_SPIN_ATTACK
Definition enums.h:1552
@ SOUND_SPIN
Definition enums.h:1550
@ ACTION_STATE_IDLE
Definition enums.h:2426
@ ACTION_STATE_WALK
Definition enums.h:2427
@ ACTION_STATE_RUN
Definition enums.h:2428
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
s32 is_ability_active(s32 arg0)
Definition inventory.c:1725
void player_input_to_move_vector(f32 *angle, f32 *magnitude)
Definition 7B440.c:140
void suggest_player_anim_always_forward(AnimID anim)
Definition 77480.c:913
f32 cos_rad(f32 x)
Definition 43F0.c:717
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
void phys_update_interact_collider(void)
Definition 7BB60.c:1127
void suggest_player_anim_allow_backward(AnimID anim)
Definition 77480.c:894
b32 check_input_hammer(void)
Definition 7E9D0.c:321
f32 sin_rad(f32 x)
Definition 43F0.c:713
b32 check_input_jump(void)
Definition 7E9D0.c:344
void sfx_stop_sound(s32 soundID)
Definition sfx.c:507
void sfx_play_sound_at_player(s32 soundID, s32 arg1)
Definition sfx.c:521
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define DEG_TO_RAD(deg)
Definition macros.h:134
#define NO_COLLIDER
Definition macros.h:156
s32 gSpinHistoryPosY[5]
Definition 7E9D0.c:27
SpinTypeFlag
Definition spin.c:20
@ SPIN_TYPE_SPEEDY
Definition spin.c:22
@ SPIN_TYPE_DEFAULT
Definition spin.c:21
@ SPIN_TYPE_ATTACK
Definition spin.c:24
@ SPIN_TYPE_DIZZY
Definition spin.c:23
s32 gSpinHistoryPosX[5]
Definition 7E9D0.c:26
s32 gSpinHistoryBufferPos
Definition 7E9D0.c:24
s16 gSpinHistoryPosAngle[5]
Definition 7E9D0.c:29
@ SUBSTATE_SPIN_0
Definition spin.c:14
@ SUBSTATE_SPIN_3
Definition spin.c:17
@ SUBSTATE_SPIN_1
Definition spin.c:15
@ SUBSTATE_SPIN_2
Definition spin.c:16
void action_update_spin(void)
Definition spin.c:27
s32 gSpinHistoryPosZ[5]
Definition 7E9D0.c:28
void phys_clear_spin_history(void)
Definition 7E9D0.c:71
CollisionStatus gCollisionStatus
Definition 7BB60.c:6
PlayerSpinState gPlayerSpinState
Definition 7B440.c:11
Camera gCameras[4]
Definition cam_main.c:17
PlayerStatus gPlayerStatus
Definition 77480.c:39
s32 gCurrentCameraID
Definition cam_math.c:4