Skip to content

fix(runner): link monsters into the area tree so hitscan connects - #18

Merged
tannevaled merged 1 commit into
mainfrom
fix-monster-hitscan-linking
Jul 5, 2026
Merged

fix(runner): link monsters into the area tree so hitscan connects#18
tannevaled merged 1 commit into
mainfrom
fix-monster-hitscan-linking

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Problem

In lq_e0m1 the player fires and consumes ammo, but shots never damage any of the 55 monsters — hitscan passes straight through them.

Root cause — two coupled defects in area-tree linking

  1. setsize was a no-op. QC monsters set solid=SOLID_SLIDEBOX, then call setmodel + setsize. Their alias .mdl bbox doesn't resolve in setmodel, so setmodel skips their area-tree link (only SOLID_BSP doors, whose submodel bbox resolves, got linked). Vanilla setsize (SV_SetSizeSV_LinkEdict) writes the entity's mins/maxs/size and relinks it — here it did nothing, so monsters had neither a collision bbox nor a tree entry. Now implemented.

  2. Wrong area-tree key. setmodel/setsize keyed the tree by ResolvePointer's second return — the byte offset within the field block, not the edict index. A setsize(self,…) pointer addresses field-offset 0, so that value is 0 for every entity → all collapsed onto world.Key(0) (the world slot the query skips). Now keyed by Arena.NumFor(ent), matching how host.SetOrigin already links.

With both fixed, traceline's candidate query returns the monsters and the swept-bbox clip connects, so the QC TraceAttackT_Damage path lands.

Verification (autonomous, Firefox/Playwright, lq_e0m1)

Via a temporary area-tree census + weapon-independent hitscan probe (since removed):

  • linked solids: 11 (0 slidebox) → 76 (55 slidebox = all 55 monster edicts)
  • monster bbox reads back [-16 -16 -24]/[16 16 40]
  • a point-blank trace through the nearest monster's centre returns that monster's slot

Physics probe still 8/8 (no spawn/view regression). Adds runner/setsize_test.go covering the bbox write, correct-slot linking (the world.Key(0) regression guard), and the SOLID_NOT unlink case.

🤖 Generated with Claude Code

Shots (and every SV_Move query) passed straight through all 55 monsters in
lq_e0m1: they fired and consumed ammo but never dealt damage. Root cause was
two coupled defects in how spawned entities enter the collision area tree.

1. setsize was a no-op. QC monsters set solid=SOLID_SLIDEBOX then call
   setmodel + setsize. Their alias .mdl bbox does not resolve in setmodel, so
   setmodel skips their area-tree link (only SOLID_BSP doors, whose submodel
   bbox resolves, were linked). setsize -- which in vanilla (SV_SetSize ->
   SV_LinkEdict) writes the entity's mins/maxs/size AND relinks it -- did
   nothing here, so monsters got neither a collision bbox nor a tree entry.
   Implement it.

2. setmodel/setsize keyed the area tree by the SECOND return of
   ResolvePointer, which is the byte OFFSET within the field block, not the
   edict index. A setmodel(self,...) / setsize(self,...) pointer addresses
   field-offset 0, so that value is 0 for every entity -- collapsing them all
   onto world.Key(0) (the world slot the query skips). Key by the edict's
   arena slot via Arena.NumFor(ent), matching how host.SetOrigin already links.

With both fixed, traceline's candidate query returns the monsters and the
swept-bbox clip connects, so the QC's TraceAttack -> T_Damage path lands.

Verified in-browser (Firefox/Playwright, lq_e0m1) via a temporary area-tree
census + weapon-independent hitscan probe (both since removed): linked solids
went 11 (0 slidebox) -> 76 (55 slidebox = all 55 monster edicts), the monster
bbox reads back [-16 -16 -24]/[16 16 40], and a point-blank trace through the
nearest monster's centre returns that monster's slot. runner physics probe
still 8/8 (no spawn/view regression). Adds runner/setsize_test.go covering the
bbox write, correct-slot linking (the world.Key(0) regression guard), and the
SOLID_NOT unlink case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 7d0ec97 into main Jul 5, 2026
7 checks passed
@tannevaled
tannevaled deleted the fix-monster-hitscan-linking branch July 5, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant