FIXES (compile clean; exe link pending -- a game client still holds btl4.exe): #57 respawn latch: deathPending was released in ONE place (btplayer.cpp:343) and only if a LATER re-post happened to find the mech alive -- so if the +5s re-post landed before the drop-zone reply, or never arrived, the flag stayed set while the pilot respawned and fought on, and their NEXT death hit the dedup at :391 and was swallowed whole (no warp, no tally, no hunt) for the rest of the process. Tonight 3 of 3 deaths in the final round were swallowed, each by a player who had respawned successfully earlier in the same process. Clear moved to the actual completion point (after Mech::Reset at the drop zone) + the four abandon paths that also stranded it. Cycle logging promoted to always-on (START / RESET / SWALLOWED warning) + a RESPAWN matchlog record. #58 reticle callsign plate drew as a SOLID RECTANGLE on some maps: my dpl2d_DrawTexturedRect bound a texture but never set COLOROP/ALPHAOP, and L4D3D.cpp:1085 sets both to SELECTARG1 from TFACTOR (ignores the texture, fills with a constant). Which state was live depended on what the 3D pass drew last -- hence 'depends on the level'. Now sets MODULATE texture x diffuse for both channels and restores. Latent sibling noted (CameraHUDDrawQuad, same omission). ROOT-CAUSE DOC (no code): docs/KD_SCOREBOARD_PLAN.md. Headlines: - the port reads DEATHS from the WRONG FIELD: the binary's PilotList draws +0x27c/+0x280; we labelled +0x280 'pad_0x280', never write it, and substituted the engine's Player::deathCount (+0x200, the respawn identity number seeded to -2) -> remote rows read a clamped fake 0 by construction; - BTPlayer::VehicleDeadMessageHandler @0x4c05c4 is MISSING from our decomp export (functions_index.tsv jumps 4c052c -> 4c083c, verified) -- that silence is what produced the 'pad' belief. An absent function is not evidence of an absent behaviour; - neither counter rides an update record, so divergence never self-heals and bystanders show 0/0 all mission; BTPlayerCountObservedDeath is unreachable dead code; - 'a kill I didn't earn' = last-hitter-takes-all via lastInflictingID, and COLLISIONS count (5 of 47 deaths had a type=0 killing blow); - the phantom kill is authentic 1995 (the kill handler bumps the victim's killCount too); - btplayer.cpp:453 does simulationFlags |= 0x1 where the binary does ForceUpdate() -- bit 0 is DelayWatchersFlag and nothing clears it, so the first death of any pilot permanently disables ExecuteWatchers on that player's simulation. Filing separately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0166KTsC7ADm7VXEi1HF1jNg
This commit is contained in:
co-authored by
Claude Opus 5
parent
326023812a
commit
5174c638ce
@@ -664,8 +664,44 @@ void dpl2d_DrawTexturedRect(
|
||||
device->SetFVF(kVertexTexFVF);
|
||||
device->SetTexture(0, (IDirect3DTexture9 *)texture);
|
||||
|
||||
//
|
||||
// TEXTURE STAGE OPS -- explicitly, every time (Gitea #58). Binding a
|
||||
// texture is NOT enough: the fixed-function stage still has whatever
|
||||
// COLOROP/ALPHAOP the last drawer left, and this TU's own list path runs
|
||||
// UNtextured (`SetTexture(0, 0)`), so nothing here establishes them. In
|
||||
// particular `L4D3D.cpp:1085-1088` sets
|
||||
// COLOROP = ALPHAOP = D3DTOP_SELECTARG1 with ARG1 = D3DTA_TFACTOR
|
||||
// which makes the pipeline ignore the texture completely and fill with a
|
||||
// constant colour -- i.e. the callsign plate renders as a SOLID RECTANGLE.
|
||||
// Whether that state happens to be live depends on what the 3D scene drew
|
||||
// last, which is why the field report was "sometimes, depends on the level
|
||||
// and the background". MODULATE texture x diffuse for BOTH channels makes
|
||||
// the draw deterministic: colour = texel * diffuse, alpha = texel * diffuse,
|
||||
// so a 0x0000 texel (the transparent background of the 1bpp raster upload,
|
||||
// L4VIDEO.cpp LoadBitSliceTexture) stays invisible.
|
||||
//
|
||||
DWORD oCOp = 0, oCA1 = 0, oCA2 = 0, oAOp = 0, oAA1 = 0, oAA2 = 0;
|
||||
device->GetTextureStageState(0, D3DTSS_COLOROP, &oCOp);
|
||||
device->GetTextureStageState(0, D3DTSS_COLORARG1, &oCA1);
|
||||
device->GetTextureStageState(0, D3DTSS_COLORARG2, &oCA2);
|
||||
device->GetTextureStageState(0, D3DTSS_ALPHAOP, &oAOp);
|
||||
device->GetTextureStageState(0, D3DTSS_ALPHAARG1, &oAA1);
|
||||
device->GetTextureStageState(0, D3DTSS_ALPHAARG2, &oAA2);
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
||||
|
||||
device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(VertexTex));
|
||||
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, oCOp);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, oCA1);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG2, oCA2);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAOP, oAOp);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG1, oAA1);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAARG2, oAA2);
|
||||
device->SetTexture(0, oldTex);
|
||||
if (oldTex) oldTex->Release();
|
||||
device->SetFVF(kVertex2DFVF);
|
||||
|
||||
Reference in New Issue
Block a user