Fixed visual bug when both players are sliding

This commit is contained in:
MysterD 2020-08-12 19:14:35 -07:00
parent bdf269c262
commit 48f42d1873
8 changed files with 43 additions and 28 deletions

View File

@ -493,6 +493,9 @@
<ClCompile Include="..\actors\lakitu_enemy\model.inc.c" />
<ClCompile Include="..\actors\leaves\geo.inc.c" />
<ClCompile Include="..\actors\leaves\model.inc.c" />
<ClCompile Include="..\actors\luigi\geo.inc.c" />
<ClCompile Include="..\actors\luigi\geo2.inc.c" />
<ClCompile Include="..\actors\luigi\model.inc.c" />
<ClCompile Include="..\actors\mad_piano\anims\anim_05009A04.inc.c" />
<ClCompile Include="..\actors\mad_piano\anims\anim_05009AFC.inc.c" />
<ClCompile Include="..\actors\mad_piano\anims\data.inc.c" />

View File

@ -303,7 +303,7 @@ struct MarioAnimation
struct MarioState
{
/*0x00*/ u16 unk00;
/*0x00*/ u16 playerIndex;
/*0x02*/ u16 input;
/*0x04*/ u32 flags;
/*0x08*/ u32 particleFlags;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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?