Radar view-wedge tracks the torso twist (Gitea issue #1)
The SECTOR radar's view cone read viewHorizontalRotation, wired by the MapDisplay ctor from the mech's Torso -- but FindSubObject and GetHorizontalRotation were NULL stubs, so the connection was never created and the wedge sat at heading 0 regardless of twist. Reconstructed from the binary: - FindSubObject (FUN_0041f98c): a subsystem-ROSTER walk (count @+0x124, array @+0x128) matching the streamed subsystem name (sub+0xd4) with a tolower-strcmp (FUN_004d4b58) -- the 'Torso' sub-object IS the roster Torso subsystem. - GetHorizontalRotation: torso+0x1D8 == Torso::currentTwist (layout-locked), via the existing task-#56 bridge BTGetTorsoTwistAddr (Radian is layout- identical to Scalar). Verified live (MadCat, Standard mode Q/E): the wedge tracks the twist in lockstep (rot 0 -> -2.21 rad), and the semantic test passes -- body turned away, torso twisted back onto the enemy: reticle green + wedge pointing at the enemy's blip on the body-fixed scope. NB the Blackhawk's torso is FIXED (+/-0.01 deg limits) -- its wedge authentically never moves; test with a twisting mech. Diag env: BT_RADAR_LOG. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
8616b62405
commit
1ed8b05160
@@ -131,6 +131,22 @@ At the authentic 1e7-unit economy (tasks #9-#10) the Heat MFD is fully dynamic:
|
||||
77→2000 (the authored failure threshold), condensers/generators run 100-1400 under sustained
|
||||
fire, and the bank plateaus ~600 — temperatures, heatLoad and the heat alarms all animate. [T2]
|
||||
|
||||
## Radar view-wedge tracks the torso twist (Gitea issue #1 — FIXED 2026-07-17) [T2]
|
||||
The SECTOR radar's view cone (`MapDisplay::DrawViewWedge` @004c2484, btl4rdr.cpp) reads
|
||||
`viewHorizontalRotation@0x31C`, fed by a per-frame `GaugeConnectionDirectOf<Radian>` the ctor
|
||||
wires from the mech's Torso. The two helpers were NULL stubs, so the connection was never
|
||||
created and the wedge sat at heading 0 (the reported "cone does not track the twist").
|
||||
Reconstructed from the binary: `FindSubObject` (FUN_0041f98c) = a SUBSYSTEM-ROSTER walk
|
||||
(count @+0x124 / array @+0x128) matching the streamed name (sub+0xd4) case-insensitively
|
||||
(FUN_004d4b58 = tolower-strcmp) — the "Torso" sub-object IS the roster Torso subsystem;
|
||||
`GetHorizontalRotation` = torso+0x1D8 = `Torso::currentTwist` (layout-locked), reached via the
|
||||
existing task-#56 bridge `BTGetTorsoTwistAddr` (Radian ≡ {Scalar angle}, exact reinterpret).
|
||||
VERIFIED live (MadCat, Standard mode Q/E): wedge rot tracks twist 0→−2.21 rad in lockstep, and
|
||||
the SEMANTIC test passes — body turned away, torso twisted back onto the enemy → reticle goes
|
||||
green AND the wedge points at the enemy's blip while the scope stays body-fixed. ⚠ Test with a
|
||||
TWISTING mech: the Blackhawk's torso is FIXED (limits ±0.01°) — its wedge authentically never
|
||||
moves. Diag: `BT_RADAR_LOG` ([radar] ctor probe + 1 Hz [radar-wedge] rot trace). [T2]
|
||||
|
||||
## Remaining = DATA FEEDS, not widgets (deferred systems)
|
||||
**✅ The condenser valve CONTROL is LIVE (task #13, 2026-07-11) [T2]:** `MoveValve` (id 4, the
|
||||
Condenser handler table @0x50E52C — exactly one entry) registered + guarded by the REAL
|
||||
|
||||
@@ -201,11 +201,13 @@ static Entity *
|
||||
|
||||
//
|
||||
// Mech sub-object lookup ("Torso") + its horizontal rotation feed.
|
||||
// (The "sub-object" IS a roster SUBSYSTEM -- FUN_0041f98c walks the entity's
|
||||
// subsystem roster by NAME; see the bodies at the end of this file.)
|
||||
//
|
||||
static Entity *
|
||||
static Subsystem *
|
||||
FindSubObject(Entity *entity, const char *name);
|
||||
static Radian *
|
||||
GetHorizontalRotation(Entity *entity);
|
||||
GetHorizontalRotation(Subsystem *torso);
|
||||
|
||||
|
||||
//###########################################################################
|
||||
@@ -471,7 +473,11 @@ MapDisplay::MapDisplay(
|
||||
//
|
||||
if (entity->GetClassID() == 0xBB9)
|
||||
{
|
||||
Entity *torso = FindSubObject(entity, "Torso"); // FUN_0041f98c
|
||||
Subsystem *torso = FindSubObject(entity, "Torso"); // FUN_0041f98c (roster walk)
|
||||
if (getenv("BT_RADAR_LOG"))
|
||||
DEBUG_STREAM << "[radar] ctor: torso sub "
|
||||
<< (torso ? "FOUND" : "NOT FOUND (roster names?)")
|
||||
<< " on mech " << (void *)entity << "\n" << std::flush;
|
||||
if (torso != NULL)
|
||||
{
|
||||
AddConnection(
|
||||
@@ -791,6 +797,19 @@ void
|
||||
Radian leftEdge = viewHorizontalRotation - viewHalfHorizontalWidth;
|
||||
Radian rightEdge = viewHorizontalRotation + viewHalfHorizontalWidth;
|
||||
|
||||
// DIAG (issue #1): 1 Hz wedge-heading trace.
|
||||
if (getenv("BT_RADAR_LOG"))
|
||||
{
|
||||
static unsigned long sLast = 0;
|
||||
unsigned long now = GetTickCount();
|
||||
if (now - sLast >= 1000)
|
||||
{
|
||||
sLast = now;
|
||||
DEBUG_STREAM << "[radar-wedge] rot=" << (Scalar)viewHorizontalRotation
|
||||
<< "\n" << std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
localView.SetColor(staticColor); // (this+0x48 vtbl+0x18)
|
||||
|
||||
Radian edges[2];
|
||||
@@ -1176,20 +1195,40 @@ static Entity *
|
||||
|
||||
//
|
||||
// FUN_0041f98c -- Entity::FindSubObject(name) (locates "Torso").
|
||||
// The binary walks the entity's SUBSYSTEM ROSTER (count @+0x124, array
|
||||
// @+0x128) and returns the first subsystem whose streamed NAME (sub+0xd4 ==
|
||||
// Subsystem::subsystemName) matches case-insensitively (FUN_004d4b58 is a
|
||||
// tolower-strcmp). Gitea issue #1 fix (2026-07-17): this and the feed below
|
||||
// were NULL stubs, so the torso-twist -> radar view-wedge connection was
|
||||
// never created and the wedge sat at heading 0 forever.
|
||||
//
|
||||
static Entity *
|
||||
FindSubObject(Entity * /*entity*/, const char * /*name*/)
|
||||
static Subsystem *
|
||||
FindSubObject(Entity *entity, const char *name)
|
||||
{
|
||||
if (entity == NULL || name == NULL)
|
||||
return NULL;
|
||||
for (int i = 0; i < entity->GetSubsystemCount(); ++i)
|
||||
{
|
||||
Subsystem *sub = entity->GetSubsystem(i);
|
||||
if (sub != NULL && sub->GetName() != NULL
|
||||
&& _stricmp(sub->GetName(), name) == 0)
|
||||
return sub;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// torso+0x1D8 -- the sub-object's horizontal (yaw) rotation feed.
|
||||
// torso+0x1D8 -- the sub-object's horizontal (yaw) rotation feed:
|
||||
// Torso::currentTwist (layout-locked @0x1D8, torso.hpp). Reached via the
|
||||
// torso.cpp complete-type bridge (task #56's BTGetTorsoTwistAddr -- the same
|
||||
// pointer the gyro's external-pitch link uses). Radian is layout-identical
|
||||
// to Scalar ({ Scalar angle }, ANGLE.h), so the reinterpret is exact.
|
||||
//
|
||||
static Radian *
|
||||
GetHorizontalRotation(Entity * /*entity*/)
|
||||
GetHorizontalRotation(Subsystem *torso)
|
||||
{
|
||||
return NULL;
|
||||
extern Scalar *BTGetTorsoTwistAddr(Subsystem *torso);
|
||||
return (Radian *)BTGetTorsoTwistAddr(torso);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user