The SoundTable probability field is a Bernoulli play/skip gate applied at
the play site (SoundManager::PlayProbability @0x005500E0), not a selection
weight — and variant selection (SoundManager::GetSound @0x00550680) is a
uniform index over (n-1) that ignores probability entirely. SoundCookbook
did the opposite: a cumulative-distribution walk weighted BY probability,
short-circuiting single-entry lists before rolling at all.
A dat census says 4,183 of 4,184 entries are single-entry and 686 of those
carry probability < 1.0, so the gate was categorically absent: Speak1 idle
chatter authored at 0.05 fired every trigger (~20x too often), wound/attack/
swoosh variants never dropped, and six 0.0001 entries always played.
Split into retail's two steps (PickVariant + PlayProbability, composed by
Select) over a new ISoundRandom modelling both retail roll ranges: the
variant roll clamped below 1.0 (0x00797D48) and the gate's 1/32767 grid,
which is why 0.0001 resolves to ~1.2e-4. PickVariant reproduces retail's
(n-1) off-by-one verbatim per the port-faithfully rule — the last variant
of a multi-entry sound is unreachable, costing exactly one wave
(0x0A00051E) in the shipped dats.
Also removes invented mechanism this review disproved: the dead Core
SoundEntry/ISoundCache scaffold (PitchMin/PitchMax, Loop, Is3D — retail
never calls SetFrequency, never sets the loop flag, and creates every
gameplay buffer 2D), the engine's pitch plumbing, the int 0..7 priority
cast (the dat field is a float in [0,1]; 4,100 entries collapsed to 0),
and the clamp-at-the-field on volume (an unbounded gain retail clamps only
after the distance divide).
Tests rewritten as conformance against the disassembled values, replacing
a self-referential suite that pinned the wrong model.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>