From 03cca2b3dce62ae29c1ab7509df5105423365b4a Mon Sep 17 00:00:00 2001 From: Kp Date: Wed, 2 Aug 2017 02:49:13 +0000 Subject: [PATCH] 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. --- common/main/physics.h | 13 +++++++------ similar/main/object.cpp | 16 ++++++++++------ similar/main/physics.cpp | 22 +++++++++------------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/common/main/physics.h b/common/main/physics.h index 5914fece8..d32ec82ea 100644 --- a/common/main/physics.h +++ b/common/main/physics.h @@ -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 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 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 diff --git a/similar/main/object.cpp b/similar/main/object.cpp index 90b207d24..589691376 100644 --- a/similar/main/object.cpp +++ b/similar/main/object.cpp @@ -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); diff --git a/similar/main/physics.cpp b/similar/main/physics.cpp index 35e4668e4..7ad5046a3 100644 --- a/similar/main/physics.cpp +++ b/similar/main/physics.cpp @@ -150,10 +150,6 @@ static void set_object_turnroll(object_base &obj) } -//list of segments went through -unsigned n_phys_segs; -array 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;