Skip to content

Commit

Permalink
🐛 Fixed SyncReset() activating hook/tie beams which it shouldn't.
Browse files Browse the repository at this point in the history
💡 This introduces the mechanism of grouping beams in `Actor::ar_beams` by their type and origin. See `struct BeamRangesByOrigin` in file 'SimData.h'.
  • Loading branch information
ohlidalp committed May 27, 2024
1 parent b4cd43b commit 340fbd3
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 7 deletions.
55 changes: 50 additions & 5 deletions source/main/physics/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions source/main/physics/Actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,10 @@ class Actor : public RefCountingObject<Actor>
std::vector<float> 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<beam_t*> ar_inter_beams; //!< Beams connecting 2 actors
shock_t* ar_shocks = nullptr; //!< Shock absorbers
int ar_num_shocks = 0; //!< Number of shock absorbers
Expand Down
10 changes: 10 additions & 0 deletions source/main/physics/ActorManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
28 changes: 26 additions & 2 deletions source/main/physics/ActorSpawnerFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ void ActorSpawner::ProcessNewActor(ActorPtr actor, ActorSpawnRequest rq, RigDef:
m_actor->m_gfx_actor = std::unique_ptr<RoR::GfxActor>(
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)
Expand All @@ -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 ----------------------------

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

Expand All @@ -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);
Expand Down
46 changes: 46 additions & 0 deletions source/main/physics/SimData.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/// @}

// --------------------------------
Expand Down

0 comments on commit 340fbd3

Please sign in to comment.