Fix displacing players when synthesizing player start positions
TORRaven reported an issue where `Descent: First Strike` level 4 in cooperative games would cause the player 0 ship to be unable to move. On investigation, this occurs when the host has enabled extra player starts, and the resulting synthesis of new player start positions moves the player 0 start out of its origin segment. The physics engine reacts poorly to this situation, causing the object to be unable to move and to report HIT_BAD_P0 in debug builds. Add a test to cancel the displacement if get_seg_masks reports that the center point would move outside the origin segment. More clever logic might be appropriate, but since this is the first report of problems with the feature since its introduction in5a64ee5132
, this commit just eliminates the immediate problem. Possible future improvements if the existing displacement causes collisions: - Reduce the magnitude of the existing displacement, instead of abandoning it entirely. - Move the player start to the segment's center before displacing it. - Add logic to move the player into a nearby logically connected segment. Reported-by: TORRaven <https://github.com/dxx-rebirth/dxx-rebirth/issues/483> Fixes:5a64ee5132
("Add experimental support for larger cooperative games")
This commit is contained in:
parent
ffb4240710
commit
b0185e44ad
|
@ -272,7 +272,7 @@ static unsigned generate_extra_starts_by_displacement_within_segment(const unsig
|
|||
if (vm_vec_dist2(v0, vcvertptr(seg.verts[4])) > size2)
|
||||
capacity_flag |= capacity_z;
|
||||
player_init_segment_capacity_flag[i] = capacity_flag;
|
||||
con_printf(CON_NORMAL, "Original player %u has size %u and segment capacity flags %x.", i, old_player_obj.size, capacity_flag);
|
||||
con_printf(CON_NORMAL, "Original player %u has size %u, starts in segment #%hu, and has segment capacity flags %x.", i, old_player_obj.size, static_cast<segnum_t>(segnum), capacity_flag);
|
||||
if (capacity_flag)
|
||||
++segments_with_spare_capacity;
|
||||
}
|
||||
|
@ -350,8 +350,14 @@ static unsigned generate_extra_starts_by_displacement_within_segment(const unsig
|
|||
return;
|
||||
vm_vec_normalize(disp);
|
||||
vm_vec_scale(disp, fixmul(old_player_obj.size, size_scalar >> 1));
|
||||
con_printf(CON_NORMAL, "Displace player %u at {%i, %i, %i} by {%i, %i, %i}.", plridx, plrobj.pos.x, plrobj.pos.y, plrobj.pos.z, disp.x, disp.y, disp.z);
|
||||
vm_vec_add2(Player_init[plridx].pos, disp);
|
||||
const auto target_position = vm_vec_add(Player_init[plridx].pos, disp);
|
||||
if (const auto sidemask = get_seg_masks(vcvertptr, target_position, vcsegptr(plrobj.segnum), 1).sidemask)
|
||||
{
|
||||
con_printf(CON_NORMAL, "Cannot displace player %u at {%i, %i, %i} to {%i, %i, %i}: would be outside segment for sides %x.", plridx, plrobj.pos.x, plrobj.pos.y, plrobj.pos.z, target_position.x, target_position.y, target_position.z, sidemask);
|
||||
return;
|
||||
}
|
||||
con_printf(CON_NORMAL, "Displace player %u at {%i, %i, %i} by {%i, %i, %i} to {%i, %i, %i}.", plridx, plrobj.pos.x, plrobj.pos.y, plrobj.pos.z, disp.x, disp.y, disp.z, target_position.x, target_position.y, target_position.z);
|
||||
Player_init[plridx].pos = target_position;
|
||||
plrobj.pos = Player_init[plridx].pos;
|
||||
};
|
||||
for (unsigned extra_player_idx = preplaced_starts, displacements = 0; extra_player_idx < k; ++extra_player_idx)
|
||||
|
|
Loading…
Reference in a new issue