fix(physics): #91 — query indoor cell shadows in FindObjCollisions
Interior items (fireplaces, tables, chests) registered via A1.5's
ShadowObjectRegistry.Register `cellScope` parameter (commit 4d3bf6f)
are stored under their ParentCellId key (e.g. 0xA9B40121). But
GetNearbyObjects's broad-phase only iterates outdoor 24m landcell
keys (0xA9B40029 etc) and never looks up indoor cell keys, so
interior shadows were registered but unreachable. User-visible
symptom: tables/boxes/fireplaces don't block movement, while walls
DO block (the indoor BSP path is separate).
Fix: GetNearbyObjects accepts an optional indoorCellIds parameter
and additionally queries _cells[indoorCellId] for each entry with
low-byte >= 0x0100u. FindObjCollisions computes the set via
CellTransit.FindCellSet (same set A4 uses for multi-cell BSP
iteration) and passes it through. Outdoor seeds typically produce
sets containing only outdoor land-cells which the new branch filters
out, so the outdoor-only behavior is preserved.
1147 + 8 baseline maintained. Closes the user-reported regression
"walls block now correct but interior items such as tables and boxes
or fireplaces do not block."
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4ca35966f8
commit
c0d84057cb
2 changed files with 50 additions and 2 deletions
|
|
@ -242,14 +242,43 @@ public sealed class ShadowObjectRegistry
|
|||
/// Get all objects near a world position. Searches the given landblock plus
|
||||
/// all 8 adjacent landblocks to handle objects near cell/landblock boundaries.
|
||||
/// Within each landblock, queries only the cells the query sphere overlaps.
|
||||
///
|
||||
/// <para>
|
||||
/// Issue #91 (2026-05-20): the optional <paramref name="indoorCellIds"/>
|
||||
/// parameter is the candidate set of indoor cells the foot-sphere overlaps
|
||||
/// (from <see cref="CellTransit.FindCellSet"/>). When supplied, indoor
|
||||
/// shadows registered via <see cref="Register"/>'s <c>cellScope</c>
|
||||
/// parameter (A1.5 fix at `4d3bf6f`) are ALSO included in the result.
|
||||
/// Without this, interior statics (fireplaces, tables, chests) registered
|
||||
/// against e.g. `0xA9B40121` are stored under that key but the outdoor-
|
||||
/// grid lookup (cell ids like `0xA9B40029`) never queries the indoor key.
|
||||
/// Net effect pre-fix: interior items don't block movement.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public void GetNearbyObjects(Vector3 worldPos, float queryRadius,
|
||||
float worldOffsetX, float worldOffsetY, uint landblockId,
|
||||
List<ShadowEntry> results)
|
||||
List<ShadowEntry> results,
|
||||
System.Collections.Generic.IReadOnlyCollection<uint>? indoorCellIds = null)
|
||||
{
|
||||
results.Clear();
|
||||
var seen = new HashSet<uint>();
|
||||
|
||||
// Indoor-scoped shadows (A1.5 cellScope). Query first so the
|
||||
// outdoor-grid lookup below skips duplicates via `seen`.
|
||||
if (indoorCellIds is not null)
|
||||
{
|
||||
foreach (uint indoorCellId in indoorCellIds)
|
||||
{
|
||||
if ((indoorCellId & 0xFFFFu) < 0x0100u) continue; // skip outdoor ids
|
||||
if (!_cells.TryGetValue(indoorCellId, out var list)) continue;
|
||||
foreach (var entry in list)
|
||||
{
|
||||
if (seen.Add(entry.EntityId))
|
||||
results.Add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract landblock X/Y from the ID.
|
||||
int lbX = (int)((landblockId >> 24) & 0xFF);
|
||||
int lbY = (int)((landblockId >> 16) & 0xFF);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue