Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
hammer.c
Go to the documentation of this file.
1#include "common.h"
2#include "effects.h"
3#include "sprite.h"
4#include "sprite/player.h"
5
6enum {
10};
11
12typedef struct HammerHitData {
13 /* 0x00 */ Vec3f hitPos;
14 /* 0x0C */ s32 unk_0C;
15 /* 0x10 */ s32 hitID;
16 /* 0x14 */ s32 unk_14;
17 /* 0x18 */ s32 timer;
18 /* 0x1C */ s32 unk_1C;
20
22
24
26
28 if (animID & SPRITE_ID_BACK_FACING) {
29 return TRUE;
30 }
31
32 // back facing swing anims
33 switch (animID) {
34 case ANIM_MarioW1_Smash1_Miss_Back:
35 case ANIM_MarioW1_Smash1_Hit_Back:
36 case ANIM_MarioW1_Smash2_Miss_Back:
37 case ANIM_MarioW1_Smash2_Hit_Back:
38 case ANIM_MarioW1_Smash3_Miss_Back:
39 case ANIM_MarioW1_Smash3_Hit_Back:
40 return TRUE;
41 }
42 return FALSE;
43}
44
46 PlayerStatus* playerStatus = &gPlayerStatus;
47 f32 shakeAmt;
48 s32 time;
49 s32 radius;
50 s32 soundID;
51 f32 theta, sinTheta, cosTheta;
52 s32 numParticles;
53 f32 x, y, z;
54
55 if (gPlayerData.hammerLevel == 2) {
56 shakeAmt = 1.2f;
57 time = 1;
58 radius = 28;
59 soundID = SOUND_HAMMER_STRIKE_3;
60 } else if (gPlayerData.hammerLevel == 1) {
61 shakeAmt = 0.8f;
62 time = 1;
63 radius = 16;
64 soundID = SOUND_HAMMER_STRIKE_2;
65 } else {
66 shakeAmt = 0.4f;
67 time = 1;
68 radius = 4;
69 soundID = SOUND_HAMMER_STRIKE_1;
70 }
71
73 sinTheta = sin_rad(theta) * 25.0f;
74 cosTheta = cos_rad(theta) * -25.0f;
75
76 if (hitID <= NO_COLLIDER) {
77 numParticles = 6;
78 x = playerStatus->pos.x + sinTheta;
79 y = playerStatus->pos.y;
80 z = playerStatus->pos.z + cosTheta;
81 } else {
82 numParticles = 3;
83 x = HammerHit->hitPos.x + sinTheta;
84 y = HammerHit->hitPos.y + playerStatus->colliderHeight - 5.0f;
85 z = HammerHit->hitPos.z + cosTheta;
86 radius = 1;
87 }
88
90 fx_smoke_impact(0, x, y, z, radius, numParticles, 0, (time + 3) * 3);
91
93 case 1:
95 break;
96 case 2:
97 soundID = SOUND_PLANTS_BELL;
98 break;
99 case 3:
100 soundID = SOUND_SLIDE_WHISTLE_OUT;
101 break;
102 case 4:
103 soundID = SOUND_YOSHI;
104 break;
105 case 5:
106 soundID = SOUND_HIT_WHACKA;
107 break;
108 case 6:
109 soundID = SOUND_FLOWERS_LAUGH;
110 break;
111 }
112
114 start_rumble(256, 50);
115}
116
118 PlayerStatus* playerStatus = &gPlayerStatus;
119 HitID ret;
120 f32 yaw;
121 f32 angle;
122 f32 outSinTheta;
123 f32 outCosTheta;
124 f32 playerX, playerY, playerZ;
125 f32 x, y, z;
126 s32 i;
127
128 // first attempt
129 yaw = player_get_side_angle();
131 angle = clamp_angle(yaw + 90.0f - gCameras[gCurrentCameraID].curYaw);
132 if (angle >= 90.0f && angle < 270.0f) {
133 yaw += -30.0f;
134 } else {
135 yaw += 30.0f;
136 }
137 }
138
139 sin_cos_rad(DEG_TO_RAD(yaw), &outSinTheta, &outCosTheta);
140 playerX = playerStatus->pos.x;
141 playerY = playerStatus->pos.y;
142 playerZ = playerStatus->pos.z;
143
144 // check collision along 16 points in a line away from the player
145 for (i = 1; i < 16; i++) {
146 x = playerX + (outSinTheta * i);
147 y = playerY;
148 z = playerZ - (outCosTheta * i);
149 ret = player_test_lateral_overlap(PLAYER_COLLISION_HAMMER, playerStatus, &x, &y, &z, 4.0f, yaw);
150 if (ret > NO_COLLIDER) {
151 HammerHit->hitPos.x = x;
152 HammerHit->hitPos.y = y;
153 HammerHit->hitPos.z = z;
154 break;
155 }
156 }
157
158 // second attempt
159 if (i >= 16) {
160 yaw = player_get_side_angle();
161 if (!action_hammer_is_swinging_away(playerStatus->trueAnimation)) {
162 angle = clamp_angle(yaw + 90.0f - gCameras[gCurrentCameraID].curYaw);
163 if (angle >= 90.0f && angle < 270.0f) {
164 yaw += 15.0f;
165 } else {
166 yaw += -15.0f;
167 }
168 }
169
170 // check collision along 16 points in a line away from the player
171 sin_cos_rad(DEG_TO_RAD(yaw), &outSinTheta, &outCosTheta);
172 for (i = 1; i < 16; i++) {
173 x = playerX + (outSinTheta * i);
174 y = playerY;
175 z = playerZ - (outCosTheta * i);
176
177 ret = player_test_lateral_overlap(PLAYER_COLLISION_HAMMER, playerStatus, &x, &y, &z, 4.0f, yaw);
178 if (ret > NO_COLLIDER) {
179 HammerHit->hitPos.x = x;
180 HammerHit->hitPos.y = y;
181 HammerHit->hitPos.z = z;
182 break;
183 }
184 }
185 }
186
187 if (ret > NO_COLLIDER && (ret & COLLISION_WITH_ENTITY_BIT)) {
188 s32 hammerLevel = gPlayerData.hammerLevel;
189
190 switch (get_entity_type(ret)) {
193 if (hammerLevel >= 0) {
194 ret = -1;
195 } else {
196 playerStatus->animFlags |= PA_FLAG_SHIVERING;
197 }
198 break;
201 if (hammerLevel >= 1) {
202 ret = -1;
203 } else {
204 playerStatus->animFlags |= PA_FLAG_SHIVERING;
205 }
206 break;
209 if (hammerLevel >= 2) {
210 ret = -1;
211 } else {
212 playerStatus->animFlags |= PA_FLAG_SHIVERING;
213 }
214 break;
217 playerStatus->animFlags |= PA_FLAG_SHIVERING;
218 break;
222 ret = -1;
223 break;
224 }
225 }
226
227 return ret;
228}
229
231 PlayerStatus* playerStatus = &gPlayerStatus;
232
233 HammerHit->unk_1C = 0;
234
235 if (playerStatus->flags & PS_FLAG_ACTION_STATE_CHANGED) {
236 AnimID anim;
237 s32 soundID;
238
239 playerStatus->flags &= ~PS_FLAG_ACTION_STATE_CHANGED;
240 playerStatus->flags |= PS_FLAG_NO_FLIPPING;
241 HammerHit->timer = 0;
242 playerStatus->actionSubstate = SUBSTATE_HAMMER_0;
243 playerStatus->curSpeed = 0.0f;
244 playerStatus->animNotifyValue = 0;
246
247 if (gPlayerData.hammerLevel == 2) {
248 soundID = SOUND_HAMMER_SWING_3;
249 anim = ANIM_MarioW1_Smash3_Hit;
250 if (HammerHit->hitID <= NO_COLLIDER) {
251 soundID = SOUND_HAMMER_SWING_3;
252 anim = ANIM_MarioW1_Smash3_Miss;
253 }
254 } else if (gPlayerData.hammerLevel == 1) {
255 soundID = SOUND_HAMMER_SWING_2;
256 anim = ANIM_MarioW1_Smash2_Hit;
257 if (HammerHit->hitID <= NO_COLLIDER) {
258 soundID = SOUND_HAMMER_SWING_2;
259 anim = ANIM_MarioW1_Smash2_Miss;
260 }
261 } else {
262 soundID = SOUND_HAMMER_SWING_1;
263 anim = ANIM_MarioW1_Smash1_Hit;
264 if (HammerHit->hitID <= NO_COLLIDER) {
265 soundID = SOUND_HAMMER_SWING_1;
266 anim = ANIM_MarioW1_Smash1_Miss;
267 }
268 }
269
272 HammerHit->unk_0C = 0;
273 HammerHit->unk_14 = 0;
274 }
275
276 playerStatus->flags &= ~PS_FLAG_HAMMER_CHECK;
277 if (HammerHit->timer < 3 && (playerStatus->flags & PS_FLAG_ENTERING_BATTLE)) {
278 // This is probably to stop Mario from triggering multiple battles at once by hammering while one is starting.
279 playerStatus->flags |= PS_FLAG_TIME_STOPPED;
280 } else if (HammerHit->timer < 2) {
281 HammerHit->timer++;
282 } else {
284 }
285}
286
288 PlayerStatus* playerStatus = &gPlayerStatus;
289 CollisionStatus* collisionStatus = &gCollisionStatus;
290 f32 yaw;
291 f32 angle;
292 f32 outSinTheta;
293 f32 outCosTheta;
294 f32 playerX, playerY, playerZ;
295 f32 x, y, z;
296 s32 result;
297 s32 hammerLevel;
298 s32 soundID;
299 u32 unk_BC;
300 s32 ten;
301 s32 ret;
302 s32 i;
303
304 yaw = player_get_side_angle();
306 angle = clamp_angle(yaw + 90.0f - gCameras[gCurrentCameraID].curYaw);
307 if (angle >= 90.0f && angle < 270.0f) {
308 yaw += -30.0f;
309 } else {
310 yaw += 30.0f;
311 }
312 }
313
314 sin_cos_rad(DEG_TO_RAD(yaw), &outSinTheta, &outCosTheta);
315 playerX = playerStatus->pos.x;
316 playerY = playerStatus->pos.y;
317 playerZ = playerStatus->pos.z;
318
319 // check collision along 16 points in a line away from the player
320 for (i = 1; i < 16; i++) {
321 x = playerX + (outSinTheta * i);
322 y = playerY;
323 z = playerZ - (outCosTheta * i);
324 result = player_test_lateral_overlap(PLAYER_COLLISION_HAMMER, playerStatus, &x, &y, &z, 4.0f, yaw);
325 if (HammerHit->unk_14 == 0) {
326 collisionStatus->lastWallHammered = result;
327 if (result > NO_COLLIDER) {
328 if (result & COLLISION_WITH_ENTITY_BIT) {
330 }
331 }
332 }
333
334 if (result > NO_COLLIDER) {
335 break;
336 }
337 }
338
339 if (i >= 16) {
340 yaw = player_get_side_angle();
341 if (action_hammer_is_swinging_away(playerStatus->trueAnimation) == 0) {
342 angle = clamp_angle(yaw + 90.0f - gCameras[gCurrentCameraID].curYaw);
343 if (angle >= 90.0f && angle < 270.0f) {
344 yaw += 15.0f;
345 } else {
346 yaw += -15.0f;
347 }
348 }
349 sin_cos_rad(DEG_TO_RAD(yaw), &outSinTheta, &outCosTheta);
350
351 // check collision along 16 points in a line away from the player
352 for (i = 1; i < 16; i++) {
353 x = playerX + (outSinTheta * i);
354 y = playerY;
355 z = playerZ - (outCosTheta * i);
356 result = player_test_lateral_overlap(PLAYER_COLLISION_HAMMER, playerStatus, &x, &y, &z, 4.0f, yaw);
357 if (HammerHit->unk_14 == 0) {
358 collisionStatus->lastWallHammered = result;
359 if (result > NO_COLLIDER) {
360 if (result & COLLISION_WITH_ENTITY_BIT) {
362 }
363 }
364 }
365
366 if (result > NO_COLLIDER) {
367 break;
368 }
369 }
370 }
371
372 if (HammerHit->timer == 2) {
373 hammerLevel = gPlayerData.hammerLevel;
374 if (hammerLevel == 2) {
375 soundID = SOUND_HAMMER_SWING_3;
376 } else if (hammerLevel == 1) {
377 soundID = SOUND_HAMMER_SWING_2;
378 } else {
379 soundID = SOUND_HAMMER_SWING_1;
380 }
382
384
385 if (collisionStatus->lastWallHammered > NO_COLLIDER && (collisionStatus->lastWallHammered & COLLISION_WITH_ENTITY_BIT)) {
387 playerStatus->flags |= PS_FLAG_HAMMER_CHECK;
388 } else if (HammerHit->hitID <= NO_COLLIDER) {
389 playerStatus->flags |= PS_FLAG_HAMMER_CHECK;
390 }
391
395 }
396 }
397
398 if (playerStatus->actionSubstate == SUBSTATE_HAMMER_0 && result > NO_COLLIDER && HammerHit->unk_14 == 0) {
399 playerStatus->actionSubstate++;
400 }
401 if (playerStatus->actionSubstate == SUBSTATE_HAMMER_1 && result <= NO_COLLIDER) {
402 playerStatus->actionSubstate = SUBSTATE_HAMMER_2;
403 }
404 HammerHit->timer++;
405 if (result > NO_COLLIDER) {
406 HammerHit->unk_14 = 1;
407 }
408 if (HammerHit->timer == 6) {
409 playerStatus->flags &= ~PS_FLAG_NO_FLIPPING;
410 }
411
412 if (playerStatus->animNotifyValue == 1) {
413 if (HammerHit->timer >= 7 && (playerStatus->pressedButtons & BUTTON_B)) {
414 HammerHit->unk_1C = 1;
415 }
416
417 HammerHit->unk_14 = 0;
418 ten = 10; // required to match
419 if (HammerHit->unk_1C != 0 || HammerHit->timer > ten) {
420 playerStatus->flags &= ~PS_FLAG_HAMMER_CHECK;
422 }
423 playerStatus->flags &= ~PS_FLAG_NO_FLIPPING;
424 }
425}
AnimID trueAnimation
Encoding back-facing sprite.
s32 HitID
u32 AnimID
#define clamp_angle
@ BUTTON_B
Definition enums.h:2789
@ CAM_SHAKE_DECAYING_VERTICAL
Definition enums.h:1809
@ PS_FLAG_TIME_STOPPED
Definition enums.h:3081
@ PS_FLAG_ENTERING_BATTLE
Definition enums.h:3061
@ PS_FLAG_ACTION_STATE_CHANGED
Definition enums.h:3084
@ PS_FLAG_HAMMER_CHECK
Definition enums.h:3073
@ PS_FLAG_NO_FLIPPING
Definition enums.h:3067
@ ENTITY_TYPE_HAMMER1_BLOCK
Definition enums.h:2564
@ ENTITY_TYPE_BOMBABLE_ROCK
Definition enums.h:2581
@ ENTITY_TYPE_HAMMER3_BLOCK
Definition enums.h:2566
@ ENTITY_TYPE_BLUE_SWITCH
Definition enums.h:2550
@ ENTITY_TYPE_HAMMER2_BLOCK
Definition enums.h:2565
@ ENTITY_TYPE_HAMMER3_BLOCK_TINY
Definition enums.h:2569
@ ENTITY_TYPE_RED_SWITCH
Definition enums.h:2551
@ ENTITY_TYPE_BRICK_BLOCK
Definition enums.h:2556
@ ENTITY_TYPE_HAMMER2_BLOCK_TINY
Definition enums.h:2568
@ ENTITY_TYPE_HAMMER1_BLOCK_TINY
Definition enums.h:2567
@ ENTITY_TYPE_WOODEN_CRATE
Definition enums.h:2579
@ PLAYER_COLLISION_HAMMER
Definition enums.h:4715
@ PA_FLAG_SHIVERING
Definition enums.h:3101
@ ABILITY_ATTACK_FX
Definition enums.h:451
@ SOUND_HAMMER_STRIKE_3
Definition enums.h:1559
@ SOUND_FLOWERS_LAUGH
Definition enums.h:1389
@ SOUND_HAMMER_SWING_3
Definition enums.h:1556
@ SOUND_HAMMER_STRIKE_1
Definition enums.h:1557
@ SOUND_SLIDE_WHISTLE_OUT
Definition enums.h:715
@ SOUND_HAMMER_SWING_1
Definition enums.h:1554
@ SOUND_HIT_WHACKA
Definition enums.h:1412
@ SOUND_HAMMER_SWING_2
Definition enums.h:1555
@ SOUND_PLANTS_BELL
Definition enums.h:727
@ SOUND_HAMMER_STRIKE_2
Definition enums.h:1558
@ SOUND_LIFE_SHROOM_CHIME
Definition enums.h:1186
@ SOUND_YOSHI
Definition enums.h:1411
@ ACTION_STATE_IDLE
Definition enums.h:2426
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
@ CAM_DEFAULT
Definition enums.h:1800
void start_rumble(s32, s32)
Definition rumble.c:15
Entity * get_entity_by_index(s32 index)
Definition entity.c:530
s32 is_ability_active(s32 arg0)
Definition inventory.c:1725
f32 cos_rad(f32 x)
Definition 43F0.c:717
f32 player_get_side_angle(void)
Definition 7BB60.c:1178
s32 player_test_lateral_overlap(s32, PlayerStatus *, f32 *, f32 *, f32 *, f32, f32)
Definition 77480.c:370
u32 get_entity_type(s32 arg0)
Definition entity.c:568
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
void suggest_player_anim_allow_backward(AnimID anim)
Definition 77480.c:894
void exec_ShakeCamX(s32 arg0, s32 arg1, s32 arg2, f32 arg3)
Definition cam_api.c:374
f32 sin_rad(f32 x)
Definition 43F0.c:713
void sin_cos_rad(f32 rad, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:706
void sfx_play_sound_at_player(s32 soundID, s32 arg1)
Definition sfx.c:521
#define COLLISION_WITH_ENTITY_BIT
Definition macros.h:152
#define BSS
Definition macros.h:7
#define DEG_TO_RAD(deg)
Definition macros.h:134
#define NO_COLLIDER
Definition macros.h:156
@ SPRITE_ID_BACK_FACING
Definition sprite.h:13
s8 collisionTimer
CollisionStatus gCollisionStatus
Definition 7BB60.c:6
Camera gCameras[4]
Definition cam_main.c:17
PlayerData gPlayerData
Definition 77480.c:40
PlayerStatus gPlayerStatus
Definition 77480.c:39
s32 gCurrentCameraID
Definition cam_math.c:4
HiddenPanelsData gCurrentHiddenPanels
Definition entity.c:36
Vec3f hitPos
Definition hammer.c:13
s32 action_hammer_is_swinging_away(s32 animID)
Definition hammer.c:27
void action_hammer_play_hit_fx(s32 hitID)
Definition hammer.c:45
HammerHitData * HammerHit
Definition hammer.c:23
@ SUBSTATE_HAMMER_2
Definition hammer.c:9
@ SUBSTATE_HAMMER_1
Definition hammer.c:8
@ SUBSTATE_HAMMER_0
Definition hammer.c:7
void action_hammer_end_swing(void)
Definition hammer.c:287
void action_update_hammer(void)
Definition hammer.c:230
BSS HammerHitData D_802B6E90
Definition hammer.c:21
HitID action_hammer_test_swing_collision(void)
Definition hammer.c:117