add sborka

This commit is contained in:
2026-03-31 10:27:04 +03:00
commit f5e5f56c84
2345 changed files with 382127 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
LeyHitreg.WeaponSpreads = {}
local vector_origin = vector_origin
function LeyHitreg:PlayerSwitchWeapon(ply, oldWep, newWep)
if (not IsValid(newWep)) then
return
end
local classname = newWep:GetClass()
if (not classname or self.WeaponSpreads[classname]) then
return
end
if (self:IsIgnoreWep(newWep)) then
self.WeaponSpreads[classname] = vector_origin
return
end
ply.LeyHitreg_NeedsSpreadForce = newWep
timer.Simple(1, function()
if (not IsValid(ply) or not IsValid(newWep)) then
return
end
ply.LeyHitreg_NeedsSpreadForce = nil
if (ply:GetActiveWeapon() != newWep) then
return
end
LeyHitreg.WeaponSpreads[classname] = LeyHitreg.WeaponSpreads[classname] or vector_origin
end)
LeyHitreg:SetFittingValidClip(newWep)
if (newWep.PrimaryAttack) then
newWep:PrimaryAttack()
elseif (newWep.Primary and newWep.Primary.Attack) then
newWep.Primary.Attack()
end
end
hook.Add("PlayerSwitchWeapon", "LeyHitreg:PlayerSwitchWeapon", function(...)
-- process switch at next frame so FireBullets uses proper wep
local t = {...}
timer.Simple(0, function()
LeyHitreg:PlayerSwitchWeapon(unpack(t))
end)
end)
function LeyHitreg:FetchSpreadFireBullets(ply, wep, bullet)
local spreadForceWep = ply.LeyHitreg_NeedsSpreadForce
local validSpreadForceWep = spreadForceWep != nil and IsValid(spreadForceWep)
-- if (validSpreadForceWep) then
-- wep = spreadForceWep
-- end
local weaponSpread = LeyHitreg:GetWeaponSpread(ply, wep, bullet)
self.WeaponSpreads[wep:GetClass()] = weaponSpread
if (validSpreadForceWep and wep == spreadForceWep) then
bullet.Damage = 1
bullet.Distance = 1
bullet.Src = Vector(-100000, -10000, -10000)
bullet.Dir = vector_origin
timer.Simple(0, function()
if (not IsValid(ply)) then
return
end
if (ply.LeyHitreg_NeedsSpreadForce == wep) then
ply.LeyHitreg_NeedsSpreadForce = nil
end
end)
return bullet
end
end
function LeyHitreg:EntityEmitSoundSpreadPrefire(data)
if (not data) then
return
end
local ent = data.Entity
if (not IsValid(ent)) then
return
end
if (ent:IsPlayer()) then
if (ent.LeyHitreg_NeedsSpreadForce) then
return false
end
local wep = ent:GetActiveWeapon()
if (not IsValid(wep)) then
return
end
if (wep.LeyHitreg_NeedsSpreadForce) then
return false
end
return
end
if (not ent:IsWeapon()) then
return
end
local ply = ent:GetOwner()
if (IsValid(ply) and ply:IsPlayer() and ply.LeyHitreg_NeedsSpreadForce) then
return false
end
if (ent.LeyHitreg_NeedsSpreadForce) then
return false
end
end
hook.Add("EntityEmitSound", "LeyHitreg:EntityEmitSoundSpreadPrefire", function(data)
local ret = LeyHitreg:EntityEmitSoundSpreadPrefire(data)
if (ret != nil) then
return ret
end
end)

View File

@@ -0,0 +1,213 @@
local IsValid = IsValid
local inputIsMouseDown = input.IsMouseDown
local vector_origin = vector_origin
IN_LEYHITREG1 = bit.lshift(1, 27)
function LeyHitreg:ShouldPrimaryAttack()
return inputIsMouseDown(MOUSE_LEFT) or inputIsMouseDown(MOUSE_RIGHT)
end
local lastPrim = nil
function LeyHitreg:CanShoot(cmd, wep, primary)
local canShoot = true
local nextPrim = wep:GetNextPrimaryFire()
if (primary) then
if (nextPrim == lastPrim or wep:Clip1() == 0) then
canShoot = false
else
lastPrim = nextPrim
end
end
return canShoot
end
local bitbor = bit.bor
local trace = {}
local traceres = {}
trace.filter = LocalPlayer()
trace.mask = MASK_SHOT
trace.output = traceres
local lply = nil
timer.Create("LeyHitreg.LocalPlayerGet", 0.1, 0, function()
if (not lply and IsValid(LocalPlayer())) then
lply = LocalPlayer()
trace.filter = lply
timer.Remove("LeyHitreg.LocalPlayerGet")
end
end)
LeyHitreg.WeaponSpreads = {}
function LeyHitreg:IsAutoWep(wep)
if (wep.Primary) then
return wep.Primary.Automatic
end
return true
end
local NeedsPrimReset = false
function LeyHitreg:CreateMove(cmd)
if (not lply or LeyHitreg.Disabled or LeyHitreg.DisabledOnlyOnClient) then
return
end
local spreadWep = lply.LeyHitreg_NeedsSpreadForce
if (spreadWep and IsValid(spreadWep)) then
LeyHitreg:SetFittingValidClip(spreadWep)
end
if (cmd:CommandNumber() == 0) then
return
end
local cmdAttack1 = cmd:KeyDown(IN_ATTACK)
if (not cmdAttack1) then
NeedsPrimReset = false
return
elseif (NeedsPrimReset and not cmdAttack1) then
NeedsPrimReset = false
end
local shouldPrimary = self:ShouldPrimaryAttack()
if (not shouldPrimary) then
return
end
local wep = lply:GetActiveWeapon()
if (not IsValid(wep)) then
return
end
if (self:IsIgnoreWep(wep)) then
return
end
if (not self:CanShoot(cmd, wep, shouldPrimary)) then
return
end
local primAuto = self:IsAutoWep(wep)
if (NeedsPrimReset and shouldPrimary) then
return
end
if (not primAuto and shouldPrimary) then
NeedsPrimReset = true
end
if (shouldPrimary) then
cmd:SetButtons(bitbor(cmd:GetButtons(), IN_LEYHITREG1))
end
trace.start = lply:GetShootPos()
local viewang = cmd:GetViewAngles()
local dir = viewang:Forward()
local weaponSpread = self:GetWeaponSpread(lply, wep)
if (weaponSpread) then
local applied, newDir = self:ApplyBulletSpread(lply, dir, weaponSpread)
if (applied) then
dir = newDir
end
else
-- LocalPlayer():ChatPrint("NO WEAPONSPREAD")
end
trace.endpos = trace.start + (dir * (56756 * 8))
traceres.Entity = nil
traceres.HitGroup = nil
traceres.HitBox = nil
util.TraceLine(trace)
local target = traceres.Entity
if (not IsValid(target) or not (target:IsNPC() or target:IsPlayer())) then
cmd:SetUpMove(-1)
if (LeyHitreg.AnnounceClientHits) then
LocalPlayer():ChatPrint("It's a miss!")
-- PrintTable(trace)
end
return
end
local hitgroup = traceres.HitGroup
local hitbox = traceres.HitBox
local hitbone = target:GetHitBoxBone(hitbox, 0)
if (not hitbone or not hitgroup) then
print("[/LeyHitreg/] Bone not found")
return
end
cmd:SetUpMove(target:EntIndex())
cmd:SetMouseWheel(hitbone)
if (LeyHitreg.AnnounceClientHits) then
LocalPlayer():ChatPrint("It's a hit!")
end
end
hook.Add("CreateMove", "LeyHitreg:CreateMove", function(...)
LeyHitreg:CreateMove(...)
end)
function LeyHitreg:EntityFireBullets(plyorwep, bullet)
if (LeyHitreg.Disabled or LeyHitreg.DisabledOnlyOnClient) then
return
end
if (bullet.Num >= 2) then
return
end
local ply, wep = self:GetPlayerFromPlyOrBullet(plyorwep, bullet)
if (not ply) then
return
end
if (not wep or self:IsIgnoreWep(wep)) then
return
end
if (not LeyHitreg.ShotDirForceDisabled) then
bullet.Dir = ply:GetAimVector()
end
local forcedShot = LeyHitreg:FetchSpreadFireBullets(ply, wep, bullet)
if (forcedShot != nil) then
return forcedShot
end
local ret = LeyHitreg:SpreadedEntityFireBullets(ply, wep, bullet)
if (ret != nil) then
return ret
end
end
hook.Add("EntityFireBullets", "LeyHitreg:EntityFireBullets", function(plyorwep, bullet)
local ret = LeyHitreg:EntityFireBullets(plyorwep, bullet)
if (ret != nil) then
return ret
end
end)

View File

@@ -0,0 +1,60 @@
-- By just locking onto a specific bone, we don't always get a match. We might lock onto a bone pos
-- and that bone pos just happens to be the center. Then, if we're looking through a edge
-- it's possible that the bullet would miss
-- so how do we fix this? well, hit scanning
-- if a bullet which should hit locked onto a bone pos misses,
-- then attempt to use a more expensive calculation to scan for the precise
-- location which would hit
-- if one is found -> fire bullet again but with that information
-- alternatively, dont fire
-- the calculation is done in bullet cb to make it less expensive
-- because most of the time, just picking the bone pos should work
-- bullet missed even though it should not have, try hitscan
function LeyHitreg:HitScan(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos)
-- TODO: do hitscan here
end
local IsValid = IsValid
function LeyHitreg:HitScanBulletCallback(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos, cbdata)
local traceres = cbdata[2]
if (IsValid(traceres.Entity)) then
return
end
self:HitScan(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos)
end
function LeyHitreg:HitScanBullet(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos)
if (self.BulletOverwriteDisabled) then
return
end
local oldCallback = bullet.Callback or function() end
bullet.Callback = function(...)
local cbdata = {...}
if (cbdata[1] != ply) then
return oldCallback(...)
end
local ignoreBullet = hook.Call("LeyHitreg.OnBulletCallback", cbdata[1], cbdata[2], cbdata[3])
if (ignoreBullet) then
return
end
if (LeyHitreg.HitScanDisabled) then
return oldCallback(...)
end
if (LeyHitreg:HitScanBulletCallback(ply, target, bullet, shot, targetBone, targetHitGroup, shootpos, cbdata)) then
return
end
return oldCallback(...)
end
end

View File

@@ -0,0 +1,322 @@
local IsValid = IsValid
local CurTime = CurTime
local ipairs = ipairs
local tableremove = table.remove
LeyHitreg.ForceHit = {}
local toRemove = {}
function LeyHitreg:CleanHits(ply, wep, tbl)
local needsRemove = false
local highestKey = nil
local curTime = CurTime()
for k,v in ipairs(tbl) do
local target = v.target
if (not IsValid(target) or target:Health() < 0 or curTime > v.expireTime or v.weapon != wep) then
toRemove[#toRemove + 1] = k
if (not highestKey or k > highestKey) then
highestKey = k
end
needsRemove = true
end
end
if (not needsRemove) then
return tbl
end
for i = #toRemove, 1, -1 do
local key = toRemove[i]
tableremove(tbl, key)
toRemove[i] = nil
end
return tbl
end
LeyHitreg.ScaleDamageBlockEntity = LeyHitreg.ScaleDamageBlockEntity or {}
local spread = vector_origin
function LeyHitreg:FallbackEntityFireBullets(ply, wep, bullet)
local ret = LeyHitreg:SpreadedEntityFireBullets(ply, wep, bullet)
if (LeyHitreg.ShowActualShotSpreadedHit) then
LeyHitreg:DebugShowActualShotHit(bullet)
end
if (ret != nil) then
return ret
end
end
function LeyHitreg:DebugShowActualShotHit(bullet)
local ocb = bullet.Callback or function() end
bullet.Callback = function(atk, tr, dmginfo, ...)
util.Decal("Eye", tr.HitPos + tr.HitNormal, tr.HitPos - tr.HitNormal)
return ocb(atk, tr, dmginfo, ...)
end
end
function LeyHitreg:EntityTakeDamage(ent, dmg)
if (not IsValid(ent)) then
return
end
if (not ent.IsNPC or not ent.IsPlayer) then
return
end
if (not ent:IsNPC() and not ent:IsPlayer()) then
return
end
local atk = dmg:GetAttacker()
if (not IsValid(atk)) then
return
end
if (atk.LeyHitreg_CurrentBullet) then
atk.LeyHitreg_CurrentBullet = nil
atk.LeyHitreg_LastShotMissed = nil
end
end
hook.Add("EntityTakeDamage","LeyHitreg:EntityTakeDamage", function(ent, dmg)
local ret = LeyHitreg:EntityTakeDamage(ent, dmg)
if (ret != nil) then
return ret
end
end)
local tickCount = engine.TickCount
function LeyHitreg:PlayerTick(ply)
if (ply.LeyHitreg_CurrentBullet) then
local curTick = tickCount()
ply.LeyHitreg_CurrentBullet = nil
ply.LeyHitreg_LastShotMissed = curTick
local hitTable = LeyHitreg.ForceHit[ply]
if (not hitTable) then
return
end
local shot = nil
local bestDelta = nil
for k,v in ipairs(hitTable) do
local delta = curTick - v.tickCount
if (delta >= 0) then
if (not bestDelta or bestDelta > delta) then
bestDelta = delta
shot = v
end
end
end
if (not shot) then
return
end
if (bestDelta > 6) then -- Ideally I'd probably assume it's the same tick
return
end
ply.LeyHitreg_LastBulletEnt:FireBullets(ply.LeyHitreg_LastBullet)
end
end
hook.Add("PlayerTick", "LeyHitreg:PlayerTick", function(ply)
LeyHitreg:PlayerTick(ply)
end)
function LeyHitreg:EntityFireBullets(plyorwep, bullet)
local ocb = bullet.Callback or function() end
bullet.Callback = function(atk, tr, dmginfo, ...)
atk.LeyHitreg_CurrentBullet = true
atk.LeyHitreg_LastBullet = table.Copy(bullet)
atk.LeyHitreg_LastBulletEnt = plyorwep
return ocb(atk, tr, dmginfo, ...)
end
if (LeyHitreg.ShowActualShotHit) then
LeyHitreg:DebugShowActualShotHit(bullet)
end
local ply, wep = self:GetPlayerFromPlyOrBullet(plyorwep, bullet)
if (not ply or not wep) then
return
end
if (self:IsIgnoreWep(wep)) then
return
end
if (not LeyHitreg.ShotDirForceDisabled) then
bullet.Dir = ply:GetAimVector()
end
local hitTable = LeyHitreg.ForceHit[ply]
if (not hitTable) then
return self:FallbackEntityFireBullets(ply, wep, bullet)
end
local shot = self:CleanHits(ply, wep, hitTable)[1]
if (not shot) then
return self:FallbackEntityFireBullets(ply, wep, bullet)
end
tableremove(hitTable, 1)
local target = shot.target
-- print(canSee)
-- print(target)
-- PrintTable(shot)
local targetpos = target:GetBonePosition(shot.targetBone)
if (not targetpos) then
ply:ChatPrint("[/LeyHitreg/] Bone not found")
return self:FallbackEntityFireBullets(ply, wep, bullet)
end
local newshootpos = ply:GetShootPos()
local newdir = (targetpos - bullet.Src)
LeyHitreg:HitScanBullet(ply, target, bullet, shot, shot.targetBone, shot.targetHitGroup, newshootpos)
bullet.Src = newshootpos
bullet.Dir = newdir
bullet.Spread = vector_origin
self.ScaleDamageBlockEntity[ply] = true
ply.LeyHitReg_ShouldHit = shot.targetHitGroup
if (LeyHitreg.LogFixedBullets) then
ply.LeyHitreg_Bullets = (ply.LeyHitreg_Bullets or 0) + 1
timer.Create("LeyHitreg." .. ply:SteamID64() .. ".LogFixedBullets", 1, 1, function()
ply:ChatPrint("bullets hitregged: " .. tostring(ply.LeyHitreg_Bullets))
ply.LeyHitreg_Bullets = 0
end)
end
if (LeyHitreg.BulletAimbot) then
timer.Simple(0, function()
ply:SetEyeAngles(newdir:Angle())
end)
end
if (LeyHitreg.LogTargetBone) then
ply:ChatPrint("Target Bone: " .. tostring(shot.targetBone))
end
return true
end
function LeyHitreg:InsertPlayerData(ply, cmd, wep, shouldPrimary, target, targetBone, targetHitGroup)
if (#self.ForceHit[ply] > 500) then
ply:Kick("[/LeyHitreg/] No Exploiting, little boy.")
return
end
table.insert(self.ForceHit[ply], {
["shouldPrimary"] = shouldPrimary,
["target"] = target,
["targetPos"] = target:GetPos(),
["targetBone"] = targetBone,
["targetHitGroup"] = targetHitGroup,
["shootPos"] = ply:GetShootPos(),
["eyeAngles"] = cmd:GetViewAngles(),
["aimVec"] = ply:GetAimVector(),
["shootPos"] = ply:GetPos(),
["weapon"] = wep,
["expireTime"] = CurTime() + 0.8,
["tickCount"] = engine.TickCount()
})
end
function LeyHitreg:CanPrimaryAttack(wep)
local ply = wep:GetOwner()
if (wep:Clip1() == 0) then
return false
end
if (not self.IgnoreCanNextPrimaryAttack and wep.CanPrimaryAttack) then
if (not wep:CanPrimaryAttack()) then
return false
end
return true
end
local nextPrim = wep:GetNextPrimaryFire()
if (wep.LastNextPrim and wep.LastNextPrim == nextPrim) then
return false
end
wep.LastNextPrim = nextPrim
return true
end
function LeyHitreg:ProcessBullet(ply, cmd, wep, shouldPrimary, target, targetBone)
self.ForceHit[ply] = self.ForceHit[ply] or {}
if (not target or target:Health() < 0) then
return
end
if (wep.LeyHitregIgnore) then
return
end
if (shouldPrimary and self:CanPrimaryAttack(wep)) then
local targetHitGroup = HITGROUP_GENERIC
local hitboxsets = target.GetHitBoxSetCount and target:GetHitBoxSetCount() or 1
for hitboxset = 0, hitboxsets - 1 do
local hitboxes = target:GetHitBoxCount(hitboxset)
for hitbox = 0, hitboxes - 1 do
local bone = target:GetHitBoxBone(hitbox, hitboxset)
if (bone == targetBone) then
targetHitGroup = target:GetHitBoxHitGroup(hitbox, hitboxset)
end
end
end
local hookRet = hook.Call("LeyHitreg:ProcessBullet", nil, ply, cmd, wep, shouldPrimary, target, targetBone, targetHitGroup)
if (hookRet == false) then
return
end
self:InsertPlayerData(ply, cmd, wep, shouldPrimary, target, targetBone, targetHitGroup)
end
end
hook.Add("EntityFireBullets", "LeyHitreg:EntityFireBullets", function(...)
local ret = LeyHitreg:EntityFireBullets(...)
if (ret != nil) then
return ret
end
end)

View File

@@ -0,0 +1,133 @@
function LeyHitreg:OriginalScaleDamage(ent, hitgroup, dmg, orighitgroup)
if (not self.LogHitgroupMismatches) then
return
end
local atk = dmg:GetAttacker()
if (orighitgroup and IsValid(atk) and atk.IsPlayer and atk:IsPlayer()) then
local shouldHit = hitgroup
atk:ChatPrint("HITGROUP_HEAD: " .. tostring(hitgroup == HITGROUP_HEAD))
atk:ChatPrint(shouldHit .. "==" .. orighitgroup)
return
end
end
hook.Add("ScalePlayerDamage", "LeyHitreg.DamageLog", function(ent, hitgroup, dmg, orighitgroup)
local ret = LeyHitreg:OriginalScaleDamage(ent, hitgroup, dmg, orighitgroup)
if (ret != nil) then
return ret
end
end)
hook.Add("ScaleNPCDamage", "LeyHitreg.DamageLog", function(ent, hitgroup, dmg, orighitgroup)
local ret = LeyHitreg:OriginalScaleDamage(ent, hitgroup, dmg, orighitgroup)
if (ret != nil) then
return ret
end
end)
LeyHitreg.ScaleDamagePlayersHooks = {}
LeyHitreg.ScaleDamageNPCsHooks = {}
function LeyHitreg:ScaleDamageCorrectly(target, hitgroup, dmg, targetisplayer)
local atk = dmg:GetAttacker()
local orighitgroup = hitgroup
if (IsValid(atk) and atk:IsPlayer()) then
if (LeyHitreg.ScaleDamageBlockEntity[atk]) then
LeyHitreg.ScaleDamageBlockEntity[atk] = false
end
hitgroup = atk.LeyHitReg_ShouldHit or hitgroup
atk.LeyHitReg_ShouldHit = nil
end
local damageHooks = targetisplayer and self.ScaleDamagePlayersHooks or self.ScaleDamageNPCsHooks
for k,v in pairs(damageHooks) do
local ret = v(target, hitgroup, dmg, orighitgroup)
if (ret != nil) then
return ret
end
end
if (targetisplayer) then
local ret = GAMEMODE:OldScalePlayerDamage(target, hitgroup, dmg, orighitgroup)
if (ret != nil) then
return ret
end
else
local ret = GAMEMODE:OldScaleNPCDamage(target, hitgroup, dmg, orighitgroup)
if (ret != nil) then
return ret
end
end
end
function LeyHitreg:ScalePlayerDamage(ply, hitgroup, dmg)
return LeyHitreg:ScaleDamageCorrectly(ply, hitgroup, dmg, true)
end
function LeyHitreg:ScaleNPCDamage(npc, hitgroup, dmg)
return LeyHitreg:ScaleDamageCorrectly(npc, hitgroup, dmg, false)
end
function LeyHitreg:AbsorbScaleDamageHooks()
if (self.Disabled) then
return
end
GAMEMODE.OldScalePlayerDamage = GAMEMODE.OldScalePlayerDamage or GAMEMODE.ScalePlayerDamage
GAMEMODE.OldScaleNPCDamage = GAMEMODE.OldScaleNPCDamage or GAMEMODE.ScaleNPCDamage
function GAMEMODE:ScalePlayerDamage(...)
if (LeyHitreg.Disabled) then
return self:OldScalePlayerDamage(...)
end
local ret = LeyHitreg:ScalePlayerDamage(...)
if (ret) then
return ret
end
end
function GAMEMODE:ScaleNPCDamage(...)
if (LeyHitreg.Disabled) then
return self:OldScaleNPCDamage(...)
end
local ret = LeyHitreg:ScaleNPCDamage(...)
if (ret) then
return ret
end
end
local allHooks = hook.GetTable()
local scalePlayers = allHooks["ScalePlayerDamage"] or {}
local scaleNPCs = allHooks["ScaleNPCDamage"] or {}
for k,v in pairs(scalePlayers) do
hook.Remove("ScalePlayerDamage", k)
self.ScaleDamagePlayersHooks[k] = v
end
for k,v in pairs(scaleNPCs) do
hook.Remove("ScaleNPCDamage", k)
self.ScaleDamageNPCsHooks[k] = v
end
end
timer.Simple(1, function()
LeyHitreg:AbsorbScaleDamageHooks()
end)
timer.Create("LeyHitreg:AbsorbScaleDamageHooks", 5, 0, function()
LeyHitreg:AbsorbScaleDamageHooks()
end)

View File

@@ -0,0 +1,12 @@
local meta = FindMetaTable("CTakeDamageInfo")
LeyHitreg.ScaleDamageBlockEntity = LeyHitreg.ScaleDamageBlockEntity or {}
meta.OldScaleDamage = meta.OldScaleDamage or meta.ScaleDamage
function meta:ScaleDamage(scale)
if (self:IsBulletDamage() and LeyHitreg and LeyHitreg.ScaleDamageBlockEntity[self:GetAttacker()]) then
return
end
return self:OldScaleDamage(scale)
end

View File

@@ -0,0 +1,101 @@
IN_LEYHITREG1 = bit.lshift(1, 27)
local Entity = Entity
local IsValid = IsValid
local PlyNeedsPrimReset = {}
LeyHitreg.BulletCount = {}
LeyHitreg.InvalidShots = {}
function LeyHitreg:StartCommand(ply, cmd)
if (not ply:Alive() or LeyHitreg.Disabled) then
return
end
local shouldPrimary = cmd:KeyDown(IN_LEYHITREG1)
if (not shouldPrimary) then
return
end
local targetEntIndex = cmd:GetUpMove()
local targetBone = cmd:GetMouseWheel()
cmd:SetUpMove(0)
cmd:SetMouseWheel(0)
if (targetBone > 0xFF) then
return
end
local wep = ply:GetActiveWeapon()
if (not IsValid(wep)) then
return
end
if (self:IsIgnoreWep(wep)) then
return
end
if ((LeyHitreg.BulletCount[ply] or 0) > 50) then
return
end
LeyHitreg.BulletCount[ply] = (LeyHitreg.BulletCount[ply] or 0) + 1
local target
if (targetEntIndex and targetEntIndex > 0) then
target = Entity(targetEntIndex)
if (not IsValid(target) or not (target:IsNPC() or target:IsPlayer())) then
target = nil
end
else
targetEntIndex = 0
end
if (target) then
if (self:IsInvalidShot(ply, cmd, wep, shouldPrimary, target, targetBone)) then
if (self.LogInvalidShots) then
ply:ChatPrint("Invalid shot!")
end
LeyHitreg.InvalidShots[ply] = (LeyHitreg.InvalidShots[ply] or 0) + 1
return
end
end
LeyHitreg:ProcessBullet(ply, cmd, wep, shouldPrimary, target, targetBone)
end
timer.Create("LeyHitreg.BulletMax", 0.1, 0, function()
for k, ply in ipairs(player.GetAll()) do
LeyHitreg.BulletCount[ply] = 0
end
end)
timer.Create("LeyHitreg.KickInvalidShooters", 30, 0, function()
for k, ply in ipairs(player.GetAll()) do
if ((LeyHitreg.InvalidShots[ply] or 0) >= 10) then
ply:Kick("[/LeyHitreg/] Too many invalid shots!")
end
LeyHitreg.InvalidShots[ply] = 0
end
end)
hook.Add("StartCommand", "LeyHitreg:StartCommand", function(ply, cmd)
LeyHitreg:StartCommand(ply, cmd)
end)
function LeyHitreg:PlayerSwitchWeapon(ply, oldWep, newWep)
PlyNeedsPrimReset[ply] = nil
end
hook.Add("PlayerSwitchWeapon", "LeyHitreg:PlayerSwitchWeapon", function(ply, oldWep, newWep)
LeyHitreg:PlayerSwitchWeapon(ply, oldWep, newWep)
end)

View File

@@ -0,0 +1,72 @@
-- just ideas to make aimbot using this harder
-- if the angle which client supposedly used to hit target is more than MaxFOVDiffDeg degrees off of the target
-- chances are it's not a information mismatch but a manipulation attempt
local mathacos = math.acos
local mathdeg = math.deg
local FOVCheckCloseDist = 350 * 350
local FOVCheckFarDist = 700 * 700
local MaxCloseFOVDiffDeg = 90
local MaxFarFOVDiffDeg = 40
local MaxCloseFOVDiffRad = math.rad(MaxCloseFOVDiffDeg)
local MaxFarFOVDiffRad = math.rad(MaxFarFOVDiffDeg)
function LeyHitreg:IsInvalidShotOutOfFOV(ply, plyang, plypos, tarpos, distsqr)
if (distsqr < FOVCheckCloseDist) then
if (self.LogInvalidFOV) then
ply:ChatPrint("FOV: Close, so no checking")
end
return false
end
local maxRad = distsqr > FOVCheckFarDist and MaxFarFOVDiffRad or MaxCloseFOVDiffRad
local targetdir = (tarpos - plypos)
local curdir = plyang:Forward()
local FOVDiff = mathacos(targetdir:Dot(curdir) / (targetdir:Length() * curdir:Length()))
if (self.LogInvalidFOV) then
ply:ChatPrint("FOV: " .. tostring(mathdeg(FOVDiff)) .. " Max: " .. tostring(mathdeg(maxRad)))
end
return FOVDiff > maxRad
end
-- if the weapon has spread, and the client did not apply any spread, then reject the bullet
-- this requires the unmodified va to be sent together in the usercmd somehow
-- then can compare the two and if equal, yeet
function LeyHitreg:IsSpreadNotApplied(ply, cmd, wep, shouldPrimary)
if (self.NoSpread) then
return false
end
return false
end
function LeyHitreg:IsInvalidShot(ply, cmd, wep, shouldPrimary, target, targetBone)
if (LeyHitreg.DisableSecurityChecks) then
return false
end
local plyang = cmd:GetViewAngles()
local plypos = ply:GetPos()
local tarpos = target:GetPos()
local distsqr = plypos:DistToSqr(tarpos)
if (self:IsInvalidShotOutOfFOV(ply, plyang, plypos, tarpos, distsqr)) then
return true
end
if (self:IsSpreadNotApplied(ply, cmd, wep, shouldPrimary)) then
return true
end
return false
end

View File

@@ -0,0 +1,10 @@
local meta = FindMetaTable("Player")
meta.OldLagCompensation = meta.OldLagCompensation or meta.LagCompensation
function meta:LagCompensation(...)
if (LeyHitreg.DisableLagComp and not LeyHitreg.Disabled) then
return
end
return self:OldLagCompensation(...)
end

View File

@@ -0,0 +1,50 @@
local Vector = Vector
local mathmodf = math.modf
local mathrandomseed = math.randomseed
local mathrandom = math.random
local mathsqrt = math.sqrt
local isnumber = isnumber
local vector_origin = vector_origin
local timefn = function()
return 1 -- os.date("%S")
end
function LeyHitreg:ApplyBulletSpread(ply, dir, spread)
if (LeyHitreg.NoSpread) then
return true, dir, vector_origin
end
if (not spread or spread == vector_origin or LeyHitreg.BrokenSpread) then
return false
end
if (isnumber(spread)) then
spread = Vector(spread, spread, spread)
end
local add = (8969 * timefn())
mathrandomseed(add + CurTime())
local ang = dir:Angle()
local appliedSpread, rgt, up = Vector(), ang:Right(), ang:Up()
local x, y, z
repeat
x = mathrandom() + mathrandom() - 1
y = mathrandom() + mathrandom() - 1
z = x * x + y * y
until z <= 1
for i = 1, 3 do
appliedSpread[i] = x * spread.x * rgt[i] + y * spread.y * up[i]
end
dir = dir + appliedSpread
return true, dir, appliedSpread
end

View File

@@ -0,0 +1,20 @@
function LeyHitreg:SpreadedEntityFireBullets(ply, wep, bullet, spread)
if (LeyHitreg.Disabled) then
return
end
if (LeyHitreg.BrokenDefaultSpread) then
return
end
local bulletSpread = spread or LeyHitreg:GetWeaponSpread(ply, wep, bullet)
local appliedAny, newDir = self:ApplyBulletSpread(ply, bullet.Dir, bulletSpread)
if (not appliedAny) then
return
end
bullet.Spread = vector_origin
bullet.Dir = newDir
return true
end

View File

@@ -0,0 +1,16 @@
function LeyHitreg:ConVarSet(name, val)
if (GetConVar(name)) then
RunConsoleCommand(name, val)
end
end
function LeyHitreg:SWEPConvars()
self:ConVarSet("arccw_enable_penetration", "0")
self:ConVarSet("sv_tfa_bullet_penetration", "0")
self:ConVarSet("sv_tfa_bullet_randomseed", "0")
end
timer.Simple(1, function()
LeyHitreg:SWEPConvars()
end)

View File

@@ -0,0 +1,205 @@
local HL2Ignore = {}
HL2Ignore["weapon_physcannon"] = true
HL2Ignore["weapon_physgun"] = true
HL2Ignore["weapon_frag"] = true
HL2Ignore["weapon_rpg"] = true
HL2Ignore["gmod_camera"] = true
HL2Ignore["gmod_tool"] = true
HL2Ignore["weapon_physcannon"] = true
HL2Ignore["weapon_shotgun"] = true
local MeleeHoldType = {}
MeleeHoldType["knife"] = true
MeleeHoldType["melee"] = true
MeleeHoldType["melee2"] = true
local ExtraIgnores = {}
function LeyHitreg:IsIgnoreWep(wep)
if (HL2Ignore[wep:GetClass()]) then
return true
end
if (ExtraIgnores[wep:GetClass()]) then
return true
end
-- Ignore all melees
if (wep.IsMelee or wep.Melee or wep:Clip1() < 0) then
return true
end
if (wep.GetHoldType) then
local holdType = wep:GetHoldType()
if (MeleeHoldType[holdType]) then
return true
end
end
-- Ignore shotguns
if (wep.Shotgun or wep.IsShotgun or wep.ShotgunReload or wep.ShotGun or wep.Primary and wep.Primary.NumShots and wep.Primary.NumShots > 1) then
return true
end
-- Ignore modern day SWEP creators who are too busy reinventing the wheel to add a single wep.IsShotgun variable
if (wep.ShotgunEmptyAnim or wep.ShotgunStartAnimShell) then
return true
end
if (wep.Category and string.find(string.lower(wep.Category), "shotgun", 1, true)) then
return true
end
if (wep.Purpose and string.find(string.lower(wep.Purpose), "shotgun", 1, true)) then
return true
end
if (wep.PrintName and string.find(string.lower(wep.PrintName), "shotgun", 1, true)) then
return true
end
if (ACT3_CAT_SHOTGUN and wep.ACT3Cat and wep.ACT3Cat == ACT3_CAT_SHOTGUN) then
return true
end
return false
end
function LeyHitreg:AddIgnoreWeapon(weporclass)
if (isstring(weporclass)) then
ExtraIgnores[weporclass] = true
else
ExtraIgnores[weporclass:GetClass()] = true
end
end
function LeyHitreg:GetPlayerFromWeapon(wep)
local ply = wep:GetOwner()
if (not IsValid(ply)) then
return
end
return ply
end
local IsValid = IsValid
function LeyHitreg:GetPlayerFromPlyOrBullet(plyorwep, bullet)
if (not bullet or not IsValid(plyorwep)) then
return
end
local ply = bullet.Attacker
if (not IsValid(ply) or not ply:IsPlayer()) then
ply = nil
end
if (plyorwep:IsWeapon()) then
if (ply) then
return ply, plyorwep
end
local owner = plyorwep:GetOwner()
if (not IsValid(owner) or not owner:IsPlayer()) then
return
end
return owner, plyorwep
end
if (not ply) then
ply = plyorwep
if (not ply:IsPlayer()) then
return
end
end
local wep = ply:GetActiveWeapon()
if (not IsValid(wep)) then
return
end
return ply, wep
end
local vector_origin = vector_origin
function LeyHitreg:GetWeaponSpread(ply, wep, bullet)
-- MW Swep pack workaround
if (wep.CalculateCone) then
return wep:CalculateCone() * 0.1 * 0.7
end
-- TFA workaround
if (wep.CalculateConeRecoil) then
return wep:CalculateConeRecoil()
end
-- ARCCW workaround
if (wep.GetBuff and wep.ApplyRandomSpread and wep.TryBustDoor and ArcCW) then
return ArcCW.MOAToAcc * wep:GetBuff("AccuracyMOA") * 4.5
end
-- CW2 workaround
if (wep.AimSpread and wep.recalculateAimSpread and wep.getBaseCone) then
return wep:getBaseCone()
end
if (bullet) then
local bulletSpread = bullet.Spread
if (bulletSpread and bulletSpread != vector_origin) then
return bulletSpread
end
end
if (self.WeaponSpreads and self.WeaponSpreads[wep:GetClass()]) then
return self.WeaponSpreads[wep:GetClass()]
end
if (wep.PrimarySpread) then
return wep.PrimarySpread
end
if (wep.PrimaryCone) then
return wep.PrimaryCone
end
if (wep.Primary) then
if (wep.Primary.Spread) then
return wep.Primary.Spread
end
if (wep.Primary.Cone) then
return wep.Primary.Cone
end
return bulletSpread
end
return vector_origin
end
function LeyHitreg:SetFittingValidClip(wep)
local clip1 = wep:Clip1()
if (clip1 == -1 or clip1 > 0) then
return
end
local max = wep:GetMaxClip1()
if (max > 0) then
wep:SetClip1(max)
return
end
wep:SetClip1(30)
end

View File

@@ -0,0 +1,142 @@
PLUGIN.name = "LeyHitReg"
PLUGIN.author = "Ley (Портирован для Helix)"
PLUGIN.description = "Улучшенная система регистрации попаданий для точной стрельбы"
-- Конфигурация системы
LeyHitreg = LeyHitreg or {}
-- Настройки через ix.config
ix.config.Add("leyHitregEnabled", true, "Включить систему улучшенной регистрации попаданий", nil, {
category = "LeyHitReg"
})
ix.config.Add("leyHitregShotDirForceDisabled", false, "Принудительно отключить направление выстрела (для тестирования проблемных SWEP баз)", nil, {
category = "LeyHitReg"
})
ix.config.Add("leyHitregDisableSecurityChecks", false, "Отключить проверки безопасности выстрелов", nil, {
category = "LeyHitReg"
})
ix.config.Add("leyHitregIgnoreCanNextPrimaryAttack", true, "Игнорировать задержку между выстрелами (рекомендуется)", nil, {
category = "LeyHitReg"
})
ix.config.Add("leyHitregNoSpread", false, "[DEBUG] Включить режим без разброса для всех", nil, {
category = "LeyHitReg - Debug"
})
ix.config.Add("leyHitregShowActualHit", false, "[DEBUG] Показывать где на самом деле попала пуля (без разброса)", nil, {
category = "LeyHitReg - Debug"
})
ix.config.Add("leyHitregShowSpreadedHit", false, "[DEBUG] Показывать где на самом деле попала пуля (с разбросом)", nil, {
category = "LeyHitReg - Debug"
})
ix.config.Add("leyHitregLogFixedBullets", false, "[DEBUG] Логировать количество исправленных пуль", nil, {
category = "LeyHitReg - Debug"
})
ix.config.Add("leyHitregLogInvalidShots", false, "[DEBUG] Логировать невалидные выстрелы", nil, {
category = "LeyHitReg - Debug"
})
-- Применяем настройки к LeyHitreg
LeyHitreg.ShotDirForceDisabled = ix.config.Get("leyHitregShotDirForceDisabled", false)
LeyHitreg.DisableSecurityChecks = ix.config.Get("leyHitregDisableSecurityChecks", false)
LeyHitreg.IgnoreCanNextPrimaryAttack = ix.config.Get("leyHitregIgnoreCanNextPrimaryAttack", true)
-- Debug настройки
LeyHitreg.Disabled = not ix.config.Get("leyHitregEnabled", true)
LeyHitreg.DisabledOnlyOnClient = false
LeyHitreg.NoSpread = ix.config.Get("leyHitregNoSpread", false)
LeyHitreg.ShowActualShotHit = ix.config.Get("leyHitregShowActualHit", false)
LeyHitreg.ShowActualShotSpreadedHit = ix.config.Get("leyHitregShowSpreadedHit", false)
LeyHitreg.BrokenDefaultSpread = false
LeyHitreg.LogHitgroupMismatches = false
LeyHitreg.LogFixedBullets = ix.config.Get("leyHitregLogFixedBullets", false)
LeyHitreg.LogInvalidFOV = false
LeyHitreg.LogInvalidShots = ix.config.Get("leyHitregLogInvalidShots", false)
LeyHitreg.BulletAimbot = false
LeyHitreg.LogTargetBone = false
LeyHitreg.HitScanDisabled = false
LeyHitreg.BulletOverwriteDisabled = false
LeyHitreg.AnnounceClientHits = false
LeyHitreg.DisableLagComp = false
if LeyHitreg.Disabled then
print("[LeyHitReg] Отключен через настройки")
return
end
-- Отключение конфликтующих систем хитрега
function LeyHitreg:DisableMoatHitreg()
if MOAT_HITREG then
MOAT_HITREG.MaxPing = 1
end
if ConVarExists("moat_alt_hitreg") then
RunConsoleCommand("moat_alt_hitreg", "0")
end
if SHR then
if SHR.Config then
SHR.Config.Enabled = false
SHR.Config.ClientDefault = 0
end
hook.Remove("EntityFireBullets", "SHR.FireBullets")
hook.Remove("EntityFireBullets", "a")
net.Receivers["shr"] = function() end
end
end
function PLUGIN:Initialize()
print("[LeyHitReg] Загрузка системы регистрации попаданий...")
-- Отключаем конфликтующие системы
LeyHitreg:DisableMoatHitreg()
print("[LeyHitReg] Система загружена!")
end
-- Обновление настроек при изменении конфига
function PLUGIN:OnConfigChanged(key, oldValue, newValue)
if key == "leyHitregEnabled" then
LeyHitreg.Disabled = not newValue
print("[LeyHitReg] Система " .. (newValue and "включена" or "отключена"))
elseif key == "leyHitregShotDirForceDisabled" then
LeyHitreg.ShotDirForceDisabled = newValue
elseif key == "leyHitregDisableSecurityChecks" then
LeyHitreg.DisableSecurityChecks = newValue
elseif key == "leyHitregIgnoreCanNextPrimaryAttack" then
LeyHitreg.IgnoreCanNextPrimaryAttack = newValue
elseif key == "leyHitregNoSpread" then
LeyHitreg.NoSpread = newValue
elseif key == "leyHitregShowActualHit" then
LeyHitreg.ShowActualShotHit = newValue
elseif key == "leyHitregShowSpreadedHit" then
LeyHitreg.ShowActualShotSpreadedHit = newValue
elseif key == "leyHitregLogFixedBullets" then
LeyHitreg.LogFixedBullets = newValue
elseif key == "leyHitregLogInvalidShots" then
LeyHitreg.LogInvalidShots = newValue
end
end
-- Загрузка модулей
ix.util.Include("leyhitreg/shared/spreadsystem/bulletspread.lua")
ix.util.Include("leyhitreg/shared/spreadsystem/firebullets.lua")
ix.util.Include("leyhitreg/shared/disablelagcomp/disablelagcomp.lua")
ix.util.Include("leyhitreg/shared/workarounds/workarounds.lua")
ix.util.Include("leyhitreg/shared/workarounds/swepbases.lua")
ix.util.Include("leyhitreg/client/sendshots/sendshots.lua")
ix.util.Include("leyhitreg/client/sendshots/fetchspreads.lua")
ix.util.Include("leyhitreg/server/bulletprocessing/hitscan.lua")
ix.util.Include("leyhitreg/server/bulletprocessing/processbullet.lua")
ix.util.Include("leyhitreg/server/damageinfo/scaledamagehack.lua")
ix.util.Include("leyhitreg/server/damageinfo/fixscaling.lua")
ix.util.Include("leyhitreg/server/receiveshotinfo/receiveshotinfo.lua")
ix.util.Include("leyhitreg/server/receiveshotinfo/shotvalidator.lua")