Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion content/baseoq4/pak0/guis/mainmenu.gui
Original file line number Diff line number Diff line change
Expand Up @@ -13649,7 +13649,7 @@ windowDef Desktop
notime 1

onTime 0 {
set "cmd" "MAPScan" ;
set "cmd" "refreshSaveGameList" ;

transition "p_loadgame::rect" "$d_main_l::rect" "$d_main::rect" "0" ;
set "p_loadgame::visible" "1" ;
Expand Down Expand Up @@ -13712,6 +13712,7 @@ windowDef Desktop
notime 1

onTime 0 {
set "cmd" "refreshSaveGameList" ;
transition "p_savegame::rect" "$d_main_l::rect" "$d_main::rect" "0" ;
set "p_savegame::visible" "1" ;
transition "t_save_title::forecolor_w" "0" "0.5" "150" ;
Expand Down Expand Up @@ -14119,6 +14120,13 @@ windowDef Desktop
if ( "gui::ingame" == 2 ) {
set "cmd" "GetCVarValue g_corpseRemoveDelayMP cvar_g_corpseRemoveDelayMP" ;
}
if ( "desktop::dest" == 4 ) {
set "cmd" "refreshKeyBindings" ;
} else if ( "desktop::dest" == 22 ) {
set "cmd" "refreshSystemSettings" ;
} else if ( "desktop::dest" == 36 ) {
set "cmd" "refreshAudioSettings" ;
}

transition "p_settings::rect" "$d_main_l::rect" "$d_main::rect" "0" ;

Expand Down Expand Up @@ -14445,6 +14453,7 @@ windowDef Desktop
notime 1

onTime 0 {
set "cmd" "refreshMods" ;
set "pop_p_mods::visible" "1" ;
namedevent "p_btns::hideMain" ;
transition "pop_mods_black::backcolor_w" "0" "0.94" "200" ;
Expand Down Expand Up @@ -18494,6 +18503,7 @@ windowDef Desktop
}

onAction {
set "cmd" "refreshKeyBindings" ;
set "p_settings_ctrls::visible" "1" ;
set "p_settings_game::visible" "0" ;
set "p_settings_sys::visible" "0" ;
Expand Down Expand Up @@ -18693,6 +18703,7 @@ windowDef Desktop
}

onAction {
set "cmd" "refreshSystemSettings" ;
set "p_settings_ctrls::visible" "0" ;
set "p_settings_game::visible" "0" ;
set "p_settings_sys::visible" "1" ;
Expand Down Expand Up @@ -18794,6 +18805,7 @@ windowDef Desktop
}

onAction {
set "cmd" "refreshAudioSettings" ;
set "p_settings_ctrls::visible" "0" ;
set "p_settings_game::visible" "0" ;
set "p_settings_sys::visible" "0" ;
Expand Down
4 changes: 4 additions & 0 deletions docs/dev/release-completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ is `docs/dev/macos-moltenvk-decision.md`.

## Ready For Changelog

- [x] Opening the in-game menu in single-player no longer waits for save-game, mod, key-binding, audio-device, display-mode, or multiplayer-model enumeration. The pause screen now activates immediately and refreshes each potentially expensive catalog only when the player opens the page that needs it; its background, fallback levelshot, and music are also re-referenced during normal level precaching instead of on the first Escape press.
- [x] Bitmap GUI text now selects its 12-, 24-, or 48-point source atlas using the final viewport enlargement as well as the authored 640x480-era text scale. Menus and HUD text therefore stay sharp at 1080p, 1440p, and 4K without the community workaround of forcing both font-limit CVars to zero, while text layout and low-resolution behavior remain unchanged.
- [x] Developer and nightly builds now regenerate their Git-derived version header on every build invocation while avoiding downstream recompilation when the value is unchanged. The console banner, executable metadata, engine, and both game modules therefore report the current commit without requiring a fresh Meson setup.
- [x] The built-in `dmap` compiler now resolves Quake 4 `func_group` entities before compiling geometry, just like the retail compiler and runtime map loader. This fixes false world leaks and missing grouped world geometry when compiling editable retail or custom `.map` sources, including the `hangar1` failure reported in GitHub discussion #124.
- [x] Linux save and configuration directories now work when an explicit home/save path contains an ordinary ellipsis (`...`) or another repeated-dot name. Directory creation still rejects a complete `..` parent component, preserving traversal protection without mistaking legitimate absolute paths for traversal attempts. This fixes the persistent-settings failure reported in GitHub issue #127.
- [x] Players can now choose smooth, sharp-mip, or deliberately pixelated material-texture sampling with the restored archived `image_filter` setting. All six retail Quake 4 filter names work on OpenGL and experimental Vulkan, changes update loaded textures immediately, and nearest-texel modes avoid anisotropic blur without overriding explicitly filtered HUD, font, shadow, or internal texture sampling. This resolves GitHub issue #121.
- [x] Milestone F now has a locally validated, default-off implementation for explicitly authored PBR materials, bounded OpenGL specular probes, and atomic OpenGL clustered decals. The 2026-08-23 current-source debug x64 evidence passed the static PBR/advanced-lighting checks, the final native 10/10 run, the final focused engine 2/2 rerun after an earlier 8/8 safe set, all four retail-PK4 compatibility roles, forced GL 3.3/4.1/4.3/4.5 PBR execution, the narrow validation-enabled Vulkan route, and exact `r_rendererModernQuality 0` rollback against leaf-disabled images. The stock baseline used all 40 retail PK4s with zero loose retail files; the generated PBR fixture remained temporary under `.tmp/`. PBR, probe, decal, and modern-visible controls stay default-off, `MODERN_LIGHTING_PARITY_PROVEN_DOMAINS` stays `0`, and this local implementation exit is not final committed-package/platform/driver promotion or broad authored probe/decal visual qualification.
Expand Down
9 changes: 8 additions & 1 deletion docs/dev/releases/v0.12.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
- **Arena Campaign scoring starts reliably.** Disabling ready-up now also clears the ready threshold, preventing deathmatch-backed Arena cards from remaining forever in a non-scoring warmup.
- **Multiplayer setup is easier to control.** The server menu exposes guarded bot controls, and competitive free-for-all disclosure now accepts the active recipients intended by the match policy.
- **Multiplayer function keys work as shown.** F1/F2 voting, F3 ready-up, F6 team switching, and F7 spectating once again use Quake 4's real impulse actions. Ready presses travel over the reliable path, the two-line warmup instruction remains fully visible, and only the exact older openQ4 defaults are upgraded—custom bindings stay untouched. No-time-limit deathmatch also starts without a spurious competitive-rules rejection.
- **Developer map compilation is more reliable.** `dmap` and other engine-side geometry tools initialize their triangle-surface allocator before generating light volumes, fixing the Windows crash seen while compiling `game/airdefense1`.
- **Pausing single-player is immediate.** Opening the in-game menu no longer blocks on save, mod, device, display, key-binding, or multiplayer-model discovery. Those lists refresh only when their own page is opened, and the normal level-loading phase prepares the menu art, fallback image, and music before the first Escape press.
- **Menu and HUD text stays sharp on modern displays.** Bitmap fonts now choose their source atlas using the final viewport enlargement, preventing a small 640x480-era atlas from being magnified at 1080p, 1440p, or 4K. Existing text layout is unchanged, and manually customized font-limit CVars still take precedence.
- **Developer map compilation is more reliable.** `dmap` now resolves editable Quake 4 `func_group` entities into world geometry before compilation, matching the retail tool and fixing false leaks such as the `hangar1` report in discussion #124. Engine-side geometry tools also initialize their triangle-surface allocator before generating light volumes, fixing the Windows crash seen while compiling `game/airdefense1`.
- **Liquids now look, sound, and behave like real volumes in combat.** Projectiles and hitscan shots cross the surface with a splash and sound, underwater travel produces bubble trails, clear water stays readable, and swimmers can reliably water-jump out over a clear ledge. Drowning, slime, and lava have distinct localized death-feed icons and messages. The multiplayer Liquid Volume Lab makes everything easy to inspect across deep, shallow, and wading water, vivid cellular slime, and bright heat-hazed, steaming lava, with restrained underwater ambience and boiling hazardous surfaces.
- **Internet multiplayer has safer administration, package negotiation, packet handling, and pure play.** The default remote console no longer sends its password over the network, private password settings stay out of console completion and persistence paths, and unauthenticated replies are bounded. A server can now update only the userinfo or synchronized-setting class owned by each message, and a truncated settings dictionary changes nothing. Server-provided package links are limited to bounded HTTP or HTTPS URLs with syntax-checked hosts; validated web redirects remain available, while standard packages keep in-process direct PK4 transfer disabled. Truncated covered messages and snapshots now fail safely and a malformed snapshot ends the affected session before another frame, the obsolete executable updater can no longer download or launch code, and pure servers keep asset checks enabled while game modules remain trusted local package components rather than server-supplied downloads.

Expand All @@ -28,6 +30,7 @@
- Mac users should replace the complete package to receive the bundled OpenAL Soft runtime; no separate OpenAL installation is needed. The package includes its corresponding licence notices and source offer.
- Linux packages no longer contain duplicate root icons whose names differ only by letter case, so the same archive can be extracted safely on Windows and other case-insensitive filesystems.
- Existing settings and compatible saves do not need to be reset. As a precaution, retain a copy of important saves before replacing an older installation.
- Map authors whose previously sealed Quake 4 maps reported an immediate leak in openQ4 should rerun `dmap` after upgrading; grouped world brushes are now compiled correctly. Keep the original editable `.map` source rather than replacing it with generated output.
- Players upgrading from released v0.10 Windows x64 builds can retry saves that previously stopped at a physics or `ReadTrace` restore error. A modded save still requires the same mod maps, GUIs, and other assets that created it; keep a backup before testing.
- The exact older broad shadow-filter defaults are upgraded once to the new balanced contact-shadow values; customized shadow profiles are left untouched. `r_shadowMapCasterCulling 2` remains the recommended value but now means topology-aware automatic culling rather than far-shell storage. Use `0` for an always-two-sided comparison or `1` to force near-shell culling.
- Level-load data under the active `fs_savepath` `generated/` directory is private and disposable. `com_levelLoadModernization` defaults to `0` and overrides older archived cache settings, so ordinary play uses the classic source path. Set it to `1` only for focused cache evaluation. Never delete the original retail or mod assets.
Expand Down Expand Up @@ -78,6 +81,10 @@
- Restored the stock F1/F2/F3/F6/F7 impulse bindings, aligned the controls menu's vote/ready rows, routed the throttled ready toggle through the reliable operation, kept the two-line readiness prompt inside its authored HUD bounds, narrowly migrated only the exact historical openQ4 defaults, and normalized no-time-limit casual matches to sudden-death overtime with a zero period.
- Corrected `s_muteUnfocused` transitions so returning to the game cannot leave audio muted for the rest of the level.
- Restored the SDL OpenGL context before applying startup or live swap-interval changes, keeping `r_swapInterval` effective when native Wayland window setup temporarily detaches the context.
- Made SP in-game menu activation constant-time with respect to saves, mods, devices, displays, bindings, and multiplayer model declarations by refreshing those catalogs only on their destination pages and precaching the menu art and audio during normal level loading.
- Made bitmap font atlas selection viewport-aware, retaining authored text metrics while using higher-resolution glyph sources when a modern display would otherwise magnify the 12- or 24-point atlas.
- Regenerated Git-derived build identity on every Meson build invocation, keeping the console banner, executable metadata, engine, and GameLib version strings current without unnecessary recompilation when the identity is unchanged.
- Resolved Quake 4 `func_group` entities before `dmap` geometry processing, restoring retail brush/entity totals and preventing grouped world geometry from becoming a false leak.
- Initialized engine-side triangle-surface allocators for `dmap` and related geometry tools.
- Restored clean, fixed-size manual save-game previews at widescreen resolutions and prevented renderer row padding from leaking into narrow captures.
- Restored the exact affected v0.10 Windows x64 version-3 save layout by defaulting its absent swim-speed and liquid-surface timer fields and accepting the empty physics frame omitted by optimized builds; current writers now use source-declared class ownership so linker folding cannot change save bytes.
Expand Down
34 changes: 25 additions & 9 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,14 @@ version_track = get_option('version_track').strip()
version_iteration = get_option('version_iteration').strip()
version_base_override = get_option('version_base_override').strip()
openal_root_override = get_option('openal_root_override').strip()
generated_version_header = meson.current_build_dir() / 'openq4_version_generated.h'
generated_version_header_path = meson.current_build_dir() / 'openq4_version_generated.h'
version_metadata_command = [
py,
meson.project_source_root() / 'tools' / 'build' / 'openq4_version.py',
'--source-root',
meson.project_source_root(),
'--track',
version_track,
'--header-out',
generated_version_header,
]
# Release builds pin the exact version. Everything else lets the helper resolve
# it: project(version:) above is only a floor, raised to the newest published v*
Expand All @@ -129,7 +127,25 @@ endif
if version_iteration != ''
version_metadata_command += ['--iteration', version_iteration]
endif
version_metadata_result = run_command(version_metadata_command, check: true)
version_metadata_result = run_command(
version_metadata_command + ['--header-out', generated_version_header_path],
check: true,
)

# Git metadata changes whenever HEAD or the worktree changes, without changing
# meson.build. Re-run the lightweight generator for every build invocation;
# write_if_changed keeps downstream recompilation limited to real version
# changes. The configure-time invocation above ensures the header also exists
# before a backend performs its first dependency scan.
generated_version_header = custom_target(
'openq4_version_generated',
output: 'openq4_version_generated.h',
command: version_metadata_command + ['--header-out', '@OUTPUT@'],
depend_files: files('tools/build/openq4_version.py'),
build_always_stale: true,
build_by_default: true,
Comment on lines +140 to +146

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh configured metadata with the version header

On an existing Linux build directory, this target updates the generated header after a commit or dirty-state change, so the rebuilt binaries report the new identity, but assets/linux/openq4.desktop.in and the Steam Deck entry are still produced by configure-time configure_file() calls using the old openq4_version_full value at meson.build:1874-1893. The same partial refresh can leave content/baseoq4/mod.json stale when a newer release tag changes the resolved base version. Regenerate these version-bearing configured artifacts from the build-time metadata as well, or the staged package can contain mutually inconsistent version identities until Meson is manually reconfigured.

AGENTS.md reference: AGENTS.md:L60-L60

Useful? React with 👍 / 👎.

install: false,
)

openq4_version_base = meson.project_version()
openq4_version_short = meson.project_version()
Expand Down Expand Up @@ -688,7 +704,7 @@ openq4_renderer_gl_sources = files(renderer_gl_source_paths)

openq4_engine_sources = files(engine_source_paths)
if build_engine
openq4_engine_sources += openq4_paks_generated_header
openq4_engine_sources += [openq4_paks_generated_header, generated_version_header]
endif

game_sp_sources = []
Expand Down Expand Up @@ -756,8 +772,8 @@ if build_games
),
install: false,
)
game_sp_sources += [savegame_compat_header]
game_mp_sources += [savegame_compat_header]
game_sp_sources += [savegame_compat_header, generated_version_header]
game_mp_sources += [savegame_compat_header, generated_version_header]
if build_engine
# Session preflights the exact GameLibs source stamp before tearing down
# the active map, so the engine target must see the same generated header.
Expand Down Expand Up @@ -1306,15 +1322,15 @@ if build_engine
if windows_gl_free_ded
# ded keeps the static renderer while the client sheds it
openq4_dedicated_sources = files(dedicated_engine_source_paths)
openq4_dedicated_sources += openq4_paks_generated_header
openq4_dedicated_sources += [openq4_paks_generated_header, generated_version_header]
if build_games
openq4_dedicated_sources += [savegame_compat_header]
endif
openq4_dedicated_sources += openq4_version_resources
endif
if host_system == 'linux'
openq4_dedicated_sources = files(dedicated_engine_source_paths)
openq4_dedicated_sources += openq4_paks_generated_header
openq4_dedicated_sources += [openq4_paks_generated_header, generated_version_header]
if build_games
openq4_dedicated_sources += [savegame_compat_header]
endif
Expand Down
Loading
Loading