mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Fixed visual bug when both players are sliding
This commit is contained in:
parent
bdf269c262
commit
48f42d1873
8 changed files with 43 additions and 28 deletions
|
|
@ -493,6 +493,9 @@
|
||||||
<ClCompile Include="..\actors\lakitu_enemy\model.inc.c" />
|
<ClCompile Include="..\actors\lakitu_enemy\model.inc.c" />
|
||||||
<ClCompile Include="..\actors\leaves\geo.inc.c" />
|
<ClCompile Include="..\actors\leaves\geo.inc.c" />
|
||||||
<ClCompile Include="..\actors\leaves\model.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_05009A04.inc.c" />
|
||||||
<ClCompile Include="..\actors\mad_piano\anims\anim_05009AFC.inc.c" />
|
<ClCompile Include="..\actors\mad_piano\anims\anim_05009AFC.inc.c" />
|
||||||
<ClCompile Include="..\actors\mad_piano\anims\data.inc.c" />
|
<ClCompile Include="..\actors\mad_piano\anims\data.inc.c" />
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ struct MarioAnimation
|
||||||
|
|
||||||
struct MarioState
|
struct MarioState
|
||||||
{
|
{
|
||||||
/*0x00*/ u16 unk00;
|
/*0x00*/ u16 playerIndex;
|
||||||
/*0x02*/ u16 input;
|
/*0x02*/ u16 input;
|
||||||
/*0x04*/ u32 flags;
|
/*0x04*/ u32 flags;
|
||||||
/*0x08*/ u32 particleFlags;
|
/*0x08*/ u32 particleFlags;
|
||||||
|
|
|
||||||
|
|
@ -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 Mario has a vanish cap, pass through the vanish cap wall.
|
||||||
if (gCurrentObject != NULL && gCurrentObject == gMarioObject
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||||
&& (gMarioState->flags & MARIO_VANISH_CAP)) {
|
if (gCurrentObject != NULL && gCurrentObject == gMarioStates[i].marioObj
|
||||||
continue;
|
&& (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;
|
Vec3f v0, v1, v2, e1, e2, h, s, q;
|
||||||
f32 a, f, u, v;
|
f32 a, f, u, v;
|
||||||
Vec3f add_dir;
|
Vec3f add_dir;
|
||||||
|
|
||||||
// Get surface normal and some other stuff
|
// Get surface normal and some other stuff
|
||||||
vec3s_to_vec3f(v0, surface->vertex1);
|
vec3s_to_vec3f(v0, surface->vertex1);
|
||||||
vec3s_to_vec3f(v1, surface->vertex2);
|
vec3s_to_vec3f(v1, surface->vertex2);
|
||||||
vec3s_to_vec3f(v2, surface->vertex3);
|
vec3s_to_vec3f(v2, surface->vertex3);
|
||||||
|
|
||||||
vec3f_dif(e1, v1, v0);
|
vec3f_dif(e1, v1, v0);
|
||||||
vec3f_dif(e2, v2, v0);
|
vec3f_dif(e2, v2, v0);
|
||||||
|
|
||||||
vec3f_cross(h, dir, e2);
|
vec3f_cross(h, dir, e2);
|
||||||
|
|
||||||
// Check if we're perpendicular from the surface
|
// Check if we're perpendicular from the surface
|
||||||
a = vec3f_dot(e1, h);
|
a = vec3f_dot(e1, h);
|
||||||
if (a > -0.00001f && a < 0.00001f)
|
if (a > -0.00001f && a < 0.00001f)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// Check if we're making contact with the surface
|
// Check if we're making contact with the surface
|
||||||
f = 1.0f / a;
|
f = 1.0f / a;
|
||||||
|
|
||||||
vec3f_dif(s, orig, v0);
|
vec3f_dif(s, orig, v0);
|
||||||
u = f * vec3f_dot(s, h);
|
u = f * vec3f_dot(s, h);
|
||||||
if (u < 0.0f || u > 1.0f)
|
if (u < 0.0f || u > 1.0f)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
vec3f_cross(q, s, e1);
|
vec3f_cross(q, s, e1);
|
||||||
v = f * vec3f_dot(dir, q);
|
v = f * vec3f_dot(dir, q);
|
||||||
if (v < 0.0f || u + v > 1.0f)
|
if (v < 0.0f || u + v > 1.0f)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// Get the length between our origin and the surface contact point
|
// Get the length between our origin and the surface contact point
|
||||||
*length = f * vec3f_dot(e2, q);
|
*length = f * vec3f_dot(e2, q);
|
||||||
if (*length <= 0.00001 || *length > dir_length)
|
if (*length <= 0.00001 || *length > dir_length)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// Successful contact
|
// Successful contact
|
||||||
vec3f_copy(add_dir, dir);
|
vec3f_copy(add_dir, dir);
|
||||||
vec3f_mul(add_dir, *length);
|
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;
|
f32 length;
|
||||||
Vec3f chk_hit_pos;
|
Vec3f chk_hit_pos;
|
||||||
f32 top, bottom;
|
f32 top, bottom;
|
||||||
|
|
||||||
// Get upper and lower bounds of ray
|
// Get upper and lower bounds of ray
|
||||||
if (dir[1] >= 0.0f)
|
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];
|
top = orig[1];
|
||||||
bottom = orig[1] + dir[1] * dir_length;
|
bottom = orig[1] + dir[1] * dir_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through every surface of the list
|
// Iterate through every surface of the list
|
||||||
for (; list != NULL; list = list->next)
|
for (; list != NULL; list = list->next)
|
||||||
{
|
{
|
||||||
// Reject surface if out of vertical bounds
|
// Reject surface if out of vertical bounds
|
||||||
if (list->surface->lowerY > top || list->surface->upperY < bottom)
|
if (list->surface->lowerY > top || list->surface->upperY < bottom)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check intersection between the ray and this surface
|
// 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 ((hit = ray_surface_intersect(orig, dir, dir_length, list->surface, chk_hit_pos, &length)) != 0)
|
||||||
{
|
{
|
||||||
if (length <= *max_length)
|
if (length <= *max_length)
|
||||||
{
|
{
|
||||||
*hit_surface = list->surface;
|
*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;
|
Vec3f normalized_dir;
|
||||||
f32 step, dx, dz;
|
f32 step, dx, dz;
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
// Set that no surface has been hit
|
// Set that no surface has been hit
|
||||||
*hit_surface = NULL;
|
*hit_surface = NULL;
|
||||||
vec3f_sum(hit_pos, orig, dir);
|
vec3f_sum(hit_pos, orig, dir);
|
||||||
|
|
||||||
// Get normalized direction
|
// Get normalized direction
|
||||||
dir_length = vec3f_length(dir);
|
dir_length = vec3f_length(dir);
|
||||||
max_length = dir_length;
|
max_length = dir_length;
|
||||||
vec3f_copy(normalized_dir, dir);
|
vec3f_copy(normalized_dir, dir);
|
||||||
vec3f_normalize(normalized_dir);
|
vec3f_normalize(normalized_dir);
|
||||||
|
|
||||||
// Get our cell coordinate
|
// Get our cell coordinate
|
||||||
fCellX = (orig[0] + LEVEL_BOUNDARY_MAX) / CELL_SIZE;
|
fCellX = (orig[0] + LEVEL_BOUNDARY_MAX) / CELL_SIZE;
|
||||||
fCellZ = (orig[2] + LEVEL_BOUNDARY_MAX) / CELL_SIZE;
|
fCellZ = (orig[2] + LEVEL_BOUNDARY_MAX) / CELL_SIZE;
|
||||||
cellX = (s16)fCellX;
|
cellX = (s16)fCellX;
|
||||||
cellZ = (s16)fCellZ;
|
cellZ = (s16)fCellZ;
|
||||||
|
|
||||||
// Don't do DDA if straight down
|
// Don't do DDA if straight down
|
||||||
if (normalized_dir[1] >= 1.0f || normalized_dir[1] <= -1.0f)
|
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);
|
find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get cells we cross using DDA
|
// Get cells we cross using DDA
|
||||||
if (absx(dir[0]) >= absx(dir[2]))
|
if (absx(dir[0]) >= absx(dir[2]))
|
||||||
step = absx(dir[0]) / CELL_SIZE;
|
step = absx(dir[0]) / CELL_SIZE;
|
||||||
else
|
else
|
||||||
step = absx(dir[2]) / CELL_SIZE;
|
step = absx(dir[2]) / CELL_SIZE;
|
||||||
|
|
||||||
dx = dir[0] / step / CELL_SIZE;
|
dx = dir[0] / step / CELL_SIZE;
|
||||||
dz = dir[2] / step / CELL_SIZE;
|
dz = dir[2] / step / CELL_SIZE;
|
||||||
|
|
||||||
for (i = 0; i < step && *hit_surface == NULL; i++)
|
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);
|
find_surface_on_ray_cell(cellX, cellZ, orig, normalized_dir, dir_length, hit_surface, hit_pos, &max_length);
|
||||||
|
|
||||||
// Move cell coordinate
|
// Move cell coordinate
|
||||||
fCellX += dx;
|
fCellX += dx;
|
||||||
fCellZ += dz;
|
fCellZ += dz;
|
||||||
|
|
|
||||||
|
|
@ -773,6 +773,7 @@ void load_object_collision_model(void) {
|
||||||
if (gCurrentObject->oDistanceToMario == 19000.0f) {
|
if (gCurrentObject->oDistanceToMario == 19000.0f) {
|
||||||
marioDist = dist_between_objects(gCurrentObject, gMarioObject);
|
marioDist = dist_between_objects(gCurrentObject, gMarioObject);
|
||||||
}
|
}
|
||||||
|
// two-player hack
|
||||||
mario2Dist = dist_between_objects(gCurrentObject, gMario2Object);
|
mario2Dist = dist_between_objects(gCurrentObject, gMario2Object);
|
||||||
|
|
||||||
// If the object collision is supposed to be loaded more than the
|
// If the object collision is supposed to be loaded more than the
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,7 @@ void mario_grab_used_object(struct MarioState *m) {
|
||||||
if (m->usedObj == NULL || m->usedObj->oHeldState == HELD_HELD) { return; }
|
if (m->usedObj == NULL || m->usedObj->oHeldState == HELD_HELD) { return; }
|
||||||
if (m->heldObj == NULL) {
|
if (m->heldObj == NULL) {
|
||||||
m->heldObj = m->usedObj;
|
m->heldObj = m->usedObj;
|
||||||
|
// two-player hack
|
||||||
m->heldObj->heldByPlayerIndex = (m == &gMarioStates[0]) ? 0 : 1;
|
m->heldObj->heldByPlayerIndex = (m == &gMarioStates[0]) ? 0 : 1;
|
||||||
obj_set_held_state(m->heldObj, bhvCarrySomething3);
|
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) {
|
int get_invincibility_flag(struct MarioState *m) {
|
||||||
|
// two-player hack
|
||||||
return (m == &gMarioStates[0])
|
return (m == &gMarioStates[0])
|
||||||
? INT_SUBTYPE_DELAY_INVINCIBILITY
|
? INT_SUBTYPE_DELAY_INVINCIBILITY
|
||||||
: INT_SUBTYPE_DELAY_INVINCIBILITY_MARIO2;
|
: INT_SUBTYPE_DELAY_INVINCIBILITY_MARIO2;
|
||||||
|
|
|
||||||
|
|
@ -1862,6 +1862,9 @@ void init_mario(void) {
|
||||||
if (isLocal && gMarioObject == NULL) { goto skippy; }
|
if (isLocal && gMarioObject == NULL) { goto skippy; }
|
||||||
if (!isLocal && gMario2Object == NULL) { goto skippy; }
|
if (!isLocal && gMario2Object == NULL) { goto skippy; }
|
||||||
|
|
||||||
|
// two-player hack
|
||||||
|
gMarioState->playerIndex = isLocal ? 0 : 1;
|
||||||
|
|
||||||
Vec3s capPos;
|
Vec3s capPos;
|
||||||
struct Object *capObject;
|
struct Object *capObject;
|
||||||
|
|
||||||
|
|
@ -1898,6 +1901,7 @@ void init_mario(void) {
|
||||||
find_water_level(gMarioSpawnInfo->startPos[0], gMarioSpawnInfo->startPos[2]);
|
find_water_level(gMarioSpawnInfo->startPos[0], gMarioSpawnInfo->startPos[2]);
|
||||||
|
|
||||||
gMarioState->area = gCurrentArea;
|
gMarioState->area = gCurrentArea;
|
||||||
|
// two-player hack
|
||||||
gMarioState->marioObj = isLocal ? gMarioObject : gMario2Object;
|
gMarioState->marioObj = isLocal ? gMarioObject : gMario2Object;
|
||||||
gMarioState->marioObj->header.gfx.unk38.animID = -1;
|
gMarioState->marioObj->header.gfx.unk38.animID = -1;
|
||||||
vec3s_copy(gMarioState->faceAngle, gMarioSpawnInfo->startAngle);
|
vec3s_copy(gMarioState->faceAngle, gMarioSpawnInfo->startAngle);
|
||||||
|
|
@ -1961,7 +1965,8 @@ skippy:
|
||||||
|
|
||||||
void init_mario_from_save_file(void) {
|
void init_mario_from_save_file(void) {
|
||||||
bool isLocal = (gMarioState == &gMarioStates[0]);
|
bool isLocal = (gMarioState == &gMarioStates[0]);
|
||||||
gMarioState->unk00 = isLocal ? 0 : 1;
|
// two-player hack
|
||||||
|
gMarioState->playerIndex = isLocal ? 0 : 1;
|
||||||
gMarioState->flags = 0;
|
gMarioState->flags = 0;
|
||||||
gMarioState->action = 0;
|
gMarioState->action = 0;
|
||||||
int i = isLocal ? 0 : 1;
|
int i = isLocal ? 0 : 1;
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ void play_step_sound(struct MarioState *m, s16 frame1, s16 frame2) {
|
||||||
|
|
||||||
void align_with_floor(struct MarioState *m) {
|
void align_with_floor(struct MarioState *m) {
|
||||||
m->pos[1] = m->floorHeight;
|
m->pos[1] = m->floorHeight;
|
||||||
mtxf_align_terrain_triangle(sFloorAlignMatrix[m->unk00], m->pos, m->faceAngle[1], 40.0f);
|
mtxf_align_terrain_triangle(sFloorAlignMatrix[m->playerIndex], m->pos, m->faceAngle[1], 40.0f);
|
||||||
m->marioObj->header.gfx.throwMatrix = &sFloorAlignMatrix[m->unk00];
|
m->marioObj->header.gfx.throwMatrix = &sFloorAlignMatrix[m->playerIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 begin_walking_action(struct MarioState *m, f32 forwardVel, u32 action, u32 actionArg) {
|
s32 begin_walking_action(struct MarioState *m, f32 forwardVel, u32 action, u32 actionArg) {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ void network_receive_player(struct Packet* p) {
|
||||||
u32 heldSyncID = NULL;
|
u32 heldSyncID = NULL;
|
||||||
u32 heldBySyncID = NULL;
|
u32 heldBySyncID = NULL;
|
||||||
|
|
||||||
|
u16 playerIndex = gMarioStates[1].playerIndex;
|
||||||
packet_read(p, &gMarioStates[1], sizeof(u32) * 24);
|
packet_read(p, &gMarioStates[1], sizeof(u32) * 24);
|
||||||
packet_read(p, gMarioStates[1].controller, 20);
|
packet_read(p, gMarioStates[1].controller, 20);
|
||||||
packet_read(p, &gMarioStates[1].marioObj->rawData.asU32, sizeof(u32) * 80);
|
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, &gMarioStates[1].marioObj->header.gfx.node.flags, sizeof(s16));
|
||||||
packet_read(p, &heldSyncID, sizeof(u32));
|
packet_read(p, &heldSyncID, sizeof(u32));
|
||||||
packet_read(p, &heldBySyncID, sizeof(u32));
|
packet_read(p, &heldBySyncID, sizeof(u32));
|
||||||
|
gMarioStates[1].playerIndex = playerIndex;
|
||||||
|
|
||||||
if (heldSyncID != NULL && syncObjects[heldSyncID].o != NULL) {
|
if (heldSyncID != NULL && syncObjects[heldSyncID].o != NULL) {
|
||||||
// TODO: do we have to move graphics nodes around to make this visible?
|
// TODO: do we have to move graphics nodes around to make this visible?
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue