Two player requests from the six-player night, one cause between them: the lobby treated hosting as somewhere you GO, and a role you could only have by being the machine that went there. Hosting no longer leaves the setup page. HOST STEAM GAME claims the lobby and stays put: the button becomes CLOSE LOBBY, joiners list under GAME LENGTH as they arrive (callsign, vehicle, a cam tag, and WRONG BUILD where launch would refuse - the reasons launch might say no, standing on the same screen as the launch button), and the track, weather and length stay changeable the whole time, republished to the members' rooms as they change. LAUNCH GAME launches the whole room from right there, and after the race the host lands back on the same page, lobby still open, roster still live. The room screen still exists - for members, whose flow is untouched. Mechanically: RPL4Lobby_Host's create-then-run-the-room split into HostOpen (create, publish, return) plus Pump/PublishSetup/RosterLines/ HostLaunch/Leave, with the owner-launch and leave blocks extracted from the room's message loop so both screens call the same code. The menu gets a timer that pumps Steam callbacks - nothing else pumps them with no room running - and republishes dirty picks at most every 1.5s, because Steam throttles chatty writers. One wrinkle: the lobby publishes through the RPL4FrontEnd_* accessors, which read globals the menu only wrote on the way OUT, so publishing from a live menu syncs them first or every publish would carry the previous visit's picks. And a member's Live Cam pick now works. It was host-only by design - the pick published as member data and the room displayed it, but the egg builder never read it, so a member who chose Live Cam raced their default loadout instead (the "default Quark - red" Cyd was listed as). The pick now rides the whole chain - lobby row, hosted-pilot table, egg entry as hostType=1 / vehicle=camera - and the member machine sets its own cockpit from its own pick at launch, before the renderers build, exactly as the host and playback already did. One rule holds it together: SOMEBODY has to race. If every pilot picks cam, every pick is stripped and the log says so - a grid of cameras has nothing to point at, and is also the shape known to hang the map load. The playtest launch failures while a member had cam picked are not directly explained - no logs were kept from those attempts - but the half-implemented state they ran in (flag published, egg ignoring it) is exactly the seam this closes, and the failure cannot recur in that form: the pick is now either honoured everywhere or stripped everywhere. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
167 lines
5.5 KiB
C
167 lines
5.5 KiB
C
#pragma once
|
|
|
|
#include "..\munga\style.h"
|
|
|
|
//########################################################################
|
|
//############################ RPL4 Front End ############################
|
|
//########################################################################
|
|
//
|
|
// The in-game race setup: shown when the game starts with no egg, no
|
|
// network, and no mission-review mode. Presents the Death Race catalog
|
|
// (track / vehicle / color / badge / time / weather / length + pilot
|
|
// name), builds the mission egg locally - the same NotationFile text
|
|
// TeslaConsole generated, including the pre-rendered plasma name
|
|
// bitmaps - and hands its path back for the standard egg-load path.
|
|
//
|
|
// Returns True with egg_path_out filled when the player launches;
|
|
// False if they close the window instead.
|
|
//
|
|
Logical
|
|
RPL4FrontEnd_Run(
|
|
HINSTANCE instance,
|
|
HWND main_window,
|
|
char *egg_path_out,
|
|
int egg_path_size
|
|
);
|
|
|
|
// The race length (seconds; 0 = endless) selected at the last
|
|
// successful launch - the local console marshals the mission with it.
|
|
int
|
|
RPL4FrontEnd_LastMissionSeconds();
|
|
|
|
// [pilots]-order pilot names of the last launched race (owner first),
|
|
// comma separated - labels for the network console's results intake.
|
|
const char *
|
|
RPL4FrontEnd_LastPilotNames();
|
|
|
|
//
|
|
// The callsign the player typed on the setup screen (persisted in
|
|
// pilot.cfg). The lobby publishes this as the member name: what somebody
|
|
// writes in the box is what the room and the race should call them.
|
|
// Empty, or still the untouched default, when they have never set one.
|
|
//
|
|
const char *
|
|
RPL4FrontEnd_Callsign();
|
|
|
|
// How the last Run() ended: a plain race, hosting a network race (the
|
|
// console marshals the other pods), or entering one as a member pod
|
|
// (the lobby owner's console marshals us; no local egg, no console).
|
|
enum FELaunchMode
|
|
{
|
|
FELaunchSingle = 0,
|
|
FELaunchHost,
|
|
FELaunchMember
|
|
};
|
|
int
|
|
RPL4FrontEnd_LastLaunchMode();
|
|
|
|
// The player's persisted loadout (lobby member data). Buffers: 24/16/24.
|
|
void
|
|
RPL4FrontEnd_GetLoadout(char *vehicle, char *color, char *badge);
|
|
|
|
//---------------------------------------------------------------
|
|
// This player's mission setup as display names. Only the host's
|
|
// picks decide the mission, so the lobby owner publishes these for
|
|
// everyone else to read - names rather than keys, because the map
|
|
// catalog differs between race and football and resolving it here
|
|
// saves the room from knowing which table a key belongs to.
|
|
//---------------------------------------------------------------
|
|
const char *
|
|
RPL4FrontEnd_SelectedMapName();
|
|
const char *
|
|
RPL4FrontEnd_SelectedTimeName();
|
|
const char *
|
|
RPL4FrontEnd_SelectedWeatherName();
|
|
const char *
|
|
RPL4FrontEnd_SelectedLengthName();
|
|
|
|
//---------------------------------------------------------------
|
|
// Catalog key -> display name, for the keys that travel as lobby
|
|
// member data. Unknown keys come back unchanged rather than blank.
|
|
//---------------------------------------------------------------
|
|
const char *
|
|
RPL4FrontEnd_VehicleNameForKey(const char *key);
|
|
const char *
|
|
RPL4FrontEnd_PositionNameForKey(const char *key);
|
|
const char *
|
|
RPL4FrontEnd_TeamNameForKey(const char *key);
|
|
|
|
//---------------------------------------------------------------
|
|
// Football team / position: the catalogs, and this player's picks.
|
|
// The lobby publishes the picks as member data and lets members
|
|
// cycle them in the room; the host's egg builder honors them.
|
|
//---------------------------------------------------------------
|
|
int
|
|
RPL4FrontEnd_TeamCount();
|
|
const char *
|
|
RPL4FrontEnd_TeamName(int index);
|
|
const char *
|
|
RPL4FrontEnd_TeamKey(int index);
|
|
|
|
int
|
|
RPL4FrontEnd_PositionCount();
|
|
const char *
|
|
RPL4FrontEnd_PositionName(int index);
|
|
const char *
|
|
RPL4FrontEnd_PositionKey(int index);
|
|
|
|
int
|
|
RPL4FrontEnd_GetTeamIndex();
|
|
void
|
|
RPL4FrontEnd_SetTeamIndex(int index);
|
|
int
|
|
RPL4FrontEnd_GetPositionIndex();
|
|
void
|
|
RPL4FrontEnd_SetPositionIndex(int index);
|
|
|
|
// True when this player's setup menu has Football selected (the host's
|
|
// pick decides the mission; members use it to know what to show).
|
|
Logical
|
|
RPL4FrontEnd_IsFootballSelected();
|
|
|
|
//
|
|
// True when this player's setup menu has YOUR ROLE on Live Cam. Only the
|
|
// HOST's pick is acted on - the host is the one that writes the egg - so
|
|
// the lobby publishes this and then shows it against the owner's row
|
|
// only. A member who picked it still races, which is what their row goes
|
|
// on saying.
|
|
//
|
|
Logical
|
|
RPL4FrontEnd_IsCameraRole();
|
|
|
|
// Hosted-race pilots fed by the Steam lobby: overrides the
|
|
// RP412HOSTPODS parsing with real personas and loadouts. owner_address
|
|
// is this pod's mesh IP (the FakeIP); count 0 clears the override.
|
|
struct FEHostedPilot
|
|
{
|
|
char address[64]; // mesh (game port) address for [pilots]
|
|
char name[32];
|
|
char vehicle[24];
|
|
char color[16];
|
|
char badge[24];
|
|
// football: the member's own picks, empty = assign one for them
|
|
char team[32]; // team key ("Red/Pink", ...)
|
|
char position[16]; // "runner" / "crusher" / "blocker"
|
|
|
|
// the member picked Live Cam: hostType=1, vehicle=camera in the egg.
|
|
// Somebody still has to race - the egg builder strips every cam pick
|
|
// if honouring them would leave nothing to point a camera at.
|
|
Logical camera;
|
|
};
|
|
void
|
|
RPL4FrontEnd_SetHostedPilots(
|
|
const char *owner_address,
|
|
const FEHostedPilot *pilots,
|
|
int count
|
|
);
|
|
|
|
// The between-races results screen: shows the last mission's final
|
|
// scores (from the local console) with a CONTINUE button. Returns
|
|
// immediately when there are no results (first boot). False only if
|
|
// the player closed the window instead of continuing.
|
|
Logical
|
|
RPL4FrontEnd_ShowResults(
|
|
HINSTANCE instance,
|
|
HWND main_window
|
|
);
|