summaryrefslogtreecommitdiff
path: root/src/code/m_collision_obj.c
diff options
context:
space:
mode:
authorAnghelo Carvajal <angheloalf95@gmail.com>2023-08-21 15:19:33 -0400
committerGitHub <noreply@github.com>2023-08-21 12:19:33 -0700
commit4a8731d40ad81cb9356bdba23e4aec772328214e (patch)
tree907c70ef7ffdcf5ac0dd3305c29d6caf7c9d4f22 /src/code/m_collision_obj.c
parent74ba3014c974ae9a260d6485be71258310edb59a (diff)
`m_collision_obj.c` OK (#64)
* C file * func_80077620_jp, CollisionCheck_dt, CollisionCheck_clear * CollisionCheck_OC * CollisionCheck_Check1ClObjNoOC and CollisionCheck_Check2ClObjNoOC * CollisionCheck_OC_Pipe_Vs_JntSph, CollisionCheck_Status_ct, CollisionCheck_Status_Clear * CollisionCheck_OC_Pipe_Vs_Pipe and CollisionCheck_OCC * CollisionCheck_OC_JntSph_Vs_Pipe * CollisionCheck_OC_JntSph_Vs_JntSph * CollisionCheck_workTrisElemCenter, CollisionCheck_OCC_Tris_Vs_Pipe * CollisionCheck_OCC_Tris_Vs_JntSph * a bunch * ClObjElem_ct, ClObjTrisElemAttr_ct, ClObjTrisElemAttr_set, ClObjTrisElem_set, ClObjTris_ct, ClObjTris_set5_nzm * fix warnings * ClObj_ct, ClObj_dt, ClObj_OCClear, ClObjElem_OCClear, ClObjJntSphElem_OCClear, ClObjJntSph_OCClear, ClObjPipeAttr_dt, ClObjPipe_dt, ClObjPipe_OCClear, ClObjTrisElem_OCClear, ClObjTris_OCClear, CollisionCheck_setOCC, CollisionCheck_Status_set3, CollisionCheck_Uty_ActorWorldPosSetPipeC * ClObjTrisElem_OCCClear, ClObj_OCCClear, ClObjTris_OCCClear, CollisionCheck_Uty_setTrisPos_ad * get_type, CollisionCheck_setOC_HitInfo * ClObjTrisElemAttr_dt, ClObjTrisElem_dt, ClObjTris_dt_nzf * func_80076CC0_jp, func_80076D68_jp, func_80076E2C_jp * match all * naming * cleanup * cleanup * name some members and flags * more naming * and more cleaning up * idk * migrate data * format * premigrate collision data in actors
Diffstat (limited to 'src/code/m_collision_obj.c')
-rw-r--r--src/code/m_collision_obj.c899
1 files changed, 899 insertions, 0 deletions
diff --git a/src/code/m_collision_obj.c b/src/code/m_collision_obj.c
new file mode 100644
index 0000000..4a30e15
--- /dev/null
+++ b/src/code/m_collision_obj.c
@@ -0,0 +1,899 @@
+#include "m_collision_obj.h"
+#include "m_actor.h"
+#include "m_lib.h"
+#include "sys_math3d.h"
+#include "libc/math.h"
+#include "attributes.h"
+#include "macros.h"
+
+typedef struct struct_mco_work {
+ /* 0x00 */ s32 count;
+ /* 0x04 */ ClObj* coliders[10];
+} struct_mco_work; // size = 0x2C
+
+struct_mco_work mco_work;
+
+typedef void (*CollisionVsFunc)(struct Game_Play*, CollisionCheck*, ClObj*, ClObj*);
+
+typedef s32 (*ClearFunc)(struct Game_Play*, ClObj*);
+
+void CollisionCheck_workTrisElemCenter(ClObjTrisElem* arg0, Vec3f* arg1) {
+ arg1->x = (arg0->attr.unk_00.unk_00.vertices[0].x + arg0->attr.unk_00.unk_00.vertices[1].x +
+ arg0->attr.unk_00.unk_00.vertices[2].x) *
+ (1.0f / 3.0f);
+ arg1->y = (arg0->attr.unk_00.unk_00.vertices[0].y + arg0->attr.unk_00.unk_00.vertices[1].y +
+ arg0->attr.unk_00.unk_00.vertices[2].y) *
+ (1.0f / 3.0f);
+ arg1->z = (arg0->attr.unk_00.unk_00.vertices[0].z + arg0->attr.unk_00.unk_00.vertices[1].z +
+ arg0->attr.unk_00.unk_00.vertices[2].z) *
+ (1.0f / 3.0f);
+}
+
+ClObj clobj_default = { NULL, NULL, { OC1_NONE, OC2_NONE, COLSHAPE_MAX } };
+
+s32 ClObj_ct(UNUSED struct Game_Play* game_play, ClObj* cl) {
+ *cl = clobj_default;
+
+ return 1;
+}
+
+s32 ClObj_dt(UNUSED struct Game_Play* game_play, UNUSED ClObj* cl) {
+ return 1;
+}
+
+s32 ClObj_set4(UNUSED struct Game_Play* game_play, ClObj* cl, struct Actor* actor, ClObj_Properties* prop) {
+ cl->actor = actor;
+ cl->prop.ocFlags1 = prop->ocFlags1;
+ cl->prop.ocFlags2 = prop->ocFlags2;
+ cl->prop.shape = prop->shape;
+
+ return 1;
+}
+
+void ClObj_OCClear(UNUSED struct Game_Play* game_play, ClObj* cl) {
+ cl->oc = NULL;
+ cl->prop.ocFlags1 &= ~OC1_2;
+ cl->prop.ocFlags2 &= ~OC2_1;
+}
+
+s32 ClObjElem_ct(ClObjElem* elem) {
+ elem->flags = ELEM_FLAG_NONE;
+
+ return 1;
+}
+
+s32 ClObjElem_set(ClObjElem* dst, ClObjElem* src) {
+ dst->flags = src->flags;
+
+ return 1;
+}
+
+void ClObjElem_OCClear(UNUSED struct Game_Play* game_play, ClObjElem* elem) {
+ elem->flags &= ~ELEM_FLAG_2;
+}
+
+ClObjJntSphElemAttr default_jntsphelem_attr = { { { 0, 0, 0 }, 0 }, { { 0, 0, 0 }, 0 }, 0.0f, 0 };
+
+s32 ClObjJntSphElemAttr_ct(UNUSED struct Game_Play* game_play, ClObjJntSphElemAttr* attr) {
+ *attr = default_jntsphelem_attr;
+
+ return 1;
+}
+
+s32 ClObjJntSphElemAttr_dt(UNUSED struct Game_Play* game_play, UNUSED ClObjJntSphElemAttr* attr) {
+ return 1;
+}
+
+s32 ClObjJntSphElemAttr_set(UNUSED struct Game_Play* game_play, ClObjJntSphElemAttr* attr,
+ ClObjJntSphElemAttr_Init* init) {
+ attr->unk_14 = init->unk_0;
+ attr->unk_00 = init->unk_2;
+ attr->unk_10 = init->unk_A * 0.01f;
+
+ return 1;
+}
+
+s32 ClObjJntSphElem_ct(struct Game_Play* game_play, ClObjJntSphElem* elem) {
+ ClObjElem_ct(&elem->elem);
+ ClObjJntSphElemAttr_ct(game_play, &elem->attr);
+
+ return 1;
+}
+
+s32 ClObjJntSphElem_dt(struct Game_Play* game_play, ClObjJntSphElem* elem) {
+ ClObjJntSphElemAttr_dt(game_play, &elem->attr);
+
+ return 1;
+}
+
+s32 ClObjJntSphElem_set(struct Game_Play* game_play, ClObjJntSphElem* elem, ClObjJntSphElem_Init* init) {
+ ClObjElem_set(&elem->elem, &init->elem);
+ ClObjJntSphElemAttr_set(game_play, &elem->attr, &init->attr);
+
+ return 1;
+}
+
+s32 ClObjJntSphElem_OCClear(struct Game_Play* game_play, ClObjJntSphElem* elem) {
+ ClObjElem_OCClear(game_play, &elem->elem);
+
+ return 1;
+}
+
+s32 ClObjJntSph_ct(struct Game_Play* game_play, ClObjJntSph* colJntSph) {
+ ClObj_ct(game_play, &colJntSph->base);
+ colJntSph->count = 0;
+ colJntSph->elements = NULL;
+
+ return 1;
+}
+
+s32 ClObjJntSph_dt_nzf(struct Game_Play* game_play, ClObjJntSph* colJntSph) {
+ ClObjJntSphElem* element;
+
+ ClObj_dt(game_play, &colJntSph->base);
+
+ for (element = colJntSph->elements; element < &colJntSph->elements[colJntSph->count]; element++) {
+ ClObjJntSphElem_dt(game_play, element);
+ }
+
+ colJntSph->count = 0;
+ colJntSph->elements = NULL;
+
+ return 1;
+}
+
+s32 ClObjJntSph_set5_nzm(struct Game_Play* game_play, ClObjJntSph* colJntSph, Actor* actor, ClObjJntSph_Init* init,
+ ClObjJntSphElem elements[]) {
+ ClObjJntSphElem_Init* elemInit;
+ ClObjJntSphElem* elem;
+
+ ClObj_set4(game_play, &colJntSph->base, actor, &init->prop);
+
+ colJntSph->count = init->count;
+ colJntSph->elements = elements;
+
+ for (elem = colJntSph->elements, elemInit = init->elements; elem < &colJntSph->elements[colJntSph->count];
+ elem++, elemInit++) {
+ ClObjJntSphElem_ct(game_play, elem);
+ ClObjJntSphElem_set(game_play, elem, elemInit);
+ }
+
+ return 1;
+}
+
+s32 ClObjJntSph_OCClear(struct Game_Play* game_play, ClObj* cl) {
+ ClObjJntSph* colJntSph = (ClObjJntSph*)cl;
+ ClObjJntSphElem* elem;
+
+ ClObj_OCClear(game_play, &colJntSph->base);
+
+ for (elem = colJntSph->elements; elem < &colJntSph->elements[colJntSph->count]; elem++) {
+ ClObjJntSphElem_OCClear(game_play, elem);
+ }
+
+ return 1;
+}
+
+ClObjPipeAttr default_pipe_attr = { { 0, 0, 0, { 0, 0, 0 } } };
+
+s32 ClObjPipeAttr_ct(UNUSED struct Game_Play* game_play, ClObjPipeAttr* attr) {
+ *attr = default_pipe_attr;
+
+ return 1;
+}
+
+s32 ClObjPipeAttr_dt(UNUSED struct Game_Play* game_play, UNUSED ClObjPipeAttr* attr) {
+ return 1;
+}
+
+s32 ClObjPipeAttr_set(UNUSED struct Game_Play* game_play, ClObjPipeAttr* dst, ClObjPipeAttr* src) {
+ *dst = *src;
+
+ return 1;
+}
+
+s32 ClObjPipe_ct(struct Game_Play* game_play, ClObjPipe* colPipe) {
+ ClObj_ct(game_play, &colPipe->base);
+ ClObjElem_ct(&colPipe->element);
+ ClObjPipeAttr_ct(game_play, &colPipe->attribute);
+
+ return 1;
+}
+
+s32 ClObjPipe_dt(struct Game_Play* game_play, ClObjPipe* colPipe) {
+ ClObj_dt(game_play, &colPipe->base);
+ ClObjPipeAttr_dt(game_play, &colPipe->attribute);
+
+ return 1;
+}
+
+s32 ClObjPipe_set5(struct Game_Play* game_play, ClObjPipe* colPipe, struct Actor* actor, ClObjPipe_Init* init) {
+ ClObj_set4(game_play, &colPipe->base, actor, &init->prop);
+ ClObjElem_set(&colPipe->element, &init->elem);
+ ClObjPipeAttr_set(game_play, &colPipe->attribute, &init->attr);
+ return 1;
+}
+
+s32 ClObjPipe_OCClear(struct Game_Play* game_play, ClObj* cl) {
+ ClObjPipe* colPipe = (ClObjPipe*)cl;
+
+ ClObj_OCClear(game_play, &colPipe->base);
+ ClObjElem_OCClear(game_play, &colPipe->element);
+
+ return 1;
+}
+
+ClObjTrisElemAttr default_clobjtriselem_attr = {
+ {
+ { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
+ { 0.0f, 0.0f, 0.0f },
+ 0.0f,
+ },
+ { 0.0f, 0.0f, 0.0f },
+};
+
+s32 ClObjTrisElemAttr_ct(UNUSED struct Game_Play* game_play, ClObjTrisElemAttr* attr) {
+ *attr = default_clobjtriselem_attr;
+
+ return 1;
+}
+
+s32 ClObjTrisElemAttr_dt(UNUSED struct Game_Play* game_play, UNUSED ClObjTrisElemAttr* attr) {
+ return 1;
+}
+
+s32 ClObjTrisElemAttr_set(UNUSED struct Game_Play* game_play, ClObjTrisElemAttr* attr, ClObjTrisElemAttr_Init* init) {
+ Vec3f* var_v0;
+ Vec3f* var_v1;
+ f32 sp44;
+ f32 sp40;
+ f32 sp3C;
+ f32 sp38;
+
+ for (var_v0 = attr->unk_00.unk_00.vertices, var_v1 = init->unk_00.vertices;
+ var_v0 < &attr->unk_00.unk_00.vertices[ARRAY_COUNT(attr->unk_00.unk_00.vertices)]; var_v0++, var_v1++) {
+ *var_v0 = *var_v1;
+ }
+
+ Math3DPlane(&init->unk_00.vertices[0], &init->unk_00.vertices[1], &init->unk_00.vertices[2], &sp44, &sp40, &sp3C,
+ &sp38);
+ attr->unk_00.unk_24.x = sp44;
+ attr->unk_00.unk_24.y = sp40;
+ attr->unk_00.unk_24.z = sp3C;
+ attr->unk_00.unk_30 = sp38;
+
+ return 1;
+}
+
+s32 ClObjTrisElem_ct(struct Game_Play* game_play, ClObjTrisElem* elem) {
+ ClObjElem_ct(&elem->elem);
+ ClObjTrisElemAttr_ct(game_play, &elem->attr);
+
+ return 1;
+}
+
+s32 ClObjTrisElem_dt(struct Game_Play* game_play, ClObjTrisElem* elem) {
+ ClObjTrisElemAttr_dt(game_play, &elem->attr);
+
+ return 1;
+}
+
+s32 ClObjTrisElem_set(struct Game_Play* game_play, ClObjTrisElem* elem, ClObjTrisElem_Init* init) {
+ ClObjElem_set(&elem->elem, &init->elem);
+ ClObjTrisElemAttr_set(game_play, &elem->attr, &init->attr);
+
+ return 1;
+}
+
+s32 ClObjTrisElem_OCClear(struct Game_Play* game_play, ClObjTrisElem* elem) {
+ ClObjElem_OCClear(game_play, &elem->elem);
+
+ return 1;
+}
+
+s32 ClObjTris_ct(struct Game_Play* game_play, ClObjTris* colTris) {
+ ClObj_ct(game_play, &colTris->base);
+ colTris->count = 0;
+ colTris->elements = NULL;
+
+ return 1;
+}
+
+s32 ClObjTris_dt_nzf(struct Game_Play* game_play, ClObjTris* colTris) {
+ ClObjTrisElem* element;
+
+ ClObj_dt(game_play, &colTris->base);
+
+ for (element = colTris->elements; element < &colTris->elements[colTris->count]; element++) {
+ ClObjTrisElem_dt(game_play, element);
+ }
+
+ colTris->count = 0;
+ colTris->elements = NULL;
+
+ return 1;
+}
+
+s32 ClObjTris_set5_nzm(struct Game_Play* game_play, ClObjTris* colTris, Actor* actor, ClObjTris_Init* init,
+ ClObjTrisElem* elements) {
+ ClObjTrisElem_Init* elemInit;
+ ClObjTrisElem* element;
+
+ ClObj_set4(game_play, &colTris->base, actor, &init->prop);
+
+ colTris->count = init->count;
+ colTris->elements = elements;
+
+ for (element = elements, elemInit = init->elem; element < &colTris->elements[colTris->count];
+ element++, elemInit++) {
+ ClObjTrisElem_ct(game_play, element);
+ ClObjTrisElem_set(game_play, element, elemInit);
+ }
+
+ return 1;
+}
+
+s32 ClObjTris_OCClear(struct Game_Play* game_play, ClObj* cl) {
+ ClObjTris* colTris = (ClObjTris*)cl;
+ ClObjTrisElem* var_s0;
+
+ ClObj_OCClear(game_play, &colTris->base);
+
+ for (var_s0 = colTris->elements; var_s0 < &colTris->elements[colTris->count]; var_s0++) {
+ ClObjTrisElem_OCClear(game_play, var_s0);
+ }
+
+ return 1;
+}
+
+void CollisionCheck_ct(struct Game_Play* game_play, CollisionCheck* colCheck) {
+ colCheck->flags = COLCHECK_FLAG_NONE;
+ CollisionCheck_clear(game_play, colCheck);
+}
+
+void CollisionCheck_dt(UNUSED struct Game_Play* game_play, UNUSED CollisionCheck* colCheck) {
+}
+
+void CollisionCheck_clear(UNUSED struct Game_Play* game_play, CollisionCheck* colCheck) {
+ ClObj** clP;
+
+ if (colCheck->flags & COLCHECK_FLAG_1) {
+ return;
+ }
+
+ colCheck->ocColCount = 0;
+ for (clP = colCheck->ocColliders; clP < &colCheck->ocColliders[ARRAY_COUNT(colCheck->ocColliders)]; clP++) {
+ *clP = NULL;
+ }
+
+ mco_work.count = 0;
+ for (clP = mco_work.coliders; clP < &mco_work.coliders[ARRAY_COUNT(mco_work.coliders)]; clP++) {
+ *clP = NULL;
+ }
+}
+
+ClearFunc OCClearFunctionTable[COLSHAPE_MAX] = {
+ ClObjJntSph_OCClear, // COLSHAPE_JNTSPH
+ ClObjPipe_OCClear, // COLSHAPE_PIPE
+ ClObjTris_OCClear, // COLSHAPE_TRIS
+};
+
+s32 CollisionCheck_setOC(struct Game_Play* game_play, CollisionCheck* colCheck, ClObj* cl) {
+ s32 index;
+
+ if (_Game_play_isPause(game_play) == 1) {
+ return -1;
+ }
+
+ OCClearFunctionTable[cl->prop.shape](game_play, cl);
+
+ if ((cl->actor != NULL) && (cl->actor->update == NULL)) {
+ return -1;
+ }
+
+ if (colCheck->ocColCount >= ARRAY_COUNT(colCheck->ocColliders)) {
+ return -1;
+ }
+
+ if (colCheck->flags & COLCHECK_FLAG_1) {
+ return -1;
+ }
+
+ index = colCheck->ocColCount;
+ colCheck->ocColliders[colCheck->ocColCount] = cl;
+ colCheck->ocColCount++;
+
+ return index;
+}
+
+ColMassType get_type(u8 mass) {
+ if (mass == MASS_IMMOVABLE) {
+ return MASSTYPE_IMMOVABLE;
+ }
+
+ if (mass == MASS_HEAVY) {
+ return MASSTYPE_HEAVY;
+ }
+
+ return MASSTYPE_NORMAL;
+}
+
+void CollisionCheck_setOC_HitInfo(ClObj* cl1, ClObjElem* clElem1, Vec3f* pos1, ClObj* cl2, ClObjElem* clElem2,
+ Vec3f* pos2, f32 overlap) {
+ f32 zDelta;
+ f32 massInverse;
+ f32 xDelta;
+ f32 xzDist;
+ f32 displacementRatio2;
+ f32 mass1;
+ f32 totalMass;
+ f32 mass2;
+ f32 displacementRatio1;
+ UNUSED s32 pad;
+ Actor* actor1 = cl1->actor;
+ Actor* actor2 = cl2->actor;
+ ColMassType massType2;
+ ColMassType massType1;
+
+ cl1->oc = actor2;
+ cl1->prop.ocFlags1 |= OC1_2;
+ clElem1->flags |= ELEM_FLAG_2;
+
+ if (cl2->prop.ocFlags2 & OC2_TYPE_8) {
+ cl1->prop.ocFlags2 |= OC2_1;
+ }
+
+ cl2->oc = actor1;
+ cl2->prop.ocFlags1 |= OC1_2;
+ clElem2->flags |= ELEM_FLAG_2;
+ if (cl1->prop.ocFlags2 & OC2_TYPE_8) {
+ cl2->prop.ocFlags2 |= OC2_1;
+ }
+
+ if ((actor1 == NULL) || (actor2 == NULL) || (cl1->prop.ocFlags1 & OC1_4) || (cl2->prop.ocFlags1 & OC1_4)) {
+ return;
+ }
+
+ massType1 = get_type(actor1->colStatus.mass);
+ massType2 = get_type(actor2->colStatus.mass);
+
+ mass1 = actor1->colStatus.mass;
+ mass2 = actor2->colStatus.mass;
+
+ totalMass = mass1 + mass2;
+ if (IS_ZERO(totalMass)) {
+ mass1 = mass2 = 1.0f;
+ totalMass = 2.0f;
+ }
+
+ xDelta = pos2->x - pos1->x;
+ zDelta = pos2->z - pos1->z;
+ xzDist = sqrtf(SQ(xDelta) + SQ(zDelta));
+
+ if (massType1 == MASSTYPE_IMMOVABLE) {
+ if (massType2 == MASSTYPE_IMMOVABLE) {
+ return;
+ }
+ displacementRatio1 = 0.0f;
+ displacementRatio2 = 1.0f;
+ } else if (massType1 == MASSTYPE_HEAVY) {
+ if (massType2 == MASSTYPE_IMMOVABLE) {
+ displacementRatio1 = 1.0f;
+ displacementRatio2 = 0.0f;
+ } else if (massType2 == MASSTYPE_HEAVY) {
+ displacementRatio1 = 0.5f;
+ displacementRatio2 = 0.5f;
+ } else {
+ displacementRatio1 = 0.0f;
+ displacementRatio2 = 1.0f;
+ }
+ } else {
+ if (massType2 == MASSTYPE_NORMAL) {
+ massInverse = 1.0f / totalMass;
+ displacementRatio1 = mass2 * massInverse;
+ displacementRatio2 = mass1 * massInverse;
+ } else {
+ displacementRatio1 = 1.0f;
+ displacementRatio2 = 0.0f;
+ }
+ }
+
+ if (cl1->prop.ocFlags1 & OC1_40) {
+ displacementRatio1 = 0.0f;
+ displacementRatio2 = 1.0f;
+ actor2->speed = 0.0f;
+ } else if (cl2->prop.ocFlags1 & OC1_40) {
+ displacementRatio1 = 1.0f;
+ displacementRatio2 = 0.0f;
+ actor1->speed = 0.0f;
+ }
+
+ if (!IS_ZERO(xzDist)) {
+ xDelta *= overlap / xzDist;
+ zDelta *= overlap / xzDist;
+
+ actor1->colStatus.displacement.x += -xDelta * displacementRatio1;
+ actor1->colStatus.displacement.z += -zDelta * displacementRatio1;
+ actor2->colStatus.displacement.x += xDelta * displacementRatio2;
+ actor2->colStatus.displacement.z += zDelta * displacementRatio2;
+ } else if (overlap != 0.0f) {
+ actor1->colStatus.displacement.x += -overlap * displacementRatio1;
+ actor2->colStatus.displacement.x += overlap * displacementRatio2;
+ } else {
+ actor1->colStatus.displacement.x -= displacementRatio1;
+ actor2->colStatus.displacement.x += displacementRatio2;
+ }
+}
+
+void CollisionCheck_OC_JntSph_Vs_JntSph(UNUSED struct Game_Play* game_play, UNUSED CollisionCheck* colCheck, ClObj* cl1,
+ ClObj* cl2) {
+ ClObjJntSph* jntSph1 = (ClObjJntSph*)cl1;
+ ClObjJntSph* jntSph2 = (ClObjJntSph*)cl2;
+ ClObjJntSphElem* elem1;
+ ClObjJntSphElem* elem2;
+
+ if ((jntSph1->count <= 0) || (jntSph1->elements == NULL) || (jntSph2->count <= 0) || (jntSph2->elements == NULL)) {
+ return;
+ }
+
+ for (elem1 = jntSph1->elements; elem1 < &jntSph1->elements[jntSph1->count]; elem1++) {
+ if (!(elem1->elem.flags & ELEM_FLAG_1)) {
+ continue;
+ }
+
+ for (elem2 = jntSph2->elements; elem2 < &jntSph2->elements[jntSph2->count]; elem2++) {
+ f32 overlap;
+
+ if (!(elem2->elem.flags & ELEM_FLAG_1)) {
+ continue;
+ }
+
+ if (Math3D_sphereCrossSphere_cl(&elem1->attr.unk_08, &elem2->attr.unk_08, &overlap) == 1) {
+ Vec3f pos1;
+ Vec3f pos2;
+
+ xyz_t_move_s_xyz(&pos1, &elem1->attr.unk_08.center);
+ xyz_t_move_s_xyz(&pos2, &elem2->attr.unk_08.center);
+ CollisionCheck_setOC_HitInfo(&jntSph1->base, &elem1->elem, &pos1, &jntSph2->base, &elem2->elem, &pos2,
+ overlap);
+ }
+ }
+ }
+}
+
+void CollisionCheck_OC_JntSph_Vs_Pipe(UNUSED struct Game_Play* game_play, UNUSED CollisionCheck* colCheck, ClObj* cl1,
+ ClObj* cl2) {
+ ClObjJntSph* colJntSph = (ClObjJntSph*)cl1;
+ ClObjPipe* colPipe = (ClObjPipe*)cl2;
+ ClObjJntSphElem* sphElem;
+
+ if ((colJntSph->count <= 0) || (colJntSph->elements == NULL)) {
+ return;
+ }
+
+ if (!(colJntSph->base.prop.ocFlags1 & OC1_1) || !(colPipe->base.prop.ocFlags1 & OC1_1) ||
+ !(colPipe->element.flags & ELEM_FLAG_1)) {
+ return;
+ }
+
+ for (sphElem = colJntSph->elements; sphElem < &colJntSph->elements[colJntSph->count]; sphElem++) {
+ f32 overlap;
+
+ if (!(sphElem->elem.flags & ELEM_FLAG_1)) {
+ continue;
+ }
+
+ if (Math3D_sphereVsPipe_cl(&sphElem->attr.unk_08, &colPipe->attribute.dim, &overlap) == 1) {
+ Vec3f sphPos;
+ Vec3f pipePos;
+
+ xyz_t_move_s_xyz(&sphPos, &sphElem->attr.unk_08.center);
+ xyz_t_move_s_xyz(&pipePos, &colPipe->attribute.dim.pos);
+ CollisionCheck_setOC_HitInfo(&colJntSph->base, &sphElem->elem, &sphPos, &colPipe->base, &colPipe->element,
+ &pipePos, overlap);
+ }
+ }
+}
+
+void CollisionCheck_OC_Pipe_Vs_JntSph(struct Game_Play* game_play, CollisionCheck* colCheck, ClObj* cl1, ClObj* cl2) {
+ CollisionCheck_OC_JntSph_Vs_Pipe(game_play, colCheck, cl2, cl1);
+}
+
+void CollisionCheck_OC_Pipe_Vs_Pipe(UNUSED struct Game_Play* game_play, UNUSED CollisionCheck* colCheck, ClObj* cl1,
+ ClObj* cl2) {
+ ClObjPipe* pipe1 = (ClObjPipe*)cl1;
+ ClObjPipe* pipe2 = (ClObjPipe*)cl2;
+ f32 overlap;
+ Vec3f pos1;
+ Vec3f pos2;
+
+ if ((!(pipe1->base.prop.ocFlags1 & OC1_1) || !(pipe2->base.prop.ocFlags1 & OC1_1) ||
+ !(pipe1->element.flags & ELEM_FLAG_1) || !(pipe2->element.flags & ELEM_FLAG_1))) {
+ return;
+ }
+
+ if (Math3D_pipeVsPipe_cl(&pipe1->attribute.dim, &pipe2->attribute.dim, &overlap) != 1) {
+ return;
+ }
+
+ xyz_t_move_s_xyz(&pos1, &pipe1->attribute.dim.pos);
+ xyz_t_move_s_xyz(&pos2, &pipe2->attribute.dim.pos);
+ CollisionCheck_setOC_HitInfo(&pipe1->base, &pipe1->element, &pos1, &pipe2->base, &pipe2->element, &pos2, overlap);
+}
+
+s32 CollisionCheck_Check1ClObjNoOC(ClObj* cl) {
+ if (!(cl->prop.ocFlags1 & OC1_1)) {
+ return 1;
+ }
+ return 0;
+}
+
+s32 CollisionCheck_Check2ClObjNoOC(ClObj* cl1, ClObj* cl2) {
+ if (!(cl1->prop.ocFlags1 & cl2->prop.ocFlags2 & OC1_TYPE_ALL) ||
+ !(cl1->prop.ocFlags2 & cl2->prop.ocFlags1 & OC1_TYPE_ALL)) {
+ return 1;
+ }
+ if (cl1->actor == cl2->actor) {
+ return 1;
+ }
+ return 0;
+}
+
+CollisionVsFunc oc_collision_function[COLSHAPE_MAX][COLSHAPE_MAX] = {
+ { CollisionCheck_OC_JntSph_Vs_JntSph, CollisionCheck_OC_JntSph_Vs_Pipe, NULL }, // COLSHAPE_JNTSPH
+ { CollisionCheck_OC_Pipe_Vs_JntSph, CollisionCheck_OC_Pipe_Vs_Pipe, NULL }, // COLSHAPE_PIPE
+ { NULL, NULL, NULL }, // COLSHAPE_TRIS
+};
+
+void CollisionCheck_OC(struct Game_Play* game_play, CollisionCheck* colCheck) {
+ ClObj** cl1P;
+
+ for (cl1P = colCheck->ocColliders; cl1P < &colCheck->ocColliders[colCheck->ocColCount]; cl1P++) {
+ ClObj** cl2P;
+
+ if ((*cl1P == NULL) || (CollisionCheck_Check1ClObjNoOC(*cl1P) == 1)) {
+ continue;
+ }
+
+ for (cl2P = cl1P + 1; cl2P < &colCheck->ocColliders[colCheck->ocColCount]; cl2P++) {
+ CollisionVsFunc func;
+
+ if ((*cl2P == NULL) || (CollisionCheck_Check1ClObjNoOC(*cl2P) == 1) ||
+ (CollisionCheck_Check2ClObjNoOC(*cl1P, *cl2P) == 1)) {
+ continue;
+ }
+
+ func = oc_collision_function[(*cl1P)->prop.shape][(*cl2P)->prop.shape];
+ if (func == NULL) {
+ continue;
+ }
+
+ func(game_play, colCheck, *cl1P, *cl2P);
+ }
+ }
+
+ CollisionCheck_OCC(game_play, colCheck);
+}
+
+void CollisionCheck_setOCC_HitInfo(UNUSED struct Game_Play* game_play, ClObj* cl1, ClObjTrisElem* trisElem,
+ UNUSED Vec3f* arg3, ClObj* cl2, UNUSED ClObjElem* arg5, UNUSED Vec3f* arg6,
+ Vec3f* arg7) {
+ cl1->oc = cl2->actor;
+ cl1->prop.ocFlags2 |= OC2_4;
+
+ trisElem->attr.unk_34.x = arg7->x;
+ trisElem->attr.unk_34.y = arg7->y;
+ trisElem->attr.unk_34.z = arg7->z;
+}
+
+void CollisionCheck_OCC_Tris_Vs_JntSph(struct Game_Play* game_play, UNUSED CollisionCheck* arg1, ClObj* cl1,
+ ClObj* cl2) {
+ ClObjJntSphElem* sphElem;
+ ClObjTris* colTris = (ClObjTris*)cl1;
+ ClObjJntSph* colJntSph = (ClObjJntSph*)cl2;
+
+ if ((colTris->count <= 0) || (colTris->elements == NULL) || (colJntSph->count <= 0) ||
+ (colJntSph->elements == NULL)) {
+ return;
+ }
+
+ for (sphElem = colJntSph->elements; sphElem < &colJntSph->elements[colJntSph->count]; sphElem++) {
+ ClObjTrisElem* trisElem;
+ Vec3f sp74;
+
+ if (!(sphElem->elem.flags & ELEM_FLAG_1)) {
+ continue;
+ }
+
+ for (trisElem = colTris->elements; trisElem < &colTris->elements[colTris->count]; trisElem++) {
+ if (Math3D_sphereCrossTriangle3_cp(&sphElem->attr.unk_08, &trisElem->attr.unk_00, &sp74) != 0) {
+ Vec3f sphPos;
+ Vec3f trisPos;
+
+ xyz_t_move_s_xyz(&sphPos, &sphElem->attr.unk_08.center);
+ CollisionCheck_workTrisElemCenter(trisElem, &trisPos);
+ CollisionCheck_setOCC_HitInfo(game_play, &colTris->base, trisElem, &trisPos, &colJntSph->base,
+ &sphElem->elem, &sphPos, &sp74);
+ }
+ }
+ }
+}
+
+void CollisionCheck_OCC_Tris_Vs_Pipe(struct Game_Play* game_play, UNUSED CollisionCheck* colCheck, ClObj* cl1,
+ ClObj* cl2) {
+ ClObjTris* colTris = (ClObjTris*)cl1;
+ ClObjPipe* colPipe = (ClObjPipe*)cl2;
+ ClObjTrisElem* elem;
+
+ if ((colPipe->attribute.dim.radius <= 0) || (colPipe->attribute.dim.unk_2 <= 0) ||
+ !(colPipe->element.flags & ELEM_FLAG_1)) {
+ return;
+ }
+
+ if ((colTris->count <= 0) || (colTris->elements == NULL)) {
+ return;
+ }
+
+ for (elem = colTris->elements; elem < &colTris->elements[colTris->count]; elem++) {
+ Vec3f sp68;
+
+ if (Math3D_pipeCrossTriangle_cp(&colPipe->attribute.dim, &elem->attr.unk_00.unk_00, &sp68) != 0) {
+ Vec3f pipePos;
+ Vec3f trisPos;
+
+ CollisionCheck_workTrisElemCenter(elem, &trisPos);
+ xyz_t_move_s_xyz(&pipePos, &colPipe->attribute.dim.pos);
+ CollisionCheck_setOCC_HitInfo(game_play, &colTris->base, elem, &trisPos, &colPipe->base, &colPipe->element,
+ &pipePos, &sp68);
+ break;
+ }
+ }
+}
+
+s32 CollisionCheck_Check1ClObjNoOCC(ClObj* cl) {
+ if (!(cl->prop.ocFlags2 & OC2_2)) {
+ return 1;
+ }
+ return 0;
+}
+
+CollisionVsFunc occ_collision_function[COLSHAPE_MAX][COLSHAPE_MAX] = {
+ { NULL, NULL, NULL }, // COLSHAPE_JNTSPH
+ { NULL, NULL, NULL }, // COLSHAPE_PIPE
+ { CollisionCheck_OCC_Tris_Vs_JntSph, CollisionCheck_OCC_Tris_Vs_Pipe, NULL }, // COLSHAPE_TRIS
+};
+
+void CollisionCheck_OCC(struct Game_Play* game_play, CollisionCheck* colCheck) {
+ ClObj** cl1P;
+
+ if (mco_work.count == 0) {
+ return;
+ }
+
+ for (cl1P = mco_work.coliders; cl1P < &mco_work.coliders[mco_work.count]; cl1P++) {
+ ClObj** cl2P;
+
+ if ((*cl1P == NULL) || (CollisionCheck_Check1ClObjNoOCC(*cl1P) == 1)) {
+ continue;
+ }
+
+ for (cl2P = colCheck->ocColliders; cl2P < &colCheck->ocColliders[colCheck->ocColCount]; cl2P++) {
+ CollisionVsFunc func;
+
+ if ((*cl2P) == NULL) {
+ continue;
+ }
+
+ if ((*cl1P)->actor == (*cl2P)->actor) {
+ continue;
+ }
+
+ func = occ_collision_function[(*cl1P)->prop.shape][(*cl2P)->prop.shape];
+ if (func == NULL) {
+ continue;
+ }
+
+ func(game_play, colCheck, *cl1P, *cl2P);
+ }
+ }
+}
+
+s32 ClObjTrisElem_OCCClear(UNUSED struct Game_Play* game_play, ClObjTrisElem* arg1) {
+ arg1->attr.unk_34.x = 0.0f;
+ arg1->attr.unk_34.y = 0.0f;
+ arg1->attr.unk_34.z = 0.0f;
+ return 1;
+}
+
+void ClObj_OCCClear(UNUSED struct Game_Play* game_play, ClObj* arg1) {
+ arg1->oc = NULL;
+ arg1->prop.ocFlags2 &= ~OC2_4;
+}
+
+s32 ClObjTris_OCCClear(struct Game_Play* game_play, ClObj* cl) {
+ ClObjTris* colTris = (ClObjTris*)cl;
+ ClObjTrisElem* elem;
+
+ ClObj_OCCClear(game_play, &colTris->base);
+
+ for (elem = colTris->elements; elem < &colTris->elements[colTris->count]; elem++) {
+ ClObjTrisElem_OCCClear(game_play, elem);
+ }
+
+ return 1;
+}
+
+ClearFunc OCCClearFunctionTable[COLSHAPE_MAX] = {
+ NULL, // COLSHAPE_JNTSPH
+ NULL, // COLSHAPE_PIPE
+ ClObjTris_OCCClear, // COLSHAPE_TRIS
+};
+
+s32 CollisionCheck_setOCC(struct Game_Play* game_play, CollisionCheck* colCheck, ClObj* cl) {
+ s32 ret;
+
+ if (_Game_play_isPause(game_play) == 1) {
+ return -1;
+ }
+
+ if ((cl->prop.shape == COLSHAPE_JNTSPH) || (cl->prop.shape == COLSHAPE_PIPE)) {
+ return -1;
+ }
+
+ OCCClearFunctionTable[cl->prop.shape](game_play, cl);
+
+ if ((cl->actor != NULL) && (cl->actor->update == NULL)) {
+ return -1;
+ }
+
+ if (mco_work.count >= ARRAY_COUNT(mco_work.coliders)) {
+ return -1;
+ }
+
+ if (colCheck->flags & COLCHECK_FLAG_1) {
+ return -1;
+ }
+
+ ret = mco_work.count;
+ mco_work.coliders[mco_work.count] = cl;
+ mco_work.count++;
+
+ return ret;
+}
+
+CollisionCheck_Status status_org = { { 0.0f, 0.0f, 0.0f }, 0xA, 0xA, 0, 50, 8, 0, 0, 0, 0 };
+
+void CollisionCheck_Status_ct(CollisionCheck_Status* status) {
+ *status = status_org;
+}
+
+void CollisionCheck_Status_Clear(CollisionCheck_Status* status) {
+ status->unk_14 = 0;
+ status->unk_15 = 0;
+ status->unk_16 = 0;
+ status->unk_17 = 0;
+ status->displacement.z = 0.0f;
+ status->displacement.y = 0.0f;
+ status->displacement.x = 0.0f;
+}
+
+void CollisionCheck_Status_set3(CollisionCheck_Status* status, CollisionCheck_Status_Init* init) {
+ status->unk_13 = init->unk_0;
+ status->unk_0C = init->unk_2;
+ status->unk_0E = init->unk_4;
+ status->unk_10 = init->unk_6;
+ status->mass = init->mass;
+}
+
+void CollisionCheck_Uty_ActorWorldPosSetPipeC(Actor* actor, ClObjPipe* colPipe) {
+ colPipe->attribute.dim.pos.x = (s16)(s32)actor->world.pos.x;
+ colPipe->attribute.dim.pos.y = (s16)(s32)actor->world.pos.y;
+ colPipe->attribute.dim.pos.z = (s16)(s32)actor->world.pos.z;
+}
+
+s32 CollisionCheck_Uty_setTrisPos_ad(struct Game_Play* game_play, ClObjTris* colTris, s32 index,
+ ClObjTrisElemAttr_Init* init) {
+ ClObjTrisElem* temp = &colTris->elements[index];
+
+ return ClObjTrisElemAttr_set(game_play, &temp->attr, init);
+}