Front end: post-mission results screen (kills/deaths scoreboard)
Completes the marshal chain: menu -> mission -> timed stop -> results -> relaunch. BT had no mission-end score flow; this builds one from the data the Comm MFD pilotList already tracks. - btl4console: at the timed stop (game thread, state still live) snapshot each roster pilot's kills/deaths via the BTResolveRosterPilot / BTPilotKills / BTPilotDeaths bridges; expose BTLocalConsole_ResultCount / GetResult. - btl4fe: BTFrontEnd_ShowResults -- a GDI green-on-black 'MISSION COMPLETE' scoreboard (PILOT / KILLS / DEATHS, slot 0 named from the menu), any key or ~12s to dismiss; store the last pilot name. - btl4main: show the scoreboard after a marshaled mission, before the relaunch. Verified: MISSION COMPLETE screen renders with the pilot row and the snapshotted score (0/0 on a no-combat test run; the data path is the same one the live Comm MFD reads). Phase 5 (front end) COMPLETE: menu + egg builder + marshal + timed stop + results + single-binary (relaunch) loop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,13 @@
|
||||
#include "appmgr.hpp" // gPerFrameHook
|
||||
#include "btl4console.hpp"
|
||||
|
||||
// The pilot roster + score bridges (btl4gau3.cpp / mechmppr.cpp / btplayer.cpp):
|
||||
// the pilotList reads them for the Comm MFD, and the marshal snapshots them at
|
||||
// the stop so the results screen has the final scores.
|
||||
extern void *BTResolveRosterPilot(int slot);
|
||||
extern int BTPilotKills(void *pilot);
|
||||
extern int BTPilotDeaths(void *pilot);
|
||||
|
||||
namespace
|
||||
{
|
||||
enum Phase { PhaseIdle, PhaseWaiting, PhaseRunning, PhaseStopped };
|
||||
@@ -22,6 +29,27 @@ namespace
|
||||
unsigned long gStartTick = 0;
|
||||
Application *gWatched = 0;
|
||||
|
||||
// Final scores snapshotted at the stop (roster order; slot 0 = local).
|
||||
enum { maxResults = 8 };
|
||||
struct Result { int kills, deaths; };
|
||||
Result gResults[maxResults];
|
||||
int gResultCount = 0;
|
||||
|
||||
void SnapshotResults()
|
||||
{
|
||||
gResultCount = 0;
|
||||
for (int slot = 0; slot < maxResults; ++slot)
|
||||
{
|
||||
void *pilot = BTResolveRosterPilot(slot);
|
||||
if (pilot == 0)
|
||||
break; // past the last occupied roster slot
|
||||
gResults[gResultCount].kills = BTPilotKills(pilot);
|
||||
gResults[gResultCount].deaths = BTPilotDeaths(pilot);
|
||||
++gResultCount;
|
||||
}
|
||||
DEBUG_STREAM << "[marshal] snapshot " << gResultCount << " pilot score(s)\n" << std::flush;
|
||||
}
|
||||
|
||||
//
|
||||
// The game-thread tick (called every frame while an application is live).
|
||||
//
|
||||
@@ -59,9 +87,11 @@ namespace
|
||||
else if (gMissionSeconds > 0 &&
|
||||
(GetTickCount() - gStartTick) >= (unsigned long)(gMissionSeconds * 1000))
|
||||
{
|
||||
// The console clock expired: stop the race exactly as the
|
||||
// arcade console did (StopMissionMessage on our own pod).
|
||||
// The console clock expired: snapshot the final scores (the
|
||||
// game state is still live here), then stop the race exactly
|
||||
// as the arcade console did (StopMissionMessage on our pod).
|
||||
DEBUG_STREAM << "[marshal] time expired -- stopping mission\n" << std::flush;
|
||||
SnapshotResults();
|
||||
Application::StopMissionMessage message(0);
|
||||
application->Dispatch(&message);
|
||||
gPhase = PhaseStopped;
|
||||
@@ -92,6 +122,20 @@ int BTLocalConsole_MissionCompleted()
|
||||
return (gPhase == PhaseStopped) ? 1 : 0;
|
||||
}
|
||||
|
||||
int BTLocalConsole_ResultCount()
|
||||
{
|
||||
return gResultCount;
|
||||
}
|
||||
|
||||
int BTLocalConsole_GetResult(int index, int *kills, int *deaths)
|
||||
{
|
||||
if (index < 0 || index >= gResultCount)
|
||||
return 0;
|
||||
if (kills) *kills = gResults[index].kills;
|
||||
if (deaths) *deaths = gResults[index].deaths;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BTLocalConsole_Uninstall()
|
||||
{
|
||||
gPerFrameHook = 0;
|
||||
|
||||
Reference in New Issue
Block a user