//===========================================================================// // matchlog.hpp -- per-peer MP forensic combat log (PORT tooling, 2026-07-22)// //---------------------------------------------------------------------------// // One compact machine-parseable text file per game instance recording the // combat-economy events this peer AUTHORITATIVELY owns. MP damage authority // is VICTIM-side (A shoots B -> zone resolution + armor math run on B's // machine), so no single peer sees the whole match: every player's file is // collected after a session and tools/matchcheck.py reconciles them -- // damage dealt vs received per pair, kill/death symmetry across observers, // out-of-economy amounts, replicant anomalies, disconnects. // // ARMING: BT_MATCHLOG=1 forces on, =0 forces off; unset -> auto-on when the // process command line carries "-net" (any networked/console launch, which // is every MP path -- join/join_lan/steam/menu). Solo stays silent. // FILE: matchlog_YYYYMMDD_HHMMSS_.txt in the working directory (the // install root the player bats run from) -- "send us the matchlog_* file". // // LINE FORMAT (every event): // t= w= st= // fflushed per line: a crash mid-match keeps everything up to the crash. // // EVENT TAGS: // HDR once at open: version/pid/machine/self/relay/cmdline // MISSION the app enters RunningMission (engine APP.cpp) // PEER_UP a game host came online (engine L4NET.CPP) // PEER_DOWN a game host dropped (engine L4NET.CPP) // VEHICLE a player got a mech (initial spawn + every respawn) // FIRE shooter-side beam-weapon damage submission (per shot) // PROJ shooter-side projectile/missile impact delivery // SPLASH shooter-side splash (cluster) delivery to a bystander // RAM shooter-side collision damage dispatch // DMG VICTIM-side applied TakeDamage (zone resolved, post level) // CRIT a critical subsystem destroyed by zone-damage cascade // DEATH a mech's death transition ran (fires on every observer too; // inst=M in the victim's own log is the authoritative one) // PLAYER_DEAD the owning player's death notification (deaths counter) // SCORE a score award folded into a player's currentScore //===========================================================================// #ifndef MATCHLOG_HPP #define MATCHLOG_HPP class EntityID; // Armed? Lazy one-time init (opens the file + writes HDR on first yes). int BTMatchLogActive(); // EntityID::GetHostID() is non-const while GetEntityID() returns a const // value -- const-safe host/local extractors for the event lines. int BTMatchHostOf(const EntityID &id); int BTMatchLocalOf(const EntityID &id); // The open log's file name ("" when not armed) -- consumed by the relay // auto-upload (L4NET BTRelayUploadMatchLog) at mission end. const char *BTMatchLogPath(); // Flush + close the file (upload wants a complete file on disk). Further // BTMatchLog calls become no-ops. void BTMatchLogClose(); // One event line; printf-style body appended after the standard prefix. // Safe no-op when not armed, but call sites on per-shot/per-hit paths should // still gate on BTMatchLogActive() to skip the varargs work. void BTMatchLog(const char *tag, const char *format, ...); #endif