#95: the SCOREBOARD banked one missile per salvo -- credit the DELIVERED amount

Two consumers of one impact, only one was ever verified: the victim gets
TakeDamage{amount=per-missile, burstCount=cluster roll} and applies it
burstCount times (armor was always right); the score post on the next line
sent the bare per-missile amount. An LRM10 salvo dealing 7-35 armor banked
3.5 points -- Rajel's "~3 points to score", to the digit.

Ground truth: the binary's score is the victim handler's tally (amount once
per applied burst @0x4a04da + crit bonuses) reported to the INFLICTING
player (the id-0x16 tail, deferred #45). The shooter-side stand-in now
posts amount x burstCount -- the identical figure handed to the victim, at
the identical one-post-per-TakeDamage granularity. Same pass:

* splash never credited score at all -- the binary tallies every
  TakeDamage; now posted per splash victim (amount x falloff bursts);
* the bridge credited the LOCAL player for ANY registered hit -- AI-master
  fire on the player, a dying mech's death-blast splash; now refused
  unless the shooter IS the local vehicle (MP unaffected: only local fire
  carries live damage on a node);
* direct-fire unchanged -- beams author burstCount=1 (emitter.cpp:355).

Verified per the harness doctrine: single-node field composition (madcat,
real fire, real enemy) 22/22 impact credits paired at damage x burst, zero
bare 3.33 posts; two-node replicant-victim run BOTH directions 31/31
paired across three missile authorings (3.33/2.0/5.0 per-missile) + 25-pt
ballistics, leftovers all burst-1 beam amounts. test-harness.md gains the
map=grass note (MP.EGG authors cavern/night; GOTO mechs shoot rock).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Joe DiPrima
2026-08-02 14:11:28 -05:00
co-authored by Claude Fable 5
parent 08ca66e5b5
commit 152249cb76
4 changed files with 42 additions and 7 deletions
+12 -1
View File
@@ -2162,7 +2162,7 @@ Logical BTResolveMessageBoard(Entity * /*tracked_mech*/, int *messageId, BitMap
// local (crediting) player is application->GetMissionPlayer(). Bridges (not inline
// in mech4.cpp) so the message construction lives in this complete-BTPlayer TU.
//
void BTPostDamageScore(Entity *victim, Scalar damage) // Step 6: per-hit SCORE
void BTPostDamageScore(Entity *victim, Scalar damage, Entity *shooter) // Step 6: per-hit SCORE
{
if (application == 0 || victim == 0)
{
@@ -2173,6 +2173,17 @@ void BTPostDamageScore(Entity *victim, Scalar damage) // Step 6: per-hit SCORE
{
return;
}
// The credit belongs to the SHOOTER, not the viewer: the binary reports the
// victim handler's damage tally to the INFLICTING player (the id-0x16 report
// tail @0x4a04da, deferred #45). This stand-in can only bank score on the
// LOCAL player, so refuse any post whose shooter is not the local vehicle --
// an AI master's fire on the player (SP), or a dying mech's death-blast
// splash, must not credit the viewer. MP is unaffected: only local fire
// carries live damage on this node.
if (shooter != (Entity *)local_player->GetPlayerVehicle())
{
return;
}
// ScoreInflicted (scoreType 0): senderMechID = the mech that TOOK the damage.
// -> ScoreInflictedMessageHandler: currentScore += tonnageRatio*CalcInflictedScore.
BTPlayer::ScoreMessage message(