The in-process console that replaces the operator for solo play: it owns
the mission clock and ends the race at the chosen length, then relaunches
to the setup menu -- the arcade launcher behavior in one binary.
- engine/APPMGR: gPerFrameHook -- a per-frame observer called on the game
thread in RunMissions (the marshal's engine-safe tick site).
- btl4console.{hpp,cpp}: BTLocalConsole_Install/MissionCompleted -- the
marshal watches for RunningMission, starts the clock, and dispatches
Application::StopMissionMessage at expiry (BT_MISSION_SECONDS overrides
for testing). Confirmed: StopMission cleanly ends the mission and
RunMissions returns.
- btl4fe: expose BTFrontEnd_LastMissionSeconds; Enter=LAUNCH / Esc=quit in
the menu loop; BT_FE_AUTOLAUNCH quick-launch (skips the menu).
- btl4main WinMain: front-end mode runs menu -> arms marshal -> mission;
when the marshal ends it, RELAUNCH a fresh instance (arcade launcher
model) -> lands back on the menu. This sidesteps BT's in-process
re-init fragility: a second mission in-process AV'd on stale gBT*
per-mission entity globals (gBTTerrainEntity et al., cdb-traced to
MakeEntityRenderables); a fresh process has none.
Verified: menu LAUNCH -> mission runs -> marshal stops it at the set
length -> RunMissions returns -> relaunch (3 distinct PIDs across a
multi-cycle run, no crash).
Remaining in Phase 5: the results screen (kills/deaths at stop).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
43 lines
1.0 KiB
C++
43 lines
1.0 KiB
C++
#pragma once
|
|
|
|
#include "app.h"
|
|
|
|
extern HWND ghWnd;
|
|
|
|
// BT412: when True, losing the console mid-race ends the mission (the
|
|
// marshaled/lobby path where the in-process console owns the clock);
|
|
// False = the arcade -net pod re-listens for its console. See APPMGR.cpp.
|
|
extern Logical gConsoleLossEndsMission;
|
|
|
|
// BT412: per-frame observer hook (the LocalConsole marshal's game-thread tick).
|
|
extern void (*gPerFrameHook)();
|
|
|
|
class ApplicationManager : public Node
|
|
{
|
|
public:
|
|
ApplicationManager(HINSTANCE hInstance, HWND hWnd, Scalar frame_rate);
|
|
~ApplicationManager();
|
|
|
|
void StartApplication(Application *new_app);
|
|
|
|
void RunMissions();
|
|
|
|
Scalar GetFrameRate()
|
|
{
|
|
Check(this);
|
|
return frameRate;
|
|
}
|
|
|
|
HINSTANCE GetHInstance() { return mHInstance; }
|
|
HWND GetHWnd() { return ghWnd; }
|
|
|
|
static ApplicationManager* GetCurrentManager() { return CurrentAppManager; }
|
|
|
|
protected:
|
|
static ApplicationManager* CurrentAppManager;
|
|
|
|
Scalar frameDuration, frameRate;
|
|
SChainOf<Application*> runningApplications;
|
|
HINSTANCE mHInstance;
|
|
};
|