Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
bow.c
Go to the documentation of this file.
1#include "common.h"
2#include "../partners.h"
3#include "npc.h"
4#include "sprite/npc/WorldBow.h"
5#include "sprite/player.h"
6
7#define NAMESPACE world_bow
8
9BSS b32 N(IsHiding);
10BSS b32 N(LockingPlayerInput);
11BSS TweesterPhysics N(TweesterPhysicsData);
12BSS s32 N(OuttaSightPosX);
13BSS s32 N(OuttaSightPosY);
14BSS s32 N(OuttaSightPosZ);
15
16void N(end_outta_sight_cleanup)(Npc* partner);
18
19void N(init)(Npc* bow) {
20 bow->collisionHeight = 26;
21 bow->collisionDiameter = 24;
22 bow->renderMode = RENDER_MODE_SURFACE_XLU_LAYER1;
23 N(LockingPlayerInput) = FALSE;
24 N(IsHiding) = FALSE;
25}
26
27API_CALLABLE(N(TakeOut)) {
28 Npc* bow = script->owner2.npc;
29
30 if (isInitialCall) {
32 }
33
34 if (partner_get_out(bow)) {
35 return ApiStatus_DONE1;
36 } else {
37 return ApiStatus_BLOCK;
38 }
39}
40
42 Call(N(TakeOut))
43 Return
44 End
45};
46
47TweesterPhysics* N(TweesterPhysicsPtr) = &N(TweesterPhysicsData);
48
49API_CALLABLE(N(Update)) {
50 PlayerData* playerData = &gPlayerData;
51 Npc* bow = script->owner2.npc;
52 f32 sinAngle, cosAngle, liftoffVelocity;
53 Entity* entity;
54
55 if (isInitialCall) {
57 mem_clear(N(TweesterPhysicsPtr), sizeof(TweesterPhysics));
59 }
60
62 playerData->partnerUsedTime[PARTNER_BOW]++;
63
64 if (entity == NULL) {
67 return ApiStatus_BLOCK;
68 }
69
70 switch (N(TweesterPhysicsPtr)->state){
72 N(TweesterPhysicsPtr)->state++;
73 N(TweesterPhysicsPtr)->prevFlags = bow->flags;
74 N(TweesterPhysicsPtr)->radius = fabsf(dist2D(bow->pos.x, bow->pos.z, entity->pos.x, entity->pos.z));
75 N(TweesterPhysicsPtr)->angle = atan2(entity->pos.x, entity->pos.z, bow->pos.x, bow->pos.z);
76 N(TweesterPhysicsPtr)->angularVel = 6.0f;
77 N(TweesterPhysicsPtr)->liftoffVelPhase = 50.0f;
78 N(TweesterPhysicsPtr)->countdown = 120;
80 bow->flags &= ~NPC_FLAG_GRAVITY;
82 sin_cos_rad(DEG_TO_RAD(N(TweesterPhysicsPtr)->angle), &sinAngle, &cosAngle);
83 bow->pos.x = entity->pos.x + (sinAngle * N(TweesterPhysicsPtr)->radius);
84 bow->pos.z = entity->pos.z - (cosAngle * N(TweesterPhysicsPtr)->radius);
85 N(TweesterPhysicsPtr)->angle = clamp_angle(N(TweesterPhysicsPtr)->angle - N(TweesterPhysicsPtr)->angularVel);
86 if (N(TweesterPhysicsPtr)->radius > 20.0f) {
87 N(TweesterPhysicsPtr)->radius -= 1.0f;
88 } else if (N(TweesterPhysicsPtr)->radius < 19.0f) {
89 N(TweesterPhysicsPtr)->radius++;
90 }
91
92 liftoffVelocity = sin_rad(DEG_TO_RAD(N(TweesterPhysicsPtr)->liftoffVelPhase)) * 3.0f;
93 N(TweesterPhysicsPtr)->liftoffVelPhase += 3.0f;
94
95 if (N(TweesterPhysicsPtr)->liftoffVelPhase > 150.0f) {
96 N(TweesterPhysicsPtr)->liftoffVelPhase = 150.0f;
97 }
98
99 bow->pos.y += liftoffVelocity;
100 bow->renderYaw = clamp_angle(360.0f - N(TweesterPhysicsPtr)->angle);
101 N(TweesterPhysicsPtr)->angularVel += 0.8;
102
103 if (N(TweesterPhysicsPtr)->angularVel > 40.0f) {
104 N(TweesterPhysicsPtr)->angularVel = 40.0f;
105 }
106 if (--N(TweesterPhysicsPtr)->countdown == 0) {
107 N(TweesterPhysicsPtr)->state++;
108 }
109 break;
111 bow->flags = N(TweesterPhysicsPtr)->prevFlags;
112 N(TweesterPhysicsPtr)->countdown = 30;
113 N(TweesterPhysicsPtr)->state++;
114 break;
118
119 if (--N(TweesterPhysicsPtr)->countdown == 0) {
120 N(TweesterPhysicsPtr)->state = TWEESTER_PARTNER_INIT;
122 }
123 break;
124 }
125 return ApiStatus_BLOCK;
126}
127
129 Call(N(Update))
130 Return
131 End
132};
133
135 if (TweesterTouchingPartner != NULL) {
137 bow->flags = N(TweesterPhysicsPtr)->prevFlags;
138 N(TweesterPhysicsPtr)->state = TWEESTER_PARTNER_INIT;
140 }
141}
142
143// check whether the player would collide with an obstacle while on a treadmill in AREA_OMO
145 PlayerStatus* playerStatus = &gPlayerStatus;
146 f32 x, y, z;
147 f32 yaw;
148
149 //TODO hardcoded map IDs
151 return NO_COLLIDER;
152 }
153
154 if (playerStatus->pushVel.x == 0.0f && playerStatus->pushVel.z == 0.0f) {
155 return NO_COLLIDER;
156 }
157
158 yaw = atan2(0.0f, 0.0f, playerStatus->pushVel.x, playerStatus->pushVel.z);
159 x = playerStatus->pos.x;
160 y = playerStatus->pos.y + (playerStatus->colliderHeight * 0.5f);
161 z = playerStatus->pos.z;
162
163 add_vec2D_polar(&x, &z, playerStatus->colliderDiameter * 0.5f, clamp_angle(yaw + 180.0f));
164 return player_test_lateral_overlap(PLAYER_COLLISION_0, playerStatus, &x, &y, &z, playerStatus->colliderDiameter, yaw);
165}
166
167API_CALLABLE(N(UseAbility)) {
168 PlayerStatus* playerStatus = &gPlayerStatus;
169 PartnerStatus* partnerStatus = &gPartnerStatus;
170 CollisionStatus* collisionStatus = &gCollisionStatus;
171 Npc* bow = script->owner2.npc;
172 f32 stickInputMag;
173
174 #define USE_STATE functionTemp[0]
175 enum {
176 // first two states lock input for a few frames, during which the ability can be canceled
177 OUTTA_SIGHT_INIT = 40,
178 OUTTA_SIGHT_DELAY = 41,
179 OUTTA_SIGHT_BEGIN = 20,
180 OUTTA_SIGHT_GATHER = 21, // move to player
181 OUTTA_SIGHT_VANISH = 1, // hide
182 OUTTA_SIGHT_IDLE = 2, // remain hidden
183 OUTTA_SIGHT_REAPPEAR = 3,
184 };
185
186 if (isInitialCall) {
187 N(try_cancel_tweester)(bow);
188 if (playerStatus->animFlags & PA_FLAG_CHANGING_MAP || !func_800EA52C(PARTNER_BOW)) {
189 return ApiStatus_DONE2;
190 }
191 if (playerStatus->animFlags & PA_FLAG_PARTNER_USAGE_FORCED) {
192 playerStatus->animFlags &= ~PA_FLAG_PARTNER_USAGE_FORCED;
193 script->functionTemp[2] = disable_player_input();
194 N(LockingPlayerInput) = TRUE;
195 script->USE_STATE = OUTTA_SIGHT_BEGIN;
196 } else {
197 script->USE_STATE = OUTTA_SIGHT_INIT;
198 }
199 }
200
201 switch (script->USE_STATE) {
202 case OUTTA_SIGHT_INIT:
203 if (playerStatus->inputDisabledCount != 0) {
204 return ApiStatus_DONE2;
205 }
206
207 playerStatus->flags |= PS_FLAG_PAUSE_DISABLED;
208 script->functionTemp[1] = 3;
209 script->functionTemp[2] = disable_player_input();
210 N(LockingPlayerInput) = TRUE;
211 script->USE_STATE++; // OUTTA_SIGHT_DELAY
212 break;
213 case OUTTA_SIGHT_DELAY:
215 && script->functionTemp[2] < playerStatus->inputDisabledCount
216 && N(LockingPlayerInput)
217 ) {
219 N(LockingPlayerInput) = FALSE;
220 playerStatus->flags &= ~PS_FLAG_PAUSE_DISABLED;
221 return ApiStatus_DONE2;
222 }
223 script->functionTemp[1]--;
224 if (script->functionTemp[1] == 0) {
225 if (script->functionTemp[2] < playerStatus->inputDisabledCount) {
226 if (N(LockingPlayerInput)) {
228 N(LockingPlayerInput) = FALSE;
229 }
230 playerStatus->flags &= ~PS_FLAG_PAUSE_DISABLED;
231 return ApiStatus_DONE2;
232 }
233 script->USE_STATE = OUTTA_SIGHT_BEGIN;
234 }
235 break;
236 }
237
238 switch (script->USE_STATE) {
239 case OUTTA_SIGHT_BEGIN:
240 if (playerStatus->flags & PS_FLAG_HIT_FIRE) {
241 playerStatus->flags &= ~PS_FLAG_PAUSE_DISABLED;
242 if (N(LockingPlayerInput)) {
244 N(LockingPlayerInput) = FALSE;
245 }
246 return ApiStatus_DONE2;
247 }
248 if (script->functionTemp[2] != 0) {
249 N(LockingPlayerInput) = TRUE;
250 }
251
252 N(IsHiding) = TRUE;
254 partnerStatus->partnerActionState = 1;
255 partnerStatus->actingPartner = 9;
256 playerStatus->flags |= PS_FLAG_HAZARD_INVINCIBILITY;
258 bow->moveToPos.x = playerStatus->pos.x;
259 bow->moveToPos.y = playerStatus->pos.y + (playerStatus->colliderHeight * 0.5f);
260 bow->moveToPos.z = playerStatus->pos.z;
261 bow->curAnim = ANIM_WorldBow_Walk;
262 bow->yaw = playerStatus->targetYaw;
264 add_vec2D_polar(&bow->moveToPos.x, &bow->moveToPos.z, playerStatus->colliderDiameter * 0.5f, bow->yaw);
265 bow->duration = 5;
266 bow->yaw = atan2(bow->pos.x, bow->pos.z, playerStatus->pos.x, playerStatus->pos.z);
268 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
269 script->USE_STATE++; // OUTTA_SIGHT_GATHER
270 break;
271
272 case OUTTA_SIGHT_GATHER:
273 if (collisionStatus->curFloor >= 0 && !(playerStatus->animFlags & PA_FLAG_CHANGING_MAP)) {
274 bow->moveToPos.x = playerStatus->pos.x;
275 bow->moveToPos.y = playerStatus->pos.y + (playerStatus->colliderHeight * 0.5f);
276 bow->moveToPos.z = playerStatus->pos.z;
277 bow->pos.x += ((bow->moveToPos.x - bow->pos.x) / bow->duration);
278 bow->pos.y += ((bow->moveToPos.y - bow->pos.y) / bow->duration);
279 bow->pos.z += ((bow->moveToPos.z - bow->pos.z) / bow->duration);
280 N(OuttaSightPosX) = playerStatus->pos.x - bow->pos.x;
281 N(OuttaSightPosY) = playerStatus->pos.y - bow->pos.y;
282 N(OuttaSightPosZ) = playerStatus->pos.z - bow->pos.z;
283 bow->duration--;
284 if (bow->duration == 0) {
285 bow->yaw = playerStatus->targetYaw;
286 npc_set_imgfx_params(bow, IMGFX_SET_ALPHA, playerStatus->curAlpha, 0, 0, 0, 0);
287 suggest_player_anim_always_forward(ANIM_Mario1_Crouch);
289 script->USE_STATE = OUTTA_SIGHT_VANISH;
290 }
291 break;
292 }
294 return ApiStatus_DONE2;
295
296 case OUTTA_SIGHT_VANISH:
297 if (collisionStatus->curFloor >= 0) {
298 playerStatus->curAlpha -= 8;
299 if (playerStatus->curAlpha <= 128) {
300 playerStatus->curAlpha = 128;
302 script->USE_STATE++; // OUTTA_SIGHT_IDLE
303 playerStatus->flags &= ~PS_FLAG_PAUSE_DISABLED;
305 }
306
307 get_shadow_by_index(bow->shadowIndex)->alpha = playerStatus->curAlpha >> 1;
308 npc_set_imgfx_params(bow, IMGFX_SET_ALPHA, playerStatus->curAlpha, 0, 0, 0, 0);
309 bow->pos.x = playerStatus->pos.x - N(OuttaSightPosX);
310 bow->pos.y = playerStatus->pos.y - N(OuttaSightPosY);
311 bow->pos.z = playerStatus->pos.z - N(OuttaSightPosZ);
312 break;
313 }
315 return ApiStatus_DONE2;
316
317 case OUTTA_SIGHT_IDLE:
318 if (collisionStatus->curFloor <= NO_COLLIDER) {
320 return ApiStatus_DONE2;
321 }
322
323 bow->pos.x = playerStatus->pos.x - N(OuttaSightPosX);
324 bow->pos.y = playerStatus->pos.y - N(OuttaSightPosY);
325 bow->pos.z = playerStatus->pos.z - N(OuttaSightPosZ);
326
327 stickInputMag = dist2D(0.0f, 0.0f, partnerStatus->stickX, partnerStatus->stickY);
328 if ((collisionStatus->curFloor <= NO_COLLIDER)
329 || stickInputMag > 10.0f
330 || partnerStatus->pressedButtons & (BUTTON_B | BUTTON_C_DOWN)
331 || playerStatus->flags & PS_FLAG_HIT_FIRE
332 ) {
333 // prevent exiting from the ground while underneath a wall
335 script->USE_STATE++; // OUTTA_SIGHT_REAPPEAR
336 script->functionTemp[1] = 3;
337 script->functionTemp[2] = playerStatus->inputDisabledCount;
338 }
339 }
340 break;
341
342 case OUTTA_SIGHT_REAPPEAR:
343 if (script->functionTemp[1] == 0) {
344 if (script->functionTemp[2] < playerStatus->inputDisabledCount) {
345 script->USE_STATE = OUTTA_SIGHT_IDLE;
346 break;
347 }
348 } else {
349 script->functionTemp[1]--;
350 break;
351 }
352
355 return ApiStatus_DONE1;
356 }
357 return ApiStatus_BLOCK;
358}
359
361 Call(N(UseAbility))
362 Return
363 End
364};
365
367 PlayerStatus* playerStatus = &gPlayerStatus;
368 PartnerStatus* partnerStatus = &gPartnerStatus;
369 s32 actionState;
370
371 playerStatus->curAlpha = 255;
372 npc_set_imgfx_params(bow, IMGFX_CLEAR, 0, 0, 0, 0, 0);
374 get_shadow_by_index(bow->shadowIndex)->alpha = playerStatus->curAlpha / 2;
375
376 if (N(LockingPlayerInput)) {
378 }
379
382 N(LockingPlayerInput) = FALSE;
383 actionState = ACTION_STATE_IDLE;
384
385 if (playerStatus->flags & PS_FLAG_HIT_FIRE) {
386 actionState = ACTION_STATE_HIT_LAVA;
387 }
388
389 set_action_state(actionState);
390 partnerStatus->partnerActionState = 0;
391 partnerStatus->actingPartner = 0;
392 playerStatus->flags &= ~PS_FLAG_PAUSE_DISABLED;
394 N(IsHiding) = FALSE;
395}
396
397API_CALLABLE(N(PutAway)) {
398 Npc* bow = script->owner2.npc;
399
400 if (isInitialCall) {
402 if (N(IsHiding)) {
404 }
406 }
407
408 if (partner_put_away(bow)) {
409 return ApiStatus_DONE1;
410 } else {
411 return ApiStatus_BLOCK;
412 }
413}
414
416 Call(N(PutAway))
417 Return
418 End
419};
420
421void N(pre_battle)(Npc* bow) {
422 PartnerStatus* partnerStatus = &gPartnerStatus;
423
424 if (N(IsHiding)) {
429 partnerStatus->actingPartner = PARTNER_NONE;
430 N(IsHiding) = FALSE;
431 bow->flags &= ~NPC_FLAG_INVISIBLE;
432 }
433}
s32 partnerUsedTime[12]
s32 b32
Bytecode EvtScript[]
#define clamp_angle
#define atan2
#define mem_clear
@ TWEESTER_PARTNER_HOLD
Definition enums.h:2477
@ TWEESTER_PARTNER_ATTRACT
Definition enums.h:2476
@ TWEESTER_PARTNER_INIT
Definition enums.h:2475
@ TWEESTER_PARTNER_RELEASE
Definition enums.h:2478
@ BUTTON_C_DOWN
Definition enums.h:2779
@ BUTTON_B
Definition enums.h:2789
@ IMGFX_SET_ALPHA
Definition enums.h:5124
@ IMGFX_CLEAR
Definition enums.h:5117
@ PS_FLAG_JUMPING
Definition enums.h:3035
@ PS_FLAG_PAUSE_DISABLED
Definition enums.h:3044
@ PS_FLAG_HAZARD_INVINCIBILITY
Definition enums.h:3056
@ PS_FLAG_HIT_FIRE
Definition enums.h:3050
@ PARTNER_ACTION_NONE
Definition enums.h:2932
@ NPC_PARTNER
Definition enums.h:2528
@ PLAYER_COLLISION_0
Definition enums.h:4712
@ AREA_OMO
Definition enums.h:2976
@ PA_FLAG_CHANGING_MAP
Definition enums.h:3112
@ PA_FLAG_PARTNER_USAGE_FORCED
Definition enums.h:3115
@ SOUND_BOW_APPEAR
Definition enums.h:1324
@ SOUND_BOW_VANISH
Definition enums.h:1323
@ RENDER_MODE_SURFACE_XLU_LAYER2
Definition enums.h:3287
@ RENDER_MODE_SURFACE_XLU_LAYER1
Definition enums.h:3282
@ PARTNER_NONE
Definition enums.h:2885
@ PARTNER_BOW
Definition enums.h:2894
@ ACTION_STATE_RIDE
Definition enums.h:2461
@ ACTION_STATE_HIT_LAVA
Definition enums.h:2451
@ ACTION_STATE_IDLE
Definition enums.h:2426
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_JUMPING
Definition enums.h:3009
@ NPC_FLAG_IGNORE_WORLD_COLLISION
Definition enums.h:3004
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:3006
@ NPC_FLAG_GRAVITY
Definition enums.h:3007
@ NPC_FLAG_INVISIBLE
Definition enums.h:2999
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
Definition enums.h:3016
#define ApiStatus_DONE2
Definition evt.h:118
#define ApiStatus_DONE1
Definition evt.h:117
#define ApiStatus_BLOCK
Definition evt.h:116
f32 fabsf(f32 f)
void suggest_player_anim_always_forward(AnimID anim)
Definition 77480.c:913
void partner_clear_player_tracking(Npc *partner)
Definition partners.c:2436
void partner_flying_update_player_tracking(Npc *partner)
Definition partners.c:1751
s32 disable_player_input(void)
Definition 77480.c:990
Shadow * get_shadow_by_index(s32 index)
Definition entity.c:534
s32 enable_player_input(void)
Definition 77480.c:998
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
s32 player_test_lateral_overlap(s32, PlayerStatus *, f32 *, f32 *, f32 *, f32, f32)
Definition 77480.c:370
s32 is_starting_conversation(void)
Definition encounter.c:2818
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
void suggest_player_anim_allow_backward(AnimID anim)
Definition 77480.c:894
void partner_flying_update_motion(Npc *partner)
Definition partners.c:1777
void partner_flying_enable(Npc *partner, s32 val)
Definition partners.c:1706
f32 sin_rad(f32 x)
Definition 43F0.c:713
void sin_cos_rad(f32 rad, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:706
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
Definition 43F0.c:685
void npc_set_imgfx_params(Npc *npc, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6)
Definition npc.c:2162
s32 func_800EA52C(s32 partnerID)
Definition partners.c:537
s32 partner_init_get_out(Npc *npc)
Definition partners.c:2252
s32 partner_init_put_away(Npc *partner)
Definition partners.c:2178
s32 partner_put_away(Npc *partner)
Definition partners.c:2185
s32 partner_force_player_flip_done(void)
Definition partners.c:2454
s32 partner_get_out(Npc *partner)
Definition partners.c:2259
void sfx_play_sound_at_npc(s32 soundID, s32 arg1, s32 npcID)
Definition sfx.c:527
#define End
Signals the end of EVT script data. A script missing this will likely crash on load.
Definition macros.h:213
#define BSS
Definition macros.h:7
#define DEG_TO_RAD(deg)
Definition macros.h:134
#define NO_COLLIDER
Definition macros.h:156
#define Call(FUNC, ARGS...)
Calls a given C EVT API function with any number of arguments.
Definition macros.h:576
#define Return
Kills the current EVT thread.
Definition macros.h:217
s8 renderMode
s32 flags
f32 renderYaw
AnimID curAnim
Vec3f moveToPos
Vec3f pos
s32 shadowIndex
s16 duration
Entity * TweesterTouchingPartner
Definition 7B440.c:5
CollisionStatus gCollisionStatus
Definition 7BB60.c:6
PartnerStatus gPartnerStatus
Definition partners.c:42
GameStatus * gGameStatusPtr
Definition main_loop.c:32
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
void N pre_battle(Npc *bow)
Definition bow.c:421
void N end_outta_sight_cleanup(Npc *partner)
Definition bow.c:366
EvtScript EVS_WorldBow_Update
Definition bow.c:128
EvtScript EVS_WorldBow_PutAway
Definition bow.c:415
void N init(Npc *bow)
Definition bow.c:19
EvtScript EVS_WorldBow_TakeOut
Definition bow.c:41
EvtScript EVS_WorldBow_UseAbility
Definition bow.c:360
s32 N check_for_treadmill_overlaps(void)
Definition bow.c:144
void N try_cancel_tweester(Npc *bow)
Definition bow.c:134