From 340fbd310d4b9009368b278576342ae0cb12bc98 Mon Sep 17 00:00:00 2001 From: Petr Ohlidal Date: Mon, 27 May 2024 10:17:01 +0200 Subject: [PATCH] :bug: Fixed `SyncReset()` activating hook/tie beams which it shouldn't. :bulb: This introduces the mechanism of grouping beams in `Actor::ar_beams` by their type and origin. See `struct BeamRangesByOrigin` in file 'SimData.h'. --- source/main/physics/Actor.cpp | 55 +++++++++++++++++++++--- source/main/physics/Actor.h | 2 + source/main/physics/ActorManager.cpp | 10 +++++ source/main/physics/ActorSpawnerFlow.cpp | 28 +++++++++++- source/main/physics/SimData.h | 46 ++++++++++++++++++++ 5 files changed, 134 insertions(+), 7 deletions(-) diff --git a/source/main/physics/Actor.cpp b/source/main/physics/Actor.cpp index df272b216f..3b29511619 100644 --- a/source/main/physics/Actor.cpp +++ b/source/main/physics/Actor.cpp @@ -1592,7 +1592,13 @@ void Actor::SyncReset(bool reset_position) ar_beams[i].L = ar_beams[i].refL; ar_beams[i].stress = 0.0; ar_beams[i].bm_broken = false; - ar_beams[i].bm_disabled = false; + + // Skip hookbeams and tiebeams ... they should only be active if they are LOCKED + if ((i < ar_beam_ranges_by_origin.hookbeams_start || i > ar_beam_ranges_by_origin.hookbeams_start + ar_beam_ranges_by_origin.hookbeams_count) + && (i < ar_beam_ranges_by_origin.tiebeams_start || i > ar_beam_ranges_by_origin.tiebeams_start + ar_beam_ranges_by_origin.tiebeams_count)) + { + ar_beams[i].bm_disabled = false; + } } this->applyNodeBeamScales(); @@ -1601,34 +1607,73 @@ void Actor::SyncReset(bool reset_position) for (auto& h : ar_hooks) { + if (h.hk_locked != UNLOCKED) + { + ROR_ASSERT(h.hk_locked_actor); + ROR_ASSERT(h.hk_lock_node); + ROR_ASSERT(h.hk_locked_actor == h.hk_beam->bm_locked_actor); + ROR_ASSERT(h.hk_beam->bm_inter_actor == true); + App::GetGameContext()->GetActorManager()->RemoveInterActorBeam(h.hk_beam, ActorLinkingRequestType::HOOK_ACTION); // OK to be invoked here - SyncReset() - processing `MSG_SIM_MODIFY_ACTOR_REQUESTED` + } h.hk_locked = UNLOCKED; h.hk_lock_node = nullptr; h.hk_locked_actor = nullptr; h.hk_beam->p2 = &ar_nodes[0]; + h.hk_beam->L = (ar_nodes[0].AbsPosition - h.hk_hook_node->AbsPosition).length(); + + // These should be adjusted by `RemoveInterActorBeam()` ~ Assert on Debug, minimize damage on Release + ROR_ASSERT(h.hk_beam->bm_disabled); h.hk_beam->bm_disabled = true; + ROR_ASSERT(h.hk_beam->bm_inter_actor == false); h.hk_beam->bm_inter_actor = false; - h.hk_beam->L = (ar_nodes[0].AbsPosition - h.hk_hook_node->AbsPosition).length(); - App::GetGameContext()->GetActorManager()->RemoveInterActorBeam(h.hk_beam, ActorLinkingRequestType::HOOK_ACTION); // OK to be invoked here - SyncReset() - `processing MSG_SIM_MODIFY_ACTOR_REQUESTED` + ROR_ASSERT(h.hk_beam->bm_locked_actor == nullptr); + h.hk_beam->bm_locked_actor = nullptr; } for (auto& r : ar_ropes) { + if (r.rp_locked != UNLOCKED) + { + ROR_ASSERT(r.rp_locked_actor); + ROR_ASSERT(r.rp_locked_actor == r.rp_beam->bm_locked_actor); + ROR_ASSERT(r.rp_beam->bm_inter_actor == true); + App::GetGameContext()->GetActorManager()->RemoveInterActorBeam(r.rp_beam, ActorLinkingRequestType::ROPE_ACTION); // OK to be invoked here - SyncReset() - processing `MSG_SIM_MODIFY_ACTOR_REQUESTED` + } r.rp_locked = UNLOCKED; r.rp_locked_ropable = nullptr; r.rp_locked_actor = nullptr; - App::GetGameContext()->GetActorManager()->RemoveInterActorBeam(r.rp_beam, ActorLinkingRequestType::ROPE_ACTION); // OK to be invoked here - SyncReset() - `processing MSG_SIM_MODIFY_ACTOR_REQUESTED` + + // These should be adjusted by `RemoveInterActorBeam()` ~ Assert on Debug, minimize damage on Release + ROR_ASSERT(r.rp_beam->bm_disabled); + r.rp_beam->bm_disabled = true; + ROR_ASSERT(r.rp_beam->bm_inter_actor == false); + r.rp_beam->bm_inter_actor = false; + ROR_ASSERT(r.rp_beam->bm_locked_actor == nullptr); + r.rp_beam->bm_locked_actor = nullptr; } for (auto& t : ar_ties) { + if (t.ti_tied) + { + ROR_ASSERT(t.ti_locked_actor); + ROR_ASSERT(t.ti_locked_actor == t.ti_beam->bm_locked_actor); + ROR_ASSERT(t.ti_beam->bm_inter_actor == true); + App::GetGameContext()->GetActorManager()->RemoveInterActorBeam(t.ti_beam, ActorLinkingRequestType::TIE_ACTION); // OK to be invoked here - SyncReset() - processing `MSG_SIM_MODIFY_ACTOR_REQUESTED` + } t.ti_tied = false; t.ti_tying = false; t.ti_locked_actor = nullptr; t.ti_locked_ropable = nullptr; t.ti_beam->p2 = &ar_nodes[0]; + + // These should be adjusted by `RemoveInterActorBeam()` ~ Assert on Debug, minimize damage on Release + ROR_ASSERT(t.ti_beam->bm_disabled); t.ti_beam->bm_disabled = true; + ROR_ASSERT(t.ti_beam->bm_inter_actor == false); t.ti_beam->bm_inter_actor = false; - App::GetGameContext()->GetActorManager()->RemoveInterActorBeam(t.ti_beam, ActorLinkingRequestType::TIE_ACTION); // OK to be invoked here - SyncReset() - `processing MSG_SIM_MODIFY_ACTOR_REQUESTED` + ROR_ASSERT(t.ti_beam->bm_locked_actor == nullptr); + t.ti_beam->bm_locked_actor = nullptr; } // Remove any possible links from other actors to this actor. diff --git a/source/main/physics/Actor.h b/source/main/physics/Actor.h index edfb885212..484620dae0 100644 --- a/source/main/physics/Actor.h +++ b/source/main/physics/Actor.h @@ -276,8 +276,10 @@ class Actor : public RefCountingObject std::vector ar_minimass; //!< minimum node mass in Kg bool ar_minimass_skip_loaded_nodes = false; + // Beams beam_t* ar_beams = nullptr; int ar_num_beams = 0; + BeamRangesByOrigin ar_beam_ranges_by_origin; std::vector ar_inter_beams; //!< Beams connecting 2 actors shock_t* ar_shocks = nullptr; //!< Shock absorbers int ar_num_shocks = 0; //!< Number of shock absorbers diff --git a/source/main/physics/ActorManager.cpp b/source/main/physics/ActorManager.cpp index d8be0bcc39..1459673320 100644 --- a/source/main/physics/ActorManager.cpp +++ b/source/main/physics/ActorManager.cpp @@ -900,6 +900,16 @@ void ActorManager::RemoveInterActorBeam(beam_t* beam, ActorLinkingRequestType ty // Remove record from interbeams list a->ar_inter_beams.erase(existing_interbeam_itor); beam->bm_locked_actor = nullptr; + beam->bm_inter_actor = false; + switch (type) + { + case ActorLinkingRequestType::HOOK_ACTION: + case ActorLinkingRequestType::TIE_ACTION: + ROR_ASSERT(!beam->bm_disabled); + beam->bm_disabled = true; + break; + default:; + } // ACTOR UNLINKING: diff --git a/source/main/physics/ActorSpawnerFlow.cpp b/source/main/physics/ActorSpawnerFlow.cpp index f3a09dccc7..ceab4d859a 100644 --- a/source/main/physics/ActorSpawnerFlow.cpp +++ b/source/main/physics/ActorSpawnerFlow.cpp @@ -139,7 +139,9 @@ void ActorSpawner::ProcessNewActor(ActorPtr actor, ActorSpawnRequest rq, RigDef: m_actor->m_gfx_actor = std::unique_ptr( new RoR::GfxActor(m_actor, this, m_custom_resource_group, m_oldstyle_renderdash)); + m_actor->ar_beam_ranges_by_origin.hookbeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::NODES, nodes, ProcessNode); + m_actor->ar_beam_ranges_by_origin.hookbeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.hookbeams_start; // Old-format exhaust (defined by flags 'x/y' in section 'nodes', one per vehicle) if (m_actor->ar_exhaust_pos_node != 0 && m_actor->ar_exhaust_dir_node != 0) @@ -149,15 +151,19 @@ void ActorSpawner::ProcessNewActor(ActorPtr actor, ActorSpawnRequest rq, RigDef: // ---------------------------- Node generating sections ---------------------------- + m_actor->ar_beam_ranges_by_origin.cinecambeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::CINECAM, cinecam, ProcessCinecam); + m_actor->ar_beam_ranges_by_origin.cinecambeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.cinecambeams_start; // ---------------------------- Wheels (also generate nodes) ---------------------------- + m_actor->ar_beam_ranges_by_origin.wheelbeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::WHEELS, wheels, ProcessWheel); PROCESS_ELEMENT(RigDef::Keyword::WHEELS2, wheels2, ProcessWheel2); PROCESS_ELEMENT(RigDef::Keyword::MESHWHEELS, meshwheels, ProcessMeshWheel); PROCESS_ELEMENT(RigDef::Keyword::MESHWHEELS2, meshwheels2, ProcessMeshWheel2); PROCESS_ELEMENT(RigDef::Keyword::FLEXBODYWHEELS, flexbodywheels, ProcessFlexBodyWheel); + m_actor->ar_beam_ranges_by_origin.wheelbeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.wheelbeams_start; // ---------------------------- WheelDetachers ---------------------------- @@ -166,14 +172,33 @@ void ActorSpawner::ProcessNewActor(ActorPtr actor, ActorSpawnRequest rq, RigDef: // ---------------------------- User-defined beams ---------------------------- // (may reference any generated/user-defined node) + m_actor->ar_beam_ranges_by_origin.regularbeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::BEAMS, beams, ProcessBeam); + m_actor->ar_beam_ranges_by_origin.cinecambeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.regularbeams_start; + m_actor->ar_beam_ranges_by_origin.shocks1beams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::SHOCKS, shocks, ProcessShock); + m_actor->ar_beam_ranges_by_origin.shocks1beams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.shocks1beams_start; + m_actor->ar_beam_ranges_by_origin.shocks2beams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::SHOCKS2, shocks2, ProcessShock2); + m_actor->ar_beam_ranges_by_origin.shocks2beams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.shocks2beams_start; + m_actor->ar_beam_ranges_by_origin.shocks3beams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::SHOCKS3, shocks3, ProcessShock3); + m_actor->ar_beam_ranges_by_origin.shocks3beams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.shocks3beams_start; + m_actor->ar_beam_ranges_by_origin.commandbeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::COMMANDS2, commands2, ProcessCommand); // 'commands' are auto-imported as 'commands2'. + m_actor->ar_beam_ranges_by_origin.commandbeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.commandbeams_start; + m_actor->ar_beam_ranges_by_origin.hydrobeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::HYDROS, hydros, ProcessHydro); + m_actor->ar_beam_ranges_by_origin.hydrobeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.hydrobeams_start; + m_actor->ar_beam_ranges_by_origin.triggerbeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::TRIGGERS, triggers, ProcessTrigger); + m_actor->ar_beam_ranges_by_origin.triggerbeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.triggerbeams_start; + m_actor->ar_beam_ranges_by_origin.ropebeams_start = m_actor->ar_num_beams; PROCESS_ELEMENT(RigDef::Keyword::ROPES, ropes, ProcessRope); + m_actor->ar_beam_ranges_by_origin.ropebeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.ropebeams_start; + m_actor->ar_beam_ranges_by_origin.tiebeams_start = m_actor->ar_num_beams; + PROCESS_ELEMENT(RigDef::Keyword::TIES, ties, ProcessTie); + m_actor->ar_beam_ranges_by_origin.tiebeams_count = m_actor->ar_num_beams - m_actor->ar_beam_ranges_by_origin.tiebeams_start; // ---------------------------- Other ---------------------------- @@ -186,8 +211,7 @@ void ActorSpawner::ProcessNewActor(ActorPtr actor, ActorSpawnRequest rq, RigDef: PROCESS_ELEMENT(RigDef::Keyword::SUBMESH, submeshes, ProcessSubmesh); PROCESS_ELEMENT(RigDef::Keyword::CONTACTERS, contacters, ProcessContacter); PROCESS_ELEMENT(RigDef::Keyword::CAMERAS, cameras, ProcessCamera); - PROCESS_ELEMENT(RigDef::Keyword::HOOKS, hooks, ProcessHook); - PROCESS_ELEMENT(RigDef::Keyword::TIES, ties, ProcessTie); + PROCESS_ELEMENT(RigDef::Keyword::HOOKS, hooks, ProcessHook); PROCESS_ELEMENT(RigDef::Keyword::ROPABLES, ropables, ProcessRopable); PROCESS_ELEMENT(RigDef::Keyword::ANIMATORS, animators, ProcessAnimator); PROCESS_ELEMENT(RigDef::Keyword::FUSEDRAG, fusedrag, ProcessFusedrag); diff --git a/source/main/physics/SimData.h b/source/main/physics/SimData.h index 342806a6d0..4eedfc7dff 100644 --- a/source/main/physics/SimData.h +++ b/source/main/physics/SimData.h @@ -700,6 +700,52 @@ class CmdKeyArray command_t m_dummykey; }; +/// Groups beams in `Actor::ar_beams` by their type and origin. +/// Introduced in 2024, this is an auxiliary mechanism with limited use (`SyncReset()`) - it relies on current spawning code processing elements in predetermined order, see `ActorSpawner::ProcessNewActor()` in file 'ActorSpawnerFlow.cpp'. +/// The original mechanism is ad-hoc detection by `SpecialBeam bounded` and `BeamType bm_type` - still used for physics. +struct BeamRangesByOrigin +{ + // Variables are _IN ORDER_ of elements in `ar_beams`, see `ActorSpawner::ProcessNewActor()` in file 'ActorSpawnerFlow.cpp'. + // ------------------------------------------------------------------------------------------------------------------------ + + // generated from `Keyword::NODES` based on 'h' flag + int hookbeams_start = -1; + int hookbeams_count = -1; + // generated from `Keyword::CINECAM` + int cinecambeams_start = -1; + int cinecambeams_count = -1; + // generated from *WHEELS* + int wheelbeams_start = -1; + int wheelbeams_count = -1; + // generated from BEAMS and BEAMS2 + int regularbeams_start = -1; + int regularbeams_count = -1; + // generated from `Keyword::SHOCKS` + int shocks1beams_start = -1; + int shocks1beams_count = -1; + // generated from `Keyword::SHOCKS2` + int shocks2beams_start = -1; + int shocks2beams_count = -1; + // generated from `Keyword::SHOCKS3` + int shocks3beams_start = -1; + int shocks3beams_count = -1; + // generated from `Keyword::COMMANDS` / COMMANDS2 + int commandbeams_start = -1; + int commandbeams_count = -1; + // generated from `Keyword::HYDROS` + int hydrobeams_start = -1; + int hydrobeams_count = -1; + // generated from `Keyword::TRIGGERS` + int triggerbeams_start = -1; + int triggerbeams_count = -1; + // generated from `Keyword::ROPES` + int ropebeams_start = -1; + int ropebeams_count = -1; + // generated from `Keyword::TIES` + int tiebeams_start = -1; + int tiebeams_count = -1; +}; + /// @} // --------------------------------