Gitea #44: the reticle TARGET NAME PLATE (PNAME1-8) -- the target's callsign under the crosshair

Reconstructed the last deferred piece of the 1995 reticle, decoded from the
Execute disassembly @004cdcf0 [T1]:
 - selection: target_mech+0x190 (owning BTPlayer) -> player+0x1e0
   (playerBitmapIndex), 1-based into the mesh table at this+0x2e8
 - placement: re-placed every frame the aim moves -- scale 0.12 uniform,
   translate (K*retPos.x, K*retPos.y - 0.08, -1.0), K = 1/2.8 (the x87 long
   double @0x4cee64) -- so the label TRACKS THE AIM POINT, not screen centre
 - visibility: the LOCK attribute (this+0x184, cached +0x188) AND an owning
   player; reticle-off / simple-X also hide it
 - art: the plate quad UV-addresses a shared 128x64 bitslice texmap whose
   texels the pod OVERWROTE each mission with the egg's callsign rasters
   (original source commented out at L4VIDEO.cpp:5682-5710) -- the baked
   'PLAYER n' art in BMAP.BSL is only the shipped fallback.  Material colour
   is a neutral (0.5,0.5,0.5): grey-white, not phosphor green.

Port: same geometry in reticle units (0.224 below the aim point, 0.336x0.084)
drawn as the target's egg callsign texture through the reticle's own MapX/MapY
mapping, so it follows the world view in every layout and BT_SHOT captures it.
New: dpl2d_DrawTexturedRect, BTReticleTargetPlate, BTGetPlayerNameTexture.

Also: kRetCaret corrected 0.02f -> 0.025f (_DAT_004cd7f4 read from the binary;
the old value was a T3 guess, 20% small).

KB: gauges-hud + open-questions corrected (the chain was filed as deferred and
mis-attributed to 'the 3D marker'); TWO PNAME consumers now distinguished (this
plate, and CameraShipHUDRenderable's ranking window which shipped 2026-07-18);
new bgf-format section on the plate atlas.

Rig-verified: 2-node relay, BT_GOTO=enemy -> '[hud] name plate: bmp=2 tex=1'
and 'Boreas' rendered under the crosshair on the locked target.  Solo clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0166KTsC7ADm7VXEi1HF1jNg
This commit is contained in:
arcattack
2026-07-24 18:36:02 -05:00
co-authored by Claude Opus 5
parent b7107b1020
commit 35c750dc7c
7 changed files with 390 additions and 10 deletions
+54
View File
@@ -7103,3 +7103,57 @@ void BTCommitLookState(void *mech_v, int look_state)
<< " rearFiring=" << m->rearFiring
<< " yaw=" << yaw << " pitch=" << pitch << "\n" << std::flush;
}
//
//#############################################################################
// BTReticleTargetPlate -- the reticle NAME PLATE's player index (Gitea #43-b)
//#############################################################################
//
// The 1995 reticle renderable (BTReticleRenderable, ctor @004cc40c) loads
// PNAME1-8.bgf into a mesh table at this+0x2e8 and, every frame in Execute,
// picks one for the plate hung under the crosshair (disasm @004cec98 [T1]):
//
// edx = [this + 0x1e0] // the reticle's TARGET entity
// eax = edx ? [edx + 0x190] : 0 // mech+0x190 == the owning player
// if (eax) { // a piloted target
// edx = [eax + 0x1e0] // player+0x1e0 == playerBitmapIndex
// mesh = [this + edx*4 + 0x2e8] // 1-BASED: index 1 -> +0x2ec = PNAME1
// dpl_SetInstanceObject(plate, mesh);
// dpl_SetInstanceVisibility(plate, 1); dpl_FlushInstance(plate);
// } else if (showing) { visibility 0; flush; }
//
// So the plate identifies the TARGET by its egg `bitmapindex` -- the same
// 1-based key the Comm pilot list and the radar labels use. This bridge lives
// in a complete-Mech TU (Reticle + Mech + Player all complete) and returns the
// 1-based index, or 0 for the binary's "hide the plate" case.
//
// GUARDED DEVIATION [T2, marked]: the binary reads `target+0x190` on ANY target
// entity; our compiled layouts differ per class (the databinding rule), so the
// mech test is explicit -- the same `IsDerivedFrom(Mech::ClassDerivations)`
// gate emitter.cpp uses. Our world-pick can target terrain and structures,
// which the 1995 pick could not, so this guard is load-bearing here.
//
int BTReticleTargetPlate(void)
{
if (application == 0)
{
return 0;
}
Entity *view = application->GetViewpointEntity();
if (view == 0 || !view->IsDerivedFrom(*Mech::GetClassDerivations()))
{
return 0;
}
Entity *target = ((Mech *)view)->targetReticle.targetEntity;
if (target == 0 || !target->IsDerivedFrom(*Mech::GetClassDerivations()))
{
return 0;
}
Player *owner = ((Mech *)target)->GetPlayerLink();
if (owner == 0)
{
return 0;
}
int index = owner->playerBitmapIndex;
return (index > 0 && index <= 8) ? index : 0;
}