From 48f42d1873c6e528a35668af9d658ef87fa061c1 Mon Sep 17 00:00:00 2001 From: MysterD Date: Wed, 12 Aug 2020 19:14:35 -0700 Subject: [PATCH] Fixed visual bug when both players are sliding --- build-windows-visual-studio/sm64ex.vcxproj | 3 ++ include/types.h | 2 +- src/engine/surface_collision.c | 50 +++++++++++----------- src/engine/surface_load.c | 1 + src/game/interaction.c | 2 + src/game/mario.c | 7 ++- src/game/mario_actions_moving.c | 4 +- src/pc/network/packets/packet_player.c | 2 + 8 files changed, 43 insertions(+), 28 deletions(-) diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index 958a3f55..694e25d1 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -493,6 +493,9 @@ + + + diff --git a/include/types.h b/include/types.h index 9408a75c..dc819d0a 100644 --- a/include/types.h +++ b/include/types.h @@ -303,7 +303,7 @@ struct MarioAnimation struct MarioState { - /*0x00*/ u16 unk00; + /*0x00*/ u16 playerIndex; /*0x02*/ u16 input; /*0x04*/ u32 flags; /*0x08*/ u32 particleFlags; diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 2c11e254..b298f752 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -130,9 +130,11 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, } // If Mario has a vanish cap, pass through the vanish cap wall. - if (gCurrentObject != NULL && gCurrentObject == gMarioObject - && (gMarioState->flags & MARIO_VANISH_CAP)) { - continue; + for (int i = 0; i < MAX_PLAYERS; i++) { + if (gCurrentObject != NULL && gCurrentObject == gMarioStates[i].marioObj + && (gMarioStates[i].flags & MARIO_VANISH_CAP)) { + continue; + } } } } @@ -837,40 +839,40 @@ s32 ray_surface_intersect(Vec3f orig, Vec3f dir, f32 dir_length, struct Surface Vec3f v0, v1, v2, e1, e2, h, s, q; f32 a, f, u, v; Vec3f add_dir; - + // Get surface normal and some other stuff vec3s_to_vec3f(v0, surface->vertex1); vec3s_to_vec3f(v1, surface->vertex2); vec3s_to_vec3f(v2, surface->vertex3); - + vec3f_dif(e1, v1, v0); vec3f_dif(e2, v2, v0); - + vec3f_cross(h, dir, e2); - + // Check if we're perpendicular from the surface a = vec3f_dot(e1, h); if (a > -0.00001f && a < 0.00001f) return FALSE; - + // Check if we're making contact with the surface f = 1.0f / a; - + vec3f_dif(s, orig, v0); u = f * vec3f_dot(s, h); if (u < 0.0f || u > 1.0f) return FALSE; - + vec3f_cross(q, s, e1); v = f * vec3f_dot(dir, q); if (v < 0.0f || u + v > 1.0f) return FALSE; - + // Get the length between our origin and the surface contact point *length = f * vec3f_dot(e2, q); if (*length <= 0.00001 || *length > dir_length) return FALSE; - + // Successful contact vec3f_copy(add_dir, dir); vec3f_mul(add_dir, *length); @@ -884,7 +886,7 @@ void find_surface_on_ray_list(struct SurfaceNode *list, Vec3f orig, Vec3f dir, f f32 length; Vec3f chk_hit_pos; f32 top, bottom; - + // Get upper and lower bounds of ray if (dir[1] >= 0.0f) { @@ -896,17 +898,17 @@ void find_surface_on_ray_list(struct SurfaceNode *list, Vec3f orig, Vec3f dir, f top = orig[1]; bottom = orig[1] + dir[1] * dir_length; } - + // Iterate through every surface of the list for (; list != NULL; list = list->next) { // Reject surface if out of vertical bounds if (list->surface->lowerY > top || list->surface->upperY < bottom) continue; - + // Check intersection between the ray and this surface if ((hit = ray_surface_intersect(orig, dir, dir_length, list->surface, chk_hit_pos, &length)) != 0) - { + { if (length <= *max_length) { *hit_surface = list->surface; @@ -948,43 +950,43 @@ void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Ve Vec3f normalized_dir; f32 step, dx, dz; u32 i; - + // Set that no surface has been hit *hit_surface = NULL; vec3f_sum(hit_pos, orig, dir); - + // Get normalized direction dir_length = vec3f_length(dir); max_length = dir_length; vec3f_copy(normalized_dir, dir); vec3f_normalize(normalized_dir); - + // Get our cell coordinate fCellX = (orig[0] + LEVEL_BOUNDARY_MAX) / CELL_SIZE; fCellZ = (orig[2] + LEVEL_BOUNDARY_MAX) / CELL_SIZE; cellX = (s16)fCellX; cellZ = (s16)fCellZ; - + // Don't do DDA if straight down if (normalized_dir[1] >= 1.0f || normalized_dir[1] <= -1.0f) { find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length); return; } - + // Get cells we cross using DDA if (absx(dir[0]) >= absx(dir[2])) step = absx(dir[0]) / CELL_SIZE; else step = absx(dir[2]) / CELL_SIZE; - + dx = dir[0] / step / CELL_SIZE; dz = dir[2] / step / CELL_SIZE; - + for (i = 0; i < step && *hit_surface == NULL; i++) { find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length); - + // Move cell coordinate fCellX += dx; fCellZ += dz; diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index f42ab041..a19667f3 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -773,6 +773,7 @@ void load_object_collision_model(void) { if (gCurrentObject->oDistanceToMario == 19000.0f) { marioDist = dist_between_objects(gCurrentObject, gMarioObject); } + // two-player hack mario2Dist = dist_between_objects(gCurrentObject, gMario2Object); // If the object collision is supposed to be loaded more than the diff --git a/src/game/interaction.c b/src/game/interaction.c index 67f1afbf..63193f80 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -289,6 +289,7 @@ void mario_grab_used_object(struct MarioState *m) { if (m->usedObj == NULL || m->usedObj->oHeldState == HELD_HELD) { return; } if (m->heldObj == NULL) { m->heldObj = m->usedObj; + // two-player hack m->heldObj->heldByPlayerIndex = (m == &gMarioStates[0]) ? 0 : 1; obj_set_held_state(m->heldObj, bhvCarrySomething3); } @@ -709,6 +710,7 @@ u32 take_damage_from_interact_object(struct MarioState *m) { } int get_invincibility_flag(struct MarioState *m) { + // two-player hack return (m == &gMarioStates[0]) ? INT_SUBTYPE_DELAY_INVINCIBILITY : INT_SUBTYPE_DELAY_INVINCIBILITY_MARIO2; diff --git a/src/game/mario.c b/src/game/mario.c index 50deae43..4d837d21 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1862,6 +1862,9 @@ void init_mario(void) { if (isLocal && gMarioObject == NULL) { goto skippy; } if (!isLocal && gMario2Object == NULL) { goto skippy; } + // two-player hack + gMarioState->playerIndex = isLocal ? 0 : 1; + Vec3s capPos; struct Object *capObject; @@ -1898,6 +1901,7 @@ void init_mario(void) { find_water_level(gMarioSpawnInfo->startPos[0], gMarioSpawnInfo->startPos[2]); gMarioState->area = gCurrentArea; + // two-player hack gMarioState->marioObj = isLocal ? gMarioObject : gMario2Object; gMarioState->marioObj->header.gfx.unk38.animID = -1; vec3s_copy(gMarioState->faceAngle, gMarioSpawnInfo->startAngle); @@ -1961,7 +1965,8 @@ skippy: void init_mario_from_save_file(void) { bool isLocal = (gMarioState == &gMarioStates[0]); - gMarioState->unk00 = isLocal ? 0 : 1; + // two-player hack + gMarioState->playerIndex = isLocal ? 0 : 1; gMarioState->flags = 0; gMarioState->action = 0; int i = isLocal ? 0 : 1; diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index 30aba6a3..e0244146 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -89,8 +89,8 @@ void play_step_sound(struct MarioState *m, s16 frame1, s16 frame2) { void align_with_floor(struct MarioState *m) { m->pos[1] = m->floorHeight; - mtxf_align_terrain_triangle(sFloorAlignMatrix[m->unk00], m->pos, m->faceAngle[1], 40.0f); - m->marioObj->header.gfx.throwMatrix = &sFloorAlignMatrix[m->unk00]; + mtxf_align_terrain_triangle(sFloorAlignMatrix[m->playerIndex], m->pos, m->faceAngle[1], 40.0f); + m->marioObj->header.gfx.throwMatrix = &sFloorAlignMatrix[m->playerIndex]; } s32 begin_walking_action(struct MarioState *m, f32 forwardVel, u32 action, u32 actionArg) { diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 99062755..1731c059 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -30,6 +30,7 @@ void network_receive_player(struct Packet* p) { u32 heldSyncID = NULL; u32 heldBySyncID = NULL; + u16 playerIndex = gMarioStates[1].playerIndex; packet_read(p, &gMarioStates[1], sizeof(u32) * 24); packet_read(p, gMarioStates[1].controller, 20); packet_read(p, &gMarioStates[1].marioObj->rawData.asU32, sizeof(u32) * 80); @@ -37,6 +38,7 @@ void network_receive_player(struct Packet* p) { packet_read(p, &gMarioStates[1].marioObj->header.gfx.node.flags, sizeof(s16)); packet_read(p, &heldSyncID, sizeof(u32)); packet_read(p, &heldBySyncID, sizeof(u32)); + gMarioStates[1].playerIndex = playerIndex; if (heldSyncID != NULL && syncObjects[heldSyncID].o != NULL) { // TODO: do we have to move graphics nodes around to make this visible?