This is how I did it:

```
s:AddHook( "Think", function( this )
local k, v, wep, pl, prim, sec, save, mul
for k, v in ipairs( player.GetAll( ) ) do
if not v:Alive( ) then continue end
wep = v:GetActiveWeapon( )
if not wep:IsValid( ) then continue end
mul = math.max( .1, 1 - ( RPG:GetSkill( v, this:GetID( ) ) * .05 ) )
mul = RPG:TimeScaleMultiplier( v, mul, 0 )
save = wep:GetSaveTable( )
prim = save.m_flNextPrimaryAttack
sec = save.m_flNextSecondaryAttack
wep.RPG_LastPrimaryDelay = wep.RPG_LastPrimaryDelay or 0
wep.RPG_LastSecondaryDelay = wep.RPG_LastSecondaryDelay or 0
if not ( prim and sec ) then continue end
if prim > wep.RPG_LastPrimaryDelay then
prim = math.max( prim > .065 and .065 or .01, prim * mul )
wep:SetSaveValue( "m_flNextPrimaryAttack", prim )
end
if sec > wep.RPG_LastSecondaryDelay then
sec = math.max( sec > .065 and .065 or .01, sec * mul )
wep:SetSaveValue( "m_flNextSecondaryAttack", sec )
end
wep.RPG_LastPrimaryDelay = prim
wep.RPG_LastSecondaryDelay = sec
end
end )
```

It’s incredibly dirty, but it will work on nearly every weapon barring those that manage the time themselves instead of using the engine methods. You should have an idea of what you need to do from that.