Code:
-- Valve's pseudo-random functions ported directly to Lua :)
random = {}
local MAX_RANDOM_RANGE = 0x7FFFFFFF
local NTAB = 32
local IA = 16807
local IM = MAX_RANDOM_RANGE
local IQ = 127773
local IR = 2836
local NDIV = math.floor(1+(IM-1)/NTAB)
-- fran1 -- return a random floating-point number on the interval [0,1)
--
local AM = (1.0/IM)
local EPS = 1.2e-7
local RNMX = (1.0-EPS)
local m_idum = 0
local m_iy = 0
local m_iv = {}
function random.SetSeed( iSeed )
m_idum = ( ( iSeed < 0 ) and iSeed or -iSeed )
m_iy = 0
end
function random.GenerateRandomNumber()
local j = 0
local k = 0
if (m_idum <= 0 or not m_iy) then
if ( -(m_idum) < 1 ) then
m_idum = 1
else
m_idum = (-m_idum)
end
for j = NTAB + 7, 0, -1 do
k = math.floor((m_idum)/IQ)
m_idum = IA*(m_idum-k*IQ)-IR*k
if (m_idum < 0) then
m_idum = m_idum + IM
end
if (j < NTAB) then
m_iv[j] = m_idum
end
end
m_iy = m_iv[0]
end
k=math.floor((m_idum)/IQ)
m_idum=IA*(m_idum-k*IQ)-IR*k
if (m_idum < 0) then
m_idum = m_idum + IM
end
j=math.floor(m_iy/NDIV)
m_iy=m_iv[j]
m_iv[j] = m_idum
return m_iy
end
function random.RandomFloat( flLow, flHigh )
flLow = flLow or 0
flHigh = flHigh or 1
-- float in [0,1)
local fl = AM * random.GenerateRandomNumber()
if (fl > RNMX) then
fl = RNMX
end
return (fl * ( flHigh - flLow ) ) + flLow -- float in [low,high)
end
function random.RandomFloatExp( flMinVal, flMaxVal, flExponent )
flMinVal = flMinVal or 0
flMaxVal = flMaxVal or 1
-- float in [0,1)
local fl = AM * random.GenerateRandomNumber()
if (fl > RNMX) then
fl = RNMX
end
if ( flExponent ) then
fl = math.pow( fl, flExponent )
end
return (fl * ( flMaxVal - flMinVal ) ) + flMinVal -- float in [low,high)
end
function random.RandomInt( iLow, iHigh )
local maxAcceptable
local x = iHigh-iLow+1
local n = 0
if (x <= 1 || MAX_RANDOM_RANGE < x-1) then
return iLow
end
-- The following maps a uniform distribution on the interval [0,MAX_RANDOM_RANGE]
-- to a smaller, client-specified range of [0,x-1] in a way that doesn't bias
-- the uniform distribution unfavorably. Even for a worst case x, the loop is
-- guaranteed to be taken no more than half the time, so for that worst case x,
-- the average number of times through the loop is 2. For cases where x is
-- much smaller than MAX_RANDOM_RANGE, the average number of times through the
-- loop is very close to 1.
--
maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x )
repeat
n = random.GenerateRandomNumber()
until (n <= maxAcceptable)
return iLow + (n % x)
end
local m_bHaveValue = false
local m_flRandomValue = 0
function random.GaussianRandomFloat( flMean, flStdDev )
local fac,rsq,v1,v2 = 0,0,0,0
if (not m_bHaveValue) then
-- Pick 2 random #s from -1 to 1
-- Make sure they lie inside the unit circle. If they don't, try again
repeat
v1 = 2.0 * random.RandomFloat() - 1.0
v2 = 2.0 * random.RandomFloat() - 1.0
rsq = v1*v1 + v2*v2
until ((rsq <= 1.0) and (rsq ~= 0.0))
-- The box-muller transformation to get the two gaussian numbers
fac = math.sqrt( -2.0 * math.log(rsq) / rsq )
-- Store off one value for later use
m_flRandomValue = v1 * fac
m_bHaveValue = true
return flStdDev * (v2 * fac) + flMean
else
m_bHaveValue = false
return flStdDev * m_flRandomValue + flMean
end
end
random.SetSeed(os.time())
// NOW LETS ATTEMPT TO DO NOSPREAD!
local _R = debug.getregistry()
_R.rbackup = _R.rbackup or table.Copy(_R)
local cones = {}
local ply = LocalPlayer()
_R.Entity.FireBullets = function(ent, bullet)
local wep = ply:GetActiveWeapon()
if !wep or !IsValid(wep) then return _R.rbackup.Entity.FireBullets(ent, bullet) end
if bullet.Spread then
cones[wep:GetClass()] = bullet.Spread
end
return _R.rbackup.Entity.FireBullets(ent, bullet)
end
local function AngleVectors(angles)
local forward, right, up = Vector(), Vector(), Vector()
local sr, sp, sy, cr, cp, cy
local sy, cy = math.sin(angles[2]), math.cos(angles[2])
local sp, cp = math.sin(angles[1]), math.cos(angles[1])
local sr, cr = math.sin(angles[3]), math.cos(angles[3])
forward.x = cp * cy
forward.y = cp * sy
forward.z = -sp
right.x = -1 * sr * sp * cy + -1 * cr * -sy
right.y = -1 * sr * sp * sy + -1 * cr * cy
right.z = -1 * sr * cp
up.x = cr * sp * cy + -sr * -sy
up.y = cr * sp * sy + -sr * cy
up.z = cr * cp
return forward, right, up
end
local function VectorAngles(forward)
local tmp, yaw, pitch
if forward[2] == 0 && forward[1] == 0 then
yaw = 0
pitch = forward[3] > 0 and 270 or 90
else
yaw = (math.atan2(forward[2], forward[1]) * 180 / math.pi)
if yaw < 0 then
yaw = yaw + 360
end
tmp = math.sqrt(forward[1] * forward[1] + forward[2] * forward[2])
pitch = math.atan2(-forward[3], tmp) * 180 / math.pi
if pitch < 0 then
pitch = pitch + 360
end
end
return Angle(pitch, yaw, 0)
end
local function GetWeaponCone(cmd, qAngs, vSpread)
random.SetSeed(cmd:CommandNumber())
local uiSeed = random.GenerateRandomNumber()// & 0x7FFFFFFF
random.SetSeed(uiSeed/* & 255*/)
local x = random.RandomFloat(-0.5, 0.5) + random.RandomFloat(-0.5, 0.5)
random.SetSeed(uiSeed/* & 255*/)
local y = random.RandomFloat(-0.5, 0.5) + random.RandomFloat(-0.5, 0.5)
local spreadAngles = Angle()
local forward, right, up = Vector(), Vector(), Vector()
forward, right, up = AngleVectors(qAngs)
local vecDir = forward + (x * vSpread.x * right) + (y * vSpread.y * up)
spreadAngles = VectorAngles(vecDir)
spreadAngles = spreadAngles - qAngs
print(qAngs)
print(spreadAngles)
return spreadAngles
end
local function GetSpread(cmd, angPos)
local pWep = ply:GetActiveWeapon() or NULL
local vecSpread
if !IsValid(pWep) then return angPos end
if cones[pWep:GetClass()] then
local pCone = cones[pWep:GetClass()]
if type(pCone) == "number" then
vecSpread = Vector(-pCone, -pCone, 0)
elseif type(pCone) == "Vector" then
vecSpread = pCone
end
return GetWeaponCone(cmd, angPos, pCone)
end
return angPos
end
local function NoSpread(cmd)
if cmd:KeyDown(IN_ATTACK) then
local ang = cmd:GetViewAngles()
ang = GetSpread(cmd, ang)
ang.p = math.NormalizeAngle(ang.p)
ang.y = math.NormalizeAngle(ang.y)
cmd:SetViewAngles(ang)
end
end
hook.Add("CreateMove", "NoSpread", NoSpread)
this probably wouldn't have worked anyway, but i got stuck @ uint uiSeed = MD5_PseudoRandom(cmd:CommandNumber()) & 0x7FFFFFFF and RandomSeed(uiSeed & 255)