Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
kooper.c
Go to the documentation of this file.
1#include "common.h"
2#include "../src/world/partners.h"
3#include "sprite/npc/WorldKooper.h"
4#include "sprite/player.h"
5#include "effects.h"
6
7#define NAMESPACE world_kooper
8
10s32 test_item_entity_position(f32, f32, f32, f32);
11void fx_damage_stars(s32, f32, f32, f32, f32, f32, f32, s32);
13
14BSS s32 N(ShellTossHoldTime);
15BSS s32 N(TriggeredBattle);
16BSS s32 N(PlayerWasFacingLeft);
17BSS s32 N(D_802BEC5C);
18BSS s32 N(ShellTossKickFalling);
19BSS b32 N(LockingPlayerInput);
20BSS s32 N(HeldItemIdx);
21BSS s32 N(HasItem);
22BSS f32 N(ShellTossPosX);
23BSS f32 N(ShellTossPosY);
24BSS f32 N(ShellTossPosZ);
25BSS s32 D_802BEC7C; // padding?
26
27enum {
31};
32
34
46
58
60 N(HeldItemIdx) = test_item_entity_position(kooper->pos.x, kooper->pos.y, kooper->pos.z, kooper->collisionDiameter);
61
62 if (N(HeldItemIdx) < 0) {
63 return FALSE;
64 }
65
66 N(HasItem) = TRUE;
69 return TRUE;
70}
71
72void N(init)(Npc* kooper) {
73 kooper->collisionHeight = 37;
74 kooper->collisionDiameter = 24;
75 kooper->collisionChannel = COLLIDER_FLAG_IGNORE_PLAYER;
76 N(TriggeredBattle) = FALSE;
77}
78
79API_CALLABLE(N(TakeOut)) {
80 Npc* kooper = script->owner2.npc;
81
82 if (isInitialCall) {
84 }
85
86 if (partner_get_out(kooper)) {
87 return ApiStatus_DONE1;
88 } else {
89 return ApiStatus_BLOCK;
90 }
91}
92
94 Call(N(TakeOut))
95 Return
96 End
97};
98
99BSS TweesterPhysics N(TweesterPhysicsData);
100TweesterPhysics* N(TweesterPhysicsPtr) = &N(TweesterPhysicsData);
101
102API_CALLABLE(N(Update)) {
103 PlayerData* playerData = &gPlayerData;
104 Npc* kooper = script->owner2.npc;
105 f32 sinAngle, cosAngle, liftoffVelocity;
106 Entity* entity;
107
108 if (isInitialCall) {
109 partner_walking_enable(kooper, 1);
110 mem_clear(N(TweesterPhysicsPtr), sizeof(TweesterPhysics));
112 }
113
114 playerData->partnerUsedTime[PARTNER_KOOPER]++;
116
117 if (entity == NULL) {
120 return ApiStatus_BLOCK;
121 }
122
123 switch (N(TweesterPhysicsPtr)->state) {
125 N(TweesterPhysicsPtr)->state++;
126 N(TweesterPhysicsPtr)->prevFlags = kooper->flags;
127 N(TweesterPhysicsPtr)->radius = fabsf(dist2D(kooper->pos.x, kooper->pos.z,
128 entity->pos.x, entity->pos.z));
129 N(TweesterPhysicsPtr)->angle = atan2(entity->pos.x, entity->pos.z, kooper->pos.x, kooper->pos.z);
130 N(TweesterPhysicsPtr)->angularVel = 6.0f;
131 N(TweesterPhysicsPtr)->liftoffVelPhase = 50.0f;
132 N(TweesterPhysicsPtr)->countdown = 120;
134 kooper->flags &= ~NPC_FLAG_GRAVITY;
136 sin_cos_rad(DEG_TO_RAD(N(TweesterPhysicsPtr)->angle), &sinAngle, &cosAngle);
137
138 kooper->pos.x = entity->pos.x + (sinAngle * N(TweesterPhysicsPtr)->radius);
139 kooper->pos.z = entity->pos.z - (cosAngle * N(TweesterPhysicsPtr)->radius);
140
141 N(TweesterPhysicsPtr)->angle = clamp_angle(N(TweesterPhysicsPtr)->angle - N(TweesterPhysicsPtr)->angularVel);
142 if (N(TweesterPhysicsPtr)->radius > 20.0f) {
143 N(TweesterPhysicsPtr)->radius--;
144 } else if (N(TweesterPhysicsPtr)->radius < 19.0f) {
145 N(TweesterPhysicsPtr)->radius++;
146 }
147
148 liftoffVelocity = sin_rad(DEG_TO_RAD(N(TweesterPhysicsPtr)->liftoffVelPhase)) * 3.0f;
149
150 N(TweesterPhysicsPtr)->liftoffVelPhase += 3.0f;
151
152 if (N(TweesterPhysicsPtr)->liftoffVelPhase > 150.0f) {
153 N(TweesterPhysicsPtr)->liftoffVelPhase = 150.0f;
154 }
155 kooper->pos.y += liftoffVelocity;
156
157 kooper->renderYaw = clamp_angle(360.0f - N(TweesterPhysicsPtr)->angle);
158 N(TweesterPhysicsPtr)->angularVel += 0.8;
159 if (N(TweesterPhysicsPtr)->angularVel > 40.0f) {
160 N(TweesterPhysicsPtr)->angularVel = 40.0f;
161 }
162
163 if (--N(TweesterPhysicsPtr)->countdown == 0) {
164 N(TweesterPhysicsPtr)->state++;
165 }
166 break;
168 kooper->flags = N(TweesterPhysicsPtr)->prevFlags;
169 N(TweesterPhysicsPtr)->countdown = 30;
170 N(TweesterPhysicsPtr)->state++;
171 break;
175
176 if (--N(TweesterPhysicsPtr)->countdown == 0) {
177 N(TweesterPhysicsPtr)->state = TWEESTER_PARTNER_INIT;
179 }
180 break;
181 }
182 return ApiStatus_BLOCK;
183}
184
185void N(try_cancel_tweester)(Npc* kooper) {
186 if (TweesterTouchingPartner != NULL) {
188 kooper->flags = N(TweesterPhysicsPtr)->prevFlags;
189 N(TweesterPhysicsPtr)->state = TWEESTER_PARTNER_INIT;
191 }
192}
193
195 Call(N(Update))
196 Return
197 End
198};
199
200API_CALLABLE(N(UseAbility)) {
201 Camera* cam;
202 ItemEntity* heldItem;
203 EncounterStatus* currentEncounter = &gCurrentEncounter;
204 PlayerStatus* playerStatus = &gPlayerStatus;
205 Npc* kooper = script->owner2.npc;
206 PartnerStatus* partnerStatus = &gPartnerStatus;
207 CollisionStatus* collisionStatus = &gCollisionStatus;
208 f32 posX, posY, posZ, hitLength;
209 f32 testLength;
210 s32 actionState;
211 f32 moveAngle;
212 f32 colheight;
213 f32 angleToStartPos;
214
215 #define USE_STATE functionTemp[0]
216 enum {
217 SHELL_TOSS_STATE_BEGIN = 20,
218 SHELL_TOSS_STATE_GATHER = 21,
219 SHELL_TOSS_STATE_JUMP = 2,
220 SHELL_TOSS_STATE_KICK = 3,
221 SHELL_TOSS_STATE_PICKUP = 4,
222 SHELL_TOSS_STATE_HOLD = 5,
223 SHELL_TOSS_STATE_RETURN = 7,
224 SHELL_TOSS_STATE_FINISH = 0,
225 };
226
227 if (currentEncounter->unk_08 != 0) {
228 return ApiStatus_BLOCK;
229 }
230
231 if (isInitialCall) {
232 N(try_cancel_tweester)(kooper);
233 if (playerStatus->animFlags & PA_FLAG_CHANGING_MAP) {
234 return ApiStatus_DONE2;
235 }
236
237 if (!N(TriggeredBattle)) {
238 actionState = playerStatus->actionState;
239 if (actionState == ACTION_STATE_IDLE
240 || actionState == ACTION_STATE_WALK
241 || actionState == ACTION_STATE_RUN
242 ) {
243 script->USE_STATE = SHELL_TOSS_STATE_BEGIN;
244 } else {
245 return ApiStatus_DONE2;
246 }
247 } else if (partnerStatus->partnerActionState == PARTNER_ACTION_NONE) {
249 partnerStatus->actingPartner = PARTNER_KOOPER;
250 script->USE_STATE = SHELL_TOSS_STATE_HOLD;
251 kooper->curAnim = ANIM_WorldKooper_SpinShell;
252 N(ShellTossHoldTime) = 30;
253 }
254 }
255
256 switch (script->USE_STATE) {
257 case SHELL_TOSS_STATE_BEGIN:
258 if (playerStatus->inputDisabledCount != 0
259 || playerStatus->timeInAir != 0
260 || !(kooper->flags & NPC_FLAG_GROUNDED)
261 ) {
262 return ApiStatus_DONE2;
263 }
264
266 script->functionTemp[2] = playerStatus->inputDisabledCount;
267 N(LockingPlayerInput) = TRUE;
269 N(HasItem) = FALSE;
272 partnerStatus->actingPartner = PARTNER_KOOPER;
274 N(PlayerWasFacingLeft) = partner_force_player_flip_done();
275 enable_npc_blur(kooper);
276 kooper->duration = 4;
277 kooper->yaw = atan2(kooper->pos.x, kooper->pos.z,
278 playerStatus->pos.x, playerStatus->pos.z);
279 script->USE_STATE++;
280 break;
281
282 case SHELL_TOSS_STATE_GATHER:
283 if (playerStatus->actionState == ACTION_STATE_HIT_FIRE
284 || playerStatus->actionState == ACTION_STATE_KNOCKBACK
285 || playerStatus->actionState == ACTION_STATE_HIT_LAVA
286 || playerStatus->timeInAir != 0
287 ) {
288 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
289 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
290 break;
291 }
292
293 suggest_player_anim_allow_backward(ANIM_Mario1_BeforeJump);
294 kooper->moveToPos.x = N(ShellTossPosX) = playerStatus->pos.x;
295 kooper->moveToPos.y = N(ShellTossPosY) = playerStatus->pos.y;
296 kooper->moveToPos.z = N(ShellTossPosZ) = playerStatus->pos.z;
297 kooper->curAnim = ANIM_WorldKooper_Run;
298 add_vec2D_polar(&kooper->moveToPos.x, &kooper->moveToPos.z,
299 playerStatus->colliderDiameter / 3, playerStatus->targetYaw);
300 moveAngle = clamp_angle(playerStatus->targetYaw + (N(PlayerWasFacingLeft) ? 90.0f : -90.0f));
301 add_vec2D_polar(&kooper->moveToPos.x, &kooper->moveToPos.z,
302 playerStatus->colliderDiameter / 4, moveAngle);
303 kooper->pos.x += (kooper->moveToPos.x - kooper->pos.x) / kooper->duration;
304 kooper->pos.y += (kooper->moveToPos.y - kooper->pos.y) / kooper->duration;
305 kooper->pos.z += (kooper->moveToPos.z - kooper->pos.z) / kooper->duration;
306
307 kooper->duration--;
308 if (kooper->duration != 0) {
309 break;
310 }
311
312 disable_npc_blur(kooper);
313 if (script->functionTemp[2] < playerStatus->inputDisabledCount) {
314 if (!(playerStatus->animFlags & PA_FLAG_CHANGING_MAP)) {
315 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
316 } else {
317 suggest_player_anim_allow_backward(ANIM_Mario1_Run);
318 }
319 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
320 break;
321 }
322
323 kooper->yaw = playerStatus->targetYaw;
324 kooper->jumpVel = 18.0f;
325 kooper->jumpScale = 3.0f;
326 kooper->curAnim = ANIM_WorldKooper_EnterShell;
327 kooper->collisionHeight = 12;
328
329 kooper->moveToPos.y = playerStatus->pos.y;
330 kooper->moveToPos.z = playerStatus->pos.y + playerStatus->colliderHeight / 3;
331 playerStatus->flags |= PS_FLAG_JUMPING;
333
334#if VERSION_PAL
335 playerStatus->gravityIntegrator[0] = 0;
336 playerStatus->gravityIntegrator[1] = 0;
337 playerStatus->gravityIntegrator[2] = 0;
338 playerStatus->gravityIntegrator[3] = 0;
339#endif
340
341 suggest_player_anim_allow_backward(ANIM_Mario1_Jump);
342 N(ShellTossKickFalling) = FALSE;
344 script->USE_STATE = SHELL_TOSS_STATE_JUMP;
345 // fallthrough
346
347 case SHELL_TOSS_STATE_JUMP:
348 if (playerStatus->actionState == ACTION_STATE_HIT_FIRE
349 || playerStatus->actionState == ACTION_STATE_KNOCKBACK
350 || playerStatus->actionState == ACTION_STATE_HIT_LAVA
351 ) {
352 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
353 break;
354 }
355
356 kooper->jumpVel -= kooper->jumpScale;
357 playerStatus->pos.y += kooper->jumpVel;
358 if (kooper->jumpVel < 0.0f) {
359 if (!N(ShellTossKickFalling)) {
360 N(ShellTossKickFalling) = TRUE;
361 suggest_player_anim_allow_backward(ANIM_Mario1_Fall);
362 }
363 }
364
365 posX = playerStatus->pos.x;
366 posY = (playerStatus->pos.y + playerStatus->colliderHeight / 2) - kooper->jumpVel;
367 posZ = playerStatus->pos.z;
368 testLength = hitLength = playerStatus->colliderHeight / 2;
369
370 if ((npc_raycast_up(COLLIDER_FLAG_IGNORE_PLAYER, &posX, &posY, &posZ, &hitLength)) && (hitLength < testLength)) {
371 collisionStatus->curCeiling = NpcHitQueryColliderID;
372 playerStatus->pos.y = posY - playerStatus->colliderHeight;
374 }
375
376 if (!(kooper->jumpVel > 0.0f) && (playerStatus->pos.y < kooper->moveToPos.z)) {
377 N(D_802BEC5C) = 0;
378 kooper->flags &= ~NPC_FLAG_IGNORE_PLAYER_COLLISION;
379 partnerStatus->actingPartner = PARTNER_KOOPER;
381 kooper->rot.z = 0.0f;
382 kooper->planarFlyDist = 0.0f;
383 kooper->moveSpeed = 8.0f;
384 kooper->curAnim = ANIM_WorldKooper_SpinShell;
386 fx_damage_stars(FX_DAMAGE_STARS_3, kooper->pos.x, kooper->pos.y + kooper->collisionHeight, kooper->pos.z,
387 sin_deg(playerStatus->targetYaw), -1.0f, -cos_deg(playerStatus->targetYaw), 3);
389
390 if (N(LockingPlayerInput)) {
392 N(LockingPlayerInput) = FALSE;
393 }
394
395 script->USE_STATE = SHELL_TOSS_STATE_KICK;
396 N(ShellTossKickFalling) = FALSE;
400 }
401 break;
402
403 case SHELL_TOSS_STATE_KICK:
404 if (playerStatus->actionState == ACTION_STATE_HIT_FIRE
405 || playerStatus->actionState == ACTION_STATE_KNOCKBACK
406 ) {
407 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
408 break;
409 }
410
411 // check the forward collision for kooper
412 #define TEST_COLLISION_AT_ANGLE(testAngle) \
413 ( \
414 posX = kooper->pos.x, \
415 posY = kooper->pos.y, \
416 posZ = kooper->pos.z, \
417 npc_test_move_taller_with_slipping(COLLIDER_FLAG_IGNORE_SHELL, \
418 &posX, &posY, &posZ, kooper->moveSpeed, testAngle, \
419 kooper->collisionHeight, kooper->collisionDiameter / 2) \
420 )
421
422 if (TEST_COLLISION_AT_ANGLE(kooper->yaw - 20.0f)) {
423 if (!N(lateral_hit_interactable_entity)(kooper)) {
425 }
426
427 fx_damage_stars(FX_DAMAGE_STARS_3, kooper->pos.x, kooper->pos.y + kooper->collisionHeight, kooper->pos.z,
428 sin_deg(kooper->yaw), -1.0f, -cos_deg(kooper->yaw), 1);
430 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
431 break;
432 }
433
434 if (TEST_COLLISION_AT_ANGLE(kooper->yaw + 20.0f)) {
435 if (!N(lateral_hit_interactable_entity)(kooper)) {
437 }
438
439 fx_damage_stars(FX_DAMAGE_STARS_3, kooper->pos.x, kooper->pos.y + kooper->collisionHeight, kooper->pos.z,
440 sin_deg(kooper->yaw), -1.0f, -cos_deg(kooper->yaw), 1);
442 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
443 break;
444 }
445
446 if (TEST_COLLISION_AT_ANGLE(kooper->yaw)) {
447 if (!N(lateral_hit_interactable_entity)(kooper)) {
449 }
450
451 fx_damage_stars(FX_DAMAGE_STARS_3, kooper->pos.x, kooper->pos.y + kooper->collisionHeight, kooper->pos.z,
452 sin_deg(kooper->yaw), -1.0f, -cos_deg(kooper->yaw), 1);
454 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
455 break;
456 }
457
458 kooper->pos.x = posX;
459 kooper->pos.y = posY;
460 kooper->pos.z = posZ;
461 kooper->planarFlyDist += kooper->moveSpeed;
463
464 kooper->moveSpeed += 2.0;
465 if (kooper->moveSpeed > 14.0) {
466 kooper->moveSpeed = 14.0f;
467 }
468
469 if (!(npc_try_snap_to_ground(kooper, 6.0f) || playerStatus->flags & (PS_FLAG_JUMPING | PS_FLAG_FALLING))) {
470 kooper->pos.y += (playerStatus->pos.y - kooper->pos.y) / 10.0f;
471 }
472
474
475 if ((kooper->flags & NPC_FLAG_COLLIDING_WITH_NPC)) {
476 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
477 kooper->moveSpeed = 0.0f;
479 break;
480 }
481
482 if (N(check_for_item_collision)(kooper)) {
484 fx_damage_stars(FX_DAMAGE_STARS_3, kooper->pos.x, kooper->pos.y + kooper->collisionHeight, kooper->pos.z,
485 sin_deg(kooper->yaw), -1.0f, -cos_deg(kooper->yaw), 1);
487 script->USE_STATE = SHELL_TOSS_STATE_PICKUP;
488 N(ShellTossHoldTime) = 8;
489 kooper->moveSpeed -= 4.0;
490 if (kooper->moveSpeed < 0.01) {
491 kooper->moveSpeed = 0.01f;
492 kooper->planarFlyDist += 1.0;
493 }
496 script->USE_STATE = SHELL_TOSS_STATE_HOLD;
497 N(ShellTossHoldTime) = 30;
498 kooper->moveSpeed = 0.0f;
499 } else {
500 if (kooper->planarFlyDist > 140.0f) {
501 label2:
502 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
503 kooper->moveSpeed = 0.0f;
505 } else if (kooper->planarFlyDist > 105.0f) {
506 kooper->moveSpeed -= 4.0;
507 if (kooper->moveSpeed < 0.01) {
508 kooper->moveSpeed = 0.01f;
509 kooper->planarFlyDist += 1.0;
510 }
511 }
512 }
513 break;
514
515 case SHELL_TOSS_STATE_PICKUP:
516 posX = kooper->pos.x;
517 posY = kooper->pos.y;
518 posZ = kooper->pos.z;
519
521 &posX, &posY, &posZ, kooper->moveSpeed, kooper->yaw,
522 kooper->collisionHeight, ( kooper->collisionDiameter / 2));
523
524 kooper->pos.x = posX;
525 kooper->pos.y = posY;
526 kooper->pos.z = posZ;
527
528 kooper->planarFlyDist += kooper->moveSpeed;
530 kooper->moveSpeed -= 6.0;
531
532 if (kooper->moveSpeed < 0.01) {
533 kooper->moveSpeed = 0.01f;
534 kooper->planarFlyDist += 1.0;
535 }
536
537 if (N(ShellTossHoldTime) == 0) {
538 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
539 }
540 N(ShellTossHoldTime)--;
541 break;
542
543 case SHELL_TOSS_STATE_HOLD:
544 if (N(ShellTossHoldTime) != 0) {
545 N(ShellTossHoldTime)--;
546 } else {
547 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
548 }
549 break;
550 }
551
552 if (script->USE_STATE == SHELL_TOSS_STATE_RETURN) {
554 if (playerStatus->actionState == ACTION_STATE_HIT_FIRE
555 || playerStatus->actionState == ACTION_STATE_KNOCKBACK
556 ) {
557 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
558 } else {
559 angleToStartPos = atan2(N(ShellTossPosX), N(ShellTossPosZ), kooper->pos.x, kooper->pos.z);
560 kooper->yaw = angleToStartPos + get_clamped_angle_diff(kooper->yaw, angleToStartPos) * 0.125f;
561 npc_move_heading(kooper, -kooper->moveSpeed, kooper->yaw);
562 kooper->planarFlyDist -= kooper->moveSpeed;
564 kooper->moveSpeed += 4.0/3.0;
565
566 if (kooper->moveSpeed > 14.0) {
567 kooper->moveSpeed = 14.0f;
568 }
569
570 if (npc_try_snap_to_ground(kooper, 6.0f) == 0) {
571 kooper->pos.y += (playerStatus->pos.y - kooper->pos.y) / 10.0f;
572 }
573
574 posX = kooper->pos.x;
575 posY = kooper->pos.y;
576 posZ = kooper->pos.z;
577
579 &posX, &posY, &posZ, kooper->moveSpeed, clamp_angle(kooper->yaw + 180.0f),
580 kooper->collisionHeight, kooper->collisionDiameter)
581 ) {
582 kooper->pos.x = posX;
583 kooper->pos.y = posY;
584 kooper->pos.z = posZ;
586 testLength = sin_deg(kooper->yaw + 180.0f);
587 fx_damage_stars(FX_DAMAGE_STARS_3, kooper->pos.x, kooper->pos.y + kooper->collisionHeight, kooper->pos.z,
588 testLength, -1.0f, -cos_deg(kooper->yaw + 180.0f), 1);
589 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
590 } else {
591 if (N(HasItem)) {
592 heldItem = get_item_entity(N(HeldItemIdx));
593 posX = kooper->pos.x;
594 posY = kooper->pos.y + 8.0f;
595 posZ = kooper->pos.z;
596
597 moveAngle = clamp_angle(playerStatus->targetYaw - (N(PlayerWasFacingLeft) ? 90.0f : -90.0f));
598
599 add_vec2D_polar(&posX, &posZ, 4.0f, moveAngle);
600 heldItem->pos.x = posX;
601 heldItem->pos.y = posY;
602 heldItem->pos.z = posZ;
603 }
604
605 if (kooper->planarFlyDist + 15.0f < kooper->moveSpeed) {
606 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
607 } else if (kooper->planarFlyDist + 15.0f < 35.0f) {
608 kooper->moveSpeed -= 4.0;
609 if (kooper->moveSpeed < 4.0) {
610 kooper->moveSpeed = 4.0;
611 }
612 }
613 }
614 }
615 }
616
617 if (script->USE_STATE == SHELL_TOSS_STATE_FINISH) {
618 if (N(LockingPlayerInput)) {
620 N(LockingPlayerInput) = FALSE;
621 }
622
626 partnerStatus->actingPartner = PARTNER_NONE;
628 kooper->jumpVel = 0.0f;
629 kooper->collisionHeight = 24;
630 kooper->curAnim = ANIM_WorldKooper_Walk;
632 disable_npc_blur(kooper);
633
634 if (N(HasItem)) {
635 auto_collect_item_entity(N(HeldItemIdx));
636 N(HasItem) = FALSE;
637 }
638
639 N(TriggeredBattle) = FALSE;
641 return ApiStatus_DONE2;
642 }
643
644 return ApiStatus_BLOCK;
645}
646
648 Call(N(UseAbility))
649 Return
650 End
651};
652
653API_CALLABLE(N(PutAway)) {
654 Npc* kooper = script->owner2.npc;
655
656 if (isInitialCall) {
657 partner_init_put_away(kooper);
658 }
659
661}
662
664 Call(N(PutAway))
665 Return
666 End
667};
668
669s32 N(test_first_strike)(Npc* kooper, Npc* enemy) {
670 f32 xTemp, yTemp, zTemp;
671 f32 enemyX, enemyY, enemyZ;
672 f32 kooperX;
673 f32 kooperZ;
674 f32 enemyCollHeight;
675 f32 kooperY;
676 f32 kooperCollHeight;
677 f32 enemyCollRadius;
678 f32 kooperCollRadius;
679 f32 angleToEnemy;
680 f32 distToEnemy;
681
683 enemyX = enemy->pos.x;
684 enemyY = enemy->pos.y;
685 enemyZ = enemy->pos.z;
686
687 kooperX = kooper->pos.x;
688 kooperY = kooper->pos.y;
689 kooperZ = kooper->pos.z;
690
691 enemyCollHeight = enemy->collisionHeight;
692 enemyCollRadius = enemy->collisionDiameter * 0.55;
693
694 kooperCollHeight = kooper->collisionHeight;
695 kooperCollRadius = kooper->collisionDiameter * 0.8;
696
697 angleToEnemy = atan2(enemyX, enemyZ, kooperX, kooperZ);
698 distToEnemy = dist2D(enemyX, enemyZ, kooperX, kooperZ);
699
700 xTemp = kooper->pos.x;
701 yTemp = kooper->pos.y;
702 zTemp = kooper->pos.z;
703
704 if (npc_test_move_taller_with_slipping(0, &xTemp, &yTemp, &zTemp, distToEnemy, angleToEnemy,
705 kooperCollHeight, kooperCollRadius + enemyCollRadius)
706 ) {
707 return FALSE;
708 }
709
710 if (kooperY > enemyY + enemyCollHeight) {
711 return FALSE;
712 }
713
714 if (enemyY > kooperY + kooperCollHeight) {
715 return FALSE;
716 }
717
718 kooperX = enemyX - kooperX;
719 kooperZ = enemyZ - kooperZ;
720 distToEnemy = SQ(kooperX) + SQ(kooperZ);
721
722 if (!(SQ(kooperCollRadius) + SQ(enemyCollRadius) <= distToEnemy)) {
724 return TRUE;
725 }
726 }
727 return FALSE;
728}
729
730void N(pre_battle)(Npc* kooper) {
731 PlayerStatus* playerStatus = &gPlayerStatus;
732 PartnerStatus* partnerStatus = &gPartnerStatus;
733 N(TriggeredBattle) = FALSE;
734
735 if (partnerStatus->partnerActionState != PARTNER_ACTION_NONE) {
736 if (partnerStatus->partnerActionState == PARTNER_ACTION_KOOPER_TOSS) {
737 N(TriggeredBattle) = TRUE;
738 }
739
740 if (N(LockingPlayerInput)) {
742 N(LockingPlayerInput) = FALSE;
743 }
744
746 playerStatus->flags &= ~PS_FLAG_JUMPING;
747
748 kooper->jumpVel = 0.0f;
749 kooper->flags &= ~NPC_FLAG_JUMPING;
750 kooper->flags &= ~NPC_FLAG_IGNORE_WORLD_COLLISION;
751
755 disable_npc_blur(kooper);
756
757 partnerStatus->actingPartner = PARTNER_NONE;
759 }
760}
761
762void N(post_battle)(Npc* npc) {
763 if (N(TriggeredBattle)) {
766 }
767}
s32 partner_use_ability(void)
Definition partners.c:964
s32 partnerUsedTime[12]
s32 b32
Bytecode EvtScript[]
f32 gravityIntegrator[4]
#define sin_deg
#define clamp_angle
#define cos_deg
#define atan2
#define mem_clear
@ FX_DAMAGE_STARS_3
Definition effects.h:359
@ 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
@ ITEM_ENTITY_FLAG_CANT_COLLECT
Definition enums.h:2715
@ PS_FLAG_FALLING
Definition enums.h:3036
@ PS_FLAG_JUMPING
Definition enums.h:3035
@ PARTNER_ACTION_KOOPER_GATHER
Definition enums.h:2934
@ PARTNER_ACTION_KOOPER_TOSS
Definition enums.h:2935
@ PARTNER_ACTION_NONE
Definition enums.h:2932
@ COLLIDER_FLAG_IGNORE_PLAYER
Definition enums.h:4696
@ COLLIDER_FLAG_IGNORE_SHELL
Definition enums.h:4695
@ NPC_PARTNER
Definition enums.h:2528
@ PA_FLAG_CHANGING_MAP
Definition enums.h:3112
@ SOUND_IMMUNE
Definition enums.h:745
@ SOUND_NONE
Definition enums.h:547
@ SOUND_KOOPER_SHELL_SWIRL
Definition enums.h:996
@ SOUND_KOOPER_SHELL_KICK
Definition enums.h:995
@ SOUND_QUICK_PLAYER_JUMP
Definition enums.h:1424
@ SOUND_KOOPER_PICKUP
Definition enums.h:997
@ PARTNER_NONE
Definition enums.h:2885
@ PARTNER_KOOPER
Definition enums.h:2887
@ ACTION_STATE_HIT_LAVA
Definition enums.h:2451
@ ACTION_STATE_IDLE
Definition enums.h:2426
@ ACTION_STATE_KNOCKBACK
Definition enums.h:2450
@ ACTION_STATE_WALK
Definition enums.h:2427
@ ACTION_STATE_HIT_FIRE
Causes Mario to fly up and take damage. Used for fire bars.
Definition enums.h:2449
@ ACTION_STATE_RUN
Definition enums.h:2428
@ CAMERA_MOVE_IGNORE_PLAYER_Y
Definition enums.h:4732
@ SURFACE_INTERACT_RUN
Definition enums.h:4685
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
@ GLOBAL_OVERRIDES_40
Definition enums.h:4325
@ CAM_DEFAULT
Definition enums.h:1800
@ 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_COLLIDING_WITH_NPC
Definition enums.h:3023
@ NPC_FLAG_GRAVITY
Definition enums.h:3007
@ NPC_FLAG_GROUNDED
Definition enums.h:3010
@ 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 disable_npc_blur(Npc *npc)
Definition npc.c:1088
void partner_walking_update_motion(Npc *partner)
Definition partners.c:1202
void partner_clear_player_tracking(Npc *partner)
Definition partners.c:2436
s32 disable_player_input(void)
Definition 77480.c:990
ItemEntity * get_item_entity(s32 itemEntityIndex)
void partner_walking_update_player_tracking(Npc *partner)
Definition partners.c:1175
void enable_npc_blur(Npc *npc)
Definition npc.c:1067
s32 enable_player_input(void)
Definition 77480.c:998
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
void start_bounce_b(void)
Definition 7E9D0.c:310
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
b32 npc_raycast_up(s32, f32 *, f32 *, f32 *, f32 *)
void suggest_player_anim_allow_backward(AnimID anim)
Definition 77480.c:894
void partner_walking_enable(Npc *partner, s32 val)
Definition partners.c:1133
f32 sin_rad(f32 x)
Definition 43F0.c:713
void set_item_entity_flags(s32 itemEntityIndex, s32 flag)
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
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:606
s32 npc_try_snap_to_ground(Npc *npc, f32 velocity)
Definition npc.c:581
void npc_surface_spawn_fx(Npc *npc, SurfaceInteractMode mode)
Definition surfaces.c:394
void npc_do_other_npc_collision(Npc *npc)
Definition npc.c:381
EncounterStatus gCurrentEncounter
Definition encounter.c:176
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:986
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
void sfx_stop_sound(s32 soundID)
Definition sfx.c:507
ApiStatus HasItem(Evt *script, b32 isInitialCall)
#define End
Signals the end of EVT script data. A script missing this will likely crash on load.
Definition macros.h:213
#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 SQ(x)
Definition macros.h:166
#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
s16 collisionDiameter
f32 jumpScale
f32 jumpVel
s32 flags
f32 renderYaw
AnimID curAnim
Vec3f moveToPos
f32 planarFlyDist
s16 collisionHeight
Vec3f rot
Vec3f pos
f32 moveSpeed
s16 duration
s32 gOverrideFlags
Definition main_loop.c:11
Entity * TweesterTouchingPartner
Definition 7B440.c:5
CollisionStatus gCollisionStatus
Definition 7BB60.c:6
PartnerStatus gPartnerStatus
Definition partners.c:42
s32 NpcHitQueryColliderID
Camera gCameras[4]
Definition cam_main.c:17
PlayerData gPlayerData
Definition 77480.c:40
PlayerStatus gPlayerStatus
Definition 77480.c:39
void N init(Npc *kooper)
Definition kooper.c:72
EvtScript EVS_WorldKooper_TakeOut
Definition kooper.c:93
s32 N check_for_item_collision(Npc *kooper)
Definition kooper.c:59
void N pre_battle(Npc *kooper)
Definition kooper.c:730
s32 ShellTossHitboxState
Definition kooper.c:33
void fx_damage_stars(s32, f32, f32, f32, f32, f32, f32, s32)
s32 N test_first_strike(Npc *kooper, Npc *enemy)
Definition kooper.c:669
#define TEST_COLLISION_AT_ANGLE(testAngle)
void auto_collect_item_entity(s32)
EvtScript EVS_WorldKooper_UseAbility
Definition kooper.c:647
@ SHELL_TOSS_HITBOX_HIT_ENEMY
Definition kooper.c:30
@ SHELL_TOSS_HITBOX_ENABLED
Definition kooper.c:29
@ SHELL_TOSS_HITBOX_DISABLED
Definition kooper.c:28
s32 entity_try_partner_interaction_trigger(s32)
Definition entity.c:677
s32 test_item_entity_position(f32, f32, f32, f32)
void N vertical_hit_interactable_entity(Npc *kooper)
Definition kooper.c:47
void N try_cancel_tweester(Npc *kooper)
Definition kooper.c:185
void N post_battle(Npc *npc)
Definition kooper.c:762
EvtScript EVS_WorldKooper_Update
Definition kooper.c:194
s32 N lateral_hit_interactable_entity(Npc *npc)
Definition kooper.c:35
BSS s32 D_802BEC7C
Definition kooper.c:25
EvtScript EVS_WorldKooper_PutAway
Definition kooper.c:663