From 2d58bddd06410718ef3f457c746c34803a9ddbec Mon Sep 17 00:00:00 2001 From: Arceveti <73617174+Arceveti@users.noreply.github.com> Date: Sun, 5 Sep 2021 12:18:00 -0700 Subject: [PATCH] Add fix for obj_resolve_object_collisions --- include/config.h | 2 ++ src/engine/surface_load.c | 4 ++-- src/game/interaction.h | 3 +++ src/game/obj_behaviors_2.c | 32 +++++++++++++++++++++++++------- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/include/config.h b/include/config.h index 848112bb..0b0cf0bf 100644 --- a/include/config.h +++ b/include/config.h @@ -104,6 +104,8 @@ //#define PUPPYCAM // Automatically calculate the optimal collision distance for an object based on its vertices. #define AUTO_COLLISION_DISTANCE +// Makes obj_resolve_object_collisions work consistently +#define FIX_RESOLVE_OBJ_COLLISIONS // HACKER QOL diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index 601b8a54..c3fdb3cc 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -828,13 +828,13 @@ void load_object_collision_model(void) { #endif // If the object collision is supposed to be loaded more than the - // drawing distance of 4000, extend the drawing range. + // drawing distance, extend the drawing range. if (gCurrentObject->oCollisionDistance > gCurrentObject->oDrawingDistance) { gCurrentObject->oDrawingDistance = gCurrentObject->oCollisionDistance; } // Update if no Time Stop, in range, and in the current room. - if (!(gTimeStopState & TIME_STOP_ACTIVE) && marioDist < gCurrentObject->oCollisionDistance + if (!(gTimeStopState & TIME_STOP_ACTIVE) && (marioDist < gCurrentObject->oCollisionDistance) && !(gCurrentObject->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) { collisionData++; transform_object_vertices(&collisionData, vertexData); diff --git a/src/game/interaction.h b/src/game/interaction.h index 1b2457be..e601556a 100644 --- a/src/game/interaction.h +++ b/src/game/interaction.h @@ -38,6 +38,9 @@ #define INTERACT_IGLOO_BARRIER /* 0x40000000 */ (1 << 30) #define INTERACT_UNKNOWN_31 /* 0x80000000 */ (1 << 31) +#ifdef FIX_RESOLVE_OBJ_COLLISIONS +#define INTERACT_MASK_NO_OBJ_COLLISIONS (INTERACT_COIN | INTERACT_CAP | INTERACT_STRONG_WIND | INTERACT_STAR_OR_KEY | INTERACT_WARP | INTERACT_WATER_RING | INTERACT_FLAME) +#endif // INTERACT_WARP #define INT_SUBTYPE_FADING_WARP 0x00000001 diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index ae01edce..323074ea 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -549,16 +549,33 @@ static void obj_update_blinking(s32 *blinkTimer, s16 baseCycleLength, s16 cycleL static s32 obj_resolve_object_collisions(s32 *targetYaw) { struct Object *otherObject; - f32 dx; - f32 dz; + f32 dx, dz; s16 angle; - f32 radius; - f32 otherRadius; - f32 relativeRadius; - f32 newCenterX; - f32 newCenterZ; + f32 radius, otherRadius, relativeRadius; if (o->numCollidedObjs != 0) { +#ifdef FIX_RESOLVE_OBJ_COLLISIONS + s32 i; + for ((i = 0); (i < o->numCollidedObjs); (i++)) { + otherObject = o->collidedObjs[i]; + if (otherObject == gMarioObject) continue; + if (otherObject->oInteractType & INTERACT_MASK_NO_OBJ_COLLISIONS) continue; + dx = (o->oPosX - otherObject->oPosX); + dz = (o->oPosZ - otherObject->oPosZ); + radius = (( o->hurtboxRadius > 0) ? o->hurtboxRadius : o->hitboxRadius); + otherRadius = ((otherObject->hurtboxRadius > 0) ? otherObject->hurtboxRadius : otherObject->hitboxRadius); + relativeRadius = (radius + otherRadius); + if ((sqr(dx) + sqr(dz)) > sqr(relativeRadius)) continue; + angle = atan2s(dz, dx); + o->oPosX = (otherObject->oPosX + (relativeRadius * sins(angle))); + o->oPosZ = (otherObject->oPosZ + (relativeRadius * coss(angle))); + if ((targetYaw != NULL) && (abs_angle_diff(o->oMoveAngleYaw, angle) < 0x4000)) { + *targetYaw = (s16)((angle - o->oMoveAngleYaw) + angle + 0x8000); + return TRUE; + } + } +#else + f32 newCenterX, newCenterZ; otherObject = o->collidedObjs[0]; if (otherObject != gMarioObject) { //! If one object moves after collisions are detected and this code @@ -588,6 +605,7 @@ static s32 obj_resolve_object_collisions(s32 *targetYaw) { return TRUE; } } +#endif } return FALSE;