Classic Quake II/III dynamic lights for muzzle flashes, bright projectiles and explosions - #148
Conversation
The implementation lives in openQ4-game (bfe7f45); this is the player- and release-facing side of it. The new guide explains what the feature adds over stock Quake 4, and gives the two things a reader actually needs to act on: where each color comes from in the shipped assets, so the choices are checkable rather than asserted, and the per-def override keys for content that wants something else. It also records the cost model and points at testClassicLight rather than making people fire a weapon at a wall to see the effect. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Both workflows pinned openQ4-game at 67fcd3e, which is now twelve commits behind. The engine's cross-repo tests assert the game tree's *current* contracts, so the pin drifting turns them into failures that have nothing to do with the commit under test: weapon_zoom_view_alignment has been red on main since the zoom-scope fix landed on the game side, because the pinned tree still calls UpdateZoomGuiViewState from the 2D overlay pass that the fix removed. Pin bfe7f45 instead, which is the game tree these workflows should have been validating all along, and which carries the ClassicLights work this branch documents. Verified by running the workflow's own 164-test list against the new pin: 158 pass, and the only six that do not are the ones that cannot run here at all - two require native Linux/macOS, three are invoked with required arguments in CI rather than bare, and one needs a built client in .install. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Merging with four red checks, all of them pre-existing. Recording the evidence
All four fail with the same message — They were invisible on recent No speculative renderer fix was attempted: it would mean editing the Green and relevant: Windows x64, all four Linux GCC/Clang Wayland variants, 🤖 Addressed by Claude Code |
What is in this PR
Documentation, plus a CI pin bump. The implementation is in the companion
repo and is already on
mainthere:themuffinator/openQ4-game@bfe7f45 —
src/{game,mpgame}/ClassicLights.{h,cpp}plus hooks in
Weapon.cpp,Projectile.cpp,Moveable.cpp,Game_local.cpp,SysCvar.*andSysCmds.cpp. Review that commit alongside this one.The CI pin bump is a fix, not incidental
Both workflows pinned
OPENQ4_GAMELIBS_SHAat67fcd3e, twelve commits behindthe game tree. The engine's cross-repo tests assert the game tree's current
contracts, so a drifting pin turns them into failures unrelated to whatever
commit is under test —
weapon_zoom_view_alignmenthas been red onmainsince before this branch existed, because the pinned tree still calls
UpdateZoomGuiViewStatefrom the 2D overlay pass that the game-side fixremoved. Moving the pin to
bfe7f45fixes that and makes CI validate againstthe tree this PR documents.
Checked by running the workflow's own 164-test list against the new pin: 158
pass; the six that do not cannot run in this environment at all (two need
native Linux/macOS, three are invoked with required arguments in CI rather than
bare, one needs a built client in
.install).What the feature does
Quake II and Quake III lit the world from the action itself. Quake 4 replaced
that with authored BSE effects, and a sweep of all 1172 shipped
.fxfilesshows how little survived: 71 light segments in total, not one of them on an
explosion, and no player projectile lit apart from the single-player rocket
and grenade trails.
g_classicDynamicLights(default1, archived) adds that layer back:authored radius, layered over the stock flash. Raised ahead of the authored
flash's bail-out, so a weapon with no flash light of its own still lights the
room.
renderLight/lightDefHandlepath, which already moves it. Gap-fill only: adef authoring
mtr_light_shaderis untouched, and the SP rocket and grenadeare skipped because their shipped trail effects already carry a light segment.
Their MP trails do not, so MP takes it.
nothing shipped does this. Exploding barrels and damagables included.
g_classicDynamicLightScale(0.25–4) scales the radius.Why the colors are what they are
They are extracted from the shipped PK4s rather than invented, which is the
part most worth checking. Muzzle flashes use the firing weapon def's own
flashColor. Projectile and explosion colors are the tints of light segmentsRaven authored elsewhere in the same asset set:
0.906 0.518 0.161effects/weapons/rocketlauncher/fly.fx0.973 0.286 0.086effects/weapons/grenadelauncher/trail.fx0.922 0.545 0.322effects/weapons/napalmgun/globburn.fx0.502 0 1effects/weapons/dmg/core.fx1 0.824 0.290effects/monsters/strogg_flyer/bomb_burst.fxBullets, nails, debris and glass are deliberately unlit — not bright, far too
many in flight to afford, and the originals did not light them either.
Safety and cost
entity gains a field, so the savegame format is untouched.
idGameLocal::PlayEffect's guards, so a re-run predictedframe on an MP client does not stack a flash every pass, and a dedicated
server never takes a light handle.
CL_AllocDlightdid; all unshadowed; culled beyond ~3000 units.authoritative tics.
classic_light,classic_light_color,classic_light_radius.Testing
Six runs against an isolated worktree build (SP maps, and an MP listen server
with bots exercising the
game_mptree) — no crashes, warnings or errors, andclean shutdown each time. Per-channel deltas measured against a baseline frame
confirm the colors reach the world:
g_classicDynamicLights 0Real AI projectile detonations produced flashes in live combat.
Not confirmed on screen, and worth a reviewer's eye in normal play: the
rvWeapon::MuzzleFlashcall site needs a trigger pull, and I could not frame alight riding a projectile in flight — the console
spawncommand drops enemies80 units away and they close to melee. Both are short call sites into functions
that are verified;
testClassicLight [muzzle|explosion] [def](cheat) raisesthe flashes without firing.
Note for anyone validating this locally
tools/build/build_gamelibs.ps1produces game DLLs that cannot run againstthe engine.
openQ4-game/src/idlib/precompiled.henablesRV_UNIFIED_ALLOCATORwhile the engine's has it commented out;stage_gamelibs.pyexists to overwriteidlib/renderer/ui/sys/bsewith theengine's copies, so only the engine build yields an ABI-matched module. The
tell is
WARNING: Unprotected allocation in DLL detected prior to initialization of memory systemimmediately before an execute-type0xC0000005right afterLoading game DLL:. Build the engine and usebuilddir/baseoq4/.🤖 Generated with Claude Code