Q2PRO-X 1.6 Beta 5 by ly — Q2PRO-X 1.6 Beta 5 Game Statistics and Demo Auto-Statistics Guide
The complete guide in HTML. The original DOCX is available from its documentation card.
Q2PRO-X 1.6 Beta 5 by ly
Q2PRO-X 1.6 Beta 5 Game Statistics and Demo Auto-Statistics Guide
Project author: ly
Recording indexing, personal figures, filters and privacy
English edition • Q2PRO-X 1.6 Beta 5 by ly • 2026-10-10
Contents
The entries are links: click one to jump to that section.
1. The vocabulary without which the numbers lie
2.1. The settings page in full
4.4. Three actions, and how they differ
4.5. How this works in the background
6. What the client can actually learn from a recording
6.3. The Data tab is the honest report
8.3. There are fewer matches than demos
What Game Statistics does
Q2PRO-X can analyse your own match recordings and turn them into a readable picture: how many matches you played, of what kind, on which maps, against whom, and with what result. Everything is computed locally, on your own machine, from demo files you already have. Nothing is sent anywhere.
The key difference from an ordinary in-mod counter: statistics do not ask the server and do not take the in-game scoreboard on trust. They analyse the recordings and show only what the recordings really carry, keeping "unknown" honestly separate from zero.
| The main idea. Automatic collection is off by default. Until you enable it or press Refresh, the client scans and parses nothing in the background. |
|---|
What you can learn
1. The vocabulary without which the numbers lie
Q2PRO-X uses these five terms strictly and never blurs them. That is exactly why its numbers differ from "how many demo files do I have".
| Term | What it means |
|---|---|
| Observed Session | One distinguishable connection epoch in a recording. It may contain spectating, warmup, settings testing or real play. It is neither a launch count nor automatically a match. |
| Active Play | An interval where mod-authoritative state identifies you as a spawned player rather than a spectator. Zero frags do not negate active play. |
| Official Match | A live scoring interval established by the active mod's match phase. OpenTDM warmup and countdown are excluded; ordinary continuous OpenFFA play needs no separate ready gate unless the server exposes warmup explicitly. |
| Meaningful Personal Match | An Official Match in which you have an accepted positive personal contribution: a frag, a scoring kill or an objective score. This is the only class of match eligible for personal intro statistics. |
| Spectator Interval | An interval positively identified as spectator/chase state by the mod's recorded truth. Absence of frags alone never proves it. |
Two practical consequences follow:
1. The match count is almost never equal to the number of demo files — and that is correct.
2. If the mod did not record what a conclusion needs, Q2PRO-X writes "unknown" instead of inventing a zero.
2. Where everything lives
| What | Menu path |
|---|---|
| Statistics settings | Main menu → Options → Advanced Q2PRO-X → Game Statistics |
| Which personal facts the intro may show | Main menu → Primary Settings Masters → Intro Statistics Content |
| Demo browser | Main menu → Options → Advanced Q2PRO-X → Demo Browser |
| Demo player and analytics | Main menu → Options → Advanced Q2PRO-X → Demo Player → Demo Analytics |
The statistics window itself opens from the Open game statistics row on the settings page, from the game_stats_open command, or from the toggle key you assign.
2.1. The settings page in full
Game Statistics
| Type | Section | Row | Variable or target | What it does |
|---|---|---|---|---|
| Section | Collection | Collection | ||
| Toggle | Collection | Automatic statistics | cl_game_stats_auto | cl_game_stats_auto: refresh the demo library automatically on a plain cold start (no map, server, demo or URL on the command line). Off by default: nothing is scanned or parsed in the background until you ask for it. Applies immediately. |
| Slider | Collection | Period (days) | cl_game_stats_days | cl_game_stats_days: how far back to analyse, in whole local calendar days. 0 = today since local midnight, 7 = the last seven calendar days. Widening the window analyses only demos whose facts are missing; narrowing it analyses nothing. Applies immediately. |
| Slider | Collection | Minimum demo size (KB) | cl_game_stats_min_size_kb | cl_game_stats_min_size_kb: smallest demo Game Statistics looks at, in KiB. A few kilobytes of demo is a connect and a disconnect, not a match. Changing this re-answers instantly and reparses nothing; the Demo Browser still lists every file, and what was excluded is counted on the Data tab. Floor 1 KiB. Applies immediately. |
| Toggle | Collection | Statistics in intro | cl_game_stats_intro | cl_game_stats_intro: while the startup intro plays, show a short sequence of personal moments beside the main menu — one fact at a time. Needs both automatic statistics and the intro itself; with no qualifying match nothing is drawn. Applies immediately. |
| Navigation | Collection | Intro statistics content... | q2prox_game_statistics_intro | Choose every type of personal fact that may appear in the startup intro. All types are enabled by default. |
| Section | Actions | Actions | ||
| Navigation | Actions | Open game statistics... | game_stats_open | Open the Game Statistics overlay |
| Key | Actions | Toggle key | game_stats_toggle | game_stats_toggle: toggle the Q2PRO-X game statistics overlay |
| Navigation | Actions | Refresh statistics | game_stats_refresh | Incremental refresh: analyse only new or changed demos |
| Navigation | Actions | Rebuild current period | game_stats_rebuild | Re-analyse every demo in the current period from scratch |
| Navigation | Actions | Clear match facts | game_stats_cache_clear | Drop all stored match facts. File metadata, demos, favorites and playlists are kept. The overlay asks for confirmation. |
| Navigation | Actions | Demo library info | game_stats_info | Print the cache path, decoder versions, roots, counters and directory-walk totals to the console |
| Section | View & layout | View & layout | ||
| Slider | View & layout | Opacity | cl_game_stats_alpha | cl_game_stats_alpha: overlay background opacity (independent from scr_alpha) Applies immediately. |
| Slider | View & layout | Text scale | cl_game_stats_scale | cl_game_stats_scale: overlay text and chrome scale (independent from scr_scale); 0.1..3.0, step 0.01 Applies immediately. |
| Toggle | View & layout | Fullscreen | cl_game_stats_fullscreen | cl_game_stats_fullscreen: maximize the statistics overlay to fill the whole HUD; hides the resize grip. Applies immediately. |
| Toggle | View & layout | Show match details | cl_game_stats_show_details | cl_game_stats_show_details: show the detail pane beside the table. It describes the selected row instead of repeating it, and lists recent matches you can open or play. Hidden on Summary and Data, which are totals Applies immediately. |
| Toggle | View & layout | Alternate row colors | cl_game_stats_row_colors | cl_game_stats_row_colors: alternate row background colour for readability Applies immediately. |
| Toggle | View & layout | Pillarbox workspace | cl_game_stats_pillarbox_workspace | cl_game_stats_pillarbox_workspace: use the full presentation surface, including the pillarbox bars, as the overlay workspace Applies immediately. |
| Toggle | View & layout | Remember last tab | cl_game_stats_remember_tab | cl_game_stats_remember_tab: reopen the overlay on whichever tab (Summary / Matches / Opponents / Maps / Modes / Search / Data) was active last time. Applies immediately. |
3. First run in two minutes
1. Open Main menu → Options → Advanced Q2PRO-X → Game Statistics.
2. Check Period (days). The default is 7. These are whole local calendar days: 0 means today since local midnight, 7 means the last seven calendar days.
3. Press Refresh statistics. The client analyses only new and changed recordings.
4. Press Open game statistics.
5. Look at the totals on the Summary tab. If the result looks empty, open the Data tab — it explains exactly what stayed unknown, and why.
If you want the refresh to happen by itself on an ordinary cold launch, enable Automatic statistics.
3.1. Who counts as you
By default the current nickname from the name variable counts. It is always included.
If you have played under several nicknames, add them to your list of names. The statistics window has a dedicated picker for this: it lists the names your own recordings were made under, with how many demos carry each and when it was last used. Clicking a row adds or removes that name.
| Variable | Accepted values | Description |
|---|---|---|
| cl_game_stats_names | empty = just the current name; otherwise up to 32 comma-separated aliases, always plus the current name | Comma-separated list of your OTHER nicknames, counted as the same person. The current name is ALWAYS tracked as well — this list extends your identity, it does not replace it, so typing one old nickname can never stop counting the matches you are playing right now. Leading and trailing spaces are trimmed, empty entries dropped, duplicates folded, and comparison ignores letter case and the high-bit form server names use. The picker beside the field offers only names your own recordings were actually made under. Changing this list is a query over facts already in memory: no demo is ever re-read because you renamed yourself. |
| Other people's names never get in. Opponents, spectators and MVD2 participants are never offered in the picker: they are other people. Changing the list re-answers instantly and parses no recordings. |
|---|
4. Collecting the data
4.1. Automatic collection
| Variable | Accepted values | Description |
|---|---|---|
| cl_game_stats_auto | 0=off (default) / 1=refresh on an eligible cold start | Refresh the Demo Library automatically on an eligible cold idle start. Off by default, and off means genuinely zero background work: no directory walk, no demo parsing, no worker job and no intro cards. A direct +map, connect, demo or URL start is never eligible, so a launch that goes straight into a game never triggers analysis. |
Automatic collection only fires on an ordinary cold launch: no map, server, demo or URL on the command line. That is the same condition the startup intro uses.
4.2. The analysis period
| Variable | Accepted values | Description |
|---|---|---|
| cl_game_stats_days | 0 .. 3650 days, default 7 | Statistics period, in whole LOCAL CALENDAR days. 0 means today since local midnight; 7 means from local midnight seven calendar days ago, inclusive. The cutoff is converted through the OS timezone and DST rules, so a 23- or 25-hour day is handled correctly; it is never now minus N*86400 and never a date taken from the file name. Widening the window analyses only demos whose match facts are missing. Narrowing it analyses nothing at all. |
One detail matters: widening the period analyses only those recordings whose facts are still missing. Narrowing it analyses nothing at all — it simply stops showing the surplus.
4.3. Minimum recording size
| Variable | Accepted values | Description |
|---|---|---|
| cl_game_stats_min_size_kb | 1 .. no maximum, in KiB, default 40 | Smallest demo, in kibibytes, that Game Statistics will look at. A few kilobytes of demo is a connect and a disconnect, not a match, and counting those distorts every rate on the Summary tab. This is a filter over facts already in memory: changing it re-answers instantly and reparses nothing, and the Demo Browser still lists every file regardless. Excluded files are counted on the Data tab rather than silently dropped. The floor is 1 KiB; there is no ceiling, because how large a real match has to be is your judgement. |
A few kilobytes of demo is a connect and a disconnect, not a match. Changing the threshold re-answers instantly and reparses nothing; the demo browser still lists every file, and how many were excluded is visible on the Data tab.
4.4. Three actions, and how they differ
| Action | Command | What it does |
|---|---|---|
| Refresh statistics | game_stats_refresh | Analyses only new and changed recordings. Everything already known is reused. |
| Rebuild current period | game_stats_rebuild | Re-analyses every recording in the period from scratch. Slower, and the honest thing to do after the analysis itself changes. |
| Clear match facts | game_stats_cache_clear | Drops every stored match fact. File metadata, demos, favourites and playlists are kept. It asks for confirmation first. |
4.5. How this works in the background
Analysis runs in one serial background worker and never blocks the game. The recording folders are walked exactly once per data generation; the demo browser, the statistics window and the intro personal-fact layer are all queries over that one published snapshot, not independent disk walks of their own.
The result lives in one shared index file, q2pro-x/demo_index.dat, in the game's base directory. One file per installation: it does not multiply across mod folders. The write is atomic — a temporary file followed by a replace — so an interrupted refresh cannot leave a damaged index behind.
The demo browser's user intent (favourites, playlists) is stored separately and is never removed by clearing facts.
5. The statistics window
The window opens over the game, moves, resizes and closes with Esc. Its title bar carries a gear button that opens the statistics settings page in the menu.
5.1. Seven tabs
| Tab | What it shows |
|---|---|
| Summary | Totals for the selected period: matches, wins and losses, frags, favourite map and mode. |
| Matches | Every match as a row, grouped by mode. Double click to play the demo. |
| Opponents | Who you played against. The names come from the final scoreboard, the only place a client demo carries them. |
| Maps | Maps: how many matches, wins and losses, frags, and when you last played there. |
| Modes | Totals per game mode: duel, FFA, TDM and the rest. |
| Search | Search by any part of a word: map, opponent name, mod, mode, demo file name. Matching is case-insensitive. |
| Data | What was analysed and what stayed unknown: files, facts, and the reasons a result is missing. |
5.2. The detail pane
The pane on the right describes the selected row instead of repeating it. Its contents follow the tab. On Summary and Data the pane is hidden: those tabs are totals, and there is no selected row to describe.
The splitter between the table and the pane can be dragged with the mouse.
5.3. Playing a recording
The Play button plays the demo of the selected match; a double click on the row does the same. If the recording was made under a different mod, the game switches to it first.
The button is always on screen. When it is unavailable, its hint says what would make it work: select a match row on the Matches or Search tab.
5.4. Appearance and layout
| Setting | What it does |
|---|---|
| Opacity | Background opacity of the window, independent of the general HUD opacity |
| Text scale | Text and chrome scale of the window, independent of the general HUD scale |
| Fullscreen | Maximizes the window to fill the HUD and hides the resize grip |
| Show match details | Shows or hides the detail pane |
| Alternate row colours | Readability of long tables |
| Pillarbox workspace | Use the full presentation surface, including the side bars |
| Remember last tab | Reopen the window on whichever tab was active last time |
Window position and size are saved automatically. The game_stats_layout_reset command restores the default layout.
6. What the client can actually learn from a recording
6.1. Formats
Both your own client recordings .dm2 and multi-view recordings .mvd2 are analysed. The format decides what information is available at all:
6.2. Mods
Match boundaries come from the active mod's match phase, not from guessing at the score:
Q2PRO-X does not pretend to understand a mod it does not understand. If the match phase is not recognised, an interval does not become an Official Match.
6.3. The Data tab is the honest report
This is where you see why the result looks the way it does:
If there was nothing to parse, the parse time reads as idle rather than as a measured zero: an empty phase must not look like a measurement.
7. Privacy and boundaries
8. Troubleshooting
8.1. Statistics are empty
1. Open the Data tab: it says directly whether files were found and what happened to them.
2. Check the period: your recordings may be older than the selected window.
3. Check the minimum recording size: very short connections are excluded deliberately.
4. Check your list of names: if you played under a different nickname, add it.
5. Press Refresh statistics — with automatic collection off, nothing is analysed by itself.
8.2. The numbers look stale
Press Refresh statistics. If you widened the period, only the missing recordings are analysed. If the result still looks wrong, press Rebuild current period.
8.3. There are fewer matches than demos
That is expected. A demo file is not a match. Observed Session, Active Play and Official Match from section 1 stand between them. Spectating, warmup and short connections are not counted as matches.
8.4. Opponents are not listed
A client recording only knows opponent names from the final scoreboard. If a match never reached it — because you disconnected earlier, for example — its opponents stay unknown for that recording.
8.5. Diagnostics
The game_stats_info command prints to the console the index path, the schema and decoder versions, the list of recording root folders, the analysis window, counters for discovered/parsed/reused, the number of directory walks, and the state of the background worker.
The same information is opened by the Demo library info row on the settings page.
9. Quick reference
| Task | What to do |
|---|---|
| See the totals | Open game statistics → Summary tab |
| Understand why it is empty | The Data tab |
| Count an old nickname | The name picker in the statistics window |
| Collect data now | Refresh statistics |
| Recompute everything | Rebuild current period |
| Collect automatically | Automatic statistics → Yes |
| Play a match back | Double click a row on the Matches tab |
| Forget what was collected | Clear match facts |