From e56d5ae8a472bde580de5704f59bbc0f74a6824f Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 13:38:57 +0100 Subject: No spread: detect pellet draws from the FireBullets seed call The ApplySpread random draws are not guaranteed to run in the player's frame (the compiler can outline them), so the frame-based shooter check missed and the shotgun kept its seed-minimised spread. The player's FireBullets RandomSeed call now arms a short 8-draw window; the next RandomFloat draws return 0. Keep the frame check as the other path. Remove the diagnostics used to find this. --- CONTEXT.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'CONTEXT.md') diff --git a/CONTEXT.md b/CONTEXT.md index 75b2f0a..98eb7d0 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -303,9 +303,13 @@ vocabulary / decisions. ApplySpread` is inlined into `CBaseEntity::FireBullets` and draws x/y via the global `CUniformRandomStream` (`_ZTV20CUniformRandomStream` + 8, slot 1 = `RandomFloat(float,float)`; confirmed against `libvstdlib.so`). The hook - returns 0 for those draws only when the calling frame's `this` (at - `ebp+8`) is the local server player, so every pellet follows the exact shot - direction. NPC fire and the client's prediction stream keep normal values. + returns 0 for those draws so every pellet follows the exact shot direction. + Detection is frame-based (`ebp+8` = the local server player) *and* a small + armed window: the player's `FireBullets` `RandomSeed` call sets a counter of + 8 draws, which the next `RandomFloat` calls consume. The window is required + because the compiler can outline the `ApplySpread` draws into a different + frame, where the first argument is not the player. NPC fire and the client's + prediction stream keep normal values. - This attacks the random cone offset only. The cone size, the pistol's `m_flAccuracyPenalty` growth, the server view punch added to `GetAutoaimVector`, and any damage falloff are server-side state. In -- cgit v1.2.3