gauge wave P3: wire the combat scoring feed (KILLS tracks combat)
The Comm roster + score gauges read 0 for 4 independent reasons (none was handler logic -- the BTPlayer ScoreMessage/VehicleDead/ScoreInflicted handlers were already reconstructed). Mapped by the scoring-feed-decode workflow; fixed all 4: - NO PRODUCER: combat only dispatched Entity::TakeDamageMessage, never a scoring message. Added producers (btplayer.cpp bridges, called from mech4.cpp): per-hit ScoreInflicted at the beam (:2171) + projectile (:831) damage dispatch -> SCORE; KillScore at the TARGET-DESTROYED edge (:2198) -> KILLS. senderMechID = the VICTIM (so the local player is credited via the !=our-mech branch, not the suicide-negate branch); dispatched to application->GetMissionPlayer(). - CROSS-FAMILY MECH OFFSETS: MECH_OWNING_PLAYER/TONNAGE/DAMAGE_BIAS read raw binary offsets (garbage in our 0x638 Mech). MECH_OWNING_PLAYER -> Entity::GetPlayerLink() (NULL for the ownerless dummy); tonnage/bias stubbed 1.0/0.0 (bring-up). - NULL scenarioRole: the BTMission role registry has no WinTesla analog, so every award path NULL-deref'd. CalcInflictedScore returns the neutral (damage+bias) when scenarioRole==0; DamageReceived guarded. - NULL-owner dummy: the KillScore sender-owner increment + StatusMessage now guard GetPlayerLink() (the dummy has none) so a solo kill credits only the local player. - DATABINDING: the PilotList read KILLS/DEATHS at raw offsets (pilot+0x27c/+0x200) that don't match our compiled layout -> silent 0. Repointed to the compiled members via bridges (BTPilotKills/BTPilotDeaths -> BTPlayer::GetKillCount/GetDeaths). ⚠ ROOT-CAUSE of the empty scoreboard: the PilotList SELECT-TARGET highlight did a raw-offset deref (*(local+0x284) objectiveMech, then *(tgt+0x190)) that AV'd on our layout -- caught silently by the SEH GuardedExecute, aborting Execute BEFORE the KILLS/DEATHS draw. Replaced with BTPilotIsSelected (accessors + GetPlayerLink). - SCORE persistence: PlayerSimulation's 10s flush zeroed currentScore (the binary's console delta); now only flushes/zeros when a console host exists (solo keeps the running score for the gauge + CalcRanking). Verified DBASE+dev gauges (BT_SCORE_LOG): SCORE climbs +5.83/hit -> 164; on the kill KILLS 0->1, and the Comm roster RENDERS KILLS=1 (screenshot). No crash. Follow-ups (noted): DEATHS=1 is a pre-existing spawn/respawn-handshake artifact (not from the producers -- the dummy's GetPlayerLink is NULL so no VehicleDead is posted; confirmed killCount=1 not 2); RANK=-1 is CalcRanking's non-scoring mark (Plasma serial surface, invisible on dev); MP VehicleDead/tonnage/role registry remain per the plan. Diagnostics kept: BT_SCORE_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
f998f2a023
commit
34aaa7dda4
@@ -611,6 +611,9 @@ static int gEnemyDestroyed = 0;
|
||||
// BRING-UP: the spawned target/enemy mech (defined in btplayer.cpp). The player
|
||||
// mech locks onto it as its current target each frame (see targeting step below).
|
||||
extern Entity *gEnemyMech;
|
||||
// gauge scoring wave: producers (btplayer.cpp) -- feed the scoreboard from combat.
|
||||
extern void BTPostDamageScore(Entity *victim, Scalar damage); // per-hit SCORE (ScoreInflicted)
|
||||
extern void BTPostKillScore(Entity *victim, Scalar damage); // KILL (+ MP death)
|
||||
|
||||
// Mech target slots (verified vs the binary's weapon/fire path, part_013.c):
|
||||
// mech+0x37c Point3D current target world position (range/aim source)
|
||||
@@ -829,6 +832,9 @@ static void
|
||||
Entity::TakeDamageMessageID, sizeof(Entity::TakeDamageMessage),
|
||||
0 /*inflictor id: bring-up*/, zone, dmg);
|
||||
tgt->Dispatch(&take_damage);
|
||||
// gauge scoring wave (Step 6): a projectile hit credits SCORE too
|
||||
// (tgt == gEnemyMech here; local player is the viewpoint shooter).
|
||||
BTPostDamageScore((Entity *)tgt, p.damage);
|
||||
DEBUG_STREAM << "[projectile] IMPACT damage=" << p.damage << " zone=" << zone << "\n" << std::flush;
|
||||
}
|
||||
}
|
||||
@@ -2170,6 +2176,10 @@ void
|
||||
dmg);
|
||||
gEnemyMech->Dispatch(&take_damage);
|
||||
|
||||
// gauge scoring wave (Step 6): credit the local player for damage
|
||||
// dealt -> SCORE climbs per hit (currentScore += tonnageRatio*award).
|
||||
BTPostDamageScore(gEnemyMech, kShotDamage);
|
||||
|
||||
Scalar s = ((Mech *)gEnemyMech)->Zone(zone)->damageLevel; // [0,1], 1.0=destroyed (engine base field)
|
||||
DEBUG_STREAM << "[damage] hit zone " << zone << "/" << zc
|
||||
<< " structure=" << s << "\n" << std::flush;
|
||||
@@ -2190,6 +2200,11 @@ void
|
||||
{
|
||||
gEnemyDestroyed = 1;
|
||||
|
||||
// gauge scoring wave (Step 7): credit the KILL to the local player
|
||||
// -> KILLS 0->1 (senderMechID = the VICTIM, so the !=our-mech branch
|
||||
// fires; the ownerless dummy yields no death, DEATHS stays 0).
|
||||
BTPostKillScore(gEnemyMech, kShotDamage);
|
||||
|
||||
// Death explosion at the target.
|
||||
Origin death_origin = ((Mech *)gEnemyMech)->localOrigin;
|
||||
Explosion::MakeMessage death_exp(
|
||||
|
||||
Reference in New Issue
Block a user