fix(physics): #149 — collide BSP-less landblock statics via Setup cylsphere
Town props placed as landblock stabs whose ONLY collision is a Setup CylSphere/Sphere (no physics BSP) registered ZERO collision shapes and were walk-through -- torches, braziers, lamp-posts, candle-stands, posts. Root: the ISSUES #83 / A1.6 gate `!_isLandblockStab` skipped Setup cyl/sphere registration for ALL landblock stabs, on the false assumption "landblock stabs collide via BSP only (retail CBuildingObj)." That over-broadened -- it also killed collision for BSP-less stabs. Retail's CPhysicsObj::FindObjCollisions (@0x0050f050) uses binary dispatch: the object's physics BSP if it HAS one (HAS_PHYSICS_BSP_PS 0x10000), ELSE its CSetup CylSpheres/Spheres -- never both. Confirmed via live retail cdb on the Holtburg torch (Setup 0x020005D8 at world (105.99,17.17)): FindObjCollisions target num_cylsphere=1, cyl h=2.2 -- a cylsphere, exact-matching the dat (cylSphere r=0.2 h=2.2); the StabList confirms stab[95]=0x020005D8 there. Fix: gate the Setup cyl/sphere registration on `entityBsp == 0` instead of stab-ness. Preserves #83's anti-doubling (stab WITH a BSP -> BSP-only) while restoring collision for BSP-less stabs. Other landblock entities on this path (scenery -- tree-trunk cylspheres) are unaffected. Live-verified: torch + candle/brazier family block now; ~115 cyl/sphere Setups register across streamed landblocks. Core suite green (1595/0). The earlier selection-sphere hypothesis was WRONG and is reverted -- the cdb's r=0.48 sphere was the player/NPC body (every body sphere is ~0.48), not the torch. The correct cdb method: capture the TARGET at FindObjCollisions (not `this` in CSphere::intersects_sphere) and confirm by position + Setup-id. (Issue numbered #149 to stay clear of main's #148; this worktree branched before main's #145-148 were added.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
989cc25d80
commit
2ac7ea776f
2 changed files with 46 additions and 12 deletions
|
|
@ -5482,6 +5482,28 @@ outdoors at the angle that previously erased it.
|
||||||
|
|
||||||
# Recently closed
|
# Recently closed
|
||||||
|
|
||||||
|
## #149 — BSP-less landblock statics (torches/braziers/lamp-posts) were walk-through
|
||||||
|
|
||||||
|
**Status:** DONE (2026-06-25, `4cf6eeb`) — town props placed as landblock stabs
|
||||||
|
whose ONLY collision is a Setup CylSphere/Sphere (no physics BSP) had ZERO collision
|
||||||
|
shapes registered → walk-through. Root: the ISSUES #83 / A1.6 gate `!_isLandblockStab`
|
||||||
|
skipped Setup cyl/sphere for ALL stabs, on the false assumption *"landblock stabs
|
||||||
|
collide via BSP only (retail CBuildingObj)."* Confirmed end-to-end via live retail
|
||||||
|
cdb: the Holtburg torch (Setup `0x020005D8`, world (105.99,17.17)) hits
|
||||||
|
`CPhysicsObj::FindObjCollisions` with `num_cylsphere=1`, cyl h=2.2 — a cylsphere,
|
||||||
|
matching the dat (cylSphere r=0.2 h=2.2) exactly; the StabList confirms stab[95]=
|
||||||
|
`0x020005D8` at that position. Fix: gate the Setup cyl/sphere registration on
|
||||||
|
`entityBsp == 0` (retail's binary dispatch — BSP if the object has one, ELSE
|
||||||
|
cyl/sphere; see `feedback_retail_binary_dispatch`) instead of stab-ness — preserves
|
||||||
|
#83's anti-doubling (stab WITH a BSP → BSP-only) while restoring collision for
|
||||||
|
BSP-less stabs. Live-verified (torch + candle/brazier family block now; ~115
|
||||||
|
cyl/sphere Setups register across streamed landblocks). The earlier selection-sphere
|
||||||
|
hypothesis was WRONG and reverted — the cdb's r=0.48 sphere was the player/NPC body
|
||||||
|
(every body sphere is ~0.48), not the torch; capturing the *target* at
|
||||||
|
`FindObjCollisions` (not `this` in `intersects_sphere`) + confirming by position +
|
||||||
|
Setup-id is the correct cdb method. `GameWindow.cs:7281`. Core suite green (1595/0).
|
||||||
|
(Numbered #149 to stay clear of main's #148; worktree branched before #145–148.)
|
||||||
|
|
||||||
## Dense-town (Arwic) FPS deep-dive — 75 → ~165 fps
|
## Dense-town (Arwic) FPS deep-dive — 75 → ~165 fps
|
||||||
|
|
||||||
**Status:** DONE (2026-06-24) — `290e731` (cell-object draw batching) + `9f51a4d`
|
**Status:** DONE (2026-06-24) — `290e731` (cell-object draw batching) + `9f51a4d`
|
||||||
|
|
|
||||||
|
|
@ -3830,7 +3830,8 @@ public sealed class GameWindow : IDisposable
|
||||||
CylHeight: (setup.Height > 0 ? setup.Height : setup.Radius * 2f) * entScale));
|
CylHeight: (setup.Height > 0 ? setup.Height : setup.Radius * 2f) * entScale));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shapes.Count == 0) return;
|
if (shapes.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// Decode PvP / Player / Impenetrable from PWD._bitfield.
|
// Decode PvP / Player / Impenetrable from PWD._bitfield.
|
||||||
// IsCreature comes from the spawn's ItemType (server-known type).
|
// IsCreature comes from the spawn's ItemType (server-known type).
|
||||||
|
|
@ -7265,17 +7266,28 @@ public sealed class GameWindow : IDisposable
|
||||||
// clobber entries via Deregister.
|
// clobber entries via Deregister.
|
||||||
{
|
{
|
||||||
var setup = _physicsDataCache.GetSetup(entity.SourceGfxObjOrSetupId);
|
var setup = _physicsDataCache.GetSetup(entity.SourceGfxObjOrSetupId);
|
||||||
// ISSUES #83 / Phase A1.6 (2026-05-21): landblock stabs use BSP
|
// Retail binary collision dispatch (CPhysicsObj::FindObjCollisions
|
||||||
// collision exclusively (retail CBuildingObj). Skip Setup-derived
|
// @0x0050f050, see feedback_retail_binary_dispatch): an object uses
|
||||||
// CylSphere/Sphere/Radius shadow registrations for stabs to
|
// its physics BSP if it HAS one (HAS_PHYSICS_BSP_PS 0x10000), ELSE
|
||||||
// prevent the same doubled-collision bug A1 fixed for the
|
// its CSetup CylSpheres/Spheres — never both. The per-part BSP loop
|
||||||
// mesh-AABB-fallback — but on the Setup path instead. Without
|
// above already registered every BSP-bearing part (entityBsp counts
|
||||||
// this gate, a stab whose source is 0x02xxxxxx (Setup) with
|
// them). So register the Setup's CylSpheres/Spheres ONLY when no BSP
|
||||||
// defined CylSpheres registers BOTH per-part BSP shadows AND a
|
// claimed this object (entityBsp == 0).
|
||||||
// CylSphere shadow with id = entity.Id, producing an invisible
|
//
|
||||||
// collision cylinder at the stab origin alongside the correct
|
// This supersedes the ISSUES #83 / A1.6 (2026-05-21) gate that
|
||||||
// BSP walls.
|
// skipped Setup cyl/sphere for ALL landblock stabs to stop a
|
||||||
if (setup is not null && !_isLandblockStab)
|
// BSP+cylinder doubled-collision. That gate over-broadened: it also
|
||||||
|
// killed collision for BSP-LESS stabs whose ONLY shape is a Setup
|
||||||
|
// CylSphere — e.g. the Holtburg town torch (stab Setup 0x020005D8,
|
||||||
|
// part 0x01001774 HasPhysics=False/BSP=null, cylSphere r=0.2 h=2.2).
|
||||||
|
// Retail collides with it via that cylsphere (live cdb 2026-06-25:
|
||||||
|
// FindObjCollisions target ncyl=1, cyl h=2.2 at world (105.99,17.17));
|
||||||
|
// acdream walked straight through. Gating on entityBsp==0 keeps #83's
|
||||||
|
// anti-doubling (stab WITH a BSP → BSP-only) while restoring cyl
|
||||||
|
// collision for BSP-less stabs. Other landblock entities on this path
|
||||||
|
// (scenery — tree-trunk cylspheres etc.) are unaffected: with no BSP
|
||||||
|
// they still register cyl/sphere exactly as before.
|
||||||
|
if (setup is not null && entityBsp == 0)
|
||||||
{
|
{
|
||||||
float entScale = entity.Scale > 0f ? entity.Scale : 1f;
|
float entScale = entity.Scale > 0f ? entity.Scale : 1f;
|
||||||
uint shapeIndex = 0;
|
uint shapeIndex = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue