Track visited segments as a local
This fixes a subtle bug where a perfectly immobile player would reuse a previous run. In practice, players are not immobile.
This commit is contained in:
parent
822249304c
commit
03cca2b3dc
|
@ -38,16 +38,17 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
//#define FL_HOVER 2
|
||||
//#define FL_REVERSE 3
|
||||
|
||||
// these global vars are set after a call to do_physics_sim(). Ugly, I know.
|
||||
// list of segments went through
|
||||
extern unsigned n_phys_segs;
|
||||
extern array<segnum_t, MAX_FVI_SEGS> phys_seglist;
|
||||
|
||||
// Simulate a physics object for this frame
|
||||
#if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
|
||||
struct phys_visited_seglist
|
||||
{
|
||||
unsigned nsegs;
|
||||
array<segnum_t, MAX_FVI_SEGS> seglist;
|
||||
};
|
||||
|
||||
#ifdef dsx
|
||||
namespace dsx {
|
||||
window_event_result do_physics_sim(vmobjptridx_t obj);
|
||||
window_event_result do_physics_sim(vmobjptridx_t obj, phys_visited_seglist *phys_segs);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1734,11 +1734,15 @@ static window_event_result object_move_one(const vmobjptridx_t obj)
|
|||
if (obj->type == OBJ_NONE || obj->flags&OF_SHOULD_BE_DEAD)
|
||||
return window_event_result::ignored; // object has been deleted
|
||||
|
||||
bool prepare_seglist = false;
|
||||
phys_visited_seglist phys_visited_segs;
|
||||
switch (obj->movement_type) {
|
||||
|
||||
case MT_NONE: break; //this doesn't move
|
||||
|
||||
case MT_PHYSICS: result = do_physics_sim(obj); break; //move by physics
|
||||
case MT_PHYSICS: //move by physics
|
||||
result = do_physics_sim(obj, obj->type == OBJ_PLAYER ? (prepare_seglist = true, phys_visited_segs.nsegs = 0, &phys_visited_segs) : nullptr);
|
||||
break;
|
||||
|
||||
case MT_SPINNING: spin_object(obj); break;
|
||||
|
||||
|
@ -1746,15 +1750,15 @@ static window_event_result object_move_one(const vmobjptridx_t obj)
|
|||
|
||||
// If player and moved to another segment, see if hit any triggers.
|
||||
// also check in player under a lavafall
|
||||
if (obj->type == OBJ_PLAYER && obj->movement_type==MT_PHYSICS) {
|
||||
|
||||
if (previous_segment != obj->segnum && n_phys_segs > 1)
|
||||
if (prepare_seglist)
|
||||
{
|
||||
if (previous_segment != obj->segnum && phys_visited_segs.nsegs > 1)
|
||||
{
|
||||
auto seg0 = vmsegptridx(phys_seglist[0]);
|
||||
auto seg0 = vmsegptridx(phys_visited_segs.seglist[0]);
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
int old_level = Current_level_num;
|
||||
#endif
|
||||
range_for (const auto i, partial_const_range(phys_seglist, 1u, n_phys_segs))
|
||||
range_for (const auto i, partial_const_range(phys_visited_segs.seglist, 1u, phys_visited_segs.nsegs))
|
||||
{
|
||||
const auto &&seg1 = seg0.absolute_sibling(i);
|
||||
const auto connect_side = find_connect_side(seg1, seg0);
|
||||
|
|
|
@ -150,10 +150,6 @@ static void set_object_turnroll(object_base &obj)
|
|||
|
||||
}
|
||||
|
||||
//list of segments went through
|
||||
unsigned n_phys_segs;
|
||||
array<segnum_t, MAX_FVI_SEGS> phys_seglist;
|
||||
|
||||
|
||||
#define MAX_IGNORE_OBJS 100
|
||||
|
||||
|
@ -300,7 +296,7 @@ public:
|
|||
// -----------------------------------------------------------------------------------------------------------
|
||||
//Simulate a physics object for this frame
|
||||
namespace dsx {
|
||||
window_event_result do_physics_sim(const vmobjptridx_t obj)
|
||||
window_event_result do_physics_sim(const vmobjptridx_t obj, phys_visited_seglist *const phys_segs)
|
||||
{
|
||||
ignore_objects_array_t ignore_obj_list;
|
||||
int try_again;
|
||||
|
@ -337,8 +333,6 @@ window_event_result do_physics_sim(const vmobjptridx_t obj)
|
|||
if (!(pi->velocity.x || pi->velocity.y || pi->velocity.z || pi->thrust.x || pi->thrust.y || pi->thrust.z))
|
||||
return window_event_result::ignored;
|
||||
|
||||
n_phys_segs = 0;
|
||||
|
||||
sim_time = FrameTime;
|
||||
|
||||
start_pos = obj->pos;
|
||||
|
@ -416,7 +410,7 @@ window_event_result do_physics_sim(const vmobjptridx_t obj)
|
|||
if (obj->type == OBJ_WEAPON)
|
||||
fq.flags |= FQ_TRANSPOINT;
|
||||
|
||||
if (obj->type == OBJ_PLAYER)
|
||||
if (phys_segs)
|
||||
fq.flags |= FQ_GET_SEGLIST;
|
||||
|
||||
fate = find_vector_intersection(fq, hit_info);
|
||||
|
@ -434,16 +428,18 @@ window_event_result do_physics_sim(const vmobjptridx_t obj)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (obj->type == OBJ_PLAYER) {
|
||||
if (n_phys_segs && !hit_info.seglist.empty() && phys_seglist[n_phys_segs-1]==hit_info.seglist[0])
|
||||
if (phys_segs && !hit_info.seglist.empty())
|
||||
{
|
||||
auto n_phys_segs = phys_segs->nsegs;
|
||||
if (n_phys_segs && phys_segs->seglist[n_phys_segs - 1] == hit_info.seglist[0])
|
||||
n_phys_segs--;
|
||||
|
||||
range_for (const auto &hs, hit_info.seglist)
|
||||
{
|
||||
if (!(n_phys_segs < MAX_FVI_SEGS-1))
|
||||
if (!(n_phys_segs < phys_segs->seglist.size() - 1))
|
||||
break;
|
||||
phys_seglist[n_phys_segs++] = hs;
|
||||
phys_segs->seglist[n_phys_segs++] = hs;
|
||||
}
|
||||
phys_segs->nsegs = n_phys_segs;
|
||||
}
|
||||
|
||||
ipos = hit_info.hit_pnt;
|
||||
|
|
Loading…
Reference in a new issue