object_collision.c (6778B)
1 #include <PR/ultratypes.h> 2 3 #include "sm64.h" 4 #include "debug.h" 5 #include "interaction.h" 6 #include "mario.h" 7 #include "object_list_processor.h" 8 #include "spawn_object.h" 9 10 struct Object *debug_print_obj_collision(struct Object *a) { 11 struct Object *sp24; 12 UNUSED u8 filler[4]; 13 s32 i; 14 15 for (i = 0; i < a->numCollidedObjs; i++) { 16 print_debug_top_down_objectinfo("ON", 0); 17 sp24 = a->collidedObjs[i]; 18 if (sp24 != gMarioObject) { 19 return sp24; 20 } 21 } 22 return NULL; 23 } 24 25 s32 detect_object_hitbox_overlap(struct Object *a, struct Object *b) { 26 f32 sp3C = a->oPosY - a->hitboxDownOffset; 27 f32 sp38 = b->oPosY - b->hitboxDownOffset; 28 f32 dx = a->oPosX - b->oPosX; 29 UNUSED f32 sp30 = sp3C - sp38; 30 f32 dz = a->oPosZ - b->oPosZ; 31 f32 collisionRadius = a->hitboxRadius + b->hitboxRadius; 32 f32 distance = sqrtf(dx * dx + dz * dz); 33 34 if (collisionRadius > distance) { 35 f32 sp20 = a->hitboxHeight + sp3C; 36 f32 sp1C = b->hitboxHeight + sp38; 37 38 if (sp3C > sp1C) { 39 return 0; 40 } 41 if (sp20 < sp38) { 42 return 0; 43 } 44 if (a->numCollidedObjs >= 4) { 45 return 0; 46 } 47 if (b->numCollidedObjs >= 4) { 48 return 0; 49 } 50 a->collidedObjs[a->numCollidedObjs] = b; 51 b->collidedObjs[b->numCollidedObjs] = a; 52 a->collidedObjInteractTypes |= b->oInteractType; 53 b->collidedObjInteractTypes |= a->oInteractType; 54 a->numCollidedObjs++; 55 b->numCollidedObjs++; 56 return 1; 57 } 58 59 //! no return value 60 #ifdef AVOID_UB 61 return 0; 62 #endif 63 } 64 65 s32 detect_object_hurtbox_overlap(struct Object *a, struct Object *b) { 66 f32 sp3C = a->oPosY - a->hitboxDownOffset; 67 f32 sp38 = b->oPosY - b->hitboxDownOffset; 68 f32 sp34 = a->oPosX - b->oPosX; 69 UNUSED f32 sp30 = sp3C - sp38; 70 f32 sp2C = a->oPosZ - b->oPosZ; 71 f32 sp28 = a->hurtboxRadius + b->hurtboxRadius; 72 f32 sp24 = sqrtf(sp34 * sp34 + sp2C * sp2C); 73 74 if (a == gMarioObject) { 75 b->oInteractionSubtype |= INT_SUBTYPE_DELAY_INVINCIBILITY; 76 } 77 78 if (sp28 > sp24) { 79 f32 sp20 = a->hitboxHeight + sp3C; 80 f32 sp1C = b->hurtboxHeight + sp38; 81 82 if (sp3C > sp1C) { 83 return 0; 84 } 85 if (sp20 < sp38) { 86 return 0; 87 } 88 if (a == gMarioObject) { 89 b->oInteractionSubtype &= ~INT_SUBTYPE_DELAY_INVINCIBILITY; 90 } 91 return 1; 92 } 93 94 //! no return value 95 #ifdef AVOID_UB 96 return 0; 97 #endif 98 } 99 100 void clear_object_collision(struct Object *a) { 101 struct Object *sp4 = (struct Object *) a->header.next; 102 103 while (sp4 != a) { 104 sp4->numCollidedObjs = 0; 105 sp4->collidedObjInteractTypes = 0; 106 if (sp4->oIntangibleTimer > 0) { 107 sp4->oIntangibleTimer--; 108 } 109 sp4 = (struct Object *) sp4->header.next; 110 } 111 } 112 113 void check_collision_in_list(struct Object *a, struct Object *b, struct Object *c) { 114 if (a->oIntangibleTimer == 0) { 115 while (b != c) { 116 if (b->oIntangibleTimer == 0) { 117 if (detect_object_hitbox_overlap(a, b) && b->hurtboxRadius != 0.0f) { 118 detect_object_hurtbox_overlap(a, b); 119 } 120 } 121 b = (struct Object *) b->header.next; 122 } 123 } 124 } 125 126 void check_player_object_collision(void) { 127 struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_PLAYER]; 128 struct Object *sp18 = (struct Object *) sp1C->header.next; 129 130 while (sp18 != sp1C) { 131 check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C); 132 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_POLELIKE].next, 133 (struct Object *) &gObjectLists[OBJ_LIST_POLELIKE]); 134 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_LEVEL].next, 135 (struct Object *) &gObjectLists[OBJ_LIST_LEVEL]); 136 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_GENACTOR].next, 137 (struct Object *) &gObjectLists[OBJ_LIST_GENACTOR]); 138 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_PUSHABLE].next, 139 (struct Object *) &gObjectLists[OBJ_LIST_PUSHABLE]); 140 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_SURFACE].next, 141 (struct Object *) &gObjectLists[OBJ_LIST_SURFACE]); 142 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_DESTRUCTIVE].next, 143 (struct Object *) &gObjectLists[OBJ_LIST_DESTRUCTIVE]); 144 sp18 = (struct Object *) sp18->header.next; 145 } 146 } 147 148 void check_pushable_object_collision(void) { 149 struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_PUSHABLE]; 150 struct Object *sp18 = (struct Object *) sp1C->header.next; 151 152 while (sp18 != sp1C) { 153 check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C); 154 sp18 = (struct Object *) sp18->header.next; 155 } 156 } 157 158 void check_destructive_object_collision(void) { 159 struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_DESTRUCTIVE]; 160 struct Object *sp18 = (struct Object *) sp1C->header.next; 161 162 while (sp18 != sp1C) { 163 if (sp18->oDistanceToMario < 2000.0f && !(sp18->activeFlags & ACTIVE_FLAG_UNK9)) { 164 check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C); 165 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_GENACTOR].next, 166 (struct Object *) &gObjectLists[OBJ_LIST_GENACTOR]); 167 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_PUSHABLE].next, 168 (struct Object *) &gObjectLists[OBJ_LIST_PUSHABLE]); 169 check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_SURFACE].next, 170 (struct Object *) &gObjectLists[OBJ_LIST_SURFACE]); 171 } 172 sp18 = (struct Object *) sp18->header.next; 173 } 174 } 175 176 void detect_object_collisions(void) { 177 clear_object_collision((struct Object *) &gObjectLists[OBJ_LIST_POLELIKE]); 178 clear_object_collision((struct Object *) &gObjectLists[OBJ_LIST_PLAYER]); 179 clear_object_collision((struct Object *) &gObjectLists[OBJ_LIST_PUSHABLE]); 180 clear_object_collision((struct Object *) &gObjectLists[OBJ_LIST_GENACTOR]); 181 clear_object_collision((struct Object *) &gObjectLists[OBJ_LIST_LEVEL]); 182 clear_object_collision((struct Object *) &gObjectLists[OBJ_LIST_SURFACE]); 183 clear_object_collision((struct Object *) &gObjectLists[OBJ_LIST_DESTRUCTIVE]); 184 check_player_object_collision(); 185 check_destructive_object_collision(); 186 check_pushable_object_collision(); 187 }