Eighteen Pellets Instead of Twenty
Riotgun spread doubled and pellet count cut so the round count survives rounding, dropped weapons that settle on the real BSP floor, and server-side PVS.
Balance Done Against The Arithmetic
riotgun fire rate 1.5625 -> 1.875 shots/sec (640ms -> ~533ms)
riotgun spread 6 deg -> 12 deg half-angle
riotgun pellets 20 -> 18Cutting pellets rather than damage is the interesting decision. Damage is Math.rounded, so 4.5 rounds back to 5 — remove the fifth of a pellet and the pellet count lands somewhere rounding respects.
Also: a dropped weapon carries at most one clip, added to reserves capped at maxAmmo. Despawn 30s → 15s. Pickup radius 128 units, vertical range [-48, 96]. Grenades pass through their owner.
Dropped Weapons Land Where They Should
DroppedWeaponSystem receives the CollisionWorld and uses trace() to find the real BSP floor — "instead of crude dropY - 24 estimate".
Server PVS
A new ServerPVS with no Babylon.js dependency, handling the Y-up/Z-up conversion itself. broadcastSnapshot() culls per client. Own player, player states, events and non-spatial entities bypass culling. Per-client lastSentState baselines, with a graceful fallback when there is no visData.
Estimated bandwidth savings 40-60% on complex BSP maps
Cost ~O(N) per client per snapshot tickThe log line reads pvs_culled: N entities across M clients.
Also Here
Docs corrected: documented tick rate 20Hz → 125Hz, and a stale tickRate: 20 removed from the engine.json example. A stale tick rate in the example config is a small thing that would have cost somebody a day.
Known Issues: none stated.