OpenQ4 Release Completion List

June 4, 2026 ยท View on GitHub

Use this file as the source list for release changelog entries.

Process:

  1. Add completed work under "Ready For Changelog".
  2. When cutting a release with curated notes, save them in docs-dev/releases/vX.Y.Z.md; the manual release workflow will use that tracked file instead of the auto-generated history summary.
  3. If no tracked release file exists, the workflow falls back to the generated release notes from commit history.
  4. Move shipped items into a historical release section here (optional), and keep remaining work in "Carry Forward".

Ready For Changelog

  • Multiplayer weapon-wheel handling no longer tries to restore the cheat-protected timescale cvar every frame, removing the repeated "timescale cannot be changed in multiplayer" warning while preserving normal MP weapon selection.
  • Startup and SP map validation logs are cleaner: stock intro loading screens now select their cinematic loading background from engine code without a mapDef override, OpenQ4 napalm gameplay decl replacements apply without duplicate-decl noise, stale staged intro-video material overrides no longer shadow stock assets, and optional packed-MD5R shader probes skip missing variants quietly.
  • Stock GUI popup animations now keep their retail-style button labels and layered panels, fixing the exit-confirmation screen regression where the Yes/No text disappeared and the button backgrounds rendered as faint translucent strips.
  • Linux packaging and launch validation are stricter: staged and packaged engine binaries must remain executable, desktop entries now point at the real case-sensitive launcher names, the Steam Deck desktop entry launches openQ4-steamdeck correctly, Linux saves honor valid absolute XDG_DATA_HOME, and executable-path discovery fails clearly instead of using a truncated path.
  • Release packages now use debug-built binaries on the stable release track, Windows packages include matching PDB diagnostic symbols, and Windows crashes write crashes/openq4_crash_*.log plus .dmp minidumps beside the executable for easier issue reports.
  • CRT Emulation no longer enables a heavy chromatic channel offset by default, fixing the red/green edge artifact that could affect gameplay, HUD, and menu output when 0.3.200 users enabled the setting; legacy archived chromatic values are capped to a subtle range.
  • Modern visible rendering now preserves scene-referred highlight energy in its FP16 lighting targets, restoring visible bloom extraction and HDR tonemapping/color controls when the hybrid renderer is enabled.
  • SSAO now darkens the final scene again under the hybrid renderer by sampling the composed scene with a world-only depth source, restoring contact darkening around wall junctions and inset details while keeping viewmodels and other foreground depth-hacked surfaces out of the effect.
  • Skyboxes and portal skies now remain visible when SSAO or other root-scene post-processing paths are enabled, so sky-portal scenes such as game/airdefense1 no longer lose their sky during the final scene-target present.
  • SSAO no longer leaves stale material or texture state after its world-depth capture, preventing blue tinting or zebra-like striping on world models when enabled.
  • Supersampling in the video menu now works as a real above-native scene render instead of being clamped away: r_screenFraction supports safe 125%, 150%, and 200% presets, clamps against GL texture limits, keeps legacy below-native scaling intact, avoids stacking MSAA onto the oversized scene target, and resolves the supersampled scene before native-resolution GUI presentation.
  • The com_showFPS overlay now uses explicit modes: 1 draws during active gameplay only, while 2 keeps the legacy always-on behavior for menus, loading, and fallback screens.
  • Weapon impact hit marks now appear on world surfaces again, with stock BSE decal effects honoring g_decals and projecting bullet-hole decals into renderer geometry correctly.
  • The multiplayer HUD's sheared ammo, health, and armor panels now remain visible under the modern Forward+ renderer instead of disappearing after the renderer rework.
  • Bloom bright-pass extraction now preserves saturated HDR highlights without making ordinary saturated LDR textures glow, clamps negative scratch-chain energy out of the bloom pyramid, and skips the bloom pass entirely when the intensity slider is effectively zero.
  • HDR tonemapping and auto exposure now sanitize scene-referred FP input before display mapping or luminance metering, preventing negative scratch-target energy from causing color inversions or exposure pumping; the tone curve uses a monotonic shoulder while preserving midrange SDR contrast, and auto exposure no longer forces the HDR scene-target path when tonemapping is disabled.
  • Bloom, HDR, SSAO, lens flare, and tonemapping now run only on the root world view instead of nested sky/mirror/camera subviews, so scene post-processing is applied once to the final frame and no longer appears attached only to subview content.
  • Linux startup and shutdown are more fault-tolerant: early executable-path and /proc/cpuinfo parsing no longer risk startup memory corruption, POSIX quit signals now exit through the main thread with the correct signal-style exit code, crash signals avoid unsafe recursive engine shutdown from the signal handler, TCP writes no longer install a temporary SIGPIPE handler, dedicated binaries no longer print client display-session guidance, OpenQ4's native GLX VidMode dependency is limited to the native backend, and the native GLX fallback tolerates partial window/context initialization without null-state cleanup crashes.
  • Linux startup now handles Quake 4 addon metadata and PK4 checksums safely, fixing the launch-time segmentation fault seen when q4cmp_pak001.pk4 or other addon PK4s trigger lexer punctuation-table setup on GCC/Clang builds and restoring deterministic official-media validation on 64-bit Unix platforms.
  • Startup asset handling now gives OpenQ4-style single-digit pakN.pk4 archives priority over wider retail-style pakNN.pk4/pakNNN.pk4 names in the same directory, and startup now reports a targeted error when official Quake 4 media PK4s are found under baseoq4 instead of q4base.
  • Startup asset validation now accepts physical/DVD-style Quake 4 installs that only include the core retail media set (pak001.pk4 through pak022.pk4), while still recognizing optional official patch/menu packs such as pak023.pk4 through pak025.pk4 when present.
  • Release packaging now generates baseoq4/mod.json from the effective engine release version, treats requiredOpenQ4Version as a minimum compatible engine version, and rejects stable packages whose manifest version drifts, fixing the v0.2.000 package startup failure where the splash screen appeared and the client exited before normal logging.
  • SMAA post anti-aliasing now keeps the resolved scene in a dedicated post-process source target, fixes the black-screen regression from copy-based scene preservation, restores stock LDR lighting parity in the post-AA render path, and marks game-level scene render targets as safe current-render feedback sources so stock heat-haze effects around fires distort the scene instead of drawing black masks.
  • BSE fire and smoke effects now preserve their authored tint when effect owners arrive with legacy zeroed color parameters while keeping explicit material-color effects opt-in.
  • Mouse input now handles modern high-DPI mice without camera stutter: the legacy hard cutoff that zeroed large view deltas is disabled by default, m_maxMouseDelta can restore an opt-in legacy clamp for genuinely noisy hardware, and the in-game mouse-sensitivity control now reaches sub-1 values for modern DPI tuning.
  • Advanced mouse tuning now covers the QuakeLive-style configuration surface while keeping OpenQ4's direct raw-input feel by default: the in-game Mouse Input section exposes CPI-normalized sensitivity, view filtering, signed acceleration, acceleration offset/curve, and sensitivity cap controls, while cl_mouseAccelDebug can write logs/mouse.log samples for calibration from the console.
  • Controller input tuning is now available directly from the in-game settings menu, with localized controls for enabling controllers, changing stick layout, adjusting radial dead zone, look sensitivity, look curve, invert-look, trigger press threshold, and toggling or scaling rumble.
  • Analog controller handling now uses radial stick shaping, response-curve cvars, configurable southpaw/inverted look behavior, and immediate recalc when controller tuning changes in the menu.
  • Controller look defaults now use lower sensitivity and a smoother response curve, so fresh configs and reset-defaults are less likely to feel twitchy or over-fast on analog sticks.
  • Controller menu navigation now feels native: focused menu buttons activate from A/Enter, D-pad and left-stick menu movement support hold-repeat, shoulder buttons page/scroll longer lists, controller users can open keybind capture without needing a mouse, and SDL3 gamepads/joysticks now receive gameplay rumble from Quake 4 sound shake/rumble metadata with in_joystickRumble controls that stop cleanly and avoid redundant motor refreshes.
  • Shadow-map quality and pacing controls advanced: static projected lights can now reuse resident shadow maps with hysteresis instead of rerendering every view, update budgets account for cached reuse separately from fresh work, optional stable Poisson and projected PCSS-lite filters improve soft-shadow tuning, the experimental point-light cubemap path remains available behind r_shadowMapPointLights 1, and translucent shadow moments gained separate softness and light-bleed controls.
  • Shadow-map diagnostics and stability improved: projected and authored parallel lights now report richer caster/timing/atlas metrics with semantic light class separated from backing resource shape, optional GL timer-query diagnostics, rejected-caster reason breakdowns, off-screen shadow-map casters submitted independently from visible receiver scissors, projected CSM bias reports per-cascade near/far ranges, receiver bias uses texel-aware terms with scalar bias as a compatibility floor, hashed alpha uses stable world-space seeds, new debug/tuning cvars expose compare sampling, filter tap budgets, update budgeting, and a bias heatmap, and multiplayer maps such as mp/q4dm1 keep their authored point lighting/shadows by using the legacy stencil path for point lights unless the experimental point-shadow-map path is explicitly enabled.
  • Projected shadow maps now store Quake 4 light-falloff depth directly instead of comparing projectively divided falloff depth, fixing detached or unraveled shadows from angled projected lights and letting the default projected bias and caster offset values drop to contact-friendly levels; GLSL cutout shadow casters also preserve material alphaFunc comparison modes instead of assuming all alpha-tested stages use greater-than thresholds.
  • Shadow-map static-cache signatures now cover caster materials, alpha/hash settings, caster offset, point-light range/depth mode, and view-fitted CSM inputs, while point/translucent caster shaders reject out-of-range depth and translucent coverage masks preserve material alphaFunc comparison modes.
  • Static models with authored collision helper surfaces now keep those surfaces available for traces without letting them cast duplicate stencil/prelight shadows, fixing stock crate-style props whose hidden collision hulls overlap the visible mesh.
  • GL renderer modernization groundwork is in place without replacing the shipping ARB2 path: SDL3 now negotiates explicit OpenGL tiers, gfxInfo reports selected tier/caps, r_glTier, r_glDebugContext, and r_rendererMetrics expose bring-up controls, extension parsing is token-safe, and the first render-graph, scene-packet, upload-manager, and metrics scaffolds wrap the legacy renderer for future GL 3.3/4.x work.
  • The GL renderer upload bridge now owns frame-temporary vertex-cache streaming behind the existing ARB2 renderer: dynamic uploads use persistent mapped buffers on capable GL 4.4+ drivers, map-range/subdata fallbacks below that, multiple frame buffers with sync when available, r_rendererUploadMegs/r_rendererUploadPersistent controls, gfxInfo reporting, and upload high-water/overflow metrics while preserving the old temp-buffer fallback.
  • The renderer upload layer now owns long-lived vertex-cache buffer uploads instead of only frame-temp streaming: idVertexCache::Alloc routes static vertex/index VBO creation and data upload through UploadManager/BufferAllocator, frees those buffers through the same owner, retains the old direct GL/virtual-memory fallback, expands rendererUploadSelfTest, and reports static upload/live-buffer counts in gfxInfo and r_rendererMetrics.
  • Renderer metrics now include nonblocking GL timer-query sampling behind r_rendererGpuTimers: the existing ARB2 backend reports resolved GPU timing for 3D views, 2D/GUI views, render-target work, copy-render work, special effects, and buffer switches when supported, gfxInfo exposes timer availability, and rendererGpuTimerSelfTest verifies the live query path without changing rendering output.
  • The renderer scene-packet contract now converts legacy draw data into ScenePacket, PassPacket, and DrawPacket records for validation and metrics: r_rendererMetrics reports scene/pass/draw packet counts, gfxInfo exposes the packet limits, and rendererScenePacketSelfTest verifies the packet contract while the legacy renderer still executes the original commands.
  • The render graph now consumes scene packets as its first packet-driven data source: legacy pass nodes are built from packet categories, graph pass/pass-packet/draw coverage appears in r_rendererMetrics, gfxInfo reports graph bridge limits, and rendererRenderGraphSelfTest validates world and GUI graph construction while ARB2 output remains unchanged.
  • Draw packets now carry legacy material/resource and sort metadata for future modern GL executors: packet records include material-resource entries, first bump/diffuse/specular stage images where available, permutation hints, legacy sort keys, geometry/scissor/cache availability, r_rendererMetrics reports material/resource/geometry packet coverage, and gfxInfo reports the material-record bridge limit without changing ARB2 output.
  • The first modern GL executor entry point is available behind r_rendererModernExecutor: capable GL 3.3+ tiers allocate a starter VAO and frame-constants UBO, consume scene packets/render-graph data each backend frame, report preparation coverage in renderer metrics and gfxInfo, and deliberately fall back to the ARB2 bridge for all drawing until modern draw submission lands.
  • The modern GL executor now validates a pass-oriented internal shader-library contract without changing visible rendering: capable GL 3.3+ tiers compile and reflect built-in depth, shadow-depth, flat-material, light-grid, fog/blend, GUI, and post-copy GLSL 330/410/430/450 variants as supported by the selected context, attach pass/material/permutation metadata plus uniform/sampler reflection, expose shader readiness in gfxInfo and renderer metrics, and keep ARB2 as the visible draw path.
  • The modern GL executor now builds its first prepare-only draw plan from scene packets and the packet render graph: capable tiers classify depth, shadow-depth, flat-material, light-grid, and fog/blend packet categories, select validated internal GLSL programs with permutation/reflection metadata, report plan draw/state-batch/fallback coverage in gfxInfo and renderer metrics, and still leave all visible drawing on the ARB2 compatibility path.
  • The modern GL executor now derives its first non-rendering submit-readiness plan from the draw plan: capable tiers identify which planned draws already have VBO-backed ambient/index cache state for a future GL 3.3 submitter, report missing-buffer fallback reasons plus program/vertex/index/scissor/material batch counts in gfxInfo and renderer metrics, and still leave all visible drawing on the ARB2 compatibility path.
  • The modern GL executor now has its first real opt-in GL 3.3 submission path behind r_rendererModernSubmit: ready draw-plan commands bind the internal GLSL programs, frame UBO, per-draw MVP, ambient VBO, and VBO-backed or uploaded CPU index data, execute masked diagnostic glDraw* calls for RenderDoc/metrics validation, report submitted/fallback/upload counts in gfxInfo and r_rendererMetrics, and still leave ARB2 responsible for the visible frame.
  • The modern GL executor now routes diagnostic submission through a shared GLStateCache: redundant program, VAO, buffer, framebuffer, viewport/scissor, blend/depth/stencil/raster, texture, sampler, and color-mask changes are suppressed and counted, ARB2 handoff invalidation is explicit, KHR_debug scopes/object labels are used where available, and rendererGLStateCacheSelfTest, gfxInfo, and detailed renderer metrics report the cache behavior without changing visible output.
  • GL 4.3+ and GL 4.5+ renderer tiers now execute real tier-gated work instead of only reporting capability labels: GpuDrivenGL43 allocates and updates SSBO scene records, validation SSBOs, draw-indirect command buffers, and compute validation dispatches from the modern draw/submit plans, while LowOverheadGL45 uses DSA buffer updates and multi-bind UBO/SSBO binding; gfxInfo, detailed renderer metrics, and the modern executor self-test report the active resource path while ARB2 remains the visible renderer.
  • The GL 4.5 low-overhead renderer path now covers the resource, binding, and upload primitives needed for CPU-cost reduction: graph textures/FBOs allocate through DSA immutable storage and named framebuffers, the modern executor creates a DSA sampler and uses buffer/texture/sampler multi-bind groups, submit-plan program/material batch compaction is reported, persistent upload streams default through the selected low-overhead tier with fence retire/wait diagnostics, and rendererLowOverheadSelfTest plus the safe validation matrix cover the path while bindless remains a default-off diagnostic experiment.
  • The GL context ladder is now shared across platform backends instead of being a Windows/SDL-local array: Windows SDL3, Linux SDL3, native Linux/GLX, and native macOS/NSOpenGL consume the same tier candidate table, forced modern tiers start at their requested version and walk downward through core and compatibility fallbacks, debug-context requests fall back to non-debug candidates, macOS caps requests at 4.1 core, and rendererContextLadderSelfTest plus gfxInfo cover the selected request.
  • The renderer validation matrix now has an automated safe runner and documented manual sign-off coverage: tools/tests/renderer_validation_matrix.py starts the staged client without map loads, runs all renderer foundation self-tests, probes forced r_glTier values, debug context fallback, and presentation cvars, emits Markdown/JSON reports under .tmp/renderer-validation/, and docs-dev/renderer-validation-matrix.md tracks the required SP/MP gameplay matrix separately until map startup is safe to automate.
  • The renderer now has an opt-in gameplay benchmark harness for target-hardware evidence: tools/tests/renderer_gameplay_benchmark.py launches from .install, enters the required SP maps or an MP listen server plus loopback client, waits for active gameplay through a one-shot SP/MP g_autoExecAfterMapLoad hook, captures screenshots, prints rendererBenchmarkCapture, framePacingSnapshot, and gfxInfo, optionally compares deterministic TGA references, and fails cases on renderer overflow/idStr/shader/link/fatal log markers.
  • Renderer recovery validation now targets high-FPS gameplay instead of low-cap smoke tests: com_maxfps defaults to 240, presentation coverage uses 120/240/uncapped instead of 30 FPS, game/storage1 is the primary smoke scene, pacing-only runs avoid diagnostic overhead, wall-clock sampling measures real three-second gameplay windows, and parsed frame-pacing thresholds can enforce a 120+ FPS acceptance window.
  • Stock Quake 4 lighting and default renderer performance are restored in dense indoor scenes: authored detail lights now remain enabled by default, portal-sky setup once again uses retail-style PVS/skybox checks, unused shadow-map caster work is skipped when shadow maps are off, expensive shadow-surface scissor tightening is opt-in on the default stencil-shadow path, and BSE effects keep conservative default servicing while the more aggressive loop-service/frustum culls remain opt-in diagnostics.
  • BSE particles now have an opt-in soft-particle path: r_softParticles 1 depth-fades eligible blended and additive effect quads against the opaque scene depth, with r_softParticleFadeDistance controlling the fade width, while the default renderer path and non-effect translucent materials remain unchanged.
  • Stock character lighting parity is protected while the new GLSL interaction paths mature: enhanced material interactions and shadow-map receiver sampling now only claim eligible static stock geometry, while MD5/MD5R skinned, deformed, packed, or dynamic character surfaces retain the proven ARB2/stencil interaction path to avoid mirrored body seams and broken eye shading.
  • Shadow-map receiver lighting now preserves stock material decoding unless enhanced materials are explicitly enabled: the projected and point shadow interaction shaders use the legacy normal/specular path by default and only apply the newer normal-scale/specular-boost/fresnel math under r_enhancedMaterials, restoring character eye and body lighting parity while retaining the opt-in enhanced material path.
  • Modern material lighting now uses the same Quake 4 bump-map channel contract as the classic interaction path and carries r_enhancedMaterials normal scale, specular boost, and fresnel controls through both uniform and draw-record submission, preventing the modern G-buffer, deferred, and forward+ paths from mis-decoding stock materials when enhanced materials are enabled.
  • Modern GL submit readiness now recognizes frame-temporary/generated index-cache blocks as real element-buffer sources: deformed surfaces, packed MD5R cache materialization, packed light interactions, and GLSL-prepared interaction paths now tag temp index allocations correctly, preserving ARB2 behavior while reducing false submit fallbacks and unnecessary CPU-index upload pressure.
  • Scene packets now originate from front-end view producers instead of being rebuilt from the backend command stream on normal frames: completed RenderWorld views emit packets after culling/subview generation/sorting, GUI fullscreen views emit their own packets, r_rendererMetrics reports whether packets came from frontend or the backend fallback, and rendererScenePacketSelfTest verifies both paths while ARB2 remains the visible renderer.
  • Renderer scene packets now describe real pass work instead of multiplying every visible surface across every pass: depth, ambient/material, GUI, post, light-grid, interaction, fog/blend, stencil-shadow, and shadow-map packets are filtered from the same inputs the legacy renderer actually consumes, reducing modern renderer preparation work and keeping lighting/shadow ownership data aligned with ARB2 fallback behavior.
  • Modern renderer pass ownership now fails closed on incomplete visual parity: material/geometry fallbacks, interaction lighting, fog/blend, light-grid contribution, and shadow receiver gaps block modern visible replacement before expensive passes are planned, ARB2 lighting/shadows stay visible instead of being dropped, and renderer metrics report the first ownership blocker plus duplicate/drop accounting.
  • The renderer graph now models resources instead of only counting passes: ordered packet-pass nodes carry virtual read/write/clear/resolve/present edges for scene color/depth, post targets, imported light-grid data, and the back buffer; resource lifetimes plus transient/imported/aliasable counts appear in r_rendererMetrics, gfxInfo reports the graph limits, and rendererRenderGraphSelfTest verifies world and GUI resource graphs while ARB2 still owns visible rendering.
  • The render graph now owns real GL resource handles without changing visible output: RenderGraphResources imports the back buffer, legacy scene color/depth, and light-grid data, allocates transient scene/post textures with complete FBOs, tracks lifetimes/alias groups/physical allocation ids, adds invalidate metadata to graph metrics, and exposes rendererRenderGraphResourceSelfTest plus rendererRenderGraphResourceDump while ARB2 remains the visible renderer.
  • The modern renderer now has a stable material resource table without changing visible output: packet material records are expanded into per-frame material ids with material class, blend/sort/alpha-test metadata, texture/sampler descriptors, shader-register ranges, GL 4.3+ descriptor placeholders, disabled bindless fields, explicit fallback reasons, materialTable(...) metrics, rendererMaterialResourceTableSelfTest, and rendererMaterialResourceTableDump while ARB2 remains the visible renderer.
  • The modern renderer now carries backend-neutral geometry and instance packet records without changing visible output: scene packets copy vertex/index cache handles, offsets, formats, bounds, skinning/deform/upload classifications, matrices, entity color, shader-register ranges, visibility categories, overflow causes, and sort-key validation into records that modern draw/submit plans can consume while ARB2 remains the visible renderer.
  • The modern renderer now has a Shader Library V2 foundation for visible pass bring-up without changing output: capable GL tiers compile controlled depth, shadow-depth, G-buffer, deferred resolve, clustered forward, transparent, GUI, post, and debug GLSL families with compact permutation keys, reflected UBO/SSBO/sampler/image/attribute records, pass/material/tier compile diagnostics, gfxInfo coverage, rendererShaderLibrarySelfTest, and a fail-closed debug reload gate behind r_rendererShaderReload while ARB2 remains the visible renderer.
  • The modern renderer now has its first opt-in visible-depth bridge for renderer bring-up: r_rendererModernVisibleDepth writes graph-backed scene depth and compatible shadow-depth resources while ARB2 still draws the final color frame, r_rendererModernDepthDebug can overlay those depth resources for inspection, unsupported materials and stencil-shadow cases fall back cleanly, and rendererVisiblePathSelfTest plus the safe validation matrix cover the path.
  • The modern renderer now has an opt-in opaque G-buffer bridge without replacing the visible ARB2 frame: r_rendererModernOpaque writes graph-backed albedo, normal, material/specular surrogate, and emissive/light-grid attachments through a GL 3.3 MRT path, r_rendererModernGBufferDebug can overlay each attachment for inspection, unsupported materials/geometry fall back cleanly, and rendererGBufferSelfTest plus the safe validation matrix cover resource, shader, packing, fallback, and bandwidth reporting.
  • The modern renderer now prepares conservative clustered-light data for the hybrid lighting path without changing the visible ARB2 frame: packet-scene viewLight_t lists are classified into point, projected, fog, ambient, and special light records, binned into 8x6x16 cluster grids with overflow accounting, uploaded through GL 3.3 UBO fallback buffers, reported through gfxInfo/renderer metrics, visualized with r_rendererClusterDebug, and covered by rendererClusterGridSelfTest plus the safe validation matrix.
  • The modern renderer now has its first opt-in deferred-lite resolve bridge: r_rendererModernDeferred consumes graph-backed G-buffer/depth resources and clustered-light UBOs, writes a graph-owned deferredLight target, accumulates baseline point/projected and light-grid contribution, reports fallback pressure for unsupported fog/special/overflow cases, exposes r_rendererModernDeferredDebug overlays, and is covered by rendererDeferredResolveSelfTest plus the safe validation matrix while ARB2 remains the visible renderer.
  • The modern renderer now has an opt-in clustered forward+ bridge for material classes outside the deferred subset: r_rendererForwardPlus routes eligible opaque, alpha-tested, and transparent/fog-blend draws through graph-backed sceneColor/sceneDepth resources and clustered-light UBOs, preserves transparent sort ordering, reports forward draw, fallback, overdraw, light-read, and GPU-timer metrics through gfxInfo/r_rendererMetrics, and is covered by rendererForwardPlusSelfTest plus the safe validation matrix while ARB2 remains the visible renderer.
  • The modern renderer now has its first guarded visible-frame bridge behind r_rendererModernVisible: the option requests modern depth, G-buffer, deferred-lite, forward+, and present ownership together, composes deferredLight plus sceneColor to the back buffer when the frame has no legacy-owned GUI/post/special/subview islands, records owner/resource fallback reasons otherwise, and is covered by rendererModernVisibleSelfTest plus the safe validation matrix while ARB2 remains the default visible renderer.
  • The modern visible bridge now has Phase 14 compatibility ownership instead of unknown command islands: every render-pass category is assigned a modern owner or explicit compatibility fallback, fullscreen GUI packets get a dedicated modern draw pipeline and overlay replay after composition, light-grid passes are modern-owned by the hybrid path, post/copy/subview/render-demo/BSE categories report graph and fallback buckets, render-demo fallback remains deterministic, and rendererModernCompatibilitySelfTest plus the safe validation matrix cover the inventory.
  • Modern visible rendering now preserves retail feedback and subview effects without forcing a full-frame fallback: heat-haze/current-render materials draw through a narrow legacy feedback lane over the composed modern scene, _currentRender is refreshed at the right moment for fire and distortion effects, and generated subview/render-demo views keep their legacy sidecar passes while the main scene stays on the modern handoff.
  • Modern renderer shadow-map gating now keeps deferred-lite and forward+ diagnostic lighting alive when shadow-map receiver sampling is unavailable, records those blocked receivers separately from real stencil fallbacks, ignores intentional no-shadow/no-receiver skips for ownership, and keeps full visible replacement fail-closed so legacy shadows remain visible until modern receiver sampling reaches parity.
  • Optimized prelight shadows now sanitize legacy invalid prelight-model sentinels before view shadow submission, preventing airdefense-style access violations while falling back to dynamic/static shadow handling when no real precomputed model exists.
  • The modern renderer now has Phase 15 compatibility gates before any default-promotion decision: gfxInfo reports driver quirks and fallback gates, startup masks known-bad driver features before tier selection, rendererCompatibilityGatesSelfTest covers missing UBO, broken MRT, missing timer query, missing buffer storage, rejected debug context, and synthetic quirk downgrades, and the validation matrix now includes deterministic capture, RenderDoc tier, long-run, SP, and MP sign-off checklists.
  • The modern renderer now has a Phase 16 benchmark and scalability contract: renderer metrics feed rendererBenchmarkCapture with CPU front-end/visibility/packet/graph/submit/present timings, GPU pass samples, upload/draw/light/cluster/fallback counts, rolling P50/P95/P99 frame-time percentiles, low/baseline/modern/high-end budget presets, threshold override cvars, and an opt-in adaptive cluster-grid experiment, with rendererBenchmarkSelfTest plus validation-report thresholds covering the capture format before performance claims are made.
  • The modern renderer now has a Phase 17 default-promotion gate instead of an unconditional renderer flip: r_rendererModernAutoPromote remains off by default, gfxInfo reports the promotion reason, rendererDefaultPromotionSelfTest covers unsigned eligibility, signed promotion, explicit r_renderer arb2 escape, forced r_glTier legacy, compatibility-gate blocks, and missing ARB2 rollback, and the validation docs now require SP/MP gameplay, RenderDoc, benchmark, and rollback sign-off before auto promotion is used.
  • The renderer recovery plan now has a conservative-default safety gate for Phase 13: gfxInfo reports Renderer default safety, rendererDefaultSafetySelfTest verifies that ARB2 remains the visible clean-start or explicit rollback path with modern executor/submit/visible/debug/validation/bindless/shader-reload side paths off by default, and the README plus renderer docs list the rollback and quarantine cvars for users testing modern renderer bring-up.
  • The OpenGL tier ladder now reports an explicit workload contract for every selected tier: gfxInfo shows selected/requested readiness, forced-tier degradation, fail-closed fallback state, ARB2 rollback availability, GL3.3 CPU workload readiness, GL4.3 GPU-driven readiness, GL4.5 low-overhead readiness, GL4.6 top-tier readiness, and concise missing reasons, with rendererTierContractSelfTest and the safe validation matrix covering the contract.
  • The GL 4.3 GPU-driven path now performs real compute work instead of only validating resource creation: submit records are uploaded to SSBOs, compute culls visible/scissor-rejected commands, validates clustered-bin counts against a CPU reference, generates compact draw-indirect commands for a compatible indexed batch, can execute the range through masked multi-draw indirect under r_rendererGpuValidation, and reports dispatch/readback/mismatch/indirect-submit metrics through gfxInfo, r_rendererMetrics, and rendererGpuDrivenSelfTest.
  • The modern renderer recovery path now keeps blocked visible-frame requests cheap: compatibility ownership is analyzed before expensive modern passes run, blocked frames stay analyze-only unless an explicit sidecar/debug request is active, shadow-map diagnostics use the same producer gate, modernPassGate explains skipped work, and renderer debug/status strings no longer flood validation logs with idStr::snPrintf overflow warnings.
  • Modern clustered lighting now carries real point/projected light data instead of placeholder vectors: per-light descriptors include origin, radius, evaluated color, falloff/projection planes, image/sampler handles, depth/scissor policy, and shadow fallback state; deferred and forward+ lookup clusters in view-depth space, use real attenuation/specular math, upload all per-view grids through UBO/SSBO paths with DSA/multi-bind support, and fail closed when cluster spill or capacity limits would otherwise drop light contribution.
  • The modern renderer now has a fail-closed pass-ownership handoff for opt-in visible replacement: modern-owned depth, lighting, light-grid, ambient/material, fog, GUI, and shadow/stencil responsibilities can suppress their exact ARB2 counterparts only after modern resources and fallbacks pass validation, while mixed diagnostics keep ARB2 active and rendererPassOwnershipSelfTest verifies duplicate-ownership prevention.
  • Modern renderer geometry correctness advanced: promoted modern draws now bind the full idDrawVert layout, carry per-draw model-view matrices into G-buffer/forward+ shaders, reconstruct view-space normals and tangent handedness for mirrored UVs/transforms, validate the layout through renderer self-tests, and keep deformed/GPU-palette-skinned surfaces on the legacy path until their contracts are safe.
  • Modern renderer material correctness advanced: promoted G-buffer and forward+ draws now use the material table's stage contract, legacy alpha-test thresholds, normal/specular/emissive textures, and conservative visible/shadow fallback gates instead of placeholder normals and first-texture-only sampling.
  • Modern renderer material/geometry promotion is now stricter and closer to retail behavior: unsupported material features and geometry producers fall into stable fallback buckets, material cull/two-sided state, mirrored or negative transforms, material color registers, transparent blend families, and weapon/model depth hacks are carried into modern submissions, and the opaque G-buffer path preserves reusable scene depth instead of clearing away a valid prepass.
  • Modern clustered lighting now scales beyond the first tiny prototype: cluster grids are budgeted from viewport/light pressure, GL 3.3 keeps a UBO-safe CPU-binned path, GL 4.3+ can upload larger SSBO-backed light/index lists, and dense clusters report spill pressure instead of turning the fifth light into a hard overflow.
  • Modern shadow mapping is now part of the shared renderer plan instead of a separate side path: the renderer builds a per-frame shadow plan from visible lights, records mapped/stencil-fallback/skipped decisions, budgets shadow candidates against the active renderer preset, names projected/point/cascade/translucent shadow resources in the render graph, and feeds shadow descriptor state into clustered light records for deferred and forward+ follow-up while preserving the existing r_shadows/r_useShadowMap fallback contract.
  • Shadow-map validation and modern receiver safety advanced again: mapped shadow descriptors now carry atlas tile, matrix, cascade, bias/filter, scissor, and readiness metadata, clustered deferred/forward+ fail closed to stencil fallback when modern receiver sampling is unavailable, and new debug modes can hard-disable receiver bias, PCF, caster polygon offset, or receiver-plane/normal bias during gameplay.
  • The modern hybrid visible path now has a graph-owned composition handoff: alpha-tested depth and shadow-depth draws can use material alpha thresholds safely, CPU-skinned depth is accepted while unsafe skinning/deforms remain legacy-owned, deferred and forward+ shaders consume the shared shadow descriptor policy, unresolved stencil/shadow fallbacks block visible replacement fail-closed, and hybridSceneColor receives the combined deferred/forward output before the final back-buffer copy.
  • The modern hybrid visible path now feeds the existing HDR and post stack instead of bypassing it: supported modern tiers allocate FP16 scene/post composition targets, the combined deferred/forward scene is copied into the active HDR scene target before SSAO, motion blur, lens flare, bloom, tone mapping, and authored _currentRender passes, graph depth is handed to depth-aware post effects, auto exposure is gated to completed modern handoff frames, and GUI replay remains a final LDR overlay.
  • The modern renderer now has a stronger conservative visibility and occlusion foundation for detailed-scene performance: submit commands cache projected bounds/depth/safety visibility packets, r_rendererOcclusion and r_rendererHiZ gate scissor/frustum/screen rejection and Hi-Z candidate accounting, graph-owned Hi-Z pyramids build through an explicit max-depth reduction path without in-frame GL state queries, and shadow-caster safety metrics preserve Quake 4 area/portal/PVS culling as the first tier.
  • The modern renderer now selects only the passes a frame actually needs: G-buffer, deferred, and forward+ work are derived from ready submit commands and explicit debug requests, empty passes are skipped, single-source modern visible composition remains valid, repeated G-buffer/forward+ FBO layouts are cached, and gfxInfo reports pipeline stability, batching, validation-readback policy, and GL 3.3/4.3/4.5 fit.
  • Modern renderer draw submission now avoids rebuilding the fixed idDrawVert vertex-input layout for every draw: GL 4.3+ tiers keep the attribute format on the modern VAO and switch only the vertex source binding, while the GL 3.3 path caches repeated VBO/stride/base-offset layouts; gfxInfo and renderer self-tests report the vertex-input cache path.
  • Modern renderer submit plans now bucket reorder-safe world opaque/depth work before execution: same-view depth, G-buffer, and forward+ opaque commands are stably sorted by pipeline/program/material/geometry/scissor state while transparent, GUI, post, viewmodel, subview, and shadow work keeps source ordering; gfxInfo, renderer metrics, and self-tests report eligible draws, moved draws, bucket counts, and saved state batches.
  • The GL 4.3 GPU-driven submit path now feeds multi-draw indirect from a real per-draw record stream instead of one first-seen signature: draw records carry MVP/model-view matrices, material ids, local parameters, alpha refs, and material flags in an SSBO, an instanced record-index attribute selects the right record for each indirect command, and the executor emits one glMultiDrawElementsIndirect call per compatible bucket while gfxInfo, renderer metrics, and GPU-driven self-tests report draw-record bytes, bucket counts, bucketed commands, and indirect fallbacks.
  • The GL 4.3 GPU-driven submit path now consumes the graph-owned Hi-Z pyramid for conservative indirect culling: modern-submit frames build a depth prepass when Hi-Z culling is enabled, compute tests eligible opaque/material draw bounds against the max-depth pyramid, compacts visible indirect commands per bucket with zero-count padding for GL 4.3-safe MDI submission, and reports bucket-buffer readiness, compacted commands, Hi-Z candidates, and validation-only rejection counts in gfxInfo and renderer metrics.
  • Conservative BSE visibility culling now avoids cached-bounds pop-ins and queued-surface flicker by default: offscreen loop service deferral stays limited to portal/PVS area culling, stale portal-culled loops get budgeted state/bounds refreshes through bse_culledLoopServiceMaxMsec and bse_culledLoopServiceRefreshBudget, frustum rejection runs after the effect model is rebuilt from current geometry, queued BSE surfaces submit frame-local vertex/index snapshots so later view rebuilds cannot clear their caches, and the older cached-bounds frustum path remains available behind bse_useCachedFrustumCull for opt-in profiling.
  • Modern clustered lighting now uses compact CSR-style cluster lists instead of fixed per-cluster slots: each per-view grid uploads (offset,count) headers plus a flat packed light-index stream, dense clusters stay lossless within the shared budget on GL 3.3, and GL 4.3+ can rebuild the same headers/index stream with compute count/prefix/fill passes while gfxInfo, renderer metrics, and rendererClusterGridSelfTest report CSR and compute-binning readiness.
  • GL 4.3+ modern material draws can now collapse repeated classic texture binds through a conservative per-frame sampler table: the material resource table assigns table indices for loaded textures and fallback images, shaders keep the GL 3.3 classic sampler path but can select table entries with per-draw texture indices, and gfxInfo, renderer metrics, and low-overhead self-tests report table size, draw usage, uniform updates, and fallback pressure while bindless remains opt-in only.
  • Modern renderer pass handoff now avoids full GL teardown between modern passes: depth, Hi-Z, G-buffer, deferred, forward+, GUI, and diagnostic submits use a soft intra-modern restore that keeps the state cache warm, then perform one full restore before the ARB2 legacy handoff, with gfxInfo, renderer metrics, and visible-path self-tests reporting soft/full restore coverage.
  • Modern renderer transient uploads now use the shared upload-manager stream for frame constants and GL 4.3 GPU-driven scene, indirect, draw-record, bucket, and validation buffers when available; fixed-buffer fallbacks remain intact, upload ring rotation is configurable through r_rendererUploadFrameBuffers, opt-in GPU validation readbacks are deferred behind nonblocking sync polling, and launch-time validation now waits for real scene draw packets instead of doing GPU-driven work on loading/GUI frames.
  • Forced modern GL tiers now keep stock-world lighting on the visible ARB2 bridge by preferring versioned compatibility contexts before core-profile diagnostics; ARB2 initialization also rejects core-profile contexts explicitly instead of advertising a bridge that can only produce a black frame.
  • Modern renderer auto-promotion now requires explicit Phase 8 validation evidence, not just a boolean sign-off: r_rendererPromotionEvidence must carry the complete zero-warning visual/gameplay/RenderDoc/performance/presentation/rollback/debug-off token before r_rendererModernAutoPromote 1 can activate, and gfxInfo, rendererDefaultPromotionSelfTest, rendererDefaultSafetySelfTest, and the validation matrix all report the same evidence gate.
  • Filter-style decal mips now fold coverage alpha into the neutral multiply color per generated level, so stock terrain stains such as game/airdefense1 no longer reveal their decal bounds when the flashlight crosses them.
  • Retail BSE trail-material parity is restored for shared bullet-impact effects: particle templates now retain the authored/default trail-material name, motion trails resolve that material at finish time instead of relying on an early static pointer, and the stock machinegun/shotgun impact spark trails once again use Quake 4's gfx/effects/particles_shapes/motionblur trail instead of falling back to the engine default texture.
  • Ragdoll startup now follows Quake 4's retail articulated-figure path again: stock corpses no longer pick up OpenQ4-only AF handoff velocity/depenetration heuristics or extra per-body angular-velocity injection during pose transfer, and the AF contact solver is back on retail's tighter contact budget and per-pair planar-contact cap for SP/MP ragdolls.
  • Animated MD5 reference bounds now use exact posed mesh extents when available, eliminating the fixed-screen-square scissor clipping that could chop up player heads/bodies and attached weapons in stock scenes such as the normal game/airdefense2 launch path.
  • VS Code launch-task runtime parity is fixed on Windows: the client and dedicated entry path now preserves native Windows argv quoting, startup +set handling now preserves the full multi-word value tail for debugger/task launches that fail to quote space-containing arguments cleanly, and projected shadow-map defaults now carry enough receiver bias to stop stock flashlight scenes such as game/airdefense2 from collapsing into near-black self-shadowing.
  • Decl reload progress now uses a shared retail-style tool print path: Common.* centralizes tool-routed print behavior, reloadDecls progress lines now use that helper instead of printing straight to the runtime console, and the decl browser can surface reload progress in its status bar while normal runtime sessions still fall back to the usual console/log output.
  • Decl late-load warning suppression now uses one shared retail-like any-tool helper: Common.* centralizes the "is any tool active?" check alongside the existing masked tool helpers, and decl late-load warnings now read through that path instead of open-coding focus and editor-bit state inside the decl manager.
  • Decl tool-state checks now share one retail-style helper: masked tool-flag queries live in Common.*, entityDef media caching uses that shared helper instead of a raw editor-bit test, and decl-validation state checks now read through the same path so tool-sensitive decl behavior stays centralized.
  • Articulated-figure fastEval text now matches retail style: the parser still accepts explicit boolean forms for tools, bare fastEval behaves like retail anywhere in the settings block, rebuilt AF text only emits fastEval when true, and default AF definitions stop writing fastEval 0.
  • Packed .decls writer policy is now explicit: OpenQ4 keeps its extended game-section export coverage by default, exact-retail game-type coverage is selectable through com_singleDeclFileWriteMode or writeDeclFile retail, and export logs now report which policy produced the file.
  • Effect decl allocation is now a hard integrated-BSE invariant: startup probes the effect allocator before registration, allocator failures fatal instead of producing plain idDecl stubs, and dedicated servers keep the disabled BSE runtime while still using the real BSE effect-decl parser.
  • Playback decl finalization now fires the retail-style playback-finished tool bridge after resampling recorded paths, giving editor/tool workflows a completion signal while remaining a no-op in normal runtime builds.
  • Articulated figure decl content masks now preserve Quake 4's vehicleclip, flyclip, and itemclip collision bits when parsing or resaving AF files, restoring retail collision-mask round-tripping for stock and SDK-derived articulated figures.
  • Light-grid baking now writes versioned v5 metadata with a deterministic bake-settings/layout hash, records probe and atlas layout stats, prints per-phase timing/counter summaries including async readback stalls, and rebuilds stale baked outputs automatically when the map layout or bake-affecting settings change.
  • Light-grid interpolation is now visibility-aware: bakes emit companion area*_lightgrid_vis.tga atlases with directional distance moments, and runtime sampling uses those moments with a self-shadow bias to reduce wall/corner light leaks.
  • Light-grid probe placement now detects solid/near-solid positions, relocates probes within a bounded search when possible, records richer validity states and relocated origins in v7 metadata, emits compact area*_lightgrid_pos.tga probe-position atlases for runtime interpolation, and reports relocated/near-solid probe counts in bake diagnostics.
  • First-person weapon/viewmodel surfaces now receive baked light-grid indirect diffuse through a dedicated weapon pass that samples the active view area's probes while keeping depth-hacked weapon geometry out of the main world receiver pass.
  • Light-grid area transitions now blend across visible, unblocked portal neighbors near doorway/window boundaries, using r_lightGridPortalBlend to smooth indirect-light seams without changing baked asset formats.
  • Light-grid atlas residency now keeps visible areas and unblocked portal neighbors hot for an age-based window controlled by r_lightGridResidencyFrames, reducing reload churn and traversal hitches when moving through connected areas.
  • Light-grid indirect rendering now uses a material-compiled representative diffuse stage instead of redrawing every diffuse stage, reducing extra geometry submissions for multi-diffuse materials while retaining a fallback when the preferred stage is conditionally disabled.
  • Startup asset validation now ignores retail Quake 4 game-binary PK4 archives (game000.pk4 through game300.pk4, plus gamex*.pk4 variants), so OpenQ4 only requires and verifies the stock media PK4s it actually uses.
  • Retail decl loading parity improved: Quake 4 decl folders now honor retail recursion/unique-file behavior, no-cache decl lookups reach entityDef inheritance/media caching, legacy Doom 3 PDA/email/video/audio console commands are no longer exposed as supported decls, and playback/table/lip-sync/material-type decl parsing plus playback runtime sampling/record hooks now handle more shipped Raven asset data safely.
  • Packed decl-manager parity advanced: the retail single-decl-file API is enabled again across engine/game headers, packed .decls sections can be read and written through controlled cvars/commands, stored decl indices are preserved during load, validation/allocation/tool hooks are available, packed stub decls expand lazily from their original source text, PDA/email/video/audio decl families are included in the framework packed section, and the startup/session/network asset-log wiring now selects and refreshes per-map packed decl files when the retail cvars are enabled.
  • Packed decl asset-log wiring now follows the retail assetlogs/<map> naming contract, including entity-filter suffixes, while the decl manager preserves the real maps/... path when selecting per-map .decls files.
  • Regenerated collision caches now keep the first map entity named as the world model even after OpenQ4's trace-model slots are initialized, preventing MP map loads from null-dereferencing the clip world when a stale stock .cm has to be rebuilt.
  • Material decl parity advanced: per-level material use counts now resolve onto image diagnostics like retail, Quake 4 material tokens for alphaFunc, fragmentParm, sky, and needCurrentRender now preserve their authored behavior instead of being ignored or defaulting to Doom 3-only semantics, sort gui and retail sort constants now resolve consistently, and unknown materialType references now warn like the shipped engine.
  • Sound shader decl parity improved: descriptions, min/max frequencyshift, frequentlyUsed, no_shakes, minSamples, and +10 dB volumeDb clamping now survive parsing, sound shader memory/list diagnostics include their retained decl state, level-load reference marking now propagates from sound decls to their loaded samples, retail entry-only default/duration queries are restored, and the retail rvSoundShaderEdit bridge now exposes sample/shake/purge/load helpers for tools.
  • Effect/player-model/skin decl parity advanced: skin and player-model decl diagnostics now report retained allocations and useful player-model fields, BSE effect decls now expose retail-style segment lookup/copy/editor-original helpers with safe bounds handling, and the integrated BSE path now wires the retail rvDeclEffectEdit bridge instead of leaving it null.
  • Decl editor/tool wiring advanced: AF, playback, and lip-sync decl edit adapters are now available engine-side, lip-sync decls can rebuild retail-style text, Raven decl parsers now expose the no-caching signatures expected by the shared SDK headers, player-model parsing performs the retail media-cache pass, and table/material-type parsing now follows recovered retail edge-case behavior.
  • Retail decl validation parity advanced: table, skin, entityDef, AF, material-type, lip-sync, playback, and player-model validation now performs the retail temporary-decl parse/default-state check instead of accepting every text block, and the base idDecl no-caching parse shim now preserves the caller's cache-suppression request.
  • Added a default-off r_motionBlur graphics option for subtle camera motion blur, including depth-aware sampling, safe history resets on map/view changes, and a debug vector view for tuning.
  • Added optional rigid-object motion vectors behind r_motionBlurObjectVectors, improving blur on moving doors, platforms, and other non-skinned opaque objects while preserving the camera-only fallback for unsupported surfaces.
  • Packed MD5R light interactions now advance along the retail ARB2 path without regressing the stable hybrid renderer: packed interaction passes switch to the stock md5rinteraction* vertex-program family, upload the retail MD5R interaction parameter block in program.env[75..91], interaction lightTris now emit the retail per-prim-batch headered index stream instead of staying on the older flat filtered list when the packed builder succeeds, packed interaction rendering consumes that headered batch stream directly while continuing to fall back to the classic interaction path if a packed program/buffer bind or retail packed light-tri build is unavailable, retail-style packed stage texturing now picks the correct MD5R program variant and submits full ambient/material stage batches directly from the packed draw buffers when the stage path is fully prepared, ARB ambient material-program stages with an authored md5r*.vp alias now use the same prepared packed draw/runtime path instead of forcing the classic ambient-cache vertex layout, packed late blend-light passes now explicitly refresh the frame-temp ambient/index view they need instead of depending on earlier light submission to have populated it, the deferred light-grid indirect pass now does the same so packed surfaces stop assuming a prior ambient submission already materialized classic cache-backed draw data, the shared depth / ambient shader passes now run through the same packed cache-prep helper before they touch classic ambientCache state, the generic RB_RenderTriangleSurface / RB_T_RenderTriangleSurface path now gives packed surfaces the same frame-temp classic draw view instead of dropping them straight to immediate-mode fallback, the last-resort RB_DrawElementsImmediate path can now materialize packed prim-batch triangles on demand instead of assuming classic verts/indexes residency, the GLSL material/projected-shadow/point-shadow interaction creators now recover packed ambient-cache state from the source ambient surface instead of assuming earlier interaction submission already populated classic draw-vertex data, the draw core now recognizes a second prepared packed direct-draw context so the MD5R depth and fog passes can route their per-prim-batch submission through RB_DrawElementsWithCounters() instead of each carrying a separate private loop, those ARB2 packed depth/fog entry points now attempt direct MD5R submission before falling back to the older classic-cache requirement, and renderer diagnostics such as r_showLightCount, r_showNormals, r_showEdges, and the other raw-geometry overlays now rematerialize packed interaction/ambient data instead of silently skipping MD5R-backed surfaces.
  • Fixed the active light-parity fog regression in game/storage1 and other stock scenes: fog passes now force the fog light's current color instead of inheriting stale per-vertex color arrays, the generated _fog / _fogEnter lookup textures once again stay full RGBA instead of collapsing to alpha-only classification, and packed MD5R fog again routes through the retail md5rbasicfog* variant/palette path for skinned packed surfaces.
  • Collision-model parity improved for generated/runtime CM data: retail Quake 4 primitive tracking and polygon texture-basis data are now preserved during CM generation/serialization, render-model collision no longer over-merges across distinct source surfaces, and .proc CRC validation now matches retail CM load behavior more closely.
  • Collision-model load parity improved for stock maps and SP entities: CM parsing now reuses existing model slots instead of exhausting submodel capacity, world/map submodel naming matches retail expectations more closely, retail-style SP clipmodel fallback no longer probes entity names, and stock game/medlabs map init no longer emits contains different model/no free slots CM failures.
  • Collision-model lifetime parity now more closely matches retail Quake 4: map teardown drops CM reference counts instead of clearing the entire manager, purges free model geometry in place for slot reuse, and SP/MP map shutdown now purges unreferenced CM data before the next level load, fixing slot exhaustion during SP transitions such as game/mcc_1 to game/convoy1.
  • MCC med-bed intro overlay now keeps its retail 128x128 ambient data/static layers tiled at native scale across the expanded GUI canvas, and edge-hugging detail widgets anchor to the appropriate wide/tall screen sides.
  • Stock split-map loading screens now preserve Raven entity filters such as game/storage1 first / second, restoring the filtered mapDef title, levelshot, autosave name, and load-size metadata instead of falling back to the raw map path.
  • Save-game command handling now matches retail Quake 4 more closely: map-start autosaves use stable map/entity-filter slot names, quicksaves rotate through tracked quick slots, saveGame checkPoint creates protected Checkpoint0/Checkpoint1 slots instead of a manual checkPoint save, restart prefers the latest checkpoint slot, and saves are blocked after a failed objective like retail.
  • Save-game loading is more stable: OpenQ4 now restores the game-state alert fields in the same order they are saved, validates save, entity, GUI, script, animation, physics, event, and collision-cache payloads before rebuilding runtime state, and reports truncated or malformed save files cleanly instead of continuing into a crash-prone misaligned stream.
  • Main menu placeholder art rotation now uses a randomized montage of eligible loadscreen levelshots, with proper wide/tall expansion-tile composition and slow zoom transitions per shot.
  • Startup/loadscreen placeholder now hands off to the main menu automatically after 3 seconds, main-menu entry transitions use a short black fade-in stretched to native screen extents, and startup logo videos can be skipped with default-on com_skipLogoVideos 1.
  • Added a depth-aware r_lensFlare graphics option with quality levels for lightweight light coronas and high-quality lens ghost/streak overlays.
  • Material handling fixes completed; engine startup no longer depends on custom material script overrides in repo q4base/.
  • Startup material/icon sizing now tolerates stock decls without drawable stages, preventing an application-load crash during UI icon registration.
  • Decl parse dispatch now follows the retail SDK no-caching path through idDeclBase again while material and sound shaders expose explicit three-argument parser overrides, preserving stock material stage/image parsing and preventing fully black map rendering after level load.
  • Decl-manager folder registration and packed-decl writing now mirror more retail bookkeeping: startup logs per-type load time/text memory again, and packed .decls writes store the decl's current linear-list slot with the retail index fallback.
  • Decl late-load diagnostics now match retail more closely by warning when uncached decls are parsed after startup/level precaching outside active editor sessions.
  • Decl editor/helper safety improved: CreateNewDecl now mirrors retail null-tolerant filename/default-definition handling, and DeclByIndex range errors report the decl type and requested/max indices.
  • Legacy PDA/email/video/audio decl families are registered engine-side again with retail list/print command wiring and parser stubs, restoring Quake 4's full decl type surface for game and tool lookups without adding content overrides.
  • Retail light material parsing parity improved: lights/* material stages and lightFalloffImage entries now load through the renderer's light image bucket instead of generic material image classification, restoring Quake 4's intended projection/falloff handling for stock map lights.
  • Retail programmable material decl parsing now recognizes Quake 4's symbolic fragmentMap bindings for lightfalloffImage, lightImage, ambientNormalMap, normalCubeMap, and specularTableImage, keeping light-driven slots tokenized instead of misloading them as ordinary images.
  • Retail guide-template decl wiring restored: rvDeclGuide now has its retail parse/evaluate/remove-bracing implementation, guide reloads clear the previous table before reparsing, duplicate guide names are rejected like retail, and guide/inlineGuide material expansion now shares the same parameter substitution path.
  • Decl validation/tool parity improved: the base idDecl::Validate wrapper now delegates through the decl base like the Quake 4 SDK, the local decl fallback validates by parsing a temporary decl instead of accepting every block, validation runs now assert the retail DoingDeclValidation() editor bit so parser-side hard errors can downgrade to warnings, entityDef media caching observes the recovered retail editor-mask bits, material/sound decls expose the retail validation slot, sound shader decls can rebuild text for resaveDecl tooling, and the engine-side idCommon/UI manager surface again exposes Raven's decl/tool hooks used by SDK validation, editDecls, model-view, debugger, and always-think GUI paths.
  • Game-library decl wiring tightened: SP model and camera decl validation now performs temporary-decl parsing instead of accepting every text block, SP validation-only model/animation failures downgrade through the same DoingDeclValidation() warning path as MP/the SDK, SP def/af folder registration uses the same Raven wrapper path as MP/the SDK, and camera validation now allocates the dedicated DECL_CAMERADEF slot rather than the SDK's stale model-def allocation.
  • Packed decl writer/export support improved: generated game-section .decls files can include the registered model and playerModel decl slots alongside entity/camera/AF/export data in OpenQ4 mode, while the interactive writeDeclFile command is exposed from the same loose-decl startup branch as retail.
  • Decl SDK/header wiring tightened: restored PDA/email/video/audio decl declarations now expose both retail parse entry points to the companion game-library headers, and optional decl-folder scans tolerate absent file lists while continuing recursive discovery.
  • Player-model decl parsing now follows the recovered retail rules more closely: malformed unquoted keys warn/default instead of being accepted, only canonical def_head / def_head_ui fields populate head data, and the fallback definition matches Quake 4's minimal marine/Kane-head pair.
  • Playback decl runtime sampling now follows retail timing more closely: recorded paths are resampled on finish, offset/angle queries return the playback expiration state, and button/impulse callbacks preserve their event offsets for game playback drivers.
  • BSE effect decl parsing now follows retail keyword handling more closely: the effect decl exposes the retail no-caching parser slot used by the decl manager, effect/segment/particle tokens are case-insensitive, doubleVision/shake/tunnel segment IDs use the shipped ordering, malformed effect bodies report failure at the same closing-brace boundary, trail segment lookups are case-insensitive, effect duration bounds rebuild on every finish, invalid particle-template entries warn/recover like retail, empty particle models fall back to _default, and overfull spawned-effect lists warn instead of terminating the client.
  • Game-library decl validation now shares the engine's temporary-decl validation/free helpers so SP/MP model and camera validation reject defaulted parses and clean allocated decl/base pairs consistently, and the companion playerModel header exposes the same retail parse overload surface as the engine.
  • Sound-shader decl parsing now reads the retail s_maxSoundsPerShader cvar, so stock configs and quality presets control per-shader sample admission instead of being ignored by the old OpenQ4-only s_maxSamples name.
  • Decl command tooling now follows retail default-creation semantics for resaveDecl <type> <name> and touch <type> <name>, sharing the same valid-type listing and materializing/defaulting named decls through FindType instead of treating absent loose declarations as hard misses.
  • Guide-template decl expansion now follows retail consumption semantics: found guide and inlineGuide calls are consumed even when their argument list does not match, inline-guide replacement runs as a single pass over the original definition, and missing inline-guide definitions return the retail failure state instead of partially succeeding.
  • Decl-file guide dispatch now follows the retail loader path in loose, packed, and lazy packed-stub parses: guide decls run the guide expansion attempt and the inline-guide pass without treating a failed expansion return as a skip, and duplicate loose decl definitions warn unconditionally like the shipped engine.
  • Decl source replacement now follows retail editor/save wiring: invalid source files report an empty filename, external-modification checks close their read handle before returning, and resaveDecl/decl-editor writes target fs_devpath instead of the launch CD path.
  • Retail guide parsing parity advanced: guides/*.guide now loads through a recovered guide-table path, guide creation shares the retail GetNewGuide helper, and unrelated top-level guide-file tokens are tolerated like the shipped engine instead of aborting startup parsing.
  • Packed decl serialization and intake now track retail more closely: loose/packed decl loaders let ParseBracedSectionExact consume non-guide bodies directly, inline-guide expansion runs from the same post-body step, and generated packed decl entries always write the retail type name header before the stored body or stub.
  • Guide-template substitution now follows retail's evolving-definition replacement loop, preserving correct behavior when guide arguments overlap with parameter names or later replacements shift the body, and the obsolete pre-retail guide preprocessor has been removed.
  • Loose decl reloads now honor retail's renderer-side image_writeProgramImages parse trigger, allowing the program-image generation path to force newly loaded decls through ParseLocal() once the renderer is running even when they have not already been referenced this level.
  • The checkDecls command now follows retail's reparse gate for every loaded decl that is not already DS_PARSED, so defaulted decls are checked again instead of being skipped as if they were clean.
  • Packed decl loading now initializes placeholder decl records completely before indexed replacement, preventing the retail com_SingleDeclFile/checkDecls path from dereferencing debug-fill memory when sparse packed indexes are replayed.
  • Decl reload/tooling diagnostics now follow the retail path more closely: reloadDecls reports per-file progress, and decl text-memory totals walk GetNumDecls/DeclByIndex(false) so packed sparse indexes and editor summaries share the normal decl access surface.
  • Guide-template edge cases now match retail parser recovery more closely: malformed parameter comma counts warn under the same rule, inline-guide body unbracing follows the shipped two-step trim, and missing guide names no longer skip ahead past the lexer position retail leaves for subsequent parsing.
  • The packed-decl cvar surface now matches retail wiring more closely: com_SingleDeclFile is exported through the shared engine headers instead of staying private to the decl manager, so renderer/session/game code can bind to the same cvar symbol as the SDK headers expect.
  • Packed-decl startup naming now follows retail's default asset-log handoff: the filesystem seeds assetlogs/default during init, and the decl manager derives default.decls from the active asset-log basename instead of falling back to OpenQ4's older decls.decls name.
  • Asset-log ownership now follows retail's decl-packaging handoff more closely: SetAssetLogName renames the active asset log without implicitly clearing collected entries, leaving log reset/write ownership to the explicit asset-log paths.
  • Retail programmable material-decl parsing now recognizes Raven GLSL shaderParm and shaderTexture built-ins from guide-expanded stages, including light origins/projection/falloff, color modulation/addition, diffuse/specular colors, matrix rows, shared lookup images, and dynamic light image slots.
  • Retail custom-lighting material stages now stay out of the ambient pass and run through the per-light interaction path, with material-authored GLSL programs receiving Quake 4 interaction uniforms, dynamic light textures, stable tangent-space attribute bindings, and the same packed MD5R ambient-cache recovery used by the other GLSL interaction paths while shadow-map lighting falls back to the stencil path for those custom material programs.
  • Retail lighting parity restored for distance-cull portal fades, Raven special-effect pass ordering, ARB2 specular scaling, and noSelfShadow stencil-shadow routing.
  • Retail light/interaction parity improved again: fog/blend lights now honor Quake 4's noFog interaction contract, sound-driven light/material shader expressions once again receive referenceSoundHandle amplitude inputs, entity ambient submission now honors retail r_lod_entities scissor-LOD gating for tiny on-screen coverage, retail r_useEntityScissors behavior is once again enabled by default so entity scissor tightening matches stock Quake 4 out of the box, view entities now follow retail's sort-by-model submission order before ambient/light interaction work, authored light detail levels once again gate view-light admission through retail-style r_lightDetailLevel, light/shadow submissions now honor retail r_limitBatchSize tiny-batch dropping before drawsurf allocation, interaction shadows now respect retail shadow-LOD / noDynamicShadows gating instead of keeping distant or explicitly disabled dynamic shadows alive, and light/shadow routing once again keys off the original interaction material instead of letting shader overrides change noSelfShadow ownership.
  • Retail shadow admission parity now carries through OpenQ4's dedicated shadow-map caster path: opaque and experimental translucent shadow-map casters honor Quake 4's cached shadow-LOD decision instead of resurrecting distant dynamic shadows, the randomized retail shadow-LOD frame hold now uses Quake 4's recovered 15-bit 1/32768 * 1000 range consistently across supported platforms, shadow-map-only ambient casters keep their interaction alive without requiring a stencil silhouette volume, cvar-gated shadow-map features can request the cached LOD decision lazily without treating "not needed yet" as "rejected", inert non-silhouette surfaces no longer refresh the retail shadow-LOD hold unless they can feed a dedicated shadow-map caster, shadow-map local/global ownership now follows the same original-material noSelfShadow split as the stencil path, point-light shadow maps keep legacy globalShadows/localShadows in mixed dedicated/fallback caster scenes, mapped lights now fall back to the retail stencil path when every opaque caster in a legacy/prelight chain is skipped instead of sampling an empty shadow map, receiverless lights now discard dedicated shadow-map caster chains alongside retail stencil shadow chains before scene-packet/planner work, and static/prelit geometry, stencil fallback, and the modern shadow planner keep their existing behavior.
  • Retail packed MD5R light-submission parity advanced again in the current hybrid renderer: packed ambient surfaces, packed-backed light interactions, and packed shadow-map casters now refresh frame-temp draw/index data per visible frame instead of forcing long-lived classic cache ownership, interaction lightTris retain retail packed ownership metadata in the front end, and packed temp-cache submissions no longer trip idVertexCache::Touch().
  • The final tracked renderer light-parity gap is now closed in code: packed MD5R depth, fog, ambient, material-stage, interaction, and stencil-shadow submission now bind retail-style MD5R vertex programs and draw packed buffers directly instead of falling back through transient classic draw-vertex uploads, while material parsing also resolves the retail md5r*.vp stage-program aliases needed by those packed paths.
  • Added a live renderer light-report tool (r_showViewLights) that prints detailed per-light diagnostics for lights affecting the current view origin/player position.
  • Added a persistent visual overlay for r_showViewLights (r_showViewLightsVisuals) that draws each last-reported light's origin marker, color, and radius volume in-world until the next report refresh.
  • Retail deform rectsprite material support restored so shipped Quake 4 multiplayer flag-display shaders follow the renderer's rectangular autosprite path.
  • Menu rendering issues fixed.
  • GUI font rendering now follows retail Quake 4 font metrics more closely: stock .fontdat files load with their native glyph bearings, advances, point-size scaling, no extra draw-time vertical glyph bias, guarded glyph atlas edge sampling, no-picmip atlas materials, retail-style DXT1 green-alpha font atlas upload/mips, .fontdat atlas-token canonicalization, embedded icon sizing/UV handling, shared Q4 color/repeat/icon escape parsing, RGB escape alpha preservation, retail-style icon measurement/escape-spanning cursor accounting, chat-window wrapping and parse-flag behavior, field edit spacing behavior, bind/choice/list/edit caller spacing parity, list tab baseline alignment, wrapped edit line-height/scrollbar wrapping behavior, end-of-text cursor handling, single-pass authored/choice/simple-window foreground text rendering, retail simple-window eligibility for static labels, transformed glyph and GUI-quad renderer clipping bounds, deterministic GUI quad vertex payload, font language/cache lifecycle cleanup, text spacing/style save-load persistence, and MP HUD wrap-index support while preserving OpenQ4's wide/tall aspect-correct UI expansion. The new uiFontParitySelfTest locks down retail glyph scaling, embedded icon sizing modes, RGB escape alpha behavior, baseline/alignment, expanded wide/tall canvas mapping, clipped UV trimming, font atlas upload options, and the tight stock HUD radio fonts/marine sizing that keeps the incoming transmission label intact instead of vertically clipping it against its own text boxes.
  • Settings menus now present cleaner Display/Game pages with compact single-display spacing, smooth clipped scrolling, corrected scroll extents, and Proper Case OpenQ4 setting labels while keeping section headings uppercase.
  • Settings-page scrolling now responds to mouse wheel, PageUp/PageDown, and controller shoulder paging on the active settings tab, keeps thumb and paging state in sync, and exposes the full Game settings scroll range.
  • SDL3 backend integrated as the default platform path (legacy Win32 backend remains transitional).
  • Meson + Ninja build system introduced as canonical build path.
  • External dependencies moved to Meson subprojects/wraps (sdl3, glew, stb_vorbis, openal-soft-prebuilt).
  • Vendored GLEW updated to 2.3.1 (both subprojects/glew and src/external/glew) while preserving local static-link/include-path compatibility tweaks.
  • Vendored OpenAL Soft updated to 1.25.1 headers/defs/import libs (both subprojects/openal-soft-prebuilt and src/external/openal-soft), with Win64 runtime DLL refreshed under src/external/openal-soft/bin/win64/OpenAL32.dll.
  • Dependency refresh validated with clean Meson reconfigure (setup --wipe) and successful rebuild in builddir.
  • Ogg Vorbis (.ogg) playback support integrated (decoded via stb_vorbis).
  • C++23-targeting baseline enabled on MSVC (cpp_std=vc++latest).
  • MSVC 2026 toolchain direction documented and implemented as an optional enforceable baseline (-Denforce_msvc_2026=true).
  • Meson setup wrapper improved to auto-recover missing/stale build directories and avoid VS tool discovery null-crash.
  • Windows SDL3 key/input parity improvements: backspace fix, control-char synthesis, locale-aware RightAlt behavior.
  • Manual key matrix audit completed and documented for console, GUI edit fields, chat, binds, numpad, and modifiers.
  • GUI scaling behavior updated to preserve uniform/aspect-correct rendering on window resize.
  • Engine-side console/UI relayout now handles wide and narrow/tall aspect ratios, with live updates on screen size/aspect changes.
  • Console mouse handling now uses native console-space cursor routing/drawing bounded to the live console rect, and adds archived con_height control for the console open height (0.1 to 1.0, default 0.5).
  • Platform/architecture roadmap documentation added for Windows/Linux/macOS direction with x64 baseline.
  • Legacy/redundant build-system artifacts reduced (CMake path retired from active source tree).
  • BSE manager/renderer lifecycle contract restored: effect completion now propagates correctly through ServiceEffect -> UpdateEffectDef, preventing immediate client-effect teardown and enabling proper expiry reporting.
  • BSE sound capability path restored at render-world boundary: EffectDefHasSound now delegates to decl metadata and manager checks instead of unconditional false.
  • BSE segment runtime no longer compiles as pure no-op stubs; core segment timing/attenuation/check/update/count plumbing has been re-enabled as the phase-4 runtime foundation.
  • BSE game-lib network/event parity restored: EVENT_PLAYEFFECT_JOINT no longer hits an assert placeholder, receive paths now validate decl/filter/rate-limit consistently, and networked effects restore gravity assignment parity.
  • BSE save/restore stability improved for active effects by clearing stale referenceSoundHandle on restore so emitters are safely reallocated.
  • Temporary BSE visibility fallback added (bse_fallbackSprite, default 1): active client effects now emit a sprite-backed render entity until full particle-surface rendering is fully restored.
  • BSE segment activation timing fixed: rvBSE::Service no longer applies a large negative per-segment spawn offset that delayed segment starts by multiple seconds.
  • BSE segment spawn lifecycle restored for SEG_EMITTER, SEG_TRAIL, and SEG_SPAWNER, including attenuation-aware interval/count spawning and loop-time progression tracking.
  • BSE trail/child spawn placement improved: non-zero spawn offsets now propagate into particle init positions, and trail segments spawn using interpolated local movement offsets.
  • BSE moving-emitter transform parity improved: non-locked particle position/velocity evaluation now converts from spawn-space into current effect-space using stored spawn origin/axis.
  • BSE owner wind propagation restored by transforming renderEffect_t::windVector into local effect wind each update.
  • BSE decal segment path restored from no-op to active world projection (SEG_DECAL now builds/projections decal winding via ProjectDecalOntoWorld using sampled spawn size/rotation).
  • BSE spawn ordering parity improved: runtime particle insertion is no longer unconditional LIFO; linked segments preserve stable chronological/end-time list order while complex segments retain front-insert behavior.
  • BSE segment draw-order refinements applied for linked-strip rendering: depth-sort is disabled for linked strip topologies and initial strip index budgeting is handled explicitly.
  • BSE runtime sort utility implemented (rvSegment::Sort) with stable depth ordering for deterministic per-segment ordering when used.
  • BSE network/entity receive rate-limiting corrected by removing duplicate cost consumption (Filtered already applies category rate checks; explicit second CanPlayRateLimited checks removed).
  • BSE particle spawn-parameter sanitization restored (rvParticleTemplate::FixupParms no longer compiles as a no-op stub).
  • BSE segment attenuation scaling parity restored: emitter interval/count attenuation now uses bse_scale interpolation semantics.
  • BSE particle cap parity restored: bse_maxParticles now drives runtime segment allocation/count clamps instead of compile-time-only MAX_PARTICLES paths.
  • BSE owner-state parity improved: mLightningAxis is now derived from current origin/end-origin direction with stable basis fallback.
  • Temporary BSE trace spam removed from hot runtime paths (spawn/expire/remove and segment render skip/state traces), and renderer counter cvar default restored to off (bse_frameCounters=0).
  • Full clean rebuild validation completed in builddir/ with both OpenQ4.exe and OpenQ4-ded.exe linking successfully after BSE parity updates.
  • BSE particle gravity parity restored: template gravity ranges now contribute spawn acceleration in rvParticle::FinishSpawn.
  • BSE debris parity advanced: debris particles now spawn client moveable entities (entityDef) through game->SpawnClientMoveable and stop CPU-side particle rendering.
  • BSE shader-parm safety defaults hardened: client effects now initialize RGBA/brightness/timeoffset in rvClientEffect::Init, with zeroed-parm fallback in rvBSE::UpdateFromOwner.
  • BSE template runtime contract completed by implementing missing declared helpers (rvParticleTemplate::Compare, GetTraceModel, GetTrailCount, ShutdownStatic).
  • BSE unlocked-bounce matrix reprojection parity improved: post-impact velocity/position persistence now uses inverse current->init axis mapping with origin-delta compensation, avoiding frame-space double transforms in moving/rotating emitter paths.
  • BSE owner-kinematics parity improved: rvBSE::UpdateFromOwner now preserves last valid owner velocity across same-timestamp updates instead of zeroing mCurrentVelocity on tiny frame deltas.
  • BSE oriented-particle matrix parity improved: oriented quad corner ordering/signs now match decompiled transform basis usage, removing mirrored orientation in rotated oriented-particle paths.
  • BSE effect culling now avoids stale portal-visibility rejects by requiring cached rendered geometry before pre-service/pre-render area or frustum culls can skip work, then rechecking with freshly rebuilt effect bounds; visible map-authored effects such as game/airdefense1's func_fx_24 no longer pop in late when turning toward them.
  • Startup command parsing hardening completed: oversized +wait stress launches no longer crash during early StartupVariable cvar processing (command-line overflow/drop handling and idCmdArgs::AppendArg bounds checks tightened).
  • Multiplayer server-side hitscan lag compensation added with configurable rewind controls (net_mpLagCompensation, net_mpLagCompMaxMS, net_mpLagCompBiasMS) and server diagnostics (net_mpLagCompDebug).
  • Multiplayer non-local prediction mode is now runtime-selectable through net_mpPredictMode (0 legacy limited behavior, 1 enhanced per-frame prediction).
  • Scope/zoom handling documentation updated to reflect multiplayer zoom stability and scope yaw alignment behavior.
  • High-refresh view interpolation now includes tunable local first-person biasing (pm_presentViewBias) so the camera, FOV, and view weapon spend less time a full tic behind at high presentation rates without changing authoritative gameplay timing.
  • High-refresh local first-person biasing was retuned so the default interpolation path no longer surges to the newest snapshot and stalls mid-tic; pm_presentViewBias now remains an opt-in bias that eases forward more gently when needed.
  • High-refresh first-person weapon FX now stay aligned with the interpolated local/spectated camera on the fire frame: view-weapon muzzle flashes refresh in presentation space immediately, and hitscan tracer/path origins sample the presentation-space muzzle instead of the last authoritative pose.
  • High-refresh multiplayer carrier/powerup halo lights now follow interpolated player presentation on repeated-state frames instead of stepping only at the 60 Hz simulation tick, keeping CTF/powerup light halos aligned with moving carriers.
  • High-refresh vehicle crash/scrape effects now interpolate persistent world-space crash FX between collision snapshots on repeated-state frames, keeping scrape contact visuals smoother when vehicles slide along world geometry.
  • High-refresh projectile fly trails and player powerup effects now keep their presentation-time attenuation/origin parameters in sync with interpolated movement on repeated-state frames instead of stepping only when the 60 Hz gameplay tick rewrites those effects.
  • Multiplayer joiners now reconstruct terminal non-predicted projectile snapshots into visible detonate/impact FX instead of silently hiding those projectiles when they arrive already exploded, restoring host-fired projectile hit visuals on clients.
  • Multiplayer clients now receive authoritative hitscan impact FX through a dedicated remote-impact packet while the legacy hitscan trace message continues to drive path/tracer replay; that replay now bypasses local effect-rate throttling, reaches the firing remote client as well as other viewers, preserves the authored bullet/shotgun impact color, and still reapplies tint for railgun-class impacts that explicitly opt into hitscan coloring.
  • High-refresh listen-server view-weapon movement offsets now collapse duplicate same-tic acceleration samples during prediction reruns, preventing forward/side movement input changes from stacking extra shove into the local first-person gun after the earlier view-bias and turn-history fixes.
  • High-refresh listen-server view-weapon presentation no longer feeds render-only interpolated weapon poses back into shared weapon state, preventing the local first-person gun from regaining the forward lunge while repeated-state draw frames refresh muzzle-flash / flashlight / GUI-light alignment.
  • Multiplayer draw now reuses the same render-prep path as single-player, so the local or spectated first-person view recalculates its render view and refreshes presentation-space player/world/view-weapon transforms immediately before RenderPlayerView() instead of drawing the weapon from a stale simulation pose during listen-server movement.
  • High-refresh first-person muzzle flashes and other bound view-weapon firing FX now refresh from the corrected draw-time presentation pose on both simulation and repeated-state frames, so they no longer stick at the pre-correction gun position on the fire frame after the listen-server lunge fix.
  • High-refresh lightning-gun follow-up was narrowed to the local first-person beam only: trailEffectView now refreshes from the corrected presentation-space muzzle/chest joint and a presentation-time local beam trace on both simulation and repeated-state render frames, while the authoritative world/chain-lightning effects remain on the normal gameplay update path.
  • High-refresh bespoke visual-owner follow-up now refreshes gib skeleton side-models and security-camera model presentation on repeated-state frames, keeping those visuals aligned with interpolated transforms instead of stepping only at the 60 Hz simulation cadence.
  • High-refresh alternative camera/view-source follow-up now refreshes remote entity render views, security-camera feeds, portal-sky/playback cameras, and steam-pipe side models from presentation-space or interpolated repeated-state data instead of leaving those views and side visuals pinned to the last 60 Hz simulation sample.
  • High-refresh bespoke-visual follow-up now interpolates SP/MP idMultiModelAF side-model render defs on repeated frames and aligns the MP jump-pad activation FX origin with the SP centered-physics path, closing another pair of effect/render-owner presentation gaps that still sat outside the base entity refresh hooks.
  • High-refresh brittle-fracture callback models now rebuild from interpolated shard transforms on repeated-state frames, keeping dropped shard geometry smooth through shatter/fall/settle motion instead of stepping only on the 60 Hz simulation tick.
  • High-refresh weapon render lights now stay aligned with interpolated weapon/player presentation on repeated-state frames, keeping active muzzle-flash, world muzzle-flash, flashlight, and weapon GUI light defs from stepping at the 60 Hz simulation tick.
  • Ragdoll activation quality improved without changing the fixed 60 Hz simulation cadence: startup now keeps owner/world motion, handles initial penetrations more cleanly, and preserves slightly richer contact support for grounded corpses.
  • Rigid-body physics timing-safe quality pass applied without changing the fixed simulation cadence: angular velocity handoff now respects world inertia, water is handled as drag instead of a one-time collision-state hack, rigid-body contacts keep richer deduplicated support points, and impacts now preserve time-of-impact momentum while consuming a small bounded amount of leftover fixed-step time.
  • Script compiler x64 pointer-temp parity fix ported from OpenD3: right-associative indirect-expression retagging now guards 4-byte object-ref temp vs 8-byte pointer temp storage mismatch by allocating pointer-sized result defs when needed, preventing trigger/door script chain corruption.
  • Retail AAS placeholder parity restored: stock dummy .aas files now load/discard like retail instead of warning-spamming and failing stock map init, and AAS tactical data is cleared correctly between loads.
  • Bloom stability and quality improved: live r_bloom/r_bloom* changes now use the offscreen scene-target path immediately, scratch render targets rebuild their FBO attachments safely after runtime reallocations, map handoffs no longer rely on the fragile back-buffer bloom path, and bright-pass extraction now keeps only highlight energy so broad lights stop producing solid white bloom discs.
  • Manual release packaging builds are healthy again: the engine restored the shared idCommon timing/error/tool accessors expected by the SP/MP game libs, fixing the cross-platform release-build break that stopped the v0.1.011 workflow before artifacts were produced.
  • High-refresh mover riding is now stable on lifts such as game/storage2: the player keeps descending mover carry, ignores tiny mover-seam pseudo-landings/step jolts, and interpolates first-person view state relative to the mover so the camera stays smooth above 60 FPS instead of vibrating against platform motion.
  • High-refresh projectile and weapon-hit impact regressions were corrected by keeping client-predicted projectile collision/explode work on authoritative game ticks only while repeated-state redraws use the dedicated projectile interpolation path, preventing lingering rocket models and impact/scorch FX from replaying every render frame after a hit.
  • Renderer effect lifetime replay regression fixed: expired one-shot BSE impact effects now stay finished until their client-effect owner frees the handle, preventing bullet marks, scorch decals, and hit sounds from being recreated every frame after a hit.
  • Phase 4 repeated-state rendering overhead reduced: SP/MP scene refresh no longer scans all spawned entities every redraw for projectile interpolation, and active entities now skip repeated-state transform/non-model refresh work unless they actually have presentation deltas or interpolation-sensitive auxiliary visuals, recovering a major agame/airdefense1 FPS regression introduced during the high-refresh work.
  • High-refresh BSE overhead reduced again: repeated-state client effects now keep renderer owner-time on authoritative game ticks instead of wall-clock presentation time, avoiding render-rate ambient effect spawning on maps like agame/airdefense1, and renderer effect servicing now runs once per rendered frame instead of repeating per view.
  • Repeated-state client-entity work is now pruned more aggressively in SP/MP: static client models and client effects no longer rerun redraw-time presentation work by default, while bound client entities only stay on the high-refresh path when their owner actually has an interpolated transform delta and client moveables stay there only while their own transform/scale interpolation is active.
  • Collision-model retail parity improved again: .proc loading now matches Quake 4's looser version-token behavior, CM precache requests stay on the .cm-only path instead of generating render-model collision data, and extension-mismatched authored collision caches (for example .lwo/.ase names requested through runtime render aliases) now reuse the existing loaded CM without renaming or duplicating cache entries.
  • Collision-model loader parity improved again: CM .proc and .cm parsing now use Quake 4's binary-aware lexer path instead of bypassing it, restoring compiled-companion fallback behavior (.procc / .cmc), normal search-path precedence, retail-style CM loader diagnostics, retail proc-clip slot reservation during map builds, retail-style .cm serialization that no longer forces synthetic proc-clip models into saved map collision caches, retail-style binary companion generation (.cmc) when com_BinaryWrite is enabled, stock load pacifier updates around collision-data generation, retail-style fatal map-load handling when the required .proc build data is missing, explicit map-entity CM exports back on fs_devpath, and the retail PROC/AAS out-of-date overlays during content bring-up.
  • Collision-model trace/debug parity improved again: rotation and contents paths now restore retail-style materialType propagation, SP/MP share the retail two-argument CM debug interface with player-view-oriented replay hooks, retained translation/rotation failure replay now mirrors retail debugging more closely, and stock game/airdefense1 no longer crashes at player spawn/level load when retail-style CM material-type lookups run against parsed .cm data.
  • Level-load filesystem robustness improved: empty-path ReadFile probes now resolve as normal missing-file checks instead of raising a fatal dialog, which unblocks stock map startup paths such as game/airdefense1 and keeps the runtime log alive for any follow-up diagnostics.
  • Collision-model diagnostics parity improved again: local CM ModelInfo() reporting is no longer a stub, single-player restores the retail collisionModelInfo debug command alongside multiplayer, Contacts() once again follows retail's translation-only contact sweep semantics, and SP validation on game/airdefense1 plus collisionModelInfo all now completes cleanly with the updated CM debug/reporting paths.
  • Collision-model cache-write parity improved again: runtime-generated .cm caches now follow retail Quake 4's fs_devpath destination instead of being diverted to fs_savepath, keeping generated CM outputs on the normal authored/dev override path alongside the existing map-entity export behavior.
  • Collision-model render-source parity improved again: LoadRenderModel() now matches retail Quake 4's authored-CM source-model whitelist by admitting only .ase, .lwo, and .obj when generating collision data from render models, dropping the extra .mdr / .dae CM-generation path that was broader than retail.
  • Single-player clip-query parity improved again: idGameLocal::ClipModelsTouchingBounds() no longer falls back from non-zero clip worlds into world 0 for trigger queries, so the SP bounds-query path now matches multiplayer and retail behavior instead of keeping the temporary OpenQ4 multi-instance trigger override.
  • MD5R parity improved again: SoA Pos3Swizzled vertex buffers now decode into usable packed geometry instead of falling back to metadata-only loads, MD5RProc companions now preserve and round-trip the real retail map CRC token instead of a stub value, and retained MD5R vertex exports now keep specular-color / point-size fields instead of discarding them.
  • Decal parity improved again: packed MD5R surfaces now prefer a retail-style native sil-trace decal projector over the transient draw-vertex materialization fallback, while still falling back safely when packed mesh state is incomplete; the fallback now reuses the current live draw geometry when available so dynamic skinned recipients do not drop back to bind-pose decal projection, the native packed path now only runs on true packed sil-trace buffers instead of misusing draw-order silTraceVerts mirrors, decal fade cleanup no longer needlessly invalidates cached tangent/plane data every frame when the decal mesh itself did not change, and decal draw-surfs now snapshot vertices plus per-stage color data into one retail-style transient upload block instead of splitting them across separate temp cache allocations.
  • SDL3 keyboard layout parity improved: printable key events now use SDL3's active-layout translation instead of the fixed US scancode map, non-English console-toggle lookup now follows the translated grave/console scancode again, and UTF-8 text input is tracked as decoded codepoints in the SDL3 event path rather than a stale byte-splitting backlog item.
  • POSIX startup now enforces the same single-instance guard as Windows by holding a per-user advisory launch lock, while sys_allowMultipleInstances 1 keeps multi-instance testing available when explicitly needed.
  • Retail flare/material deform parity improved again: ambient submission no longer clips deform flare / sprite-style materials to tiny authored entity scissors, so stock map-authored effects such as game/storage1's moving beamBlastFlare render as expanded flare geometry instead of a boxed white square; the flare deform path also restores retail prim-batch handling and cleared-temp-vertex setup.
  • Retail decl folder registration parity improved: recursive decl folder scans now register each child folder as its own folder/default-type pair before loading files, and DECL_MODELEXPORT ownership is back on the game-library model/export/camera registration path instead of the framework pre-claiming the parser-only export slot.
  • Direct no-post scene rendering now clears the backbuffer before drawing the world, preventing full-screen GUI/material overlays such as stock vehicle screen dirt from persisting after the GUI that drew them has stopped rendering.

Carry Forward

  • Linux and macOS bring-up needs full compile/link/runtime validation to reach first-class status.
  • Replace temporary MSVC compatibility flag (/Zc:strictStrings-) with full strict-strings codebase compliance.