scoring: restore the type-0 INTERCEPTOR -- per-hit inflicted credit was live all along
Players reported scoring and K/D going screwy on 4.11.817. Cause: build 787
(#45/#134) retired the port's per-hit inflicted crediting as an "invention",
on the strength of a KB claim that the type-0 score handler was dead code.
That claim was wrong.
BTPlayer overrides Dispatch -- vtable @00513300 slot 3 = FUN_004bffa0 -- and
splits type 0 off BEFORE base dispatch:
if (msg->id == 0x16 && msg->type == 0) FUN_004c0200(...); // ScoreInflicted
else base dispatch;
@004c0200 names itself in its own Verify string
("BTPlayer::ScoreInflictedMessageHandler") and computes
CalcInflicted(basis) -> negate if target==self -> x (targetTonnage/ownTonnage)
-> accumulate into +0x278. ScoreMessageHandler's type-0 arm Verify-rejects
precisely BECAUSE this interceptor guarantees type 0 never reaches it.
The port had the handler, faithfully reconstructed, and no interceptor -- so
Block B's inflicted reports all landed in the rejecting arm and banked 0.
Per-hit damage credit was silently deleted.
Independently corroborated by the ORIGINAL MANUAL'S SCORING CHART (filed as
reference/manual/scoring_chart.webp, from Lynx): "+1 each damage point scored
on opponent's armor" and "-1 each self-inflicted point of armor damage" -- the
negate-if-target-is-self arm exactly. Without that chart the dead-code note
would probably have stood.
Verified (scratchpad/night13/scoreverify.sh, cross-node kill, 2 nodes):
type-0 Verify rejections 0 (was firing on every non-lethal hit)
inflicted score rows 83 awards 0.98..25.00, all positive, tracking damage
kill path un-regressed type=2 award=4.88 kills=1, victim respawn x1
KB: combat-damage.md report B and the score-model paragraph rewritten, with
the full chart and THREE unreconciled rows flagged [T4] -- flat +500 kill vs
the benched 4.88, +1000 at game start, and -1000 eject / -500 ammo (which
would live in ScenarioRole::specialCaseDeathPenalty @role+0x20, read by the
port but authored nowhere in shipped content).
KNOWN, NOT FIXED HERE: in MP the running total does not persist -- currentScore
is flushed to the operator console and ZEROED (btplayer.cpp ~1219) because the
binary treats it as a console DELTA. Restoring the credit makes that very
visible (bench: totals climb to ~35 then reset). Needs its own decision; the
chart's "+1000 starting the game" implies a persistent total lives somewhere.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCJQkvq6G2JNrpVbA75tVZ
This commit is contained in:
co-authored by
Claude Opus 5
parent
4642129e76
commit
27721754da
@@ -731,6 +731,47 @@ void
|
||||
suppressConsole = 0; // this+0x258
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Dispatch (@004bffa0, vtable @00513300 slot 3)
|
||||
//
|
||||
// THE TYPE-0 INTERCEPTOR. Restored 2026-08-07 -- it was missing, and its
|
||||
// absence silently deleted per-hit inflicted scoring:
|
||||
//
|
||||
// * the binary carries all three score reports under ONE id (0x16) and
|
||||
// splits type 0 off here, BEFORE base dispatch, straight into
|
||||
// ScoreInflictedMessageHandler (@004c0200 -- which names itself in its own
|
||||
// Verify string, "BTPlayer::ScoreInflictedMessageHandler");
|
||||
// * ScoreMessageHandler's type-0 arm Verify-rejects ON PURPOSE, because this
|
||||
// interceptor guarantees type 0 never gets that far;
|
||||
// * the port had the handler, faithfully reconstructed, and NO interceptor.
|
||||
// Block B sends its inflicted report under Player::ScoreMessageID, so every
|
||||
// one of them landed in the rejecting arm and banked 0.
|
||||
//
|
||||
// The KB previously recorded @004c0200 as "in NO table entry: dead code" and
|
||||
// concluded 1995 folded an uninitialised stack float into the shooter's score
|
||||
// on every non-lethal hit -- and the port's per-hit crediting was retired as an
|
||||
// "invention" on that basis (#45/#134, build 787, the build players report
|
||||
// scoring regressed in). That reading was wrong: the handler is live through
|
||||
// THIS vtable slot, and the original manual's SCORING CHART independently
|
||||
// corroborates what it computes -- "+1 each damage point scored on opponent's
|
||||
// armor" and "-1 each self-inflicted point of armor damage", which is exactly
|
||||
// this handler's negate-if-target-is-self arm. combat-damage.md is corrected.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
void
|
||||
BTPlayer::Dispatch(Receiver::Message *what)
|
||||
{
|
||||
if (what != 0
|
||||
&& what->messageID == Player::ScoreMessageID
|
||||
&& ((BTPlayer::ScoreMessage *)what)->scoreType
|
||||
== BTPlayer::ScoreMessage::DamageInflictedScore)
|
||||
{
|
||||
ScoreInflictedMessageHandler((BTPlayer::ScoreMessage *)what);
|
||||
return;
|
||||
}
|
||||
Player::Dispatch(what);
|
||||
}
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// ScoreInflictedMessageHandler
|
||||
//
|
||||
@@ -2351,9 +2392,14 @@ void BTMechPostCombatReports(
|
||||
else if (damage_tally != 0.0f && shooter_player != 0)
|
||||
{
|
||||
//
|
||||
// Block B: the plain inflicted report. Wire fidelity only -- the 0x16
|
||||
// handler Verify-rejects type 0 and banks award 0 (1995 banked an
|
||||
// uninitialized stack float; see the handler's type-0 arm note).
|
||||
// Block B: the inflicted report -- "+1 each damage point scored on
|
||||
// opponent's armor" (original manual scoring chart). Goes out under
|
||||
// Player::ScoreMessageID with type 0, exactly as the binary does; the
|
||||
// Dispatch override (@004bffa0) intercepts it into
|
||||
// ScoreInflictedMessageHandler. It is NOT wire-fidelity-only -- the
|
||||
// old note here claimed the handler banks 0 because @004c0200 was
|
||||
// "dead code", which was a misreading of the vtable; corrected
|
||||
// 2026-08-07 and the interceptor restored.
|
||||
//
|
||||
BTPlayer::ScoreMessage inflicted(
|
||||
Player::ScoreMessageID,
|
||||
|
||||
Reference in New Issue
Block a user