diff options
| author | Anghelo Carvajal <angheloalf95@gmail.com> | 2023-08-21 15:19:33 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-21 12:19:33 -0700 |
| commit | 4a8731d40ad81cb9356bdba23e4aec772328214e (patch) | |
| tree | 907c70ef7ffdcf5ac0dd3305c29d6caf7c9d4f22 /src/code | |
| parent | 74ba3014c974ae9a260d6485be71258310edb59a (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')
| -rw-r--r-- | src/code/m_collision_obj.c | 899 |
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); +} |
