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:
Kp 2017-08-02 02:49:13 +00:00
parent 822249304c
commit 03cca2b3dc
3 changed files with 26 additions and 25 deletions

View file

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

View file

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

View file

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